gKit2 light
tuto_uniform_buffers.cpp
Go to the documentation of this file.
1 
3 
4 #include <cstddef>
5 #include <cassert>
6 
7 #include <vector>
8 
9 #include "window.h"
10 
11 #include "vec.h"
12 #include "color.h"
13 #include "program.h"
14 
15 
16 namespace glsl
17 {
18  // type de base alignes sur 4 octets
19  template < typename T >
20  struct alignas(4) gscalar
21  {
22  alignas(4) T x;
23 
24  gscalar( ) : x(T()) {}
25  gscalar( const T& v ) : x(v) {}
26  gscalar& operator= ( const T& v ) { x= v; return *this; }
27  operator T ( ) { return x; }
28  };
29 
30  typedef gscalar<float> gfloat;
31  typedef gscalar<int> gint;
32  typedef gscalar<unsigned int> guint;
33  typedef gscalar<bool> gbool;
34 
35  // vec2, alignes sur 2 * alignement type de base du vecteur
36  template < typename T >
37  struct alignas(8) gvec2
38  {
39  alignas(4) T x, y;
40 
41  gvec2( ) {}
42  gvec2( const gvec2<T>& v ) : x(v.x), y(v.y) {}
43  gvec2( const ::vec2& v ) : x(v.x), y(v.y) {}
44  gvec2& operator= ( const gvec2<T>& v ) { x= v.x; y= v.y; return *this; }
45  gvec2& operator= ( const ::vec2& v ) { x= v.x; y= v.y; return *this; }
46  operator ::vec2 ( ) { return ::vec2(float(x), float(y)); }
47  };
48 
49  typedef gvec2<float> vec2;
50  typedef gvec2<int> ivec2;
51  typedef gvec2<unsigned int> uvec2;
52  typedef gvec2<int> bvec2;
53 
54  // vec3, alignes sur 4 * alignement type de base du vecteur
55  template < typename T >
56  struct alignas(16) gvec3
57  {
58  alignas(4) T x, y, z;
59 
60  gvec3( ) {}
61  gvec3( const gvec3<T>& v ) : x(v.x), y(v.y), z(v.z) {}
62  gvec3( const ::vec3& v ) : x(v.x), y(v.y), z(v.z) {}
63  gvec3( const Point& v ) : x(v.x), y(v.y), z(v.z) {}
64  gvec3( const Vector& v ) : x(v.x), y(v.y), z(v.z) {}
65  gvec3& operator= ( const gvec3<T>& v ) { x= v.x; y= v.y; z= v.z; return *this; }
66  gvec3& operator= ( const ::vec3& v ) { x= v.x; y= v.y; z= v.z; return *this; }
67  gvec3& operator= ( const Point& v ) { x= v.x; y= v.y; z= v.z; return *this; }
68  gvec3& operator= ( const Vector& v ) { x= v.x; y= v.y; z= v.z; return *this; }
69  operator ::vec3 ( ) { return ::vec3(float(x), float(y), float(y)); }
70  };
71 
72  typedef gvec3<float> vec3;
73  typedef gvec3<int> ivec3;
74  typedef gvec3<unsigned int> uvec3;
75  typedef gvec3<int> bvec3;
76 
77  // vec4, alignes sur 4 * alignement type de base du vecteur
78  template < typename T >
79  struct alignas(16) gvec4
80  {
81  alignas(4) T x, y, z, w;
82 
83  gvec4( ) {}
84  gvec4( const gvec4<T>& v ) : x(v.x), y(v.y), z(v.z), w(v.w) {}
85  gvec4( const ::vec4& v ) : x(v.x), y(v.y), z(v.z), w(v.w) {}
86  gvec4& operator= ( const gvec4<T>& v ) { x(v.x), y(v.y), z(v.z), w(v.w) ; return *this; }
87  gvec4& operator= ( const ::vec4& v ) { x(v.x), y(v.y), z(v.z), w(v.w) ; return *this; }
88  gvec4& operator= ( const Color& c ) { x= c.r; y= c.g; z= c.b; w= c.a; return *this; }
89  operator ::vec4 ( ) { return ::vec4(float(x), float(y), float(y), float(w)); }
90  };
91 
92  typedef gvec4<float> vec4;
93  typedef gvec4<int> ivec4;
94  typedef gvec4<unsigned int> uvec4;
95  typedef gvec4<int> bvec4;
96 
97  // alignement different pour les elements d'un tableau : 16 octets, meme pour les types plus petits comme les float, int, bool
98  namespace array
99  {
100  template < typename T >
101  struct alignas(16) gscalar
102  {
103  T x;
104 
105  gscalar( ) : x(T()) {}
106  gscalar( const T& v ) : x(v) {}
107  gscalar& operator= ( const T& v ) { x= v; return *this; }
108  operator T ( ) { return x; }
109  };
110 
111  typedef gscalar<float> gfloat;
112  typedef gscalar<int> gint;
114  typedef gscalar<bool> gbool;
115 
116  template < typename T >
117  struct alignas(16) gvec2
118  {
119  alignas(4) T x, y;
120 
121  gvec2( ) {}
122  gvec2( const gvec2<T>& v ) : x(v.x), y(v.y) {}
123  gvec2( const ::vec2& v ) : x(v.x), y(v.y) {}
124  gvec2& operator= ( const gvec2<T>& v ) { x= v.x; y= v.y; return *this; }
125  gvec2& operator= ( const ::vec2& v ) { x= v.x; y= v.y; return *this; }
126  operator ::vec2 ( ) { return ::vec2(float(x), float(y)); }
127  };
128 
129  typedef gvec2<float> vec2;
130  typedef gvec2<int> ivec2;
131  typedef gvec2<unsigned int> uvec2;
132  typedef gvec2<int> bvec2;
133 
134  template < typename T >
135  struct alignas(16) gvec3
136  {
137  alignas(4) T x, y, z;
138 
139  gvec3( ) {}
140  gvec3( const gvec3<T>& v ) : x(v.x), y(v.y), z(v.z) {}
141  gvec3( const ::vec3& v ) : x(v.x), y(v.y), z(v.z) {}
142  gvec3( const Point& v ) : x(v.x), y(v.y), z(v.z) {}
143  gvec3( const Vector& v ) : x(v.x), y(v.y), z(v.z) {}
144  gvec3& operator= ( const gvec3<T>& v ) { x= v.x; y= v.y; z= v.z; return *this; }
145  gvec3& operator= ( const ::vec3& v ) { x= v.x; y= v.y; z= v.z; return *this; }
146  gvec3& operator= ( const Point& v ) { x= v.x; y= v.y; z= v.z; return *this; }
147  gvec3& operator= ( const Vector& v ) { x= v.x; y= v.y; z= v.z; return *this; }
148  operator ::vec3 ( ) { return ::vec3(float(x), float(y), float(y)); }
149  };
150 
151  typedef gvec3<float> vec3;
152  typedef gvec3<int> ivec3;
153  typedef gvec3<unsigned int> uvec3;
154  typedef gvec3<int> bvec3;
155 
156  template < typename T >
157  struct alignas(16) gvec4
158  {
159  alignas(4) T x, y, z, w;
160 
161  gvec4( ) {}
162  gvec4( const gvec4<T>& v ) : x(v.x), y(v.y), z(v.z), w(v.w) {}
163  gvec4( const ::vec4& v ) : x(v.x), y(v.y), z(v.z), w(v.w) {}
164  gvec4& operator= ( const gvec4<T>& v ) { x(v.x), y(v.y), z(v.z), w(v.w) ; return *this; }
165  gvec4& operator= ( const ::vec4& v ) { x(v.x), y(v.y), z(v.z), w(v.w) ; return *this; }
166  gvec4& operator= ( const Color& c ) { x= c.r; y= c.g; z= c.b; w= c.a; return *this; }
167  operator ::vec4 ( ) { return ::vec4(float(x), float(y), float(y), float(w)); }
168  };
169 
170  typedef gvec4<float> vec4;
171  typedef gvec4<int> ivec4;
172  typedef gvec4<unsigned int> uvec4;
173  typedef gvec4<int> bvec4;
174  }
175 }
176 
177 
178 
179 // utilitaire : renvoie la chaine de caracteres pour un type glsl.
180 const char *glsl_string( const GLenum type )
181 {
182  switch(type)
183  {
184  case GL_BOOL:
185  return "bool";
186  case GL_UNSIGNED_INT:
187  return "uint";
188  case GL_INT:
189  return "int";
190  case GL_FLOAT:
191  return "float";
192  case GL_FLOAT_VEC2:
193  return "vec2";
194  case GL_FLOAT_VEC3:
195  return "vec3";
196  case GL_FLOAT_VEC4:
197  return "vec4";
198  case GL_FLOAT_MAT3:
199  return "mat3";
200  case GL_FLOAT_MAT4:
201  return "mat4";
202 
203  default:
204  return "";
205  }
206 }
207 
208 int print_uniform( const GLuint program )
209 {
210  if(program == 0)
211  {
212  printf("[error] program 0, no buffers...\n");
213  return -1;
214  }
215 
216  // recupere le nombre d'uniform buffers
217  GLint buffer_count= 0;
218  glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &buffer_count);
219 
220  for(int i= 0; i < buffer_count; i++)
221  {
222  // recupere le nom du block et son indice
223  char bname[1024]= { 0 };
224  glGetActiveUniformBlockName(program, i, sizeof(bname), nullptr, bname);
225 
226  GLint binding= 0;
227  glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_BINDING, &binding);
228 
229  printf(" uniform '%s' binding %d\n", bname, binding);
230 
231  GLint variable_count= 0;
232  glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &variable_count);
233 
234  std::vector<GLint> variables(variable_count);
235  glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, variables.data());
236  for(int k= 0; k < variable_count; k++)
237  {
238  // recupere chaque info... une variable a la fois,
239  GLint glsl_type= 0;
240  glGetActiveUniformsiv(program, 1, (GLuint *) &variables[k], GL_UNIFORM_TYPE, &glsl_type);
241  GLint offset= 0;
242  glGetActiveUniformsiv(program, 1, (GLuint *) &variables[k], GL_UNIFORM_OFFSET, &offset);
243 
244  GLint array_size= 0;
245  glGetActiveUniformsiv(program, 1, (GLuint *) &variables[k], GL_UNIFORM_SIZE, &array_size);
246  GLint array_stride= 0;
247  glGetActiveUniformsiv(program, 1, (GLuint *) &variables[k], GL_UNIFORM_ARRAY_STRIDE, &array_stride);
248 
249  GLint matrix_stride= 0;
250  glGetActiveUniformsiv(program, 1, (GLuint *) &variables[k], GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
251  GLint matrix_row_major= 0;
252  glGetActiveUniformsiv(program, 1, (GLuint *) &variables[k], GL_UNIFORM_IS_ROW_MAJOR, &matrix_row_major);
253 
254  // nom de la variable
255  char vname[1024]= { 0 };
256  glGetActiveUniformName(program, variables[k], sizeof(vname), nullptr, vname);
257 
258  printf(" '%s %s': offset %d", glsl_string(glsl_type), vname, offset);
259  if(array_size > 1)
260  printf(", array size %d, stride %d", array_size, array_stride);
261 
262  // organisation des matrices
263  if(glsl_type == GL_FLOAT_MAT4 || glsl_type == GL_FLOAT_MAT3)
264  printf(", %s, matrix stride %d", matrix_row_major ? "row major" : "column major", matrix_stride);
265 
266  printf("\n");
267  }
268 
269  GLint buffer_size= 0;
270  glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_DATA_SIZE, &buffer_size);
271  printf(" buffer size %d\n\n", buffer_size);
272  }
273 
274  return 0;
275 }
276 
277 // application
278 GLuint program;
279 
280 int init( )
281 {
282  // compile le shader program, le program est selectionne
283  program= read_program("tutos/uniform.glsl");
284  program_print_errors(program);
285 
286  // affiche l'organisation memoire des uniforms
287  print_uniform(program);
288 
289  struct buffer
290  {
291  glsl::vec2 a;
292  glsl::vec3 b;
293  glsl::vec4 c;
294  glsl::array::vec2 d[3];
295 
296  //~ vec2 a; // align 4
297  //~ float pad0;
298  //~ float pad1;
299  //~ vec3 b; // align 16
300  //~ float pad2;
301  //~ vec4 c; // align 16
302  //~ struct { vec2 v; float pad0; float pad1; } d[3]; // d[i].v align 16
303 
304  //~ vec2 a;
305  //~ vec3 b;
306  //~ vec4 c;
307  //~ vec2 d[3];
308  };
309 
310  printf("a %ld\n", offsetof(buffer, a));
311  printf("a.x %ld\n", offsetof(buffer, a.x));
312  printf("a.y %ld\n", offsetof(buffer, a.y));
313 
314  printf("b %ld\n", offsetof(buffer, b));
315  printf("b.x %ld\n", offsetof(buffer, b.x));
316  printf("b.y %ld\n", offsetof(buffer, b.y));
317  printf("b.z %ld\n", offsetof(buffer, b.z));
318 
319  printf("c %ld\n", offsetof(buffer, c));
320  printf("c.x %ld\n", offsetof(buffer, c.x));
321  printf("c.y %ld\n", offsetof(buffer, c.y));
322  printf("c.z %ld\n", offsetof(buffer, c.z));
323  printf("c.w %ld\n", offsetof(buffer, c.w));
324 
325  printf("d %ld\n", offsetof(buffer, d));
326  printf("d[0] %ld\n", offsetof(buffer, d[0]));
327  printf("d[1] %ld\n", offsetof(buffer, d[1]));
328  printf("d[2] %ld\n", offsetof(buffer, d[2]));
329 
330  buffer B;
331  B.a= vec2(1, 2);
332  B.d[0]= vec2(3, 4);
333  B.d[1]= B.d[0];
334 
335  //~ vec2 d0= B.d[0];
336  vec2 d0= B.d[1];
337  printf("%f %f\n", d0.x, d0.y);
338  return 0;
339 }
340 
341 int quit( )
342 {
343  release_program(program);
344  return 0;
345 }
346 
347 
348 int main( int argc, char **argv )
349 {
350  // etape 1 : creer la fenetre
351  Window window= create_window(1024, 640);
352  if(window == nullptr)
353  return 1;
354 
355  // etape 2 : creer un contexte opengl pour pouvoir dessiner
356  Context context= create_context(window);
357  if(context == nullptr)
358  return 1;
359 
360  // etape 3 : creation des objets
361  if(init() < 0)
362  {
363  printf("[error] init failed.\n");
364  return 1;
365  }
366 
367  // etape 5 : nettoyage
368  quit();
369  release_context(context);
370  release_window(window);
371  return 0;
372 }
373 
Context create_context(Window window)
cree et configure un contexte opengl
Definition: window.cpp:356
void release_window(Window window)
destruction de la fenetre.
Definition: window.cpp:325
void printf(Text &text, const int px, const int py, const char *format,...)
affiche un texte a la position x, y. meme utilisation que printf().
Definition: text.cpp:140
Window create_window(const int w, const int h, const int major, const int minor, const int samples)
creation d'une fenetre pour l'application.
Definition: window.cpp:259
void release_context(Context context)
detruit le contexte openGL.
Definition: window.cpp:422
GLuint read_program(const char *filename, const char *definitions)
Definition: program.cpp:204
int program_print_errors(const GLuint program)
affiche les erreurs de compilation.
Definition: program.cpp:432
int release_program(const GLuint program)
detruit les shaders et le program.
Definition: program.cpp:211
int init(std::vector< const char * > &options)
Definition: shader_kit.cpp:96
representation d'une couleur (rgba) transparente ou opaque.
Definition: color.h:14
representation d'un point 3d.
Definition: vec.h:21
representation d'un vecteur 3d.
Definition: vec.h:59
vecteur generique, utilitaire.
Definition: vec.h:131
vecteur generique, utilitaire.
Definition: vec.h:146
vecteur generique 4d, ou 3d homogene, utilitaire.
Definition: vec.h:168