File: stb_glprog.h

package info (click to toggle)
libstb 0.0~git20180212.15.e6afb9c-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 5,440 kB
  • sloc: ansic: 65,656; cpp: 1,020; makefile: 54
file content (504 lines) | stat: -rw-r--r-- 20,283 bytes parent folder | download | duplicates (5)
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
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
// stb_glprog v0.02 public domain         functions to reduce GLSL boilerplate
// http://nothings.org/stb/stb_glprog.h   especially with GL1 + ARB extensions
//
// Following defines *before* including have following effects:
//
//     STB_GLPROG_IMPLEMENTATION
//           creates the implementation
//
//     STB_GLPROG_STATIC
//           forces the implementation to be static (private to file that creates it)
//
//     STB_GLPROG_ARB
//           uses ARB extension names for GLSL functions and enumerants instead of core names
//
//     STB_GLPROG_ARB_DEFINE_EXTENSIONS
//           instantiates function pointers needed, static to implementing file
//           to avoid collisions (but will collide if implementing file also
//           defines any; best to isolate this to its own file in this case).
//           This will try to automatically #include glext.h, but if it's not
//           in the default include directories you'll need to include it
//           yourself and define the next macro.
//
//     STB_GLPROG_SUPPRESS_GLEXT_INCLUDE
//           disables the automatic #include of glext.h which is normally
//           forced by STB_GLPROG_ARB_DEFINE_EXTENSIONS
//
// So, e.g., sample usage on an old Windows compiler:
//
//     #define STB_GLPROG_IMPLEMENTATION
//     #define STB_GLPROG_ARB_DEFINE_EXTENSIONS
//     #include <windows.h>
//     #include "gl/gl.h"
//     #include "stb_glprog.h"
//
// Note though that the header-file version of this (when you don't define
// STB_GLPROG_IMPLEMENTATION) still uses GLint and such, so you basically
// can only include it in places where you're already including GL, especially
// on Windows where including "gl.h" requires (some of) "windows.h".
//
// See following comment blocks for function documentation.
//
// Version history:
//    2013-12-08   v0.02   slightly simplified API and reduced GL resource usage (@rygorous)
//    2013-12-08   v0.01   initial release


// header file section starts here
#if !defined(INCLUDE_STB_GLPROG_H)
#define INCLUDE_STB_GLPROG_H

