1 // stb_glprog v0.02 public domain functions to reduce GLSL boilerplate
2 // http://nothings.org/stb/stb_glprog.h especially with GL1 + ARB extensions
4 // Following defines *before* including have following effects:
6 // STB_GLPROG_IMPLEMENTATION
7 // creates the implementation
10 // forces the implementation to be static (private to file that creates it)
13 // uses ARB extension names for GLSL functions and enumerants instead of core names
15 // STB_GLPROG_ARB_DEFINE_EXTENSIONS
16 // instantiates function pointers needed, static to implementing file
17 // to avoid collisions (but will collide if implementing file also
18 // defines any; best to isolate this to its own file in this case).
19 // This will try to automatically #include glext.h, but if it's not
20 // in the default include directories you'll need to include it
21 // yourself and define the next macro.
23 // STB_GLPROG_SUPPRESS_GLEXT_INCLUDE
24 // disables the automatic #include of glext.h which is normally
25 // forced by STB_GLPROG_ARB_DEFINE_EXTENSIONS
27 // So, e.g., sample usage on an old Windows compiler:
29 // #define STB_GLPROG_IMPLEMENTATION
30 // #define STB_GLPROG_ARB_DEFINE_EXTENSIONS
31 // #include <windows.h>
33 // #include "stb_glprog.h"
35 // Note though that the header-file version of this (when you don't define
36 // STB_GLPROG_IMPLEMENTATION) still uses GLint and such, so you basically
37 // can only include it in places where you're already including GL, especially
38 // on Windows where including "gl.h" requires (some of) "windows.h".
40 // See following comment blocks for function documentation.
43 // 2013-12-08 v0.02 slightly simplified API and reduced GL resource usage (@rygorous)
44 // 2013-12-08 v0.01 initial release
47 // header file section starts here
48 #if !defined(INCLUDE_STB_GLPROG_H)
49 #define INCLUDE_STB_GLPROG_H
51 #ifndef STB_GLPROG_STATIC
56 //////////////////////////////////////////////////////////////////////////////
58 ///////////// SHADER CREATION
63 extern GLuint
stbgl_create_program(char const **vertex_source
, char const **frag_source
, char const **binds
, char *error
, int error_buflen
);
64 // This function returns a compiled program or 0 if there's an error.
65 // To free the created program, call stbgl_delete_program.
67 // stbgl_create_program(
68 // char **vertex_source, // NULL or one or more strings with the vertex shader source, with a final NULL
69 // char **frag_source, // NULL or one or more strings with the fragment shader source, with a final NULL
70 // char **binds, // NULL or zero or more strings with attribute bind names, with a final NULL
71 // char *error, // output location where compile error message is placed
72 // int error_buflen) // length of error output buffer
74 // Returns a GLuint with the GL program object handle.
76 // If an individual bind string is "", no name is bound to that slot (this
77 // allows you to create binds that aren't continuous integers starting at 0).
79 // If the vertex shader is NULL, then fixed-function vertex pipeline
80 // is used, if that's legal in your version of GL.
82 // If the fragment shader is NULL, then fixed-function fragment pipeline
83 // is used, if that's legal in your version of GL.
85 extern void stgbl_delete_program(GLuint program
);
86 // deletes a program created by stbgl_create_program or stbgl_link_program
91 extern GLuint
stbgl_compile_shader(GLenum type
, char const **sources
, int num_sources
, char *error
, int error_buflen
);
92 // compiles a shader. returns the shader on success or 0 on failure.
94 // type either: GL_VERTEX_SHADER or GL_FRAGMENT_SHADER
95 // or GL_VERTEX_SHADER_ARB or GL_FRAGMENT_SHADER_ARB
96 // or STBGL_VERTEX_SHADER or STBGL_FRAGMENT_SHADER
97 // sources array of strings containing the shader source
98 // num_sources number of string in sources, or -1 meaning sources is NULL-terminated
99 // error string to output compiler error to
100 // error_buflen length of error buffer in chars
102 extern GLuint
stbgl_link_program(GLuint vertex_shader
, GLuint fragment_shader
, char const **binds
, int num_binds
, char *error
, int error_buflen
);
103 // links a shader. returns the linked program on success or 0 on failure.
105 // vertex_shader a compiled vertex shader from stbgl_compile_shader, or 0 for fixed-function (if legal)
106 // fragment_shader a compiled fragment shader from stbgl_compile_shader, or 0 for fixed-function (if legal)
109 extern void stbgl_delete_shader(GLuint shader
);
110 // deletes a shader created by stbgl_compile_shader
113 ///////////// RENDERING WITH SHADERS
115 extern GLint
stbgl_find_uniform(GLuint prog
, char *uniform
);
117 extern void stbgl_find_uniforms(GLuint prog
, GLint
*locations
, char const **uniforms
, int num_uniforms
);
118 // Given the locations array that is num_uniforms long, fills out
119 // the locations of each of those uniforms for the specified program.
120 // If num_uniforms is -1, then uniforms[] must be NULL-terminated
122 // the following functions just wrap the difference in naming between GL2+ and ARB,
123 // so you don't need them unless you're using both ARB and GL2+ in the same codebase,
124 // or you're relying on this lib to provide the extensions
125 extern void stbglUseProgram(GLuint program
);
126 extern void stbglVertexAttribPointer(GLuint index
, GLint size
, GLenum type
, GLboolean normalized
, GLsizei stride
, const GLvoid
* pointer
);
127 extern void stbglEnableVertexAttribArray(GLuint index
);
128 extern void stbglDisableVertexAttribArray(GLuint index
);
129 extern void stbglUniform1fv(GLint loc
, GLsizei count
, const GLfloat
*v
);
130 extern void stbglUniform2fv(GLint loc
, GLsizei count
, const GLfloat
*v
);
131 extern void stbglUniform3fv(GLint loc
, GLsizei count
, const GLfloat
*v
);
132 extern void stbglUniform4fv(GLint loc
, GLsizei count
, const GLfloat
*v
);
133 extern void stbglUniform1iv(GLint loc
, GLsizei count
, const GLint
*v
);
134 extern void stbglUniform2iv(GLint loc
, GLsizei count
, const GLint
*v
);
135 extern void stbglUniform3iv(GLint loc
, GLsizei count
, const GLint
*v
);
136 extern void stbglUniform4iv(GLint loc
, GLsizei count
, const GLint
*v
);
137 extern void stbglUniform1f(GLint loc
, float v0
);
138 extern void stbglUniform2f(GLint loc
, float v0
, float v1
);
139 extern void stbglUniform3f(GLint loc
, float v0
, float v1
, float v2
);
140 extern void stbglUniform4f(GLint loc
, float v0
, float v1
, float v2
, float v3
);
141 extern void stbglUniform1i(GLint loc
, GLint v0
);
142 extern void stbglUniform2i(GLint loc
, GLint v0
, GLint v1
);
143 extern void stbglUniform3i(GLint loc
, GLint v0
, GLint v1
, GLint v2
);
144 extern void stbglUniform4i(GLint loc
, GLint v0
, GLint v1
, GLint v2
, GLint v3
);
147 ////////////// END OF FUNCTIONS
149 //////////////////////////////////////////////////////////////////////////////
154 #endif // STB_GLPROG_STATIC
156 #ifdef STB_GLPROG_ARB
157 #define STBGL_VERTEX_SHADER GL_VERTEX_SHADER_ARB
158 #define STBGL_FRAGMENT_SHADER GL_FRAGMENT_SHADER_ARB
160 #define STBGL_VERTEX_SHADER GL_VERTEX_SHADER
161 #define STBGL_FRAGMENT_SHADER GL_FRAGMENT_SHADER
164 #endif // INCLUDE_STB_GLPROG_H
167 ///////// header file section ends here
170 #ifdef STB_GLPROG_IMPLEMENTATION
171 #include <string.h> // strncpy
173 #ifdef STB_GLPROG_STATIC
174 #define STB_GLPROG_DECLARE static
176 #define STB_GLPROG_DECLARE extern
179 // check if user wants this file to define the GL extensions itself
180 #ifdef STB_GLPROG_ARB_DEFINE_EXTENSIONS
181 #define STB_GLPROG_ARB // make sure later code uses the extensions
183 #ifndef STB_GLPROG_SUPPRESS_GLEXT_INCLUDE
187 #define STB_GLPROG_EXTENSIONS \
188 STB_GLPROG_FUNC(ATTACHOBJECT , AttachObject ) \
189 STB_GLPROG_FUNC(BINDATTRIBLOCATION , BindAttribLocation ) \
190 STB_GLPROG_FUNC(COMPILESHADER , CompileShader ) \
191 STB_GLPROG_FUNC(CREATEPROGRAMOBJECT , CreateProgramObject ) \
192 STB_GLPROG_FUNC(CREATESHADEROBJECT , CreateShaderObject ) \
193 STB_GLPROG_FUNC(DELETEOBJECT , DeleteObject ) \
194 STB_GLPROG_FUNC(DETACHOBJECT , DetachObject ) \
195 STB_GLPROG_FUNC(DISABLEVERTEXATTRIBARRAY, DisableVertexAttribArray) \
196 STB_GLPROG_FUNC(ENABLEVERTEXATTRIBARRAY, EnableVertexAttribArray ) \
197 STB_GLPROG_FUNC(GETATTACHEDOBJECTS , GetAttachedObjects ) \
198 STB_GLPROG_FUNC(GETOBJECTPARAMETERIV, GetObjectParameteriv) \
199 STB_GLPROG_FUNC(GETINFOLOG , GetInfoLog ) \
200 STB_GLPROG_FUNC(GETUNIFORMLOCATION , GetUniformLocation ) \
201 STB_GLPROG_FUNC(LINKPROGRAM , LinkProgram ) \
202 STB_GLPROG_FUNC(SHADERSOURCE , ShaderSource ) \
203 STB_GLPROG_FUNC(UNIFORM1F , Uniform1f ) \
204 STB_GLPROG_FUNC(UNIFORM2F , Uniform2f ) \
205 STB_GLPROG_FUNC(UNIFORM3F , Uniform3f ) \
206 STB_GLPROG_FUNC(UNIFORM4F , Uniform4f ) \
207 STB_GLPROG_FUNC(UNIFORM1I , Uniform1i ) \
208 STB_GLPROG_FUNC(UNIFORM2I , Uniform2i ) \
209 STB_GLPROG_FUNC(UNIFORM3I , Uniform3i ) \
210 STB_GLPROG_FUNC(UNIFORM4I , Uniform4i ) \
211 STB_GLPROG_FUNC(UNIFORM1FV , Uniform1fv ) \
212 STB_GLPROG_FUNC(UNIFORM2FV , Uniform2fv ) \
213 STB_GLPROG_FUNC(UNIFORM3FV , Uniform3fv ) \
214 STB_GLPROG_FUNC(UNIFORM4FV , Uniform4fv ) \
215 STB_GLPROG_FUNC(UNIFORM1IV , Uniform1iv ) \
216 STB_GLPROG_FUNC(UNIFORM2IV , Uniform2iv ) \
217 STB_GLPROG_FUNC(UNIFORM3IV , Uniform3iv ) \
218 STB_GLPROG_FUNC(UNIFORM4IV , Uniform4iv ) \
219 STB_GLPROG_FUNC(USEPROGRAMOBJECT , UseProgramObject ) \
220 STB_GLPROG_FUNC(VERTEXATTRIBPOINTER , VertexAttribPointer )
222 // define the static function pointers
224 #define STB_GLPROG_FUNC(x,y) static PFNGL##x##ARBPROC gl##y##ARB;
225 STB_GLPROG_EXTENSIONS
226 #undef STB_GLPROG_FUNC
228 // define the GetProcAddress
232 #ifndef STB__HAS_WGLPROC
233 typedef int (__stdcall
*stbgl__voidfunc
)(void);
234 static __declspec(dllimport
) stbgl__voidfunc
wglGetProcAddress(char *);
237 #define STBGL__GET_FUNC(x) wglGetProcAddress(x)
239 #error "need to define how this platform gets extensions"
242 // create a function that fills out the function pointers
244 static void stb_glprog_init(void)
246 static int initialized
= 0; // not thread safe!
247 if (initialized
) return;
248 #define STB_GLPROG_FUNC(x,y) gl##y##ARB = (PFNGL##x##ARBPROC) STBGL__GET_FUNC("gl" #y "ARB");
249 STB_GLPROG_EXTENSIONS
250 #undef STB_GLPROG_FUNC
252 #undef STB_GLPROG_EXTENSIONS
255 static void stb_glprog_init(void)
261 // define generic names for many of the gl functions or extensions for later use;
262 // note that in some cases there are two functions in core and one function in ARB
263 #ifdef STB_GLPROG_ARB
264 #define stbglCreateShader glCreateShaderObjectARB
265 #define stbglDeleteShader glDeleteObjectARB
266 #define stbglAttachShader glAttachObjectARB
267 #define stbglDetachShader glDetachObjectARB
268 #define stbglShaderSource glShaderSourceARB
269 #define stbglCompileShader glCompileShaderARB
270 #define stbglGetShaderStatus(a,b) glGetObjectParameterivARB(a, GL_OBJECT_COMPILE_STATUS_ARB, b)
271 #define stbglGetShaderInfoLog glGetInfoLogARB
272 #define stbglCreateProgram glCreateProgramObjectARB
273 #define stbglDeleteProgram glDeleteObjectARB
274 #define stbglLinkProgram glLinkProgramARB
275 #define stbglGetProgramStatus(a,b) glGetObjectParameterivARB(a, GL_OBJECT_LINK_STATUS_ARB, b)
276 #define stbglGetProgramInfoLog glGetInfoLogARB
277 #define stbglGetAttachedShaders glGetAttachedObjectsARB
278 #define stbglBindAttribLocation glBindAttribLocationARB
279 #define stbglGetUniformLocation glGetUniformLocationARB
280 #define stbgl_UseProgram glUseProgramObjectARB
282 #define stbglCreateShader glCreateShader
283 #define stbglDeleteShader glDeleteShader
284 #define stbglAttachShader glAttachShader
285 #define stbglDetachShader glDetachShader
286 #define stbglShaderSource glShaderSource
287 #define stbglCompileShader glCompileShader
288 #define stbglGetShaderStatus(a,b) glGetShaderiv(a, GL_COMPILE_STATUS, b)
289 #define stbglGetShaderInfoLog glGetShaderInfoLog
290 #define stbglCreateProgram glCreateProgram
291 #define stbglDeleteProgram glDeleteProgram
292 #define stbglLinkProgram glLinkProgram
293 #define stbglGetProgramStatus(a,b) glGetProgramiv(a, GL_LINK_STATUS, b)
294 #define stbglGetProgramInfoLog glGetProgramInfoLog
295 #define stbglGetAttachedShaders glGetAttachedShaders
296 #define stbglBindAttribLocation glBindAttribLocation
297 #define stbglGetUniformLocation glGetUniformLocation
298 #define stbgl_UseProgram glUseProgram
302 // perform a safe strcat of 3 strings, given that we can't rely on portable snprintf
303 // if you need to break on error, this is the best place to place a breakpoint
304 static void stb_glprog_error(char *error
, int error_buflen
, char *str1
, char *str2
, char *str3
)
306 int n
= strlen(str1
);
307 strncpy(error
, str1
, error_buflen
);
308 if (n
< error_buflen
&& str2
) {
309 strncpy(error
+n
, str2
, error_buflen
- n
);
311 if (n
< error_buflen
&& str3
) {
312 strncpy(error
+n
, str3
, error_buflen
- n
);
315 error
[error_buflen
-1] = 0;
318 STB_GLPROG_DECLARE GLuint
stbgl_compile_shader(GLenum type
, char const **sources
, int num_sources
, char *error
, int error_buflen
)
320 char *typename
= (type
== STBGL_VERTEX_SHADER
? "vertex" : "fragment");
325 // initialize the extensions if we haven't already
330 shader
= stbglCreateShader(type
);
332 stb_glprog_error(error
, error_buflen
, "Couldn't allocate shader object in stbgl_compile_shader for ", typename
, NULL
);
338 // if num_sources is negative, assume source is NULL-terminated and count the non-NULL ones
340 for (num_sources
= 0; sources
[num_sources
] != NULL
; ++num_sources
)
342 stbglShaderSource(shader
, num_sources
, sources
, NULL
);
343 stbglCompileShader(shader
);
344 stbglGetShaderStatus(shader
, &result
);
350 stb_glprog_error(error
, error_buflen
, "Compile error for ", typename
, " shader: ");
352 if (len
< error_buflen
)
353 stbglGetShaderInfoLog(shader
, error_buflen
-len
, NULL
, error
+len
);
355 stbglDeleteShader(shader
);
359 STB_GLPROG_DECLARE GLuint
stbgl_link_program(GLuint vertex_shader
, GLuint fragment_shader
, char const **binds
, int num_binds
, char *error
, int error_buflen
)
366 GLuint prog
= stbglCreateProgram();
368 stb_glprog_error(error
, error_buflen
, "Couldn't allocate program object in stbgl_link_program", NULL
, NULL
);
375 stbglAttachShader(prog
, vertex_shader
);
377 stbglAttachShader(prog
, fragment_shader
);
383 // if num_binds is negative, then it is NULL terminated
385 for (num_binds
=0; binds
[num_binds
]; ++num_binds
)
387 for (i
=0; i
< num_binds
; ++i
)
388 if (binds
[i
] && binds
[i
][0]) // empty binds can be NULL or ""
389 stbglBindAttribLocation(prog
, i
, binds
[i
]);
394 stbglLinkProgram(prog
);
399 stbglDetachShader(prog
, vertex_shader
);
401 stbglDetachShader(prog
, fragment_shader
);
405 stbglGetProgramStatus(prog
, &result
);
409 stb_glprog_error(error
, error_buflen
, "Link error: ", NULL
, NULL
);
411 if (len
< error_buflen
)
412 stbglGetProgramInfoLog(prog
, error_buflen
-len
, NULL
, error
+len
);
414 stbglDeleteProgram(prog
);
418 STB_GLPROG_DECLARE GLuint
stbgl_create_program(char const **vertex_source
, char const **frag_source
, char const **binds
, char *error
, int error_buflen
)
420 GLuint vertex
, fragment
, prog
=0;
421 vertex
= stbgl_compile_shader(STBGL_VERTEX_SHADER
, vertex_source
, -1, error
, error_buflen
);
423 fragment
= stbgl_compile_shader(STBGL_FRAGMENT_SHADER
, frag_source
, -1, error
, error_buflen
);
425 prog
= stbgl_link_program(vertex
, fragment
, binds
, -1, error
, error_buflen
);
427 stbglDeleteShader(fragment
);
428 stbglDeleteShader(vertex
);
433 STB_GLPROG_DECLARE
void stbgl_delete_shader(GLuint shader
)
435 stbglDeleteShader(shader
);
438 STB_GLPROG_DECLARE
void stgbl_delete_program(GLuint program
)
440 stbglDeleteProgram(program
);
443 GLint
stbgl_find_uniform(GLuint prog
, char *uniform
)
445 return stbglGetUniformLocation(prog
, uniform
);
448 STB_GLPROG_DECLARE
void stbgl_find_uniforms(GLuint prog
, GLint
*locations
, char const **uniforms
, int num_uniforms
)
451 if (num_uniforms
< 0)
452 num_uniforms
= 999999;
453 for (i
=0; i
< num_uniforms
&& uniforms
[i
]; ++i
)
454 locations
[i
] = stbglGetUniformLocation(prog
, uniforms
[i
]);
457 STB_GLPROG_DECLARE
void stbglUseProgram(GLuint program
)
459 stbgl_UseProgram(program
);
462 #ifdef STB_GLPROG_ARB
463 #define STBGL_ARBIFY(name) name##ARB
465 #define STBGL_ARBIFY(name) name
468 STB_GLPROG_DECLARE
void stbglVertexAttribPointer(GLuint index
, GLint size
, GLenum type
, GLboolean normalized
, GLsizei stride
, const GLvoid
* pointer
)
470 STBGL_ARBIFY(glVertexAttribPointer
)(index
, size
, type
, normalized
, stride
, pointer
);
473 STB_GLPROG_DECLARE
void stbglEnableVertexAttribArray (GLuint index
) { STBGL_ARBIFY(glEnableVertexAttribArray
)(index
); }
474 STB_GLPROG_DECLARE
void stbglDisableVertexAttribArray(GLuint index
) { STBGL_ARBIFY(glDisableVertexAttribArray
)(index
); }
476 STB_GLPROG_DECLARE
void stbglUniform1fv(GLint loc
, GLsizei count
, const GLfloat
*v
) { STBGL_ARBIFY(glUniform1fv
)(loc
,count
,v
); }
477 STB_GLPROG_DECLARE
void stbglUniform2fv(GLint loc
, GLsizei count
, const GLfloat
*v
) { STBGL_ARBIFY(glUniform2fv
)(loc
,count
,v
); }
478 STB_GLPROG_DECLARE
void stbglUniform3fv(GLint loc
, GLsizei count
, const GLfloat
*v
) { STBGL_ARBIFY(glUniform3fv
)(loc
,count
,v
); }
479 STB_GLPROG_DECLARE
void stbglUniform4fv(GLint loc
, GLsizei count
, const GLfloat
*v
) { STBGL_ARBIFY(glUniform4fv
)(loc
,count
,v
); }
481 STB_GLPROG_DECLARE
void stbglUniform1iv(GLint loc
, GLsizei count
, const GLint
*v
) { STBGL_ARBIFY(glUniform1iv
)(loc
,count
,v
); }
482 STB_GLPROG_DECLARE
void stbglUniform2iv(GLint loc
, GLsizei count
, const GLint
*v
) { STBGL_ARBIFY(glUniform2iv
)(loc
,count
,v
); }
483 STB_GLPROG_DECLARE
void stbglUniform3iv(GLint loc
, GLsizei count
, const GLint
*v
) { STBGL_ARBIFY(glUniform3iv
)(loc
,count
,v
); }
484 STB_GLPROG_DECLARE
void stbglUniform4iv(GLint loc
, GLsizei count
, const GLint
*v
) { STBGL_ARBIFY(glUniform4iv
)(loc
,count
,v
); }
486 STB_GLPROG_DECLARE
void stbglUniform1f(GLint loc
, float v0
)
487 { STBGL_ARBIFY(glUniform1f
)(loc
,v0
); }
488 STB_GLPROG_DECLARE
void stbglUniform2f(GLint loc
, float v0
, float v1
)
489 { STBGL_ARBIFY(glUniform2f
)(loc
,v0
,v1
); }
490 STB_GLPROG_DECLARE
void stbglUniform3f(GLint loc
, float v0
, float v1
, float v2
)
491 { STBGL_ARBIFY(glUniform3f
)(loc
,v0
,v1
,v2
); }
492 STB_GLPROG_DECLARE
void stbglUniform4f(GLint loc
, float v0
, float v1
, float v2
, float v3
)
493 { STBGL_ARBIFY(glUniform4f
)(loc
,v0
,v1
,v2
,v3
); }
495 STB_GLPROG_DECLARE
void stbglUniform1i(GLint loc
, GLint v0
)
496 { STBGL_ARBIFY(glUniform1i
)(loc
,v0
); }
497 STB_GLPROG_DECLARE
void stbglUniform2i(GLint loc
, GLint v0
, GLint v1
)
498 { STBGL_ARBIFY(glUniform2i
)(loc
,v0
,v1
); }
499 STB_GLPROG_DECLARE
void stbglUniform3i(GLint loc
, GLint v0
, GLint v1
, GLint v2
)
500 { STBGL_ARBIFY(glUniform3i
)(loc
,v0
,v1
,v2
); }
501 STB_GLPROG_DECLARE
void stbglUniform4i(GLint loc
, GLint v0
, GLint v1
, GLint v2
, GLint v3
)
502 { STBGL_ARBIFY(glUniform4i
)(loc
,v0
,v1
,v2
,v3
); }