1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
use std::collections::HashMap;
use std::vec::Vec;
extern crate gl;
use interface::i_renderobj;
use implement::render::util_gl;
#[derive(Debug)]
#[derive(Clone)]
#[derive(Copy)]
pub struct BufferFormat {
pub _buff_data_type: i_renderobj::BuffDataType,
pub _index: u64,
pub _num_data: u64,
pub _stride_bytes: u64,
pub _offset_bytes: u64,
}
#[derive(Debug)]
pub struct RenderDrawGroup {
pub _group_handle: u64,
pub _buffer_handle: u64,
pub _buffer_draw: Vec< f32 >,
pub _format: Vec< BufferFormat >,
pub _stride: u64,
pub _primitive_type: i_renderobj::RenderObjType,
}
impl RenderDrawGroup {
pub fn init( internal_group_handle: u64, buffer_handle: u64, format: Vec< BufferFormat >, stride: u64, primitive_type: i_renderobj::RenderObjType ) -> RenderDrawGroup {
RenderDrawGroup {
_group_handle: internal_group_handle,
_buffer_handle: buffer_handle,
_buffer_draw: vec![],
_format: format,
_stride: stride,
_primitive_type: primitive_type,
}
}
pub fn init_with_default_format_triangle( internal_group_handle: u64, buffer_handle: u64 ) -> RenderDrawGroup {
let stride = 8 * ::std::mem::size_of::<f32>();
let format = vec![ BufferFormat { _buff_data_type: i_renderobj::BuffDataType::POS, _index: 0, _num_data: 3, _stride_bytes: stride as _, _offset_bytes: 0 },
BufferFormat { _buff_data_type: i_renderobj::BuffDataType::NORMAL, _index: 1, _num_data: 3, _stride_bytes: stride as _, _offset_bytes: (3 * ::std::mem::size_of::<f32>()) as _ },
BufferFormat { _buff_data_type: i_renderobj::BuffDataType::TC, _index: 2, _num_data: 2, _stride_bytes: stride as _, _offset_bytes: (6 * ::std::mem::size_of::<f32>()) as _ },
];
RenderDrawGroup {
_group_handle: internal_group_handle,
_buffer_handle: buffer_handle,
_buffer_draw: vec![],
_format: format,
_stride: stride as _,
_primitive_type: i_renderobj::RenderObjType::TRI,
}
}
pub fn init_with_default_format_point( internal_group_handle: u64, buffer_handle: u64 ) -> RenderDrawGroup {
let stride = 8 * ::std::mem::size_of::<f32>();
let format = vec![ BufferFormat { _buff_data_type: i_renderobj::BuffDataType::POS, _index: 0, _num_data: 3, _stride_bytes: stride as _, _offset_bytes: 0 },
BufferFormat { _buff_data_type: i_renderobj::BuffDataType::NORMAL, _index: 1, _num_data: 3, _stride_bytes: stride as _, _offset_bytes: (3 * ::std::mem::size_of::<f32>()) as _ },
BufferFormat { _buff_data_type: i_renderobj::BuffDataType::TC, _index: 2, _num_data: 2, _stride_bytes: stride as _, _offset_bytes: (6 * ::std::mem::size_of::<f32>()) as _ },
];
RenderDrawGroup {
_group_handle: internal_group_handle,
_buffer_handle: buffer_handle,
_buffer_draw: vec![],
_format: format,
_stride: stride as _,
_primitive_type: i_renderobj::RenderObjType::POINT,
}
}
}
impl i_renderobj::RenderDevice for RenderDrawGroup{
fn bind_buffer( & mut self ) -> Result< (), & 'static str > {
let data_len = self._buffer_draw.len() * ::std::mem::size_of::<f32>();
unsafe {
gl::BindVertexArray( self._group_handle as _ );
gl::BindBuffer( gl::ARRAY_BUFFER, self._buffer_handle as _ );
gl::BufferData( gl::ARRAY_BUFFER, data_len as isize, self._buffer_draw.as_ptr() as _, gl::STATIC_DRAW );
util_gl::check_last_op();
for &i in self._format.iter() {
gl::VertexAttribPointer( i._index as _, i._num_data as _, gl::FLOAT, gl::FALSE, i._stride_bytes as i32, i._offset_bytes as _ );
gl::EnableVertexAttribArray( i._index as _ );
util_gl::check_last_op();
}
gl::BindBuffer( gl::ARRAY_BUFFER, 0 );
gl::BindVertexArray( 0 );
}
Ok( () )
}
fn draw_buffer_all( & mut self) -> Result< (), & 'static str > {
unsafe {
gl::BindVertexArray( self._group_handle as _ );
let num_elements = self._buffer_draw.len() / (self._stride as usize / ::std::mem::size_of::<f32>());
match self._primitive_type {
i_renderobj::RenderObjType::TRI => {
println!("draw buffer all: num verts: {}", num_elements );
gl::DrawArrays(gl::TRIANGLES, 0, num_elements as _ );
},
i_renderobj::RenderObjType::POINT => {
println!("draw buffer all: num points: {}", num_elements );
gl::PointSize(3f32);
gl::DrawArrays(gl::POINTS, 0, num_elements as _ );
},
_=> return Err( "unsupported primite type for drawing detected" )
}
gl::BindVertexArray( 0 );
}
Ok( () )
}
fn draw_buffer_range( & mut self) -> Result< (), & 'static str > {
unimplemented!();
}
fn clear_buff_data( & mut self ){
self._buffer_draw.clear();
}
fn store_buff_data( & mut self, data: & HashMap< i_renderobj::BuffDataType, Vec< f32 > > ) -> Result< (), & 'static str > {
let mut data_pos : Vec< f32 > = vec![];
let mut data_normal : Vec< f32 > = vec![];
let mut data_tc : Vec< f32 > = vec![];
for i in self._format.iter() {
match i._buff_data_type {
i_renderobj::BuffDataType::POS => {
match data.get( &i_renderobj::BuffDataType::POS ) {
None => return Err( "render buffer data expected data not found: pos" ),
Some( ref pos ) => {
data_pos.extend_from_slice( &pos[..] );
}
}
},
i_renderobj::BuffDataType::NORMAL => {
match data.get( &i_renderobj::BuffDataType::NORMAL ) {
None => return Err( "render buffer data expected data not found: normal" ),
Some( ref normal ) => {
data_normal.extend_from_slice( &normal[..] );
}
}
},
i_renderobj::BuffDataType::TC => {
match data.get( &i_renderobj::BuffDataType::TC ) {
None => return Err( "render buffer data expected data not found: tc" ),
Some( ref tc ) => {
data_tc.extend_from_slice( &tc[..] );
}
}
},
}
}
match self._primitive_type {
i_renderobj::RenderObjType::TRI => {
if data_pos.len() != data_normal.len() {
return Err( "render buffer data length not equal" )
}
if data_pos.len() % 3 != 0 {
return Err( "render buffer data length not divisible by 3" )
}
if data_tc.len() % 2 != 0 {
return Err( "render buffer data length not divisible by 2" )
}
let count_data = data_pos.len() / 3;
if count_data != data_tc.len() / 2 {
return Err( "render buffer data length not equal" )
}
for i in 0..count_data {
self._buffer_draw.push( data_pos[i*3] );
self._buffer_draw.push( data_pos[i*3+1] );
self._buffer_draw.push( data_pos[i*3+2] );
self._buffer_draw.push( data_normal[i*3] );
self._buffer_draw.push( data_normal[i*3+1] );
self._buffer_draw.push( data_normal[i*3+2] );
self._buffer_draw.push( data_tc[i*2] );
self._buffer_draw.push( data_tc[i*2+1] );
}
},
i_renderobj::RenderObjType::POINT => {
if data_pos.len() != data_normal.len() {
return Err( "render buffer data length not equal" )
}
if data_pos.len() % 3 != 0 {
return Err( "render buffer data length not divisible by 3" )
}
if data_tc.len() % 2 != 0 {
return Err( "render buffer data length not divisible by 2" )
}
let count_data = data_pos.len() / 3;
if count_data != data_tc.len() / 2 {
return Err( "render buffer data length not equal" )
}
for i in 0..count_data {
self._buffer_draw.push( data_pos[i*3] );
self._buffer_draw.push( data_pos[i*3+1] );
self._buffer_draw.push( data_pos[i*3+2] );
self._buffer_draw.push( data_normal[i*3] );
self._buffer_draw.push( data_normal[i*3+1] );
self._buffer_draw.push( data_normal[i*3+2] );
self._buffer_draw.push( data_tc[i*2] );
self._buffer_draw.push( data_tc[i*2+1] );
}
},
i_renderobj::RenderObjType::LINE => {
},
_ => { unimplemented!(); }
}
Ok( () )
}
}
#[derive(Debug)]
#[derive(Clone)]
#[derive(Copy)]
pub enum UniformType {
VEC,
MAT4,
MAT4X1,
MAT4X2,
MAT4X3,
MAT3,
MAT3X1,
MAT3X2,
MAT2,
MAT2X1,
}
pub struct RenderUniformCollection {
pub _uniforms_f: HashMap< (u64, String), ( UniformType, Vec<f32> ) >,
pub _uniforms_groups: HashMap< u64, (u64, Vec<String>) >,
}
impl Default for RenderUniformCollection {
fn default() -> RenderUniformCollection {
RenderUniformCollection {
_uniforms_f: HashMap::new(),
_uniforms_groups: HashMap::new(),
}
}
}
impl RenderUniformCollection {
pub fn set_uniform_f( & mut self, shader_program: u64, name: &str, val_type: UniformType, vals: &[f32] ) {
self._uniforms_f.insert( (shader_program, String::from( name ) ), ( val_type, vals.to_vec() ) );
}
pub fn set_group( & mut self, shader_program: u64, group_id: u64, names: Vec< String > ) -> Result< (), & 'static str > {
for i in names.iter() {
match self._uniforms_f.get( &( shader_program, i.clone() ) ) {
None => return Err( &"unfound uniform name" ),
_ => (),
}
}
self._uniforms_groups.insert( group_id, ( shader_program, names ) );
Ok( () )
}
pub fn get_group( & self, group_id: u64 ) -> Result< Vec< (String, UniformType, Vec<f32> )>, & 'static str > {
let mut ret = vec![];
match self._uniforms_groups.get( &group_id ) {
None => return Err( &"unfound uniform group id" ),
Some( &( ref program, ref v ) ) => {
for name in v.iter() {
match self._uniforms_f.get( &( *program, name.clone()) ) {
None => return Err( &"unfound uniform name" ),
Some( &( ref uniform_type , ref vals) ) => {
ret.push( ( name.clone(), uniform_type.clone(), vals.clone() ) );
}
}
}
}
}
Ok( ret )
}
pub fn send_uniform_group( & self, group_id: u64 ) -> Result< (), & 'static str > {
match self._uniforms_groups.get( &group_id ) {
None => return Err( &"unfound uniform group id" ),
Some( &( ref program, ref v ) ) => {
for name in v.iter() {
match self._uniforms_f.get( &( *program, name.clone()) ) {
None => return Err( &"unfound uniform name" ),
Some( &( ref uniform_type , ref vals) ) => {
match *uniform_type {
UniformType::VEC => {
unsafe {
match vals.len() {
1 => gl::Uniform1f( gl::GetUniformLocation( *program as _, name.as_ptr() as * const i8 ), vals[0] ),
2 => gl::Uniform2fv( gl::GetUniformLocation( *program as _, name.as_ptr() as * const i8 ), 1, vals.as_ptr() as _ ),
3 => gl::Uniform3fv( gl::GetUniformLocation( *program as _, name.as_ptr() as * const i8 ), 1, vals.as_ptr() as _ ),
4 => gl::Uniform4fv( gl::GetUniformLocation( *program as _, name.as_ptr() as * const i8 ), 1, vals.as_ptr() as _ ),
_ => return Err( &"unsupported uniform data length" ),
}
}
},
UniformType::MAT4 => {
if vals.len() != 16 {
return Err( &"unmatched uniform length for MAT4" )
}
unsafe {
gl::UniformMatrix4fv( gl::GetUniformLocation( *program as _, name.as_ptr() as * const i8 ), 1, gl::TRUE, vals.as_ptr() as _ );
}
},
UniformType::MAT3 => {
if vals.len() != 9 {
return Err( &"unmatched uniform length for MAT3" )
}
unsafe {
gl::UniformMatrix3fv( gl::GetUniformLocation( *program as _, name.as_ptr() as * const i8 ), 1, gl::TRUE, vals.as_ptr() as _ );
}
},
_ => { unimplemented!(); },
}
}
}
}
}
}
Ok( () )
}
}