#ifndef STB_GLPROG_STATIC
#ifdef __cplusplus
extern "C" {
#endif

//////////////////////////////////////////////////////////////////////////////

/////////////    SHADER CREATION


/// EASY API

extern GLuint stbgl_create_program(char const **vertex_source, char const **frag_source, char const **binds, char *error, int error_buflen);
// This function returns a compiled program or 0 if there's an error.
// To free the created program, call stbgl_delete_program.
//
//     stbgl_create_program(
//             char **vertex_source,   // NULL or one or more strings with the vertex shader source, with a final NULL
//             char **frag_source,     // NULL or one or more strings with the fragment shader source, with a final NULL
//             char **binds,           // NULL or zero or more strings with attribute bind names, with a final NULL
//             char *error,            // output location where compile error message is placed
//             int error_buflen)       // length of error output buffer
//
// Returns a GLuint with the GL program object handle.
//
// If an individual bind string is "", no name is bound to that slot (this
// allows you to create binds that aren't continuous integers starting at 0).
//
// If the vertex shader is NULL, then fixed-function vertex pipeline
// is used, if that's legal in your version of GL.
//
// If the fragment shader is NULL, then fixed-function fragment pipeline
// is used, if that's legal in your version of GL.

extern void stgbl_delete_program(GLuint program);
// deletes a program created by stbgl_create_program or stbgl_link_program


/// FLEXIBLE API

extern GLuint stbgl_compile_shader(GLenum type, char const **sources, int num_sources, char *error, int error_buflen);
// compiles a shader. returns the shader on success or 0 on failure.
//
//    type          either:  GL_VERTEX_SHADER or GL_FRAGMENT_SHADER
//                     or    GL_VERTEX_SHADER_ARB or GL_FRAGMENT_SHADER_ARB
//                     or    STBGL_VERTEX_SHADER or STBGL_FRAGMENT_SHADER
//    sources       array of strings containing the shader source
//    num_sources   number of string in sources, or -1 meaning sources is NULL-terminated
//    error         string to output compiler error to
//    error_buflen  length of error buffer in chars

extern GLuint stbgl_link_program(GLuint vertex_shader, GLuint fragment_shader, char const **binds, int num_binds, char *error, int error_buflen);
// links a shader. returns the linked program on success or 0 on failure.
//
//    vertex_shader    a compiled vertex shader from stbgl_compile_shader, or 0 for fixed-function (if legal)
//    fragment_shader  a compiled fragment shader from stbgl_compile_shader, or 0 for fixed-function (if legal)
//

extern void stbgl_delete_shader(GLuint shader);
// deletes a shader created by stbgl_compile_shader


/////////////    RENDERING WITH SHADERS

extern GLint stbgl_find_uniform(GLuint prog, char *uniform);

extern void stbgl_find_uniforms(GLuint prog, GLint *locations, char const **uniforms, int num_uniforms);
// Given the locations array that is num_uniforms long, fills out
// the locations of each of those uniforms for the specified program.
// If num_uniforms is -1, then uniforms[] must be NULL-terminated

// the following functions just wrap the difference in naming between GL2+ and ARB,
// so you don't need them unless you're using both ARB and GL2+ in the same codebase,
// or you're relying on this lib to provide the extensions
extern void stbglUseProgram(GLuint program);
extern void stbglVertexAttribPointer(GLuint index,  GLint size,  GLenum type,  GLboolean normalized,  GLsizei stride,  const GLvoid * pointer);
extern void stbglEnableVertexAttribArray(GLuint index);
extern void stbglDisableVertexAttribArray(GLuint index);
extern void stbglUniform1fv(GLint loc, GLsizei count, const GLfloat *v);
extern void stbglUniform2fv(GLint loc, GLsizei count, const GLfloat *v);
extern void stbglUniform3fv(GLint loc, GLsizei count, const GLfloat *v);
extern void stbglUniform4fv(GLint loc, GLsizei count, const GLfloat *v);
extern void stbglUniform1iv(GLint loc, GLsizei count, const GLint *v);
extern void stbglUniform2iv(GLint loc, GLsizei count, const GLint *v);
extern void stbglUniform3iv(GLint loc, GLsizei count, const GLint *v);
extern void stbglUniform4iv(GLint loc, GLsizei count, const GLint *v);
extern void stbglUniform1f(GLint loc, float v0);
extern void stbglUniform2f(GLint loc, float v0, float v1);
extern void stbglUniform3f(GLint loc, float v0, float v1, float v2);
extern void stbglUniform4f(GLint loc, float v0, float v1, float v2, float v3);
extern void stbglUniform1i(GLint loc, GLint v0);
extern void stbglUniform2i(GLint loc, GLint v0, GLint v1);
extern void stbglUniform3i(GLint loc, GLint v0, GLint v1, GLint v2);
extern void stbglUniform4i(GLint loc, GLint v0, GLint v1, GLint v2, GLint v3);


//////////////     END OF FUNCTIONS

//////////////////////////////////////////////////////////////////////////////

#ifdef __cplusplus
}
#endif
#endif // STB_GLPROG_STATIC

#ifdef STB_GLPROG_ARB
#define STBGL_VERTEX_SHADER    GL_VERTEX_SHADER_ARB
#define STBGL_FRAGMENT_SHADER  GL_FRAGMENT_SHADER_ARB
#else
#define STBGL_VERTEX_SHADER    GL_VERTEX_SHADER
#define STBGL_FRAGMENT_SHADER  GL_FRAGMENT_SHADER
#endif

#endif // INCLUDE_STB_GLPROG_H


/////////    header file section ends here


#ifdef STB_GLPROG_IMPLEMENTATION
#include <string.h> // strncpy

#ifdef STB_GLPROG_STATIC
#define STB_GLPROG_DECLARE static
#else
#define STB_GLPROG_DECLARE extern
#endif

