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 = bound(1, gl_textureunits, MAX_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);
171 backendimageunits = bound(1, backendimageunits, MAX_TEXTUREUNITS);
172 backendarrayunits = bound(1, backendarrayunits, MAX_TEXTUREUNITS);
174 else if (backendunits > 1)
175 Con_Printf("multitexture detected: texture units = %i\n", backendunits);
177 Con_Printf("singletexture\n");
179 GL_Backend_AllocArrays();
181 Con_Printf("OpenGL backend started.\n");
185 backendactive = true;
188 static void gl_backend_shutdown(void)
191 backendimageunits = 0;
192 backendarrayunits = 0;
193 backendactive = false;
195 Con_Print("OpenGL Backend shutting down\n");
197 GL_Backend_FreeArrays();
200 static void gl_backend_newmap(void)
204 void gl_backend_init(void)
208 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
210 polygonelements[i * 3 + 0] = 0;
211 polygonelements[i * 3 + 1] = i + 1;
212 polygonelements[i * 3 + 2] = i + 2;
214 // elements for rendering a series of quads as triangles
215 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
217 quadelements[i * 6 + 0] = i * 4;
218 quadelements[i * 6 + 1] = i * 4 + 1;
219 quadelements[i * 6 + 2] = i * 4 + 2;
220 quadelements[i * 6 + 3] = i * 4;
221 quadelements[i * 6 + 4] = i * 4 + 2;
222 quadelements[i * 6 + 5] = i * 4 + 3;
225 Cvar_RegisterVariable(&r_render);
226 Cvar_RegisterVariable(&r_waterwarp);
227 Cvar_RegisterVariable(&gl_polyblend);
228 Cvar_RegisterVariable(&gl_dither);
229 Cvar_RegisterVariable(&gl_lockarrays);
230 Cvar_RegisterVariable(&gl_paranoid);
231 Cvar_RegisterVariable(&gl_printcheckerror);
233 Cvar_SetValue("r_render", 0);
236 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
237 Cvar_RegisterVariable(&gl_mesh_testarrayelement);
238 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
240 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
243 void GL_SetupView_Orientation_Identity (void)
245 backend_viewmatrix = identitymatrix;
246 memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
249 void GL_SetupView_Orientation_FromEntity(const matrix4x4_t *matrix)
251 matrix4x4_t tempmatrix, basematrix;
252 Matrix4x4_Invert_Simple(&tempmatrix, matrix);
253 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
254 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
255 Matrix4x4_Concat(&backend_viewmatrix, &basematrix, &tempmatrix);
256 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[2], 1, 0, 0);
257 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[0], 0, 1, 0);
258 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[1], 0, 0, 1);
259 //Matrix4x4_ConcatTranslate(&backend_viewmatrix, -origin[0], -origin[1], -origin[2]);
260 memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
263 void GL_SetupView_Mode_Perspective (double frustumx, double frustumy, double zNear, double zFar)
269 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
270 qglLoadIdentity();CHECKGLERROR
272 qglFrustum(-frustumx * zNear, frustumx * zNear, -frustumy * zNear, frustumy * zNear, zNear, zFar);CHECKGLERROR
273 qglGetDoublev(GL_PROJECTION_MATRIX, m);CHECKGLERROR
274 Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
275 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
276 GL_SetupView_Orientation_Identity();
280 void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double frustumx, double frustumy, double zNear)
286 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
287 qglLoadIdentity();CHECKGLERROR
289 nudge = 1.0 - 1.0 / (1<<23);
290 m[ 0] = 1.0 / frustumx;
295 m[ 5] = 1.0 / frustumy;
304 m[14] = -2 * zNear * nudge;
306 qglLoadMatrixd(m);CHECKGLERROR
307 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
308 GL_SetupView_Orientation_Identity();
310 Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
313 void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double zNear, double zFar)
319 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
320 qglLoadIdentity();CHECKGLERROR
321 qglOrtho(x1, x2, y2, y1, zNear, zFar);CHECKGLERROR
322 qglGetDoublev(GL_PROJECTION_MATRIX, m);CHECKGLERROR
323 Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
324 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
325 GL_SetupView_Orientation_Identity();
329 typedef struct gltextureunit_s
331 int t1d, t2d, t3d, tcubemap;
333 unsigned int arraycomponents;
334 const void *pointer_texcoord;
335 int rgbscale, alphascale;
336 int combinergb, combinealpha;
337 // FIXME: add more combine stuff
338 // texmatrixenabled exists only to avoid unnecessary texmatrix compares
339 int texmatrixenabled;
344 static struct gl_state_s
352 int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
357 unsigned int clientunit;
358 gltextureunit_t units[MAX_TEXTUREUNITS];
362 const void *pointer_vertex;
363 const void *pointer_color;
367 void GL_SetupTextureState(void)
370 gltextureunit_t *unit;
372 gl_state.unit = MAX_TEXTUREUNITS;
373 gl_state.clientunit = MAX_TEXTUREUNITS;
374 for (i = 0;i < MAX_TEXTUREUNITS;i++)
376 unit = gl_state.units + i;
381 unit->arrayenabled = false;
382 unit->arraycomponents = 0;
383 unit->pointer_texcoord = NULL;
385 unit->alphascale = 1;
386 unit->combinergb = GL_MODULATE;
387 unit->combinealpha = GL_MODULATE;
388 unit->texmatrixenabled = false;
389 unit->matrix = identitymatrix;
392 for (i = 0;i < backendimageunits;i++)
395 qglBindTexture(GL_TEXTURE_1D, 0);CHECKGLERROR
396 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
399 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
401 if (gl_texturecubemap)
403 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
407 for (i = 0;i < backendarrayunits;i++)
409 GL_ClientActiveTexture(i);
410 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
411 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
414 for (i = 0;i < backendunits;i++)
417 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
418 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
421 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
423 if (gl_texturecubemap)
425 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
427 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
428 qglLoadIdentity();CHECKGLERROR
429 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
430 if (gl_combine.integer)
432 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
433 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);CHECKGLERROR
434 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);CHECKGLERROR
435 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
436 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
437 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
438 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
439 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);CHECKGLERROR
440 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);CHECKGLERROR
441 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);CHECKGLERROR
442 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
443 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);CHECKGLERROR
444 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
445 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
446 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
447 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
448 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
452 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
459 void GL_Backend_ResetState(void)
461 memset(&gl_state, 0, sizeof(gl_state));
462 gl_state.depthtest = true;
463 gl_state.alphatest = false;
464 gl_state.blendfunc1 = GL_ONE;
465 gl_state.blendfunc2 = GL_ZERO;
466 gl_state.blend = false;
467 gl_state.depthmask = GL_TRUE;
468 gl_state.colormask = 15;
469 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
470 gl_state.lockrange_first = 0;
471 gl_state.lockrange_count = 0;
472 gl_state.pointer_vertex = NULL;
473 gl_state.pointer_color = NULL;
474 gl_state.cullface = GL_FRONT; // quake is backwards, this culls back faces
475 gl_state.cullfaceenable = true;
479 qglColorMask(1, 1, 1, 1);
480 qglAlphaFunc(GL_GEQUAL, 0.5);CHECKGLERROR
481 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
482 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
483 qglDisable(GL_BLEND);CHECKGLERROR
484 qglCullFace(gl_state.cullface);CHECKGLERROR
485 qglEnable(GL_CULL_FACE);CHECKGLERROR
486 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
487 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
488 qglDepthMask(gl_state.depthmask);CHECKGLERROR
490 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
491 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
493 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
494 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
496 GL_Color(0, 0, 0, 0);
497 GL_Color(1, 1, 1, 1);
499 GL_SetupTextureState();
502 void GL_ActiveTexture(unsigned int num)
504 if (gl_state.unit != num)
507 if (qglActiveTexture)
510 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
516 void GL_ClientActiveTexture(unsigned int num)
518 if (gl_state.clientunit != num)
520 gl_state.clientunit = num;
521 if (qglActiveTexture)
524 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
530 void GL_BlendFunc(int blendfunc1, int blendfunc2)
532 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
535 qglBlendFunc(gl_state.blendfunc1 = blendfunc1, gl_state.blendfunc2 = blendfunc2);CHECKGLERROR
536 if (gl_state.blendfunc2 == GL_ZERO)
538 if (gl_state.blendfunc1 == GL_ONE)
543 qglDisable(GL_BLEND);CHECKGLERROR
551 qglEnable(GL_BLEND);CHECKGLERROR
560 qglEnable(GL_BLEND);CHECKGLERROR
566 void GL_DepthMask(int state)
568 if (gl_state.depthmask != state)
571 qglDepthMask(gl_state.depthmask = state);CHECKGLERROR
575 void GL_DepthTest(int state)
577 if (gl_state.depthtest != state)
579 gl_state.depthtest = state;
581 if (gl_state.depthtest)
583 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
587 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
592 void GL_CullFace(int state)
594 if (gl_state.cullface != state)
597 if (state != GL_NONE)
599 if (!gl_state.cullfaceenable)
601 gl_state.cullfaceenable = true;
602 qglEnable(GL_CULL_FACE);CHECKGLERROR
604 if (gl_state.cullface != state)
606 gl_state.cullface = state;
607 qglCullFace(state);CHECKGLERROR
612 if (gl_state.cullfaceenable)
614 gl_state.cullfaceenable = false;
615 qglDisable(GL_CULL_FACE);CHECKGLERROR
621 void GL_AlphaTest(int state)
623 if (gl_state.alphatest != state)
625 gl_state.alphatest = state;
627 if (gl_state.alphatest)
629 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
633 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
638 void GL_ColorMask(int r, int g, int b, int a)
640 int state = r*8 + g*4 + b*2 + a*1;
641 if (gl_state.colormask != state)
643 gl_state.colormask = state;
645 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
649 void GL_Color(float cr, float cg, float cb, float ca)
651 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)
653 gl_state.color4f[0] = cr;
654 gl_state.color4f[1] = cg;
655 gl_state.color4f[2] = cb;
656 gl_state.color4f[3] = ca;
658 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
663 void GL_LockArrays(int first, int count)
665 if (gl_state.lockrange_count != count || gl_state.lockrange_first != first)
667 if (gl_state.lockrange_count)
669 gl_state.lockrange_count = 0;
671 qglUnlockArraysEXT();
674 if (count && gl_supportslockarrays && gl_lockarrays.integer && r_render.integer)
676 gl_state.lockrange_first = first;
677 gl_state.lockrange_count = count;
679 qglLockArraysEXT(first, count);
685 void GL_Scissor (int x, int y, int width, int height)
688 qglScissor(x, vid.height - (y + height),width,height);
692 void GL_ScissorTest(int state)
694 if(gl_state.scissortest == state)
698 if((gl_state.scissortest = state))
699 qglEnable(GL_SCISSOR_TEST);
701 qglDisable(GL_SCISSOR_TEST);
705 void GL_Clear(int mask)
708 qglClear(mask);CHECKGLERROR
711 void GL_TransformToScreen(const vec4_t in, vec4_t out)
715 Matrix4x4_Transform4 (&backend_viewmatrix, in, temp);
716 Matrix4x4_Transform4 (&backend_projectmatrix, temp, out);
718 out[0] = r_view.x + (out[0] * iw + 1.0f) * r_view.width * 0.5f;
719 out[1] = r_view.y + r_view.height - (out[1] * iw + 1.0f) * r_view.height * 0.5f;
720 out[2] = r_view.z + (out[2] * iw + 1.0f) * r_view.depth * 0.5f;
723 // called at beginning of frame
724 void R_Mesh_Start(void)
728 if (gl_printcheckerror.integer && !gl_paranoid.integer)
730 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
731 Cvar_SetValueQuick(&gl_paranoid, 1);
733 GL_Backend_ResetState();
736 unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **vertexstrings_list, int fragmentstrings_count, const char **fragmentstrings_list)
738 GLint vertexshadercompiled, fragmentshadercompiled, programlinked;
739 GLuint vertexshaderobject, fragmentshaderobject, programobject = 0;
740 char compilelog[MAX_INPUTLINE];
743 programobject = qglCreateProgramObjectARB();CHECKGLERROR
747 if (developer.integer >= 100)
750 Con_Printf("Compiling shader:\n");
751 if (vertexstrings_count)
753 Con_Printf("------ VERTEX SHADER ------\n");
754 for (i = 0;i < vertexstrings_count;i++)
755 Con_Print(vertexstrings_list[i]);
758 if (fragmentstrings_count)
760 Con_Printf("------ FRAGMENT SHADER ------\n");
761 for (i = 0;i < fragmentstrings_count;i++)
762 Con_Print(fragmentstrings_list[i]);
767 if (vertexstrings_count)
769 vertexshaderobject = qglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);CHECKGLERROR
770 if (!vertexshaderobject)
772 qglDeleteObjectARB(programobject);
776 qglShaderSourceARB(vertexshaderobject, vertexstrings_count, vertexstrings_list, NULL);CHECKGLERROR
777 qglCompileShaderARB(vertexshaderobject);CHECKGLERROR
778 qglGetObjectParameterivARB(vertexshaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &vertexshadercompiled);CHECKGLERROR
779 qglGetInfoLogARB(vertexshaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
781 Con_DPrintf("vertex shader compile log:\n%s\n", compilelog);
782 if (!vertexshadercompiled)
784 qglDeleteObjectARB(programobject);CHECKGLERROR
785 qglDeleteObjectARB(vertexshaderobject);CHECKGLERROR
788 qglAttachObjectARB(programobject, vertexshaderobject);CHECKGLERROR
789 qglDeleteObjectARB(vertexshaderobject);CHECKGLERROR
792 if (fragmentstrings_count)
794 fragmentshaderobject = qglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);CHECKGLERROR
795 if (!fragmentshaderobject)
797 qglDeleteObjectARB(programobject);CHECKGLERROR
800 qglShaderSourceARB(fragmentshaderobject, fragmentstrings_count, fragmentstrings_list, NULL);CHECKGLERROR
801 qglCompileShaderARB(fragmentshaderobject);CHECKGLERROR
802 qglGetObjectParameterivARB(fragmentshaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &fragmentshadercompiled);CHECKGLERROR
803 qglGetInfoLogARB(fragmentshaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
805 Con_DPrintf("fragment shader compile log:\n%s\n", compilelog);
806 if (!fragmentshadercompiled)
808 qglDeleteObjectARB(programobject);CHECKGLERROR
809 qglDeleteObjectARB(fragmentshaderobject);CHECKGLERROR
812 qglAttachObjectARB(programobject, fragmentshaderobject);CHECKGLERROR
813 qglDeleteObjectARB(fragmentshaderobject);CHECKGLERROR
816 qglLinkProgramARB(programobject);CHECKGLERROR
817 qglGetObjectParameterivARB(programobject, GL_OBJECT_LINK_STATUS_ARB, &programlinked);CHECKGLERROR
818 qglGetInfoLogARB(programobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
821 Con_DPrintf("program link log:\n%s\n", compilelog);
822 // software vertex shader is ok but software fragment shader is WAY
823 // too slow, fail program if so.
824 // NOTE: this string might be ATI specific, but that's ok because the
825 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
826 // software fragment shader due to low instruction and dependent
828 if (strstr(compilelog, "fragment shader will run in software"))
829 programlinked = false;
833 qglDeleteObjectARB(programobject);CHECKGLERROR
837 return programobject;
840 void GL_Backend_FreeProgram(unsigned int prog)
843 qglDeleteObjectARB(prog);
847 int gl_backend_rebindtextures;
849 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
854 for (i = 0;i < count;i++)
855 *out++ = *in++ + offset;
858 memcpy(out, in, sizeof(*out) * count);
861 // renders triangles using vertices from the active arrays
862 int paranoidblah = 0;
863 void R_Mesh_Draw(int firstvertex, int numvertices, int numtriangles, const int *elements)
865 unsigned int numelements = numtriangles * 3;
866 if (numvertices < 3 || numtriangles < 1)
868 Con_Printf("R_Mesh_Draw(%d, %d, %d, %08p);\n", firstvertex, numvertices, numtriangles, elements);
872 r_refdef.stats.meshes++;
873 r_refdef.stats.meshes_elements += numelements;
874 if (gl_paranoid.integer)
876 unsigned int i, j, size;
878 if (!qglIsEnabled(GL_VERTEX_ARRAY))
879 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
881 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
883 if (gl_state.pointer_color)
885 if (!qglIsEnabled(GL_COLOR_ARRAY))
886 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
888 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
891 for (i = 0;i < backendarrayunits;i++)
893 if (gl_state.units[i].arrayenabled)
895 GL_ClientActiveTexture(i);
896 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
897 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
899 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++)
903 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
905 if (elements[i] < firstvertex || elements[i] >= firstvertex + numvertices)
907 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in elements list\n", elements[i], firstvertex, firstvertex + numvertices);
913 if (r_render.integer)
916 if (gl_mesh_testmanualfeeding.integer)
920 qglBegin(GL_TRIANGLES);
921 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
923 for (j = 0;j < backendarrayunits;j++)
925 if (gl_state.units[j].pointer_texcoord)
927 if (backendarrayunits > 1)
929 if (gl_state.units[j].arraycomponents == 4)
931 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
932 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
934 else if (gl_state.units[j].arraycomponents == 3)
936 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
937 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
939 else if (gl_state.units[j].arraycomponents == 2)
941 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
942 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
946 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
947 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
952 if (gl_state.units[j].arraycomponents == 4)
954 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
955 qglTexCoord4f(p[0], p[1], p[2], p[3]);
957 else if (gl_state.units[j].arraycomponents == 3)
959 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
960 qglTexCoord3f(p[0], p[1], p[2]);
962 else if (gl_state.units[j].arraycomponents == 2)
964 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
965 qglTexCoord2f(p[0], p[1]);
969 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
975 if (gl_state.pointer_color)
977 p = ((const GLfloat *)(gl_state.pointer_color)) + elements[i] * 4;
978 qglColor4f(p[0], p[1], p[2], p[3]);
980 p = ((const GLfloat *)(gl_state.pointer_vertex)) + elements[i] * 3;
981 qglVertex3f(p[0], p[1], p[2]);
986 else if (gl_mesh_testarrayelement.integer)
989 qglBegin(GL_TRIANGLES);
990 for (i = 0;i < numtriangles * 3;i++)
992 qglArrayElement(elements[i]);
997 else if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
999 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_INT, elements);
1004 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, elements);
1010 // restores backend state, used when done with 3D rendering
1011 void R_Mesh_Finish(void)
1016 GL_LockArrays(0, 0);
1019 for (i = 0;i < backendimageunits;i++)
1021 GL_ActiveTexture(i);
1022 qglBindTexture(GL_TEXTURE_1D, 0);CHECKGLERROR
1023 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1026 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1028 if (gl_texturecubemap)
1030 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1033 for (i = 0;i < backendarrayunits;i++)
1035 GL_ActiveTexture(backendarrayunits - 1 - i);
1036 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1038 for (i = 0;i < backendunits;i++)
1040 GL_ActiveTexture(backendunits - 1 - i);
1041 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1042 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1045 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1047 if (gl_texturecubemap)
1049 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1051 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1052 if (gl_combine.integer)
1054 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
1055 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
1058 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1059 qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1061 qglDisable(GL_BLEND);CHECKGLERROR
1062 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1063 qglDepthMask(GL_TRUE);CHECKGLERROR
1064 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);CHECKGLERROR
1067 void R_Mesh_Matrix(const matrix4x4_t *matrix)
1069 if (memcmp(matrix, &backend_modelmatrix, sizeof(matrix4x4_t)))
1071 double glmatrix[16];
1072 backend_modelmatrix = *matrix;
1073 Matrix4x4_Concat(&backend_modelviewmatrix, &backend_viewmatrix, matrix);
1074 Matrix4x4_ToArrayDoubleGL(&backend_modelviewmatrix, glmatrix);
1076 qglLoadMatrixd(glmatrix);CHECKGLERROR
1080 void R_Mesh_VertexPointer(const float *vertex3f)
1082 if (gl_state.pointer_vertex != vertex3f)
1084 gl_state.pointer_vertex = vertex3f;
1086 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), gl_state.pointer_vertex);
1091 void R_Mesh_ColorPointer(const float *color4f)
1093 if (gl_state.pointer_color != color4f)
1096 if (!gl_state.pointer_color)
1098 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1102 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1103 // when color array is on the glColor gets trashed, set it again
1104 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
1106 gl_state.pointer_color = color4f;
1107 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), gl_state.pointer_color);CHECKGLERROR
1111 void R_Mesh_TexCoordPointer(unsigned int unitnum, unsigned int numcomponents, const float *texcoord)
1113 gltextureunit_t *unit = gl_state.units + unitnum;
1114 // update array settings
1119 if (unit->pointer_texcoord != texcoord || unit->arraycomponents != numcomponents)
1121 unit->pointer_texcoord = texcoord;
1122 unit->arraycomponents = numcomponents;
1123 GL_ClientActiveTexture(unitnum);
1124 qglTexCoordPointer(unit->arraycomponents, GL_FLOAT, sizeof(float) * unit->arraycomponents, unit->pointer_texcoord);CHECKGLERROR
1126 // texture array unit is enabled, enable the array
1127 if (!unit->arrayenabled)
1129 unit->arrayenabled = true;
1130 GL_ClientActiveTexture(unitnum);
1131 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1136 // texture array unit is disabled, disable the array
1137 if (unit->arrayenabled)
1139 unit->arrayenabled = false;
1140 GL_ClientActiveTexture(unitnum);
1141 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1146 void R_Mesh_TexBindAll(unsigned int unitnum, int tex1d, int tex2d, int tex3d, int texcubemap)
1148 gltextureunit_t *unit = gl_state.units + unitnum;
1149 if (unitnum >= backendimageunits)
1151 // update 1d texture binding
1152 if (unit->t1d != tex1d)
1154 GL_ActiveTexture(unitnum);
1155 if (unitnum < backendunits)
1161 qglEnable(GL_TEXTURE_1D);CHECKGLERROR
1168 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1173 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1175 // update 2d texture binding
1176 if (unit->t2d != tex2d)
1178 GL_ActiveTexture(unitnum);
1179 if (unitnum < backendunits)
1185 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
1192 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1197 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1199 // update 3d texture binding
1200 if (unit->t3d != tex3d)
1202 GL_ActiveTexture(unitnum);
1203 if (unitnum < backendunits)
1209 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
1216 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1221 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1223 // update cubemap texture binding
1224 if (unit->tcubemap != texcubemap)
1226 GL_ActiveTexture(unitnum);
1227 if (unitnum < backendunits)
1231 if (unit->tcubemap == 0)
1233 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1240 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1244 unit->tcubemap = texcubemap;
1245 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1249 void R_Mesh_TexBind1D(unsigned int unitnum, int texnum)
1251 gltextureunit_t *unit = gl_state.units + unitnum;
1252 if (unitnum >= backendimageunits)
1254 // update 1d texture binding
1255 if (unit->t1d != texnum)
1257 GL_ActiveTexture(unitnum);
1258 if (unitnum < backendunits)
1264 qglEnable(GL_TEXTURE_1D);CHECKGLERROR
1271 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1276 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1278 // update 2d texture binding
1281 GL_ActiveTexture(unitnum);
1282 if (unitnum < backendunits)
1286 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1290 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1292 // update 3d texture binding
1295 GL_ActiveTexture(unitnum);
1296 if (unitnum < backendunits)
1300 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1304 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1306 // update cubemap texture binding
1309 GL_ActiveTexture(unitnum);
1310 if (unitnum < backendunits)
1314 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1318 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1322 void R_Mesh_TexBind(unsigned int unitnum, int texnum)
1324 gltextureunit_t *unit = gl_state.units + unitnum;
1325 if (unitnum >= backendimageunits)
1327 // update 1d texture binding
1330 GL_ActiveTexture(unitnum);
1331 if (unitnum < backendunits)
1335 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1339 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1341 // update 2d texture binding
1342 if (unit->t2d != texnum)
1344 GL_ActiveTexture(unitnum);
1345 if (unitnum < backendunits)
1351 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
1358 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1363 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1365 // update 3d texture binding
1368 GL_ActiveTexture(unitnum);
1369 if (unitnum < backendunits)
1373 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1377 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1379 // update cubemap texture binding
1380 if (unit->tcubemap != 0)
1382 GL_ActiveTexture(unitnum);
1383 if (unitnum < backendunits)
1387 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1391 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1395 void R_Mesh_TexBind3D(unsigned int unitnum, int texnum)
1397 gltextureunit_t *unit = gl_state.units + unitnum;
1398 if (unitnum >= backendimageunits)
1400 // update 1d texture binding
1403 GL_ActiveTexture(unitnum);
1404 if (unitnum < backendunits)
1408 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1412 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1414 // update 2d texture binding
1417 GL_ActiveTexture(unitnum);
1418 if (unitnum < backendunits)
1422 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1426 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1428 // update 3d texture binding
1429 if (unit->t3d != texnum)
1431 GL_ActiveTexture(unitnum);
1432 if (unitnum < backendunits)
1438 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
1445 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1450 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1452 // update cubemap texture binding
1453 if (unit->tcubemap != 0)
1455 GL_ActiveTexture(unitnum);
1456 if (unitnum < backendunits)
1460 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1464 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1468 void R_Mesh_TexBindCubeMap(unsigned int unitnum, int texnum)
1470 gltextureunit_t *unit = gl_state.units + unitnum;
1471 if (unitnum >= backendimageunits)
1473 // update 1d texture binding
1476 GL_ActiveTexture(unitnum);
1477 if (unitnum < backendunits)
1481 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1485 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1487 // update 2d texture binding
1490 GL_ActiveTexture(unitnum);
1491 if (unitnum < backendunits)
1495 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1499 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1501 // update 3d texture binding
1504 GL_ActiveTexture(unitnum);
1505 if (unitnum < backendunits)
1509 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1513 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1515 // update cubemap texture binding
1516 if (unit->tcubemap != texnum)
1518 GL_ActiveTexture(unitnum);
1519 if (unitnum < backendunits)
1523 if (unit->tcubemap == 0)
1525 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1532 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1536 unit->tcubemap = texnum;
1537 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1541 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
1543 gltextureunit_t *unit = gl_state.units + unitnum;
1544 if (matrix->m[3][3])
1546 // texmatrix specified, check if it is different
1547 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
1549 double glmatrix[16];
1550 unit->texmatrixenabled = true;
1551 unit->matrix = *matrix;
1553 Matrix4x4_ToArrayDoubleGL(&unit->matrix, glmatrix);
1554 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1555 GL_ActiveTexture(unitnum);
1556 qglLoadMatrixd(glmatrix);CHECKGLERROR
1557 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1562 // no texmatrix specified, revert to identity
1563 if (unit->texmatrixenabled)
1565 unit->texmatrixenabled = false;
1567 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1568 GL_ActiveTexture(unitnum);
1569 qglLoadIdentity();CHECKGLERROR
1570 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1575 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
1577 gltextureunit_t *unit = gl_state.units + unitnum;
1579 if (gl_combine.integer)
1581 // GL_ARB_texture_env_combine
1583 combinergb = GL_MODULATE;
1585 combinealpha = GL_MODULATE;
1590 if (unit->combinergb != combinergb)
1592 unit->combinergb = combinergb;
1593 GL_ActiveTexture(unitnum);
1594 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1596 if (unit->combinealpha != combinealpha)
1598 unit->combinealpha = combinealpha;
1599 GL_ActiveTexture(unitnum);
1600 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1602 if (unit->rgbscale != rgbscale)
1604 GL_ActiveTexture(unitnum);
1605 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = rgbscale));CHECKGLERROR
1607 if (unit->alphascale != alphascale)
1609 GL_ActiveTexture(unitnum);
1610 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = alphascale));CHECKGLERROR
1617 combinergb = GL_MODULATE;
1618 if (unit->combinergb != combinergb)
1620 unit->combinergb = combinergb;
1621 GL_ActiveTexture(unitnum);
1622 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
1627 void R_Mesh_TextureState(const rmeshstate_t *m)
1634 if (gl_backend_rebindtextures)
1636 gl_backend_rebindtextures = false;
1637 GL_SetupTextureState();
1641 for (i = 0;i < backendimageunits;i++)
1642 R_Mesh_TexBindAll(i, m->tex1d[i], m->tex[i], m->tex3d[i], m->texcubemap[i]);
1643 for (i = 0;i < backendarrayunits;i++)
1645 if (m->pointer_texcoord3f[i])
1646 R_Mesh_TexCoordPointer(i, 3, m->pointer_texcoord3f[i]);
1648 R_Mesh_TexCoordPointer(i, 2, m->pointer_texcoord[i]);
1650 for (i = 0;i < backendunits;i++)
1652 R_Mesh_TexMatrix(i, &m->texmatrix[i]);
1653 R_Mesh_TexCombine(i, m->texcombinergb[i], m->texcombinealpha[i], m->texrgbscale[i], m->texalphascale[i]);
1658 void R_Mesh_ResetTextureState(void)
1660 unsigned int unitnum;
1665 if (gl_backend_rebindtextures)
1667 gl_backend_rebindtextures = false;
1668 GL_SetupTextureState();
1672 for (unitnum = 0;unitnum < backendimageunits;unitnum++)
1674 gltextureunit_t *unit = gl_state.units + unitnum;
1675 // update 1d texture binding
1678 GL_ActiveTexture(unitnum);
1679 if (unitnum < backendunits)
1681 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1684 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1686 // update 2d texture binding
1689 GL_ActiveTexture(unitnum);
1690 if (unitnum < backendunits)
1692 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1695 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1697 // update 3d texture binding
1700 GL_ActiveTexture(unitnum);
1701 if (unitnum < backendunits)
1703 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1706 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1708 // update cubemap texture binding
1711 GL_ActiveTexture(unitnum);
1712 if (unitnum < backendunits)
1714 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1717 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1720 for (unitnum = 0;unitnum < backendarrayunits;unitnum++)
1722 gltextureunit_t *unit = gl_state.units + unitnum;
1723 // texture array unit is disabled, disable the array
1724 if (unit->arrayenabled)
1726 unit->arrayenabled = false;
1727 GL_ClientActiveTexture(unitnum);
1728 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1731 for (unitnum = 0;unitnum < backendunits;unitnum++)
1733 gltextureunit_t *unit = gl_state.units + unitnum;
1734 // no texmatrix specified, revert to identity
1735 if (unit->texmatrixenabled)
1737 unit->texmatrixenabled = false;
1739 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1740 GL_ActiveTexture(unitnum);
1741 qglLoadIdentity();CHECKGLERROR
1742 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1744 if (gl_combine.integer)
1746 // GL_ARB_texture_env_combine
1747 if (unit->combinergb != GL_MODULATE)
1749 unit->combinergb = GL_MODULATE;
1750 GL_ActiveTexture(unitnum);
1751 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1753 if (unit->combinealpha != GL_MODULATE)
1755 unit->combinealpha = GL_MODULATE;
1756 GL_ActiveTexture(unitnum);
1757 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1759 if (unit->rgbscale != 1)
1761 GL_ActiveTexture(unitnum);
1762 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = 1));CHECKGLERROR
1764 if (unit->alphascale != 1)
1766 GL_ActiveTexture(unitnum);
1767 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = 1));CHECKGLERROR
1773 if (unit->combinergb != GL_MODULATE)
1775 unit->combinergb = GL_MODULATE;
1776 GL_ActiveTexture(unitnum);
1777 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
1783 void R_Mesh_Draw_ShowTris(int firstvertex, int numvertices, int numtriangles, const int *elements)
1787 for (;numtriangles;numtriangles--, elements += 3)
1789 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
1790 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
1791 qglArrayElement(elements[2]);qglArrayElement(elements[0]);