| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- // 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
|