// check if user wants this file to define the GL extensions itself
#ifdef STB_GLPROG_ARB_DEFINE_EXTENSIONS
#define STB_GLPROG_ARB  // make sure later code uses the extensions

#ifndef STB_GLPROG_SUPPRESS_GLEXT_INCLUDE
#include "glext.h"
#endif

#define STB_GLPROG_EXTENSIONS                                 \
   STB_GLPROG_FUNC(ATTACHOBJECT        , AttachObject        ) \
   STB_GLPROG_FUNC(BINDATTRIBLOCATION  , BindAttribLocation  ) \
   STB_GLPROG_FUNC(COMPILESHADER       , CompileShader       ) \
   STB_GLPROG_FUNC(CREATEPROGRAMOBJECT , CreateProgramObject ) \
   STB_GLPROG_FUNC(CREATESHADEROBJECT  , CreateShaderObject  ) \
   STB_GLPROG_FUNC(DELETEOBJECT        , DeleteObject        ) \
   STB_GLPROG_FUNC(DETACHOBJECT        , DetachObject        ) \
   STB_GLPROG_FUNC(DISABLEVERTEXATTRIBARRAY, DisableVertexAttribArray) \
   STB_GLPROG_FUNC(ENABLEVERTEXATTRIBARRAY,  EnableVertexAttribArray ) \
   STB_GLPROG_FUNC(GETATTACHEDOBJECTS  , GetAttachedObjects  ) \
   STB_GLPROG_FUNC(GETOBJECTPARAMETERIV, GetObjectParameteriv) \
   STB_GLPROG_FUNC(GETINFOLOG          , GetInfoLog          ) \
   STB_GLPROG_FUNC(GETUNIFORMLOCATION  , GetUniformLocation  ) \
   STB_GLPROG_FUNC(LINKPROGRAM         , LinkProgram         ) \
   STB_GLPROG_FUNC(SHADERSOURCE        , ShaderSource        ) \
   STB_GLPROG_FUNC(UNIFORM1F           , Uniform1f           ) \
   STB_GLPROG_FUNC(UNIFORM2F           , Uniform2f           ) \
   STB_GLPROG_FUNC(UNIFORM3F           , Uniform3f           ) \
   STB_GLPROG_FUNC(UNIFORM4F           , Uniform4f           ) \
   STB_GLPROG_FUNC(UNIFORM1I           , Uniform1i           ) \
   STB_GLPROG_FUNC(UNIFORM2I           , Uniform2i           ) \
   STB_GLPROG_FUNC(UNIFORM3I           , Uniform3i           ) \
   STB_GLPROG_FUNC(UNIFORM4I           , Uniform4i           ) \
   STB_GLPROG_FUNC(UNIFORM1FV          , Uniform1fv          ) \
   STB_GLPROG_FUNC(UNIFORM2FV          , Uniform2fv          ) \
   STB_GLPROG_FUNC(UNIFORM3FV          , Uniform3fv          ) \
   STB_GLPROG_FUNC(UNIFORM4FV          , Uniform4fv          ) \
   STB_GLPROG_FUNC(UNIFORM1IV          , Uniform1iv          ) \
   STB_GLPROG_FUNC(UNIFORM2IV          , Uniform2iv          ) \
   STB_GLPROG_FUNC(UNIFORM3IV          , Uniform3iv          ) \
   STB_GLPROG_FUNC(UNIFORM4IV          , Uniform4iv          ) \
   STB_GLPROG_FUNC(USEPROGRAMOBJECT    , UseProgramObject    ) \
   STB_GLPROG_FUNC(VERTEXATTRIBPOINTER , VertexAttribPointer )

// define the static function pointers

#define STB_GLPROG_FUNC(x,y)  static PFNGL##x##ARBPROC gl##y##ARB;
STB_GLPROG_EXTENSIONS
#undef STB_GLPROG_FUNC

// define the GetProcAddress

#ifdef _WIN32
#ifndef WINGDIAPI
#ifndef STB__HAS_WGLPROC
typedef int (__stdcall *stbgl__voidfunc)(void);
static __declspec(dllimport) stbgl__voidfunc wglGetProcAddress(char *);
#endif
#endif
#define STBGL__GET_FUNC(x)   wglGetProcAddress(x)
#else
#error "need to define how this platform gets extensions"
#endif

