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)
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(gl_state.cullface);CHECKGLERROR
610 if (gl_state.cullfaceenable)
612 gl_state.cullfaceenable = false;
613 qglDisable(GL_CULL_FACE);CHECKGLERROR
618 void GL_AlphaTest(int state)
620 if (gl_state.alphatest != state)
622 gl_state.alphatest = state;
624 if (gl_state.alphatest)
626 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
630 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
635 void GL_ColorMask(int r, int g, int b, int a)
637 int state = r*8 + g*4 + b*2 + a*1;
638 if (gl_state.colormask != state)
640 gl_state.colormask = state;
642 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
646 void GL_Color(float cr, float cg, float cb, float ca)
648 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)
650 gl_state.color4f[0] = cr;
651 gl_state.color4f[1] = cg;
652 gl_state.color4f[2] = cb;
653 gl_state.color4f[3] = ca;
655 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
660 void GL_LockArrays(int first, int count)
662 if (gl_state.lockrange_count != count || gl_state.lockrange_first != first)
664 if (gl_state.lockrange_count)
666 gl_state.lockrange_count = 0;
668 qglUnlockArraysEXT();
671 if (count && gl_supportslockarrays && gl_lockarrays.integer && r_render.integer)
673 gl_state.lockrange_first = first;
674 gl_state.lockrange_count = count;
676 qglLockArraysEXT(first, count);
682 void GL_Scissor (int x, int y, int width, int height)
685 qglScissor(x, vid.height - (y + height),width,height);
689 void GL_ScissorTest(int state)
691 if(gl_state.scissortest == state)
695 if((gl_state.scissortest = state))
696 qglEnable(GL_SCISSOR_TEST);
698 qglDisable(GL_SCISSOR_TEST);
702 void GL_Clear(int mask)
705 qglClear(mask);CHECKGLERROR
708 void GL_TransformToScreen(const vec4_t in, vec4_t out)
712 Matrix4x4_Transform4 (&backend_viewmatrix, in, temp);
713 Matrix4x4_Transform4 (&backend_projectmatrix, temp, out);
715 out[0] = r_view.x + (out[0] * iw + 1.0f) * r_view.width * 0.5f;
716 out[1] = r_view.y + r_view.height - (out[1] * iw + 1.0f) * r_view.height * 0.5f;
717 out[2] = r_view.z + (out[2] * iw + 1.0f) * r_view.depth * 0.5f;
720 // called at beginning of frame
721 void R_Mesh_Start(void)
725 if (gl_printcheckerror.integer && !gl_paranoid.integer)
727 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
728 Cvar_SetValueQuick(&gl_paranoid, 1);
730 GL_Backend_ResetState();
733 unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **vertexstrings_list, int fragmentstrings_count, const char **fragmentstrings_list)
735 GLint vertexshadercompiled, fragmentshadercompiled, programlinked;
736 GLuint vertexshaderobject, fragmentshaderobject, programobject = 0;
737 char compilelog[MAX_INPUTLINE];
740 programobject = qglCreateProgramObjectARB();CHECKGLERROR
744 if (developer.integer >= 100)
747 Con_Printf("Compiling shader:\n");
748 if (vertexstrings_count)
750 Con_Printf("------ VERTEX SHADER ------\n");
751 for (i = 0;i < vertexstrings_count;i++)
752 Con_Print(vertexstrings_list[i]);
755 if (fragmentstrings_count)
757 Con_Printf("------ FRAGMENT SHADER ------\n");
758 for (i = 0;i < fragmentstrings_count;i++)
759 Con_Print(fragmentstrings_list[i]);
764 if (vertexstrings_count)
766 vertexshaderobject = qglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);CHECKGLERROR
767 if (!vertexshaderobject)
769 qglDeleteObjectARB(programobject);
773 qglShaderSourceARB(vertexshaderobject, vertexstrings_count, vertexstrings_list, NULL);CHECKGLERROR
774 qglCompileShaderARB(vertexshaderobject);CHECKGLERROR
775 qglGetObjectParameterivARB(vertexshaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &vertexshadercompiled);CHECKGLERROR
776 qglGetInfoLogARB(vertexshaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
778 Con_DPrintf("vertex shader compile log:\n%s\n", compilelog);
779 if (!vertexshadercompiled)
781 qglDeleteObjectARB(programobject);CHECKGLERROR
782 qglDeleteObjectARB(vertexshaderobject);CHECKGLERROR
785 qglAttachObjectARB(programobject, vertexshaderobject);CHECKGLERROR
786 qglDeleteObjectARB(vertexshaderobject);CHECKGLERROR
789 if (fragmentstrings_count)
791 fragmentshaderobject = qglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);CHECKGLERROR
792 if (!fragmentshaderobject)
794 qglDeleteObjectARB(programobject);CHECKGLERROR
797 qglShaderSourceARB(fragmentshaderobject, fragmentstrings_count, fragmentstrings_list, NULL);CHECKGLERROR
798 qglCompileShaderARB(fragmentshaderobject);CHECKGLERROR
799 qglGetObjectParameterivARB(fragmentshaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &fragmentshadercompiled);CHECKGLERROR
800 qglGetInfoLogARB(fragmentshaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
802 Con_DPrintf("fragment shader compile log:\n%s\n", compilelog);
803 if (!fragmentshadercompiled)
805 qglDeleteObjectARB(programobject);CHECKGLERROR
806 qglDeleteObjectARB(fragmentshaderobject);CHECKGLERROR
809 qglAttachObjectARB(programobject, fragmentshaderobject);CHECKGLERROR
810 qglDeleteObjectARB(fragmentshaderobject);CHECKGLERROR
813 qglLinkProgramARB(programobject);CHECKGLERROR
814 qglGetObjectParameterivARB(programobject, GL_OBJECT_LINK_STATUS_ARB, &programlinked);CHECKGLERROR
815 qglGetInfoLogARB(programobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
818 Con_DPrintf("program link log:\n%s\n", compilelog);
819 // software vertex shader is ok but software fragment shader is WAY
820 // too slow, fail program if so.
821 // NOTE: this string might be ATI specific, but that's ok because the
822 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
823 // software fragment shader due to low instruction and dependent
825 if (strstr(compilelog, "fragment shader will run in software"))
826 programlinked = false;
830 qglDeleteObjectARB(programobject);CHECKGLERROR
834 return programobject;
837 void GL_Backend_FreeProgram(unsigned int prog)
840 qglDeleteObjectARB(prog);
844 int gl_backend_rebindtextures;
846 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
851 for (i = 0;i < count;i++)
852 *out++ = *in++ + offset;
855 memcpy(out, in, sizeof(*out) * count);
858 // renders triangles using vertices from the active arrays
859 int paranoidblah = 0;
860 void R_Mesh_Draw(int firstvertex, int numvertices, int numtriangles, const int *elements)
862 unsigned int numelements = numtriangles * 3;
863 if (numvertices < 3 || numtriangles < 1)
865 Con_Printf("R_Mesh_Draw(%d, %d, %d, %8p);\n", firstvertex, numvertices, numtriangles, elements);
869 r_refdef.stats.meshes++;
870 r_refdef.stats.meshes_elements += numelements;
871 if (gl_paranoid.integer)
873 unsigned int i, j, size;
875 if (!qglIsEnabled(GL_VERTEX_ARRAY))
876 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
878 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
880 if (gl_state.pointer_color)
882 if (!qglIsEnabled(GL_COLOR_ARRAY))
883 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
885 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
888 for (i = 0;i < backendarrayunits;i++)
890 if (gl_state.units[i].arrayenabled)
892 GL_ClientActiveTexture(i);
893 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
894 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
896 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++)
900 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
902 if (elements[i] < firstvertex || elements[i] >= firstvertex + numvertices)
904 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in elements list\n", elements[i], firstvertex, firstvertex + numvertices);
910 if (r_render.integer)
913 if (gl_mesh_testmanualfeeding.integer)
917 qglBegin(GL_TRIANGLES);
918 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
920 for (j = 0;j < backendarrayunits;j++)
922 if (gl_state.units[j].pointer_texcoord)
924 if (backendarrayunits > 1)
926 if (gl_state.units[j].arraycomponents == 4)
928 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
929 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
931 else if (gl_state.units[j].arraycomponents == 3)
933 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
934 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
936 else if (gl_state.units[j].arraycomponents == 2)
938 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
939 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
943 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
944 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
949 if (gl_state.units[j].arraycomponents == 4)
951 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
952 qglTexCoord4f(p[0], p[1], p[2], p[3]);
954 else if (gl_state.units[j].arraycomponents == 3)
956 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
957 qglTexCoord3f(p[0], p[1], p[2]);
959 else if (gl_state.units[j].arraycomponents == 2)
961 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
962 qglTexCoord2f(p[0], p[1]);
966 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
972 if (gl_state.pointer_color)
974 p = ((const GLfloat *)(gl_state.pointer_color)) + elements[i] * 4;
975 qglColor4f(p[0], p[1], p[2], p[3]);
977 p = ((const GLfloat *)(gl_state.pointer_vertex)) + elements[i] * 3;
978 qglVertex3f(p[0], p[1], p[2]);
983 else if (gl_mesh_testarrayelement.integer)
986 qglBegin(GL_TRIANGLES);
987 for (i = 0;i < numtriangles * 3;i++)
989 qglArrayElement(elements[i]);
994 else if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
996 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_INT, elements);
1001 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, elements);
1007 // restores backend state, used when done with 3D rendering
1008 void R_Mesh_Finish(void)
1013 GL_LockArrays(0, 0);
1016 for (i = 0;i < backendimageunits;i++)
1018 GL_ActiveTexture(i);
1019 qglBindTexture(GL_TEXTURE_1D, 0);CHECKGLERROR
1020 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1023 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1025 if (gl_texturecubemap)
1027 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1030 for (i = 0;i < backendarrayunits;i++)
1032 GL_ActiveTexture(backendarrayunits - 1 - i);
1033 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1035 for (i = 0;i < backendunits;i++)
1037 GL_ActiveTexture(backendunits - 1 - i);
1038 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1039 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1042 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1044 if (gl_texturecubemap)
1046 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1048 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1049 if (gl_combine.integer)
1051 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
1052 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
1055 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1056 qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1058 qglDisable(GL_BLEND);CHECKGLERROR
1059 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1060 qglDepthMask(GL_TRUE);CHECKGLERROR
1061 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);CHECKGLERROR
1064 void R_Mesh_Matrix(const matrix4x4_t *matrix)
1066 if (memcmp(matrix, &backend_modelmatrix, sizeof(matrix4x4_t)))
1068 double glmatrix[16];
1069 backend_modelmatrix = *matrix;
1070 Matrix4x4_Concat(&backend_modelviewmatrix, &backend_viewmatrix, matrix);
1071 Matrix4x4_ToArrayDoubleGL(&backend_modelviewmatrix, glmatrix);
1073 qglLoadMatrixd(glmatrix);CHECKGLERROR
1077 void R_Mesh_VertexPointer(const float *vertex3f)
1079 if (gl_state.pointer_vertex != vertex3f)
1081 gl_state.pointer_vertex = vertex3f;
1083 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), gl_state.pointer_vertex);
1088 void R_Mesh_ColorPointer(const float *color4f)
1090 if (gl_state.pointer_color != color4f)
1093 if (!gl_state.pointer_color)
1095 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1099 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1100 // when color array is on the glColor gets trashed, set it again
1101 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
1103 gl_state.pointer_color = color4f;
1104 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), gl_state.pointer_color);CHECKGLERROR
1108 void R_Mesh_TexCoordPointer(unsigned int unitnum, unsigned int numcomponents, const float *texcoord)
1110 gltextureunit_t *unit = gl_state.units + unitnum;
1111 // update array settings
1116 if (unit->pointer_texcoord != texcoord || unit->arraycomponents != numcomponents)
1118 unit->pointer_texcoord = texcoord;
1119 unit->arraycomponents = numcomponents;
1120 GL_ClientActiveTexture(unitnum);
1121 qglTexCoordPointer(unit->arraycomponents, GL_FLOAT, sizeof(float) * unit->arraycomponents, unit->pointer_texcoord);CHECKGLERROR
1123 // texture array unit is enabled, enable the array
1124 if (!unit->arrayenabled)
1126 unit->arrayenabled = true;
1127 GL_ClientActiveTexture(unitnum);
1128 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1133 // texture array unit is disabled, disable the array
1134 if (unit->arrayenabled)
1136 unit->arrayenabled = false;
1137 GL_ClientActiveTexture(unitnum);
1138 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1143 void R_Mesh_TexBindAll(unsigned int unitnum, int tex1d, int tex2d, int tex3d, int texcubemap)
1145 gltextureunit_t *unit = gl_state.units + unitnum;
1146 if (unitnum >= backendimageunits)
1148 // update 1d texture binding
1149 if (unit->t1d != tex1d)
1151 GL_ActiveTexture(unitnum);
1152 if (unitnum < backendunits)
1158 qglEnable(GL_TEXTURE_1D);CHECKGLERROR
1165 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1170 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1172 // update 2d texture binding
1173 if (unit->t2d != tex2d)
1175 GL_ActiveTexture(unitnum);
1176 if (unitnum < backendunits)
1182 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
1189 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1194 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1196 // update 3d texture binding
1197 if (unit->t3d != tex3d)
1199 GL_ActiveTexture(unitnum);
1200 if (unitnum < backendunits)
1206 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
1213 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1218 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1220 // update cubemap texture binding
1221 if (unit->tcubemap != texcubemap)
1223 GL_ActiveTexture(unitnum);
1224 if (unitnum < backendunits)
1228 if (unit->tcubemap == 0)
1230 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1237 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1241 unit->tcubemap = texcubemap;
1242 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1246 void R_Mesh_TexBind1D(unsigned int unitnum, int texnum)
1248 gltextureunit_t *unit = gl_state.units + unitnum;
1249 if (unitnum >= backendimageunits)
1251 // update 1d texture binding
1252 if (unit->t1d != texnum)
1254 GL_ActiveTexture(unitnum);
1255 if (unitnum < backendunits)
1261 qglEnable(GL_TEXTURE_1D);CHECKGLERROR
1268 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1273 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1275 // update 2d texture binding
1278 GL_ActiveTexture(unitnum);
1279 if (unitnum < backendunits)
1283 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1287 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1289 // update 3d texture binding
1292 GL_ActiveTexture(unitnum);
1293 if (unitnum < backendunits)
1297 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1301 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1303 // update cubemap texture binding
1306 GL_ActiveTexture(unitnum);
1307 if (unitnum < backendunits)
1311 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1315 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1319 void R_Mesh_TexBind(unsigned int unitnum, int texnum)
1321 gltextureunit_t *unit = gl_state.units + unitnum;
1322 if (unitnum >= backendimageunits)
1324 // update 1d texture binding
1327 GL_ActiveTexture(unitnum);
1328 if (unitnum < backendunits)
1332 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1336 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1338 // update 2d texture binding
1339 if (unit->t2d != texnum)
1341 GL_ActiveTexture(unitnum);
1342 if (unitnum < backendunits)
1348 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
1355 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1360 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1362 // update 3d texture binding
1365 GL_ActiveTexture(unitnum);
1366 if (unitnum < backendunits)
1370 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1374 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1376 // update cubemap texture binding
1377 if (unit->tcubemap != 0)
1379 GL_ActiveTexture(unitnum);
1380 if (unitnum < backendunits)
1384 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1388 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1392 void R_Mesh_TexBind3D(unsigned int unitnum, int texnum)
1394 gltextureunit_t *unit = gl_state.units + unitnum;
1395 if (unitnum >= backendimageunits)
1397 // update 1d texture binding
1400 GL_ActiveTexture(unitnum);
1401 if (unitnum < backendunits)
1405 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1409 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1411 // update 2d texture binding
1414 GL_ActiveTexture(unitnum);
1415 if (unitnum < backendunits)
1419 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1423 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1425 // update 3d texture binding
1426 if (unit->t3d != texnum)
1428 GL_ActiveTexture(unitnum);
1429 if (unitnum < backendunits)
1435 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
1442 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1447 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1449 // update cubemap texture binding
1450 if (unit->tcubemap != 0)
1452 GL_ActiveTexture(unitnum);
1453 if (unitnum < backendunits)
1457 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1461 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1465 void R_Mesh_TexBindCubeMap(unsigned int unitnum, int texnum)
1467 gltextureunit_t *unit = gl_state.units + unitnum;
1468 if (unitnum >= backendimageunits)
1470 // update 1d texture binding
1473 GL_ActiveTexture(unitnum);
1474 if (unitnum < backendunits)
1478 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1482 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1484 // update 2d texture binding
1487 GL_ActiveTexture(unitnum);
1488 if (unitnum < backendunits)
1492 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1496 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1498 // update 3d texture binding
1501 GL_ActiveTexture(unitnum);
1502 if (unitnum < backendunits)
1506 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1510 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1512 // update cubemap texture binding
1513 if (unit->tcubemap != texnum)
1515 GL_ActiveTexture(unitnum);
1516 if (unitnum < backendunits)
1520 if (unit->tcubemap == 0)
1522 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1529 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1533 unit->tcubemap = texnum;
1534 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1538 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
1540 gltextureunit_t *unit = gl_state.units + unitnum;
1541 if (matrix->m[3][3])
1543 // texmatrix specified, check if it is different
1544 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
1546 double glmatrix[16];
1547 unit->texmatrixenabled = true;
1548 unit->matrix = *matrix;
1550 Matrix4x4_ToArrayDoubleGL(&unit->matrix, glmatrix);
1551 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1552 GL_ActiveTexture(unitnum);
1553 qglLoadMatrixd(glmatrix);CHECKGLERROR
1554 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1559 // no texmatrix specified, revert to identity
1560 if (unit->texmatrixenabled)
1562 unit->texmatrixenabled = false;
1564 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1565 GL_ActiveTexture(unitnum);
1566 qglLoadIdentity();CHECKGLERROR
1567 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1572 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
1574 gltextureunit_t *unit = gl_state.units + unitnum;
1576 if (gl_combine.integer)
1578 // GL_ARB_texture_env_combine
1580 combinergb = GL_MODULATE;
1582 combinealpha = GL_MODULATE;
1587 if (unit->combinergb != combinergb)
1589 unit->combinergb = combinergb;
1590 GL_ActiveTexture(unitnum);
1591 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1593 if (unit->combinealpha != combinealpha)
1595 unit->combinealpha = combinealpha;
1596 GL_ActiveTexture(unitnum);
1597 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1599 if (unit->rgbscale != rgbscale)
1601 GL_ActiveTexture(unitnum);
1602 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = rgbscale));CHECKGLERROR
1604 if (unit->alphascale != alphascale)
1606 GL_ActiveTexture(unitnum);
1607 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = alphascale));CHECKGLERROR
1614 combinergb = GL_MODULATE;
1615 if (unit->combinergb != combinergb)
1617 unit->combinergb = combinergb;
1618 GL_ActiveTexture(unitnum);
1619 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
1624 void R_Mesh_TextureState(const rmeshstate_t *m)
1631 if (gl_backend_rebindtextures)
1633 gl_backend_rebindtextures = false;
1634 GL_SetupTextureState();
1638 for (i = 0;i < backendimageunits;i++)
1639 R_Mesh_TexBindAll(i, m->tex1d[i], m->tex[i], m->tex3d[i], m->texcubemap[i]);
1640 for (i = 0;i < backendarrayunits;i++)
1642 if (m->pointer_texcoord3f[i])
1643 R_Mesh_TexCoordPointer(i, 3, m->pointer_texcoord3f[i]);
1645 R_Mesh_TexCoordPointer(i, 2, m->pointer_texcoord[i]);
1647 for (i = 0;i < backendunits;i++)
1649 R_Mesh_TexMatrix(i, &m->texmatrix[i]);
1650 R_Mesh_TexCombine(i, m->texcombinergb[i], m->texcombinealpha[i], m->texrgbscale[i], m->texalphascale[i]);
1655 void R_Mesh_ResetTextureState(void)
1657 unsigned int unitnum;
1662 if (gl_backend_rebindtextures)
1664 gl_backend_rebindtextures = false;
1665 GL_SetupTextureState();
1669 for (unitnum = 0;unitnum < backendimageunits;unitnum++)
1671 gltextureunit_t *unit = gl_state.units + unitnum;
1672 // update 1d texture binding
1675 GL_ActiveTexture(unitnum);
1676 if (unitnum < backendunits)
1678 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1681 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1683 // update 2d texture binding
1686 GL_ActiveTexture(unitnum);
1687 if (unitnum < backendunits)
1689 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1692 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1694 // update 3d texture binding
1697 GL_ActiveTexture(unitnum);
1698 if (unitnum < backendunits)
1700 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1703 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1705 // update cubemap texture binding
1708 GL_ActiveTexture(unitnum);
1709 if (unitnum < backendunits)
1711 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1714 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1717 for (unitnum = 0;unitnum < backendarrayunits;unitnum++)
1719 gltextureunit_t *unit = gl_state.units + unitnum;
1720 // texture array unit is disabled, disable the array
1721 if (unit->arrayenabled)
1723 unit->arrayenabled = false;
1724 GL_ClientActiveTexture(unitnum);
1725 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1728 for (unitnum = 0;unitnum < backendunits;unitnum++)
1730 gltextureunit_t *unit = gl_state.units + unitnum;
1731 // no texmatrix specified, revert to identity
1732 if (unit->texmatrixenabled)
1734 unit->texmatrixenabled = false;
1736 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1737 GL_ActiveTexture(unitnum);
1738 qglLoadIdentity();CHECKGLERROR
1739 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1741 if (gl_combine.integer)
1743 // GL_ARB_texture_env_combine
1744 if (unit->combinergb != GL_MODULATE)
1746 unit->combinergb = GL_MODULATE;
1747 GL_ActiveTexture(unitnum);
1748 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1750 if (unit->combinealpha != GL_MODULATE)
1752 unit->combinealpha = GL_MODULATE;
1753 GL_ActiveTexture(unitnum);
1754 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1756 if (unit->rgbscale != 1)
1758 GL_ActiveTexture(unitnum);
1759 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = 1));CHECKGLERROR
1761 if (unit->alphascale != 1)
1763 GL_ActiveTexture(unitnum);
1764 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = 1));CHECKGLERROR
1770 if (unit->combinergb != GL_MODULATE)
1772 unit->combinergb = GL_MODULATE;
1773 GL_ActiveTexture(unitnum);
1774 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
1780 void R_Mesh_Draw_ShowTris(int firstvertex, int numvertices, int numtriangles, const int *elements)
1784 for (;numtriangles;numtriangles--, elements += 3)
1786 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
1787 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
1788 qglArrayElement(elements[2]);qglArrayElement(elements[0]);