Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

504 lines
20 KiB

  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
  3. //
  4. // Following defines *before* including have following effects:
  5. //
  6. // STB_GLPROG_IMPLEMENTATION
  7. // creates the implementation
  8. //
  9. // STB_GLPROG_STATIC
  10. // forces the implementation to be static (private to file that creates it)
  11. //
  12. // STB_GLPROG_ARB
  13. // uses ARB extension names for GLSL functions and enumerants instead of core names
  14. //
  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.
  22. //
  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
  26. //
  27. // So, e.g., sample usage on an old Windows compiler:
  28. //
  29. // #define STB_GLPROG_IMPLEMENTATION
  30. // #define STB_GLPROG_ARB_DEFINE_EXTENSIONS
  31. // #include <windows.h>
  32. // #include "gl/gl.h"
  33. // #include "stb_glprog.h"
  34. //
  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".
  39. //
  40. // See following comment blocks for function documentation.
  41. //
  42. // Version history:
  43. // 2013-12-08 v0.02 slightly simplified API and reduced GL resource usage (@rygorous)
  44. // 2013-12-08 v0.01 initial release
  45. // header file section starts here
  46. #if !defined(INCLUDE_STB_GLPROG_H)
  47. #define INCLUDE_STB_GLPROG_H
  48. #ifndef STB_GLPROG_STATIC
  49. #ifdef __cplusplus
  50. extern "C" {
  51. #endif
  52. //////////////////////////////////////////////////////////////////////////////
  53. ///////////// SHADER CREATION
  54. /// EASY API
  55. extern GLuint stbgl_create_program(char const **vertex_source, char const **frag_source, char const **binds, char *error, int error_buflen);
  56. // This function returns a compiled program or 0 if there's an error.
  57. // To free the created program, call stbgl_delete_program.
  58. //
  59. // stbgl_create_program(
  60. // char **vertex_source, // NULL or one or more strings with the vertex shader source, with a final NULL
  61. // char **frag_source, // NULL or one or more strings with the fragment shader source, with a final NULL
  62. // char **binds, // NULL or zero or more strings with attribute bind names, with a final NULL
  63. // char *error, // output location where compile error message is placed
  64. // int error_buflen) // length of error output buffer
  65. //
  66. // Returns a GLuint with the GL program object handle.
  67. //
  68. // If an individual bind string is "", no name is bound to that slot (this
  69. // allows you to create binds that aren't continuous integers starting at 0).
  70. //
  71. // If the vertex shader is NULL, then fixed-function vertex pipeline
  72. // is used, if that's legal in your version of GL.
  73. //
  74. // If the fragment shader is NULL, then fixed-function fragment pipeline
  75. // is used, if that's legal in your version of GL.
  76. extern void stgbl_delete_program(GLuint program);
  77. // deletes a program created by stbgl_create_program or stbgl_link_program
  78. /// FLEXIBLE API
  79. extern GLuint stbgl_compile_shader(GLenum type, char const **sources, int num_sources, char *error, int error_buflen);
  80. // compiles a shader. returns the shader on success or 0 on failure.
  81. //
  82. // type either: GL_VERTEX_SHADER or GL_FRAGMENT_SHADER
  83. // or GL_VERTEX_SHADER_ARB or GL_FRAGMENT_SHADER_ARB
  84. // or STBGL_VERTEX_SHADER or STBGL_FRAGMENT_SHADER
  85. // sources array of strings containing the shader source
  86. // num_sources number of string in sources, or -1 meaning sources is NULL-terminated
  87. // error string to output compiler error to
  88. // error_buflen length of error buffer in chars
  89. extern GLuint stbgl_link_program(GLuint vertex_shader, GLuint fragment_shader, char const **binds, int num_binds, char *error, int error_buflen);
  90. // links a shader. returns the linked program on success or 0 on failure.
  91. //
  92. // vertex_shader a compiled vertex shader from stbgl_compile_shader, or 0 for fixed-function (if legal)
  93. // fragment_shader a compiled fragment shader from stbgl_compile_shader, or 0 for fixed-function (if legal)
  94. //
  95. extern void stbgl_delete_shader(GLuint shader);
  96. // deletes a shader created by stbgl_compile_shader
  97. ///////////// RENDERING WITH SHADERS
  98. extern GLint stbgl_find_uniform(GLuint prog, char *uniform);
  99. extern void stbgl_find_uniforms(GLuint prog, GLint *locations, char const **uniforms, int num_uniforms);
  100. // Given the locations array that is num_uniforms long, fills out
  101. // the locations of each of those uniforms for the specified program.
  102. // If num_uniforms is -1, then uniforms[] must be NULL-terminated
  103. // the following functions just wrap the difference in naming between GL2+ and ARB,
  104. // so you don't need them unless you're using both ARB and GL2+ in the same codebase,
  105. // or you're relying on this lib to provide the extensions
  106. extern void stbglUseProgram(GLuint program);
  107. extern void stbglVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer);
  108. extern void stbglEnableVertexAttribArray(GLuint index);
  109. extern void stbglDisableVertexAttribArray(GLuint index);
  110. extern void stbglUniform1fv(GLint loc, GLsizei count, const GLfloat *v);
  111. extern void stbglUniform2fv(GLint loc, GLsizei count, const GLfloat *v);
  112. extern void stbglUniform3fv(GLint loc, GLsizei count, const GLfloat *v);
  113. extern void stbglUniform4fv(GLint loc, GLsizei count, const GLfloat *v);
  114. extern void stbglUniform1iv(GLint loc, GLsizei count, const GLint *v);
  115. extern void stbglUniform2iv(GLint loc, GLsizei count, const GLint *v);
  116. extern void stbglUniform3iv(GLint loc, GLsizei count, const GLint *v);
  117. extern void stbglUniform4iv(GLint loc, GLsizei count, const GLint *v);
  118. extern void stbglUniform1f(GLint loc, float v0);
  119. extern void stbglUniform2f(GLint loc, float v0, float v1);
  120. extern void stbglUniform3f(GLint loc, float v0, float v1, float v2);
  121. extern void stbglUniform4f(GLint loc, float v0, float v1, float v2, float v3);
  122. extern void stbglUniform1i(GLint loc, GLint v0);
  123. extern void stbglUniform2i(GLint loc, GLint v0, GLint v1);
  124. extern void stbglUniform3i(GLint loc, GLint v0, GLint v1, GLint v2);
  125. extern void stbglUniform4i(GLint loc, GLint v0, GLint v1, GLint v2, GLint v3);
  126. ////////////// END OF FUNCTIONS
  127. //////////////////////////////////////////////////////////////////////////////
  128. #ifdef __cplusplus
  129. }
  130. #endif
  131. #endif // STB_GLPROG_STATIC
  132. #ifdef STB_GLPROG_ARB
  133. #define STBGL_VERTEX_SHADER GL_VERTEX_SHADER_ARB
  134. #define STBGL_FRAGMENT_SHADER GL_FRAGMENT_SHADER_ARB
  135. #else
  136. #define STBGL_VERTEX_SHADER GL_VERTEX_SHADER
  137. #define STBGL_FRAGMENT_SHADER GL_FRAGMENT_SHADER
  138. #endif
  139. #endif // INCLUDE_STB_GLPROG_H
  140. ///////// header file section ends here
  141. #ifdef STB_GLPROG_IMPLEMENTATION
  142. #include <string.h> // strncpy
  143. #ifdef STB_GLPROG_STATIC
  144. #define STB_GLPROG_DECLARE static
  145. #else
  146. #define STB_GLPROG_DECLARE extern
  147. #endif
  148. // check if user wants this file to define the GL extensions itself
  149. #ifdef STB_GLPROG_ARB_DEFINE_EXTENSIONS
  150. #define STB_GLPROG_ARB // make sure later code uses the extensions
  151. #ifndef STB_GLPROG_SUPPRESS_GLEXT_INCLUDE
  152. #include "glext.h"
  153. #endif
  154. #define STB_GLPROG_EXTENSIONS \
  155. STB_GLPROG_FUNC(ATTACHOBJECT , AttachObject ) \
  156. STB_GLPROG_FUNC(BINDATTRIBLOCATION , BindAttribLocation ) \
  157. STB_GLPROG_FUNC(COMPILESHADER , CompileShader ) \
  158. STB_GLPROG_FUNC(CREATEPROGRAMOBJECT , CreateProgramObject ) \
  159. STB_GLPROG_FUNC(CREATESHADEROBJECT , CreateShaderObject ) \
  160. STB_GLPROG_FUNC(DELETEOBJECT , DeleteObject ) \
  161. STB_GLPROG_FUNC(DETACHOBJECT , DetachObject ) \
  162. STB_GLPROG_FUNC(DISABLEVERTEXATTRIBARRAY, DisableVertexAttribArray) \
  163. STB_GLPROG_FUNC(ENABLEVERTEXATTRIBARRAY, EnableVertexAttribArray ) \
  164. STB_GLPROG_FUNC(GETATTACHEDOBJECTS , GetAttachedObjects ) \
  165. STB_GLPROG_FUNC(GETOBJECTPARAMETERIV, GetObjectParameteriv) \
  166. STB_GLPROG_FUNC(GETINFOLOG , GetInfoLog ) \
  167. STB_GLPROG_FUNC(GETUNIFORMLOCATION , GetUniformLocation ) \
  168. STB_GLPROG_FUNC(LINKPROGRAM , LinkProgram ) \
  169. STB_GLPROG_FUNC(SHADERSOURCE , ShaderSource ) \
  170. STB_GLPROG_FUNC(UNIFORM1F , Uniform1f ) \
  171. STB_GLPROG_FUNC(UNIFORM2F , Uniform2f ) \
  172. STB_GLPROG_FUNC(UNIFORM3F , Uniform3f ) \
  173. STB_GLPROG_FUNC(UNIFORM4F , Uniform4f ) \
  174. STB_GLPROG_FUNC(UNIFORM1I , Uniform1i ) \
  175. STB_GLPROG_FUNC(UNIFORM2I , Uniform2i ) \
  176. STB_GLPROG_FUNC(UNIFORM3I , Uniform3i ) \
  177. STB_GLPROG_FUNC(UNIFORM4I , Uniform4i ) \
  178. STB_GLPROG_FUNC(UNIFORM1FV , Uniform1fv ) \
  179. STB_GLPROG_FUNC(UNIFORM2FV , Uniform2fv ) \
  180. STB_GLPROG_FUNC(UNIFORM3FV , Uniform3fv ) \
  181. STB_GLPROG_FUNC(UNIFORM4FV , Uniform4fv ) \
  182. STB_GLPROG_FUNC(UNIFORM1IV , Uniform1iv ) \
  183. STB_GLPROG_FUNC(UNIFORM2IV , Uniform2iv ) \
  184. STB_GLPROG_FUNC(UNIFORM3IV , Uniform3iv ) \
  185. STB_GLPROG_FUNC(UNIFORM4IV , Uniform4iv ) \
  186. STB_GLPROG_FUNC(USEPROGRAMOBJECT , UseProgramObject ) \
  187. STB_GLPROG_FUNC(VERTEXATTRIBPOINTER , VertexAttribPointer )
  188. // define the static function pointers
  189. #define STB_GLPROG_FUNC(x,y) static PFNGL##x##ARBPROC gl##y##ARB;
  190. STB_GLPROG_EXTENSIONS
  191. #undef STB_GLPROG_FUNC
  192. // define the GetProcAddress
  193. #ifdef _WIN32
  194. #ifndef WINGDIAPI
  195. #ifndef STB__HAS_WGLPROC
  196. typedef int (__stdcall *stbgl__voidfunc)(void);
  197. static __declspec(dllimport) stbgl__voidfunc wglGetProcAddress(char *);
  198. #endif
  199. #endif
  200. #define STBGL__GET_FUNC(x) wglGetProcAddress(x)
  201. #else
  202. #error "need to define how this platform gets extensions"
  203. #endif
  204. // create a function that fills out the function pointers
  205. static void stb_glprog_init(void)
  206. {
  207. static int initialized = 0; // not thread safe!
  208. if (initialized) return;
  209. #define STB_GLPROG_FUNC(x,y) gl##y##ARB = (PFNGL##x##ARBPROC) STBGL__GET_FUNC("gl" #y "ARB");
  210. STB_GLPROG_EXTENSIONS
  211. #undef STB_GLPROG_FUNC
  212. }
  213. #undef STB_GLPROG_EXTENSIONS
  214. #else
  215. static void stb_glprog_init(void)
  216. {
  217. }
  218. #endif
  219. // define generic names for many of the gl functions or extensions for later use;
  220. // note that in some cases there are two functions in core and one function in ARB
  221. #ifdef STB_GLPROG_ARB
  222. #define stbglCreateShader glCreateShaderObjectARB
  223. #define stbglDeleteShader glDeleteObjectARB
  224. #define stbglAttachShader glAttachObjectARB
  225. #define stbglDetachShader glDetachObjectARB
  226. #define stbglShaderSource glShaderSourceARB
  227. #define stbglCompileShader glCompileShaderARB
  228. #define stbglGetShaderStatus(a,b) glGetObjectParameterivARB(a, GL_OBJECT_COMPILE_STATUS_ARB, b)
  229. #define stbglGetShaderInfoLog glGetInfoLogARB
  230. #define stbglCreateProgram glCreateProgramObjectARB
  231. #define stbglDeleteProgram glDeleteObjectARB
  232. #define stbglLinkProgram glLinkProgramARB
  233. #define stbglGetProgramStatus(a,b) glGetObjectParameterivARB(a, GL_OBJECT_LINK_STATUS_ARB, b)
  234. #define stbglGetProgramInfoLog glGetInfoLogARB
  235. #define stbglGetAttachedShaders glGetAttachedObjectsARB
  236. #define stbglBindAttribLocation glBindAttribLocationARB
  237. #define stbglGetUniformLocation glGetUniformLocationARB
  238. #define stbgl_UseProgram glUseProgramObjectARB
  239. #else
  240. #define stbglCreateShader glCreateShader
  241. #define stbglDeleteShader glDeleteShader
  242. #define stbglAttachShader glAttachShader
  243. #define stbglDetachShader glDetachShader
  244. #define stbglShaderSource glShaderSource
  245. #define stbglCompileShader glCompileShader
  246. #define stbglGetShaderStatus(a,b) glGetShaderiv(a, GL_COMPILE_STATUS, b)
  247. #define stbglGetShaderInfoLog glGetShaderInfoLog
  248. #define stbglCreateProgram glCreateProgram
  249. #define stbglDeleteProgram glDeleteProgram
  250. #define stbglLinkProgram glLinkProgram
  251. #define stbglGetProgramStatus(a,b) glGetProgramiv(a, GL_LINK_STATUS, b)
  252. #define stbglGetProgramInfoLog glGetProgramInfoLog
  253. #define stbglGetAttachedShaders glGetAttachedShaders
  254. #define stbglBindAttribLocation glBindAttribLocation
  255. #define stbglGetUniformLocation glGetUniformLocation
  256. #define stbgl_UseProgram glUseProgram
  257. #endif
  258. // perform a safe strcat of 3 strings, given that we can't rely on portable snprintf
  259. // if you need to break on error, this is the best place to place a breakpoint
  260. static void stb_glprog_error(char *error, int error_buflen, char *str1, char *str2, char *str3)
  261. {
  262. int n = strlen(str1);
  263. strncpy(error, str1, error_buflen);
  264. if (n < error_buflen && str2) {
  265. strncpy(error+n, str2, error_buflen - n);
  266. n += strlen(str2);
  267. if (n < error_buflen && str3) {
  268. strncpy(error+n, str3, error_buflen - n);
  269. }
  270. }
  271. error[error_buflen-1] = 0;
  272. }
  273. STB_GLPROG_DECLARE GLuint stbgl_compile_shader(GLenum type, char const **sources, int num_sources, char *error, int error_buflen)
  274. {
  275. char *typename = (type == STBGL_VERTEX_SHADER ? "vertex" : "fragment");
  276. int len;
  277. GLint result;
  278. GLuint shader;
  279. // initialize the extensions if we haven't already
  280. stb_glprog_init();
  281. // allocate
  282. shader = stbglCreateShader(type);
  283. if (!shader) {
  284. stb_glprog_error(error, error_buflen, "Couldn't allocate shader object in stbgl_compile_shader for ", typename, NULL);
  285. return 0;
  286. }
  287. // compile
  288. // if num_sources is negative, assume source is NULL-terminated and count the non-NULL ones
  289. if (num_sources < 0)
  290. for (num_sources = 0; sources[num_sources] != NULL; ++num_sources)
  291. ;
  292. stbglShaderSource(shader, num_sources, sources, NULL);
  293. stbglCompileShader(shader);
  294. stbglGetShaderStatus(shader, &result);
  295. if (result)
  296. return shader;
  297. // errors
  298. stb_glprog_error(error, error_buflen, "Compile error for ", typename, " shader: ");
  299. len = strlen(error);
  300. if (len < error_buflen)
  301. stbglGetShaderInfoLog(shader, error_buflen-len, NULL, error+len);
  302. stbglDeleteShader(shader);
  303. return 0;
  304. }
  305. STB_GLPROG_DECLARE GLuint stbgl_link_program(GLuint vertex_shader, GLuint fragment_shader, char const **binds, int num_binds, char *error, int error_buflen)
  306. {
  307. int len;
  308. GLint result;
  309. // allocate
  310. GLuint prog = stbglCreateProgram();
  311. if (!prog) {
  312. stb_glprog_error(error, error_buflen, "Couldn't allocate program object in stbgl_link_program", NULL, NULL);
  313. return 0;
  314. }
  315. // attach
  316. if (vertex_shader)
  317. stbglAttachShader(prog, vertex_shader);
  318. if (fragment_shader)
  319. stbglAttachShader(prog, fragment_shader);
  320. // attribute binds
  321. if (binds) {
  322. int i;
  323. // if num_binds is negative, then it is NULL terminated
  324. if (num_binds < 0)
  325. for (num_binds=0; binds[num_binds]; ++num_binds)
  326. ;
  327. for (i=0; i < num_binds; ++i)
  328. if (binds[i] && binds[i][0]) // empty binds can be NULL or ""
  329. stbglBindAttribLocation(prog, i, binds[i]);
  330. }
  331. // link
  332. stbglLinkProgram(prog);
  333. // detach
  334. if (vertex_shader)
  335. stbglDetachShader(prog, vertex_shader);
  336. if (fragment_shader)
  337. stbglDetachShader(prog, fragment_shader);
  338. // errors
  339. stbglGetProgramStatus(prog, &result);
  340. if (result)
  341. return prog;
  342. stb_glprog_error(error, error_buflen, "Link error: ", NULL, NULL);
  343. len = strlen(error);
  344. if (len < error_buflen)
  345. stbglGetProgramInfoLog(prog, error_buflen-len, NULL, error+len);
  346. stbglDeleteProgram(prog);
  347. return 0;
  348. }
  349. STB_GLPROG_DECLARE GLuint stbgl_create_program(char const **vertex_source, char const **frag_source, char const **binds, char *error, int error_buflen)
  350. {
  351. GLuint vertex, fragment, prog=0;
  352. vertex = stbgl_compile_shader(STBGL_VERTEX_SHADER, vertex_source, -1, error, error_buflen);
  353. if (vertex) {
  354. fragment = stbgl_compile_shader(STBGL_FRAGMENT_SHADER, frag_source, -1, error, error_buflen);
  355. if (fragment)
  356. prog = stbgl_link_program(vertex, fragment, binds, -1, error, error_buflen);
  357. if (fragment)
  358. stbglDeleteShader(fragment);
  359. stbglDeleteShader(vertex);
  360. }
  361. return prog;
  362. }
  363. STB_GLPROG_DECLARE void stbgl_delete_shader(GLuint shader)
  364. {
  365. stbglDeleteShader(shader);
  366. }
  367. STB_GLPROG_DECLARE void stgbl_delete_program(GLuint program)
  368. {
  369. stbglDeleteProgram(program);
  370. }
  371. GLint stbgl_find_uniform(GLuint prog, char *uniform)
  372. {
  373. return stbglGetUniformLocation(prog, uniform);
  374. }
  375. STB_GLPROG_DECLARE void stbgl_find_uniforms(GLuint prog, GLint *locations, char const **uniforms, int num_uniforms)
  376. {
  377. int i;
  378. if (num_uniforms < 0)
  379. num_uniforms = 999999;
  380. for (i=0; i < num_uniforms && uniforms[i]; ++i)
  381. locations[i] = stbglGetUniformLocation(prog, uniforms[i]);
  382. }
  383. STB_GLPROG_DECLARE void stbglUseProgram(GLuint program)
  384. {
  385. stbgl_UseProgram(program);
  386. }
  387. #ifdef STB_GLPROG_ARB
  388. #define STBGL_ARBIFY(name) name##ARB
  389. #else
  390. #define STBGL_ARBIFY(name) name
  391. #endif
  392. STB_GLPROG_DECLARE void stbglVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer)
  393. {
  394. STBGL_ARBIFY(glVertexAttribPointer)(index, size, type, normalized, stride, pointer);
  395. }
  396. STB_GLPROG_DECLARE void stbglEnableVertexAttribArray (GLuint index) { STBGL_ARBIFY(glEnableVertexAttribArray )(index); }
  397. STB_GLPROG_DECLARE void stbglDisableVertexAttribArray(GLuint index) { STBGL_ARBIFY(glDisableVertexAttribArray)(index); }
  398. STB_GLPROG_DECLARE void stbglUniform1fv(GLint loc, GLsizei count, const GLfloat *v) { STBGL_ARBIFY(glUniform1fv)(loc,count,v); }
  399. STB_GLPROG_DECLARE void stbglUniform2fv(GLint loc, GLsizei count, const GLfloat *v) { STBGL_ARBIFY(glUniform2fv)(loc,count,v); }
  400. STB_GLPROG_DECLARE void stbglUniform3fv(GLint loc, GLsizei count, const GLfloat *v) { STBGL_ARBIFY(glUniform3fv)(loc,count,v); }
  401. STB_GLPROG_DECLARE void stbglUniform4fv(GLint loc, GLsizei count, const GLfloat *v) { STBGL_ARBIFY(glUniform4fv)(loc,count,v); }
  402. STB_GLPROG_DECLARE void stbglUniform1iv(GLint loc, GLsizei count, const GLint *v) { STBGL_ARBIFY(glUniform1iv)(loc,count,v); }
  403. STB_GLPROG_DECLARE void stbglUniform2iv(GLint loc, GLsizei count, const GLint *v) { STBGL_ARBIFY(glUniform2iv)(loc,count,v); }
  404. STB_GLPROG_DECLARE void stbglUniform3iv(GLint loc, GLsizei count, const GLint *v) { STBGL_ARBIFY(glUniform3iv)(loc,count,v); }
  405. STB_GLPROG_DECLARE void stbglUniform4iv(GLint loc, GLsizei count, const GLint *v) { STBGL_ARBIFY(glUniform4iv)(loc,count,v); }
  406. STB_GLPROG_DECLARE void stbglUniform1f(GLint loc, float v0)
  407. { STBGL_ARBIFY(glUniform1f)(loc,v0); }
  408. STB_GLPROG_DECLARE void stbglUniform2f(GLint loc, float v0, float v1)
  409. { STBGL_ARBIFY(glUniform2f)(loc,v0,v1); }
  410. STB_GLPROG_DECLARE void stbglUniform3f(GLint loc, float v0, float v1, float v2)
  411. { STBGL_ARBIFY(glUniform3f)(loc,v0,v1,v2); }
  412. STB_GLPROG_DECLARE void stbglUniform4f(GLint loc, float v0, float v1, float v2, float v3)
  413. { STBGL_ARBIFY(glUniform4f)(loc,v0,v1,v2,v3); }
  414. STB_GLPROG_DECLARE void stbglUniform1i(GLint loc, GLint v0)
  415. { STBGL_ARBIFY(glUniform1i)(loc,v0); }
  416. STB_GLPROG_DECLARE void stbglUniform2i(GLint loc, GLint v0, GLint v1)
  417. { STBGL_ARBIFY(glUniform2i)(loc,v0,v1); }
  418. STB_GLPROG_DECLARE void stbglUniform3i(GLint loc, GLint v0, GLint v1, GLint v2)
  419. { STBGL_ARBIFY(glUniform3i)(loc,v0,v1,v2); }
  420. STB_GLPROG_DECLARE void stbglUniform4i(GLint loc, GLint v0, GLint v1, GLint v2, GLint v3)
  421. { STBGL_ARBIFY(glUniform4i)(loc,v0,v1,v2,v3); }
  422. #endif