// create a function that fills out the function pointers

static void stb_glprog_init(void)
{
   static int initialized = 0; // not thread safe!
   if (initialized) return;
   #define STB_GLPROG_FUNC(x,y) gl##y##ARB = (PFNGL##x##ARBPROC) STBGL__GET_FUNC("gl" #y "ARB");
   STB_GLPROG_EXTENSIONS
   #undef STB_GLPROG_FUNC
}
#undef STB_GLPROG_EXTENSIONS

#else
static void stb_glprog_init(void)
{
}
#endif


// define generic names for many of the gl functions or extensions for later use;
// note that in some cases there are two functions in core and one function in ARB
#ifdef STB_GLPROG_ARB
#define stbglCreateShader          glCreateShaderObjectARB
#define stbglDeleteShader          glDeleteObjectARB
#define stbglAttachShader          glAttachObjectARB
#define stbglDetachShader          glDetachObjectARB
#define stbglShaderSource          glShaderSourceARB
#define stbglCompileShader         glCompileShaderARB
#define stbglGetShaderStatus(a,b)  glGetObjectParameterivARB(a, GL_OBJECT_COMPILE_STATUS_ARB, b)
#define stbglGetShaderInfoLog      glGetInfoLogARB
#define stbglCreateProgram         glCreateProgramObjectARB
#define stbglDeleteProgram         glDeleteObjectARB
#define stbglLinkProgram           glLinkProgramARB
#define stbglGetProgramStatus(a,b) glGetObjectParameterivARB(a, GL_OBJECT_LINK_STATUS_ARB, b)
#define stbglGetProgramInfoLog     glGetInfoLogARB
#define stbglGetAttachedShaders    glGetAttachedObjectsARB
#define stbglBindAttribLocation    glBindAttribLocationARB
#define stbglGetUniformLocation    glGetUniformLocationARB
#define stbgl_UseProgram           glUseProgramObjectARB
#else
#define stbglCreateShader          glCreateShader
#define stbglDeleteShader          glDeleteShader
#define stbglAttachShader          glAttachShader
#define stbglDetachShader          glDetachShader
#define stbglShaderSource          glShaderSource
#define stbglCompileShader         glCompileShader
#define stbglGetShaderStatus(a,b)  glGetShaderiv(a, GL_COMPILE_STATUS, b)
#define stbglGetShaderInfoLog      glGetShaderInfoLog
#define stbglCreateProgram         glCreateProgram
#define stbglDeleteProgram         glDeleteProgram
#define stbglLinkProgram           glLinkProgram
#define stbglGetProgramStatus(a,b) glGetProgramiv(a, GL_LINK_STATUS, b)
#define stbglGetProgramInfoLog     glGetProgramInfoLog
#define stbglGetAttachedShaders    glGetAttachedShaders
#define stbglBindAttribLocation    glBindAttribLocation
#define stbglGetUniformLocation    glGetUniformLocation
#define stbgl_UseProgram           glUseProgram
#endif


// perform a safe strcat of 3 strings, given that we can't rely on portable snprintf
// if you need to break on error, this is the best place to place a breakpoint
static void stb_glprog_error(char *error, int error_buflen, char *str1, char *str2, char *str3)
{
   int n = strlen(str1);
   strncpy(error, str1, error_buflen);
   if (n < error_buflen && str2) {
      strncpy(error+n, str2, error_buflen - n);
      n += strlen(str2);
      if (n < error_buflen && str3) {
         strncpy(error+n, str3, error_buflen - n);
      }
   }
   error[error_buflen-1] = 0;
}

STB_GLPROG_DECLARE GLuint stbgl_compile_shader(GLenum type, char const **sources, int num_sources, char *error, int error_buflen)
{
   char *typename = (type == STBGL_VERTEX_SHADER ? "vertex" : "fragment");
   int len;
   GLint result;
   GLuint shader;

   // initialize the extensions if we haven't already
   stb_glprog_init();

   // allocate

   shader = stbglCreateShader(type);
   if (!shader) {
      stb_glprog_error(error, error_buflen, "Couldn't allocate shader object in stbgl_compile_shader for ", typename, NULL);
      return 0;
   }

   // compile

   // if num_sources is negative, assume source is NULL-terminated and count the non-NULL ones
   if (num_sources < 0)
      for (num_sources = 0; sources[num_sources] != NULL; ++num_sources)
         ;
   stbglShaderSource(shader, num_sources, sources, NULL);
   stbglCompileShader(shader);
   stbglGetShaderStatus(shader, &result);
   if (result)
      return shader;

   // errors

   stb_glprog_error(error, error_buflen, "Compile error for ", typename, " shader: ");
   len = strlen(error);
   if (len < error_buflen)
      stbglGetShaderInfoLog(shader, error_buflen-len, NULL, error+len);

   stbglDeleteShader(shader);
   return 0;
}

STB_GLPROG_DECLARE GLuint stbgl_link_program(GLuint vertex_shader, GLuint fragment_shader, char const **binds, int num_binds, char *error, int error_buflen)
{
   int len;
   GLint result;

   // allocate

   GLuint prog = stbglCreateProgram();
   if (!prog) {
      stb_glprog_error(error, error_buflen, "Couldn't allocate program object in stbgl_link_program", NULL, NULL);
      return 0;
   }

   // attach

   if (vertex_shader)
      stbglAttachShader(prog, vertex_shader);
   if (fragment_shader)
      stbglAttachShader(prog, fragment_shader);

   // attribute binds

   if (binds) {
      int i;
      // if num_binds is negative, then it is NULL terminated
      if (num_binds < 0)
         for (num_binds=0; binds[num_binds]; ++num_binds)
            ;
      for (i=0; i < num_binds; ++i)
         if (binds[i] && binds[i][0]) // empty binds can be NULL or ""
            stbglBindAttribLocation(prog, i, binds[i]);
   }

   // link

   stbglLinkProgram(prog);

   // detach

   if (vertex_shader)
      stbglDetachShader(prog, vertex_shader);
   if (fragment_shader)
      stbglDetachShader(prog, fragment_shader);

   // errors

   stbglGetProgramStatus(prog, &result);
   if (result)
      return prog;

   stb_glprog_error(error, error_buflen, "Link error: ", NULL, NULL);
   len = strlen(error);
   if (len < error_buflen)
      stbglGetProgramInfoLog(prog, error_buflen-len, NULL, error+len);

   stbglDeleteProgram(prog);
   return 0;   
}

STB_GLPROG_DECLARE GLuint stbgl_create_program(char const **vertex_source, char const **frag_source, char const **binds, char *error, int error_buflen)
{
   GLuint vertex, fragment, prog=0;
   vertex = stbgl_compile_shader(STBGL_VERTEX_SHADER, vertex_source, -1, error, error_buflen);
   if (vertex) {
      fragment = stbgl_compile_shader(STBGL_FRAGMENT_SHADER, frag_source, -1, error, error_buflen);
      if (fragment)
         prog = stbgl_link_program(vertex, fragment, binds, -1, error, error_buflen);
      if (fragment)
         stbglDeleteShader(fragment);
      stbglDeleteShader(vertex);
   }
   return prog;
}

STB_GLPROG_DECLARE void stbgl_delete_shader(GLuint shader)
{
   stbglDeleteShader(shader);
}

STB_GLPROG_DECLARE void stgbl_delete_program(GLuint program)
{
   stbglDeleteProgram(program);
}

GLint stbgl_find_uniform(GLuint prog, char *uniform)
{
   return stbglGetUniformLocation(prog, uniform);
}

STB_GLPROG_DECLARE void stbgl_find_uniforms(GLuint prog, GLint *locations, char const **uniforms, int num_uniforms)
{
   int i;
   if (num_uniforms < 0)
      num_uniforms = 999999;
   for (i=0; i < num_uniforms && uniforms[i]; ++i)
      locations[i] = stbglGetUniformLocation(prog, uniforms[i]);
}

STB_GLPROG_DECLARE void stbglUseProgram(GLuint program)
{
   stbgl_UseProgram(program);
}

#ifdef STB_GLPROG_ARB
#define STBGL_ARBIFY(name)   name##ARB
#else
#define STBGL_ARBIFY(name)   name
#endif

STB_GLPROG_DECLARE void stbglVertexAttribPointer(GLuint index,  GLint size,  GLenum type,  GLboolean normalized,  GLsizei stride,  const GLvoid * pointer)
{
   STBGL_ARBIFY(glVertexAttribPointer)(index, size, type, normalized, stride, pointer);
}

STB_GLPROG_DECLARE void stbglEnableVertexAttribArray (GLuint index) { STBGL_ARBIFY(glEnableVertexAttribArray )(index); }
STB_GLPROG_DECLARE void stbglDisableVertexAttribArray(GLuint index) { STBGL_ARBIFY(glDisableVertexAttribArray)(index); }

STB_GLPROG_DECLARE void stbglUniform1fv(GLint loc, GLsizei count, const GLfloat *v) { STBGL_ARBIFY(glUniform1fv)(loc,count,v); }
STB_GLPROG_DECLARE void stbglUniform2fv(GLint loc, GLsizei count, const GLfloat *v) { STBGL_ARBIFY(glUniform2fv)(loc,count,v); }
STB_GLPROG_DECLARE void stbglUniform3fv(GLint loc, GLsizei count, const GLfloat *v) { STBGL_ARBIFY(glUniform3fv)(loc,count,v); }
STB_GLPROG_DECLARE void stbglUniform4fv(GLint loc, GLsizei count, const GLfloat *v) { STBGL_ARBIFY(glUniform4fv)(loc,count,v); }

STB_GLPROG_DECLARE void stbglUniform1iv(GLint loc, GLsizei count, const GLint   *v) { STBGL_ARBIFY(glUniform1iv)(loc,count,v); }
STB_GLPROG_DECLARE void stbglUniform2iv(GLint loc, GLsizei count, const GLint   *v) { STBGL_ARBIFY(glUniform2iv)(loc,count,v); }
STB_GLPROG_DECLARE void stbglUniform3iv(GLint loc, GLsizei count, const GLint   *v) { STBGL_ARBIFY(glUniform3iv)(loc,count,v); }
STB_GLPROG_DECLARE void stbglUniform4iv(GLint loc, GLsizei count, const GLint   *v) { STBGL_ARBIFY(glUniform4iv)(loc,count,v); }

STB_GLPROG_DECLARE void stbglUniform1f(GLint loc, float v0)
    { STBGL_ARBIFY(glUniform1f)(loc,v0); }
STB_GLPROG_DECLARE void stbglUniform2f(GLint loc, float v0, float v1)
    { STBGL_ARBIFY(glUniform2f)(loc,v0,v1); }
STB_GLPROG_DECLARE void stbglUniform3f(GLint loc, float v0, float v1, float v2)
    { STBGL_ARBIFY(glUniform3f)(loc,v0,v1,v2); }
STB_GLPROG_DECLARE void stbglUniform4f(GLint loc, float v0, float v1, float v2, float v3)
    { STBGL_ARBIFY(glUniform4f)(loc,v0,v1,v2,v3); }

STB_GLPROG_DECLARE void stbglUniform1i(GLint loc, GLint v0)
    { STBGL_ARBIFY(glUniform1i)(loc,v0); }
STB_GLPROG_DECLARE void stbglUniform2i(GLint loc, GLint v0, GLint v1)
    { STBGL_ARBIFY(glUniform2i)(loc,v0,v1); }
STB_GLPROG_DECLARE void stbglUniform3i(GLint loc, GLint v0, GLint v1, GLint v2)
    { STBGL_ARBIFY(glUniform3i)(loc,v0,v1,v2); }
STB_GLPROG_DECLARE void stbglUniform4i(GLint loc, GLint v0, GLint v1, GLint v2, GLint v3)
    { STBGL_ARBIFY(glUniform4i)(loc,v0,v1,v2,v3); }

#endif