3 #include "cl_collision.h"
5 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
6 cvar_t gl_mesh_testarrayelement = {0, "gl_mesh_testarrayelement", "0", "use glBegin(GL_TRIANGLES);glArrayElement();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
7 cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0", "use glBegin(GL_TRIANGLES);glTexCoord2f();glVertex3f();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
8 cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
9 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
11 cvar_t r_render = {0, "r_render", "1", "enables rendering calls (you want this on!)"};
12 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"};
13 cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
14 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
15 cvar_t gl_lockarrays = {0, "gl_lockarrays", "1", "enables use of glLockArraysEXT, may cause glitches with some broken drivers"};
17 int gl_maxdrawrangeelementsvertices;
18 int gl_maxdrawrangeelementsindices;
23 void GL_PrintError(int errornumber, char *filename, int linenumber)
27 #ifdef GL_INVALID_ENUM
29 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
32 #ifdef GL_INVALID_VALUE
33 case GL_INVALID_VALUE:
34 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
37 #ifdef GL_INVALID_OPERATION
38 case GL_INVALID_OPERATION:
39 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
42 #ifdef GL_STACK_OVERFLOW
43 case GL_STACK_OVERFLOW:
44 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
47 #ifdef GL_STACK_UNDERFLOW
48 case GL_STACK_UNDERFLOW:
49 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
52 #ifdef GL_OUT_OF_MEMORY
53 case GL_OUT_OF_MEMORY:
54 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
57 #ifdef GL_TABLE_TOO_LARGE
58 case GL_TABLE_TOO_LARGE:
59 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
63 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
69 #define BACKENDACTIVECHECK if (!backendactive) Sys_Error("GL backend function called when backend is not active");
71 void SCR_ScreenShot_f (void);
73 static matrix4x4_t backend_viewmatrix;
74 static matrix4x4_t backend_modelmatrix;
75 static matrix4x4_t backend_modelviewmatrix;
76 static matrix4x4_t backend_projectmatrix;
78 static unsigned int backendunits, backendimageunits, backendarrayunits, backendactive;
81 note: here's strip order for a terrain row:
88 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
90 *elements++ = i + row;
92 *elements++ = i + row + 1;
95 *elements++ = i + row + 1;
98 for (y = 0;y < rows - 1;y++)
100 for (x = 0;x < columns - 1;x++)
103 *elements++ = i + columns;
105 *elements++ = i + columns + 1;
108 *elements++ = i + columns + 1;
119 for (y = 0;y < rows - 1;y++)
121 for (x = 0;x < columns - 1;x++)
125 *elements++ = i + columns;
126 *elements++ = i + columns + 1;
127 *elements++ = i + columns;
128 *elements++ = i + columns + 1;
134 int polygonelements[(POLYGONELEMENTS_MAXPOINTS-2)*3];
135 int quadelements[QUADELEMENTS_MAXQUADS*6];
137 void GL_Backend_AllocArrays(void)
141 void GL_Backend_FreeArrays(void)
145 static void gl_backend_start(void)
147 Con_Print("OpenGL Backend starting...\n");
150 if (qglDrawRangeElements != NULL)
153 qglGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &gl_maxdrawrangeelementsvertices);
155 qglGetIntegerv(GL_MAX_ELEMENTS_INDICES, &gl_maxdrawrangeelementsindices);
157 Con_Printf("glDrawRangeElements detected (max vertices %i, max indices %i)\n", gl_maxdrawrangeelementsvertices, gl_maxdrawrangeelementsindices);
160 backendunits = min(MAX_TEXTUREUNITS, gl_textureunits);
161 backendimageunits = backendunits;
162 backendarrayunits = backendunits;
163 if (gl_support_fragment_shader)
166 qglGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, (int *)&backendimageunits);
168 qglGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, (int *)&backendarrayunits);
170 Con_Printf("GLSL shader support detected: texture units = %i texenv, %i image, %i array\n", backendunits, backendimageunits, backendarrayunits);
172 else if (backendunits > 1)
173 Con_Printf("multitexture detected: texture units = %i\n", backendunits);
175 Con_Printf("singletexture\n");
177 GL_Backend_AllocArrays();
179 Con_Printf("OpenGL backend started.\n");
183 backendactive = true;
186 static void gl_backend_shutdown(void)
189 backendimageunits = 0;
190 backendarrayunits = 0;
191 backendactive = false;
193 Con_Print("OpenGL Backend shutting down\n");
195 GL_Backend_FreeArrays();
198 static void gl_backend_newmap(void)
202 void gl_backend_init(void)
206 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
208 polygonelements[i * 3 + 0] = 0;
209 polygonelements[i * 3 + 1] = i + 1;
210 polygonelements[i * 3 + 2] = i + 2;
212 // elements for rendering a series of quads as triangles
213 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
215 quadelements[i * 6 + 0] = i * 4;
216 quadelements[i * 6 + 1] = i * 4 + 1;
217 quadelements[i * 6 + 2] = i * 4 + 2;
218 quadelements[i * 6 + 3] = i * 4;
219 quadelements[i * 6 + 4] = i * 4 + 2;
220 quadelements[i * 6 + 5] = i * 4 + 3;
223 Cvar_RegisterVariable(&r_render);
224 Cvar_RegisterVariable(&r_waterwarp);
225 Cvar_RegisterVariable(&gl_polyblend);
226 Cvar_RegisterVariable(&gl_dither);
227 Cvar_RegisterVariable(&gl_lockarrays);
228 Cvar_RegisterVariable(&gl_paranoid);
229 Cvar_RegisterVariable(&gl_printcheckerror);
231 Cvar_SetValue("r_render", 0);
234 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
235 Cvar_RegisterVariable(&gl_mesh_testarrayelement);
236 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
238 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
241 void GL_SetupView_Orientation_Identity (void)
243 backend_viewmatrix = identitymatrix;
244 memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
247 void GL_SetupView_Orientation_FromEntity(matrix4x4_t *matrix)
249 matrix4x4_t tempmatrix, basematrix;
250 Matrix4x4_Invert_Simple(&tempmatrix, matrix);
251 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
252 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
253 Matrix4x4_Concat(&backend_viewmatrix, &basematrix, &tempmatrix);
254 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[2], 1, 0, 0);
255 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[0], 0, 1, 0);
256 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[1], 0, 0, 1);
257 //Matrix4x4_ConcatTranslate(&backend_viewmatrix, -origin[0], -origin[1], -origin[2]);
258 memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
261 void GL_SetupView_Mode_Perspective (double frustumx, double frustumy, double zNear, double zFar)
267 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
268 qglLoadIdentity();CHECKGLERROR
270 qglFrustum(-frustumx * zNear, frustumx * zNear, -frustumy * zNear, frustumy * zNear, zNear, zFar);CHECKGLERROR
271 qglGetDoublev(GL_PROJECTION_MATRIX, m);CHECKGLERROR
272 Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
273 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
274 GL_SetupView_Orientation_Identity();
278 void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double frustumx, double frustumy, double zNear)
284 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
285 qglLoadIdentity();CHECKGLERROR
287 nudge = 1.0 - 1.0 / (1<<23);
288 m[ 0] = 1.0 / frustumx;
293 m[ 5] = 1.0 / frustumy;
302 m[14] = -2 * zNear * nudge;
304 qglLoadMatrixd(m);CHECKGLERROR
305 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
306 GL_SetupView_Orientation_Identity();
308 Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
311 void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double zNear, double zFar)
317 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
318 qglLoadIdentity();CHECKGLERROR
319 qglOrtho(x1, x2, y2, y1, zNear, zFar);CHECKGLERROR
320 qglGetDoublev(GL_PROJECTION_MATRIX, m);CHECKGLERROR
321 Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
322 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
323 GL_SetupView_Orientation_Identity();
327 typedef struct gltextureunit_s
329 int t1d, t2d, t3d, tcubemap;
331 unsigned int arraycomponents;
332 const void *pointer_texcoord;
333 int rgbscale, alphascale;
334 int combinergb, combinealpha;
335 // FIXME: add more combine stuff
336 // texmatrixenabled exists only to avoid unnecessary texmatrix compares
337 int texmatrixenabled;
342 static struct gl_state_s
350 int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
355 unsigned int clientunit;
356 gltextureunit_t units[MAX_TEXTUREUNITS];
360 const void *pointer_vertex;
361 const void *pointer_color;
365 void GL_SetupTextureState(void)
368 gltextureunit_t *unit;
370 gl_state.unit = MAX_TEXTUREUNITS;
371 gl_state.clientunit = MAX_TEXTUREUNITS;
372 for (i = 0;i < MAX_TEXTUREUNITS;i++)
374 unit = gl_state.units + i;
379 unit->arrayenabled = false;
380 unit->arraycomponents = 0;
381 unit->pointer_texcoord = NULL;
383 unit->alphascale = 1;
384 unit->combinergb = GL_MODULATE;
385 unit->combinealpha = GL_MODULATE;
386 unit->texmatrixenabled = false;
387 unit->matrix = identitymatrix;
390 for (i = 0;i < backendimageunits;i++)
393 qglBindTexture(GL_TEXTURE_1D, 0);CHECKGLERROR
394 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
397 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
399 if (gl_texturecubemap)
401 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
405 for (i = 0;i < backendarrayunits;i++)
407 GL_ClientActiveTexture(i);
408 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
409 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
412 for (i = 0;i < backendunits;i++)
415 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
416 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
419 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
421 if (gl_texturecubemap)
423 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
425 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
426 qglLoadIdentity();CHECKGLERROR
427 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
428 if (gl_combine.integer)
430 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
431 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);CHECKGLERROR
432 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);CHECKGLERROR
433 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
434 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
435 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
436 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
437 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);CHECKGLERROR
438 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);CHECKGLERROR
439 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);CHECKGLERROR
440 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
441 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);CHECKGLERROR
442 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
443 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
444 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
445 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
446 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
450 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
457 void GL_Backend_ResetState(void)
459 memset(&gl_state, 0, sizeof(gl_state));
460 gl_state.depthtest = true;
461 gl_state.alphatest = false;
462 gl_state.blendfunc1 = GL_ONE;
463 gl_state.blendfunc2 = GL_ZERO;
464 gl_state.blend = false;
465 gl_state.depthmask = GL_TRUE;
466 gl_state.colormask = 15;
467 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
468 gl_state.lockrange_first = 0;
469 gl_state.lockrange_count = 0;
470 gl_state.pointer_vertex = NULL;
471 gl_state.pointer_color = NULL;
472 gl_state.cullface = GL_FRONT; // quake is backwards, this culls back faces
473 gl_state.cullfaceenable = true;
477 qglColorMask(1, 1, 1, 1);
478 qglAlphaFunc(GL_GEQUAL, 0.5);CHECKGLERROR
479 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
480 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
481 qglDisable(GL_BLEND);CHECKGLERROR
482 qglCullFace(gl_state.cullface);CHECKGLERROR
483 qglEnable(GL_CULL_FACE);CHECKGLERROR
484 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
485 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
486 qglDepthMask(gl_state.depthmask);CHECKGLERROR
488 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
489 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
491 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
492 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
494 GL_Color(0, 0, 0, 0);
495 GL_Color(1, 1, 1, 1);
497 GL_SetupTextureState();
500 void GL_ActiveTexture(unsigned int num)
502 if (gl_state.unit != num)
505 if (qglActiveTexture)
508 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
514 void GL_ClientActiveTexture(unsigned int num)
516 if (gl_state.clientunit != num)
518 gl_state.clientunit = num;
519 if (qglActiveTexture)
522 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
528 void GL_BlendFunc(int blendfunc1, int blendfunc2)
530 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
533 qglBlendFunc(gl_state.blendfunc1 = blendfunc1, gl_state.blendfunc2 = blendfunc2);CHECKGLERROR
534 if (gl_state.blendfunc2 == GL_ZERO)
536 if (gl_state.blendfunc1 == GL_ONE)
541 qglDisable(GL_BLEND);CHECKGLERROR
549 qglEnable(GL_BLEND);CHECKGLERROR
558 qglEnable(GL_BLEND);CHECKGLERROR
564 void GL_DepthMask(int state)
566 if (gl_state.depthmask != state)
569 qglDepthMask(gl_state.depthmask = state);CHECKGLERROR
573 void GL_DepthTest(int state)
575 if (gl_state.depthtest != state)
577 gl_state.depthtest = state;
579 if (gl_state.depthtest)
581 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
585 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
590 void GL_CullFace(int state)
592 if (gl_state.cullface != state)
595 if (state != GL_NONE)
597 if (!gl_state.cullfaceenable)
599 gl_state.cullfaceenable = true;
600 qglEnable(GL_CULL_FACE);CHECKGLERROR
602 if (gl_state.cullface != state)
604 gl_state.cullface = state;
605 qglCullFace(state);CHECKGLERROR
610 if (gl_state.cullfaceenable)
612 gl_state.cullfaceenable = false;
613 qglDisable(GL_CULL_FACE);CHECKGLERROR
619 void GL_AlphaTest(int state)
621 if (gl_state.alphatest != state)
623 gl_state.alphatest = state;
625 if (gl_state.alphatest)
627 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
631 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
636 void GL_ColorMask(int r, int g, int b, int a)
638 int state = r*8 + g*4 + b*2 + a*1;
639 if (gl_state.colormask != state)
641 gl_state.colormask = state;
643 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
647 void GL_Color(float cr, float cg, float cb, float ca)
649 if (gl_state.pointer_color || gl_state.color4f[0] != cr || gl_state.color4f[1] != cg || gl_state.color4f[2] != cb || gl_state.color4f[3] != ca)
651 gl_state.color4f[0] = cr;
652 gl_state.color4f[1] = cg;
653 gl_state.color4f[2] = cb;
654 gl_state.color4f[3] = ca;
656 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
661 void GL_LockArrays(int first, int count)
663 if (gl_state.lockrange_count != count || gl_state.lockrange_first != first)
665 if (gl_state.lockrange_count)
667 gl_state.lockrange_count = 0;
669 qglUnlockArraysEXT();
672 if (count && gl_supportslockarrays && gl_lockarrays.integer && r_render.integer)
674 gl_state.lockrange_first = first;
675 gl_state.lockrange_count = count;
677 qglLockArraysEXT(first, count);
683 void GL_Scissor (int x, int y, int width, int height)
686 qglScissor(x, vid.height - (y + height),width,height);
690 void GL_ScissorTest(int state)
692 if(gl_state.scissortest == state)
696 if((gl_state.scissortest = state))
697 qglEnable(GL_SCISSOR_TEST);
699 qglDisable(GL_SCISSOR_TEST);
703 void GL_Clear(int mask)
706 qglClear(mask);CHECKGLERROR
709 void GL_TransformToScreen(const vec4_t in, vec4_t out)
713 Matrix4x4_Transform4 (&backend_viewmatrix, in, temp);
714 Matrix4x4_Transform4 (&backend_projectmatrix, temp, out);
716 out[0] = r_view.x + (out[0] * iw + 1.0f) * r_view.width * 0.5f;
717 out[1] = r_view.y + r_view.height - (out[1] * iw + 1.0f) * r_view.height * 0.5f;
718 out[2] = r_view.z + (out[2] * iw + 1.0f) * r_view.depth * 0.5f;
721 // called at beginning of frame
722 void R_Mesh_Start(void)
726 if (gl_printcheckerror.integer && !gl_paranoid.integer)
728 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
729 Cvar_SetValueQuick(&gl_paranoid, 1);
731 GL_Backend_ResetState();
734 unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **vertexstrings_list, int fragmentstrings_count, const char **fragmentstrings_list)
736 GLint vertexshadercompiled, fragmentshadercompiled, programlinked;
737 GLuint vertexshaderobject, fragmentshaderobject, programobject = 0;
738 char compilelog[MAX_INPUTLINE];
741 programobject = qglCreateProgramObjectARB();CHECKGLERROR
745 if (developer.integer >= 100)
748 Con_Printf("Compiling shader:\n");
749 if (vertexstrings_count)
751 Con_Printf("------ VERTEX SHADER ------\n");
752 for (i = 0;i < vertexstrings_count;i++)
753 Con_Print(vertexstrings_list[i]);
756 if (fragmentstrings_count)
758 Con_Printf("------ FRAGMENT SHADER ------\n");
759 for (i = 0;i < fragmentstrings_count;i++)
760 Con_Print(fragmentstrings_list[i]);
765 if (vertexstrings_count)
767 vertexshaderobject = qglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);CHECKGLERROR
768 if (!vertexshaderobject)
770 qglDeleteObjectARB(programobject);
774 qglShaderSourceARB(vertexshaderobject, vertexstrings_count, vertexstrings_list, NULL);CHECKGLERROR
775 qglCompileShaderARB(vertexshaderobject);CHECKGLERROR
776 qglGetObjectParameterivARB(vertexshaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &vertexshadercompiled);CHECKGLERROR
777 qglGetInfoLogARB(vertexshaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
779 Con_DPrintf("vertex shader compile log:\n%s\n", compilelog);
780 if (!vertexshadercompiled)
782 qglDeleteObjectARB(programobject);CHECKGLERROR
783 qglDeleteObjectARB(vertexshaderobject);CHECKGLERROR
786 qglAttachObjectARB(programobject, vertexshaderobject);CHECKGLERROR
787 qglDeleteObjectARB(vertexshaderobject);CHECKGLERROR
790 if (fragmentstrings_count)
792 fragmentshaderobject = qglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);CHECKGLERROR
793 if (!fragmentshaderobject)
795 qglDeleteObjectARB(programobject);CHECKGLERROR
798 qglShaderSourceARB(fragmentshaderobject, fragmentstrings_count, fragmentstrings_list, NULL);CHECKGLERROR
799 qglCompileShaderARB(fragmentshaderobject);CHECKGLERROR
800 qglGetObjectParameterivARB(fragmentshaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &fragmentshadercompiled);CHECKGLERROR
801 qglGetInfoLogARB(fragmentshaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
803 Con_DPrintf("fragment shader compile log:\n%s\n", compilelog);
804 if (!fragmentshadercompiled)
806 qglDeleteObjectARB(programobject);CHECKGLERROR
807 qglDeleteObjectARB(fragmentshaderobject);CHECKGLERROR
810 qglAttachObjectARB(programobject, fragmentshaderobject);CHECKGLERROR
811 qglDeleteObjectARB(fragmentshaderobject);CHECKGLERROR
814 qglLinkProgramARB(programobject);CHECKGLERROR
815 qglGetObjectParameterivARB(programobject, GL_OBJECT_LINK_STATUS_ARB, &programlinked);CHECKGLERROR
816 qglGetInfoLogARB(programobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
819 Con_DPrintf("program link log:\n%s\n", compilelog);
820 // software vertex shader is ok but software fragment shader is WAY
821 // too slow, fail program if so.
822 // NOTE: this string might be ATI specific, but that's ok because the
823 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
824 // software fragment shader due to low instruction and dependent
826 if (strstr(compilelog, "fragment shader will run in software"))
827 programlinked = false;
831 qglDeleteObjectARB(programobject);CHECKGLERROR
835 return programobject;
838 void GL_Backend_FreeProgram(unsigned int prog)
841 qglDeleteObjectARB(prog);
845 int gl_backend_rebindtextures;
847 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
852 for (i = 0;i < count;i++)
853 *out++ = *in++ + offset;
856 memcpy(out, in, sizeof(*out) * count);
859 // renders triangles using vertices from the active arrays
860 int paranoidblah = 0;
861 void R_Mesh_Draw(int firstvertex, int numvertices, int numtriangles, const int *elements)
863 unsigned int numelements = numtriangles * 3;
864 if (numvertices < 3 || numtriangles < 1)
866 Con_Printf("R_Mesh_Draw(%d, %d, %d, %08p);\n", firstvertex, numvertices, numtriangles, elements);
870 r_refdef.stats.meshes++;
871 r_refdef.stats.meshes_elements += numelements;
872 if (gl_paranoid.integer)
874 unsigned int i, j, size;
876 if (!qglIsEnabled(GL_VERTEX_ARRAY))
877 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
879 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
881 if (gl_state.pointer_color)
883 if (!qglIsEnabled(GL_COLOR_ARRAY))
884 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
886 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
889 for (i = 0;i < backendarrayunits;i++)
891 if (gl_state.units[i].arrayenabled)
893 GL_ClientActiveTexture(i);
894 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
895 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
897 for (j = 0, size = numvertices * gl_state.units[i].arraycomponents, p = (int *)((float *)gl_state.units[i].pointer_texcoord + firstvertex * gl_state.units[i].arraycomponents);j < size;j++, p++)
901 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
903 if (elements[i] < firstvertex || elements[i] >= firstvertex + numvertices)
905 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in elements list\n", elements[i], firstvertex, firstvertex + numvertices);
911 if (r_render.integer)
914 if (gl_mesh_testmanualfeeding.integer)
918 qglBegin(GL_TRIANGLES);
919 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
921 for (j = 0;j < backendarrayunits;j++)
923 if (gl_state.units[j].pointer_texcoord)
925 if (backendarrayunits > 1)
927 if (gl_state.units[j].arraycomponents == 4)
929 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
930 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
932 else if (gl_state.units[j].arraycomponents == 3)
934 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
935 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
937 else if (gl_state.units[j].arraycomponents == 2)
939 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
940 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
944 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
945 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
950 if (gl_state.units[j].arraycomponents == 4)
952 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
953 qglTexCoord4f(p[0], p[1], p[2], p[3]);
955 else if (gl_state.units[j].arraycomponents == 3)
957 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
958 qglTexCoord3f(p[0], p[1], p[2]);
960 else if (gl_state.units[j].arraycomponents == 2)
962 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
963 qglTexCoord2f(p[0], p[1]);
967 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
973 if (gl_state.pointer_color)
975 p = ((const GLfloat *)(gl_state.pointer_color)) + elements[i] * 4;
976 qglColor4f(p[0], p[1], p[2], p[3]);
978 p = ((const GLfloat *)(gl_state.pointer_vertex)) + elements[i] * 3;
979 qglVertex3f(p[0], p[1], p[2]);
984 else if (gl_mesh_testarrayelement.integer)
987 qglBegin(GL_TRIANGLES);
988 for (i = 0;i < numtriangles * 3;i++)
990 qglArrayElement(elements[i]);
995 else if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
997 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_INT, elements);
1002 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, elements);
1008 // restores backend state, used when done with 3D rendering
1009 void R_Mesh_Finish(void)
1014 GL_LockArrays(0, 0);
1017 for (i = 0;i < backendimageunits;i++)
1019 GL_ActiveTexture(i);
1020 qglBindTexture(GL_TEXTURE_1D, 0);CHECKGLERROR
1021 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1024 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1026 if (gl_texturecubemap)
1028 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1031 for (i = 0;i < backendarrayunits;i++)
1033 GL_ActiveTexture(backendarrayunits - 1 - i);
1034 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1036 for (i = 0;i < backendunits;i++)
1038 GL_ActiveTexture(backendunits - 1 - i);
1039 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1040 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1043 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1045 if (gl_texturecubemap)
1047 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1049 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1050 if (gl_combine.integer)
1052 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
1053 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
1056 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1057 qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1059 qglDisable(GL_BLEND);CHECKGLERROR
1060 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1061 qglDepthMask(GL_TRUE);CHECKGLERROR
1062 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);CHECKGLERROR
1065 void R_Mesh_Matrix(const matrix4x4_t *matrix)
1067 if (memcmp(matrix, &backend_modelmatrix, sizeof(matrix4x4_t)))
1069 double glmatrix[16];
1070 backend_modelmatrix = *matrix;
1071 Matrix4x4_Concat(&backend_modelviewmatrix, &backend_viewmatrix, matrix);
1072 Matrix4x4_ToArrayDoubleGL(&backend_modelviewmatrix, glmatrix);
1074 qglLoadMatrixd(glmatrix);CHECKGLERROR
1078 void R_Mesh_VertexPointer(const float *vertex3f)
1080 if (gl_state.pointer_vertex != vertex3f)
1082 gl_state.pointer_vertex = vertex3f;
1084 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), gl_state.pointer_vertex);
1089 void R_Mesh_ColorPointer(const float *color4f)
1091 if (gl_state.pointer_color != color4f)
1094 if (!gl_state.pointer_color)
1096 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1100 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1101 // when color array is on the glColor gets trashed, set it again
1102 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
1104 gl_state.pointer_color = color4f;
1105 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), gl_state.pointer_color);CHECKGLERROR
1109 void R_Mesh_TexCoordPointer(unsigned int unitnum, unsigned int numcomponents, const float *texcoord)
1111 gltextureunit_t *unit = gl_state.units + unitnum;
1112 // update array settings
1117 if (unit->pointer_texcoord != texcoord || unit->arraycomponents != numcomponents)
1119 unit->pointer_texcoord = texcoord;
1120 unit->arraycomponents = numcomponents;
1121 GL_ClientActiveTexture(unitnum);
1122 qglTexCoordPointer(unit->arraycomponents, GL_FLOAT, sizeof(float) * unit->arraycomponents, unit->pointer_texcoord);CHECKGLERROR
1124 // texture array unit is enabled, enable the array
1125 if (!unit->arrayenabled)
1127 unit->arrayenabled = true;
1128 GL_ClientActiveTexture(unitnum);
1129 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1134 // texture array unit is disabled, disable the array
1135 if (unit->arrayenabled)
1137 unit->arrayenabled = false;
1138 GL_ClientActiveTexture(unitnum);
1139 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1144 void R_Mesh_TexBindAll(unsigned int unitnum, int tex1d, int tex2d, int tex3d, int texcubemap)
1146 gltextureunit_t *unit = gl_state.units + unitnum;
1147 if (unitnum >= backendimageunits)
1149 // update 1d texture binding
1150 if (unit->t1d != tex1d)
1152 GL_ActiveTexture(unitnum);
1153 if (unitnum < backendunits)
1159 qglEnable(GL_TEXTURE_1D);CHECKGLERROR
1166 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1171 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1173 // update 2d texture binding
1174 if (unit->t2d != tex2d)
1176 GL_ActiveTexture(unitnum);
1177 if (unitnum < backendunits)
1183 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
1190 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1195 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1197 // update 3d texture binding
1198 if (unit->t3d != tex3d)
1200 GL_ActiveTexture(unitnum);
1201 if (unitnum < backendunits)
1207 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
1214 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1219 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1221 // update cubemap texture binding
1222 if (unit->tcubemap != texcubemap)
1224 GL_ActiveTexture(unitnum);
1225 if (unitnum < backendunits)
1229 if (unit->tcubemap == 0)
1231 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1238 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1242 unit->tcubemap = texcubemap;
1243 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1247 void R_Mesh_TexBind1D(unsigned int unitnum, int texnum)
1249 gltextureunit_t *unit = gl_state.units + unitnum;
1250 if (unitnum >= backendimageunits)
1252 // update 1d texture binding
1253 if (unit->t1d != texnum)
1255 GL_ActiveTexture(unitnum);
1256 if (unitnum < backendunits)
1262 qglEnable(GL_TEXTURE_1D);CHECKGLERROR
1269 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1274 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1276 // update 2d texture binding
1279 GL_ActiveTexture(unitnum);
1280 if (unitnum < backendunits)
1284 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1288 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1290 // update 3d texture binding
1293 GL_ActiveTexture(unitnum);
1294 if (unitnum < backendunits)
1298 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1302 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1304 // update cubemap texture binding
1307 GL_ActiveTexture(unitnum);
1308 if (unitnum < backendunits)
1312 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1316 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1320 void R_Mesh_TexBind(unsigned int unitnum, int texnum)
1322 gltextureunit_t *unit = gl_state.units + unitnum;
1323 if (unitnum >= backendimageunits)
1325 // update 1d texture binding
1328 GL_ActiveTexture(unitnum);
1329 if (unitnum < backendunits)
1333 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1337 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1339 // update 2d texture binding
1340 if (unit->t2d != texnum)
1342 GL_ActiveTexture(unitnum);
1343 if (unitnum < backendunits)
1349 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
1356 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1361 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1363 // update 3d texture binding
1366 GL_ActiveTexture(unitnum);
1367 if (unitnum < backendunits)
1371 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1375 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1377 // update cubemap texture binding
1378 if (unit->tcubemap != 0)
1380 GL_ActiveTexture(unitnum);
1381 if (unitnum < backendunits)
1385 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1389 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1393 void R_Mesh_TexBind3D(unsigned int unitnum, int texnum)
1395 gltextureunit_t *unit = gl_state.units + unitnum;
1396 if (unitnum >= backendimageunits)
1398 // update 1d texture binding
1401 GL_ActiveTexture(unitnum);
1402 if (unitnum < backendunits)
1406 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1410 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1412 // update 2d texture binding
1415 GL_ActiveTexture(unitnum);
1416 if (unitnum < backendunits)
1420 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1424 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1426 // update 3d texture binding
1427 if (unit->t3d != texnum)
1429 GL_ActiveTexture(unitnum);
1430 if (unitnum < backendunits)
1436 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
1443 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1448 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1450 // update cubemap texture binding
1451 if (unit->tcubemap != 0)
1453 GL_ActiveTexture(unitnum);
1454 if (unitnum < backendunits)
1458 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1462 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1466 void R_Mesh_TexBindCubeMap(unsigned int unitnum, int texnum)
1468 gltextureunit_t *unit = gl_state.units + unitnum;
1469 if (unitnum >= backendimageunits)
1471 // update 1d texture binding
1474 GL_ActiveTexture(unitnum);
1475 if (unitnum < backendunits)
1479 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1483 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1485 // update 2d texture binding
1488 GL_ActiveTexture(unitnum);
1489 if (unitnum < backendunits)
1493 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1497 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1499 // update 3d texture binding
1502 GL_ActiveTexture(unitnum);
1503 if (unitnum < backendunits)
1507 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1511 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1513 // update cubemap texture binding
1514 if (unit->tcubemap != texnum)
1516 GL_ActiveTexture(unitnum);
1517 if (unitnum < backendunits)
1521 if (unit->tcubemap == 0)
1523 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1530 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1534 unit->tcubemap = texnum;
1535 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1539 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
1541 gltextureunit_t *unit = gl_state.units + unitnum;
1542 if (matrix->m[3][3])
1544 // texmatrix specified, check if it is different
1545 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
1547 double glmatrix[16];
1548 unit->texmatrixenabled = true;
1549 unit->matrix = *matrix;
1551 Matrix4x4_ToArrayDoubleGL(&unit->matrix, glmatrix);
1552 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1553 GL_ActiveTexture(unitnum);
1554 qglLoadMatrixd(glmatrix);CHECKGLERROR
1555 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1560 // no texmatrix specified, revert to identity
1561 if (unit->texmatrixenabled)
1563 unit->texmatrixenabled = false;
1565 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1566 GL_ActiveTexture(unitnum);
1567 qglLoadIdentity();CHECKGLERROR
1568 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1573 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
1575 gltextureunit_t *unit = gl_state.units + unitnum;
1577 if (gl_combine.integer)
1579 // GL_ARB_texture_env_combine
1581 combinergb = GL_MODULATE;
1583 combinealpha = GL_MODULATE;
1588 if (unit->combinergb != combinergb)
1590 unit->combinergb = combinergb;
1591 GL_ActiveTexture(unitnum);
1592 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1594 if (unit->combinealpha != combinealpha)
1596 unit->combinealpha = combinealpha;
1597 GL_ActiveTexture(unitnum);
1598 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1600 if (unit->rgbscale != rgbscale)
1602 GL_ActiveTexture(unitnum);
1603 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = rgbscale));CHECKGLERROR
1605 if (unit->alphascale != alphascale)
1607 GL_ActiveTexture(unitnum);
1608 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = alphascale));CHECKGLERROR
1615 combinergb = GL_MODULATE;
1616 if (unit->combinergb != combinergb)
1618 unit->combinergb = combinergb;
1619 GL_ActiveTexture(unitnum);
1620 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
1625 void R_Mesh_TextureState(const rmeshstate_t *m)
1632 if (gl_backend_rebindtextures)
1634 gl_backend_rebindtextures = false;
1635 GL_SetupTextureState();
1639 for (i = 0;i < backendimageunits;i++)
1640 R_Mesh_TexBindAll(i, m->tex1d[i], m->tex[i], m->tex3d[i], m->texcubemap[i]);
1641 for (i = 0;i < backendarrayunits;i++)
1643 if (m->pointer_texcoord3f[i])
1644 R_Mesh_TexCoordPointer(i, 3, m->pointer_texcoord3f[i]);
1646 R_Mesh_TexCoordPointer(i, 2, m->pointer_texcoord[i]);
1648 for (i = 0;i < backendunits;i++)
1650 R_Mesh_TexMatrix(i, &m->texmatrix[i]);
1651 R_Mesh_TexCombine(i, m->texcombinergb[i], m->texcombinealpha[i], m->texrgbscale[i], m->texalphascale[i]);
1656 void R_Mesh_ResetTextureState(void)
1658 unsigned int unitnum;
1663 if (gl_backend_rebindtextures)
1665 gl_backend_rebindtextures = false;
1666 GL_SetupTextureState();
1670 for (unitnum = 0;unitnum < backendimageunits;unitnum++)
1672 gltextureunit_t *unit = gl_state.units + unitnum;
1673 // update 1d texture binding
1676 GL_ActiveTexture(unitnum);
1677 if (unitnum < backendunits)
1679 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1682 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1684 // update 2d texture binding
1687 GL_ActiveTexture(unitnum);
1688 if (unitnum < backendunits)
1690 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1693 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1695 // update 3d texture binding
1698 GL_ActiveTexture(unitnum);
1699 if (unitnum < backendunits)
1701 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1704 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1706 // update cubemap texture binding
1709 GL_ActiveTexture(unitnum);
1710 if (unitnum < backendunits)
1712 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1715 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1718 for (unitnum = 0;unitnum < backendarrayunits;unitnum++)
1720 gltextureunit_t *unit = gl_state.units + unitnum;
1721 // texture array unit is disabled, disable the array
1722 if (unit->arrayenabled)
1724 unit->arrayenabled = false;
1725 GL_ClientActiveTexture(unitnum);
1726 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1729 for (unitnum = 0;unitnum < backendunits;unitnum++)
1731 gltextureunit_t *unit = gl_state.units + unitnum;
1732 // no texmatrix specified, revert to identity
1733 if (unit->texmatrixenabled)
1735 unit->texmatrixenabled = false;
1737 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1738 GL_ActiveTexture(unitnum);
1739 qglLoadIdentity();CHECKGLERROR
1740 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1742 if (gl_combine.integer)
1744 // GL_ARB_texture_env_combine
1745 if (unit->combinergb != GL_MODULATE)
1747 unit->combinergb = GL_MODULATE;
1748 GL_ActiveTexture(unitnum);
1749 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1751 if (unit->combinealpha != GL_MODULATE)
1753 unit->combinealpha = GL_MODULATE;
1754 GL_ActiveTexture(unitnum);
1755 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1757 if (unit->rgbscale != 1)
1759 GL_ActiveTexture(unitnum);
1760 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = 1));CHECKGLERROR
1762 if (unit->alphascale != 1)
1764 GL_ActiveTexture(unitnum);
1765 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = 1));CHECKGLERROR
1771 if (unit->combinergb != GL_MODULATE)
1773 unit->combinergb = GL_MODULATE;
1774 GL_ActiveTexture(unitnum);
1775 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
1781 void R_Mesh_Draw_ShowTris(int firstvertex, int numvertices, int numtriangles, const int *elements)
1785 for (;numtriangles;numtriangles--, elements += 3)
1787 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
1788 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
1789 qglArrayElement(elements[2]);qglArrayElement(elements[0]);