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", "0", "enables use of glLockArraysEXT, may cause glitches with some broken drivers, and may be slower than normal"};
16 cvar_t gl_lockarrays_minimumvertices = {0, "gl_lockarrays_minimumvertices", "1", "minimum number of vertices required for use of glLockArraysEXT, setting this too low may reduce performance"};
17 cvar_t gl_vbo = {0, "gl_vbo", "1", "make use of GL_ARB_vertex_buffer_object extension to store static geometry in video memory for faster rendering"};
19 int gl_maxdrawrangeelementsvertices;
20 int gl_maxdrawrangeelementsindices;
25 void GL_PrintError(int errornumber, char *filename, int linenumber)
29 #ifdef GL_INVALID_ENUM
31 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
34 #ifdef GL_INVALID_VALUE
35 case GL_INVALID_VALUE:
36 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
39 #ifdef GL_INVALID_OPERATION
40 case GL_INVALID_OPERATION:
41 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
44 #ifdef GL_STACK_OVERFLOW
45 case GL_STACK_OVERFLOW:
46 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
49 #ifdef GL_STACK_UNDERFLOW
50 case GL_STACK_UNDERFLOW:
51 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
54 #ifdef GL_OUT_OF_MEMORY
55 case GL_OUT_OF_MEMORY:
56 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
59 #ifdef GL_TABLE_TOO_LARGE
60 case GL_TABLE_TOO_LARGE:
61 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
65 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
71 #define BACKENDACTIVECHECK if (!backendactive) Sys_Error("GL backend function called when backend is not active");
73 void SCR_ScreenShot_f (void);
75 static matrix4x4_t backend_viewmatrix;
76 static matrix4x4_t backend_modelmatrix;
77 static matrix4x4_t backend_modelviewmatrix;
78 static matrix4x4_t backend_projectmatrix;
80 static unsigned int backendunits, backendimageunits, backendarrayunits, backendactive;
83 note: here's strip order for a terrain row:
90 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
92 *elements++ = i + row;
94 *elements++ = i + row + 1;
97 *elements++ = i + row + 1;
100 for (y = 0;y < rows - 1;y++)
102 for (x = 0;x < columns - 1;x++)
105 *elements++ = i + columns;
107 *elements++ = i + columns + 1;
110 *elements++ = i + columns + 1;
121 for (y = 0;y < rows - 1;y++)
123 for (x = 0;x < columns - 1;x++)
127 *elements++ = i + columns;
128 *elements++ = i + columns + 1;
129 *elements++ = i + columns;
130 *elements++ = i + columns + 1;
136 int polygonelements[(POLYGONELEMENTS_MAXPOINTS-2)*3];
137 int quadelements[QUADELEMENTS_MAXQUADS*6];
139 void GL_Backend_AllocArrays(void)
143 void GL_Backend_FreeArrays(void)
147 static void gl_backend_start(void)
149 Con_Print("OpenGL Backend starting...\n");
152 if (qglDrawRangeElements != NULL)
155 qglGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &gl_maxdrawrangeelementsvertices);
157 qglGetIntegerv(GL_MAX_ELEMENTS_INDICES, &gl_maxdrawrangeelementsindices);
159 Con_Printf("glDrawRangeElements detected (max vertices %i, max indices %i)\n", gl_maxdrawrangeelementsvertices, gl_maxdrawrangeelementsindices);
162 backendunits = bound(1, gl_textureunits, MAX_TEXTUREUNITS);
163 backendimageunits = backendunits;
164 backendarrayunits = backendunits;
165 if (gl_support_fragment_shader)
168 qglGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, (int *)&backendimageunits);
170 qglGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, (int *)&backendarrayunits);
172 Con_Printf("GLSL shader support detected: texture units = %i texenv, %i image, %i array\n", backendunits, backendimageunits, backendarrayunits);
173 backendimageunits = bound(1, backendimageunits, MAX_TEXTUREUNITS);
174 backendarrayunits = bound(1, backendarrayunits, MAX_TEXTUREUNITS);
176 else if (backendunits > 1)
177 Con_Printf("multitexture detected: texture units = %i\n", backendunits);
179 Con_Printf("singletexture\n");
181 GL_Backend_AllocArrays();
183 Con_Printf("OpenGL backend started.\n");
187 backendactive = true;
190 static void gl_backend_shutdown(void)
193 backendimageunits = 0;
194 backendarrayunits = 0;
195 backendactive = false;
197 Con_Print("OpenGL Backend shutting down\n");
199 GL_Backend_FreeArrays();
202 static void gl_backend_newmap(void)
206 void gl_backend_init(void)
210 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
212 polygonelements[i * 3 + 0] = 0;
213 polygonelements[i * 3 + 1] = i + 1;
214 polygonelements[i * 3 + 2] = i + 2;
216 // elements for rendering a series of quads as triangles
217 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
219 quadelements[i * 6 + 0] = i * 4;
220 quadelements[i * 6 + 1] = i * 4 + 1;
221 quadelements[i * 6 + 2] = i * 4 + 2;
222 quadelements[i * 6 + 3] = i * 4;
223 quadelements[i * 6 + 4] = i * 4 + 2;
224 quadelements[i * 6 + 5] = i * 4 + 3;
227 Cvar_RegisterVariable(&r_render);
228 Cvar_RegisterVariable(&r_waterwarp);
229 Cvar_RegisterVariable(&gl_polyblend);
230 Cvar_RegisterVariable(&gl_dither);
231 Cvar_RegisterVariable(&gl_lockarrays);
232 Cvar_RegisterVariable(&gl_lockarrays_minimumvertices);
233 Cvar_RegisterVariable(&gl_vbo);
234 Cvar_RegisterVariable(&gl_paranoid);
235 Cvar_RegisterVariable(&gl_printcheckerror);
237 Cvar_SetValue("r_render", 0);
240 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
241 Cvar_RegisterVariable(&gl_mesh_testarrayelement);
242 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
244 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
247 void GL_SetupView_Orientation_Identity (void)
249 backend_viewmatrix = identitymatrix;
250 memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
253 void GL_SetupView_Orientation_FromEntity(const matrix4x4_t *matrix)
255 matrix4x4_t tempmatrix, basematrix;
256 Matrix4x4_Invert_Simple(&tempmatrix, matrix);
257 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
258 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
259 Matrix4x4_Concat(&backend_viewmatrix, &basematrix, &tempmatrix);
260 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[2], 1, 0, 0);
261 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[0], 0, 1, 0);
262 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[1], 0, 0, 1);
263 //Matrix4x4_ConcatTranslate(&backend_viewmatrix, -origin[0], -origin[1], -origin[2]);
264 memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
267 void GL_SetupView_Mode_Perspective (double frustumx, double frustumy, double zNear, double zFar)
273 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
274 qglLoadIdentity();CHECKGLERROR
276 qglFrustum(-frustumx * zNear, frustumx * zNear, -frustumy * zNear, frustumy * zNear, zNear, zFar);CHECKGLERROR
277 qglGetDoublev(GL_PROJECTION_MATRIX, m);CHECKGLERROR
278 Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
279 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
280 GL_SetupView_Orientation_Identity();
284 void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double frustumx, double frustumy, double zNear)
290 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
291 qglLoadIdentity();CHECKGLERROR
293 nudge = 1.0 - 1.0 / (1<<23);
294 m[ 0] = 1.0 / frustumx;
299 m[ 5] = 1.0 / frustumy;
308 m[14] = -2 * zNear * nudge;
310 qglLoadMatrixd(m);CHECKGLERROR
311 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
312 GL_SetupView_Orientation_Identity();
314 Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
317 void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double zNear, double zFar)
323 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
324 qglLoadIdentity();CHECKGLERROR
325 qglOrtho(x1, x2, y2, y1, zNear, zFar);CHECKGLERROR
326 qglGetDoublev(GL_PROJECTION_MATRIX, m);CHECKGLERROR
327 Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
328 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
329 GL_SetupView_Orientation_Identity();
333 typedef struct gltextureunit_s
335 const void *pointer_texcoord;
336 size_t pointer_texcoord_offset;
337 int pointer_texcoord_buffer;
338 int t1d, t2d, t3d, tcubemap;
340 unsigned int arraycomponents;
341 int rgbscale, alphascale;
342 int combinergb, combinealpha;
343 // FIXME: add more combine stuff
344 // texmatrixenabled exists only to avoid unnecessary texmatrix compares
345 int texmatrixenabled;
350 static struct gl_state_s
358 int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
363 unsigned int clientunit;
364 gltextureunit_t units[MAX_TEXTUREUNITS];
368 int vertexbufferobject;
369 int elementbufferobject;
370 qboolean pointer_color_enabled;
371 const void *pointer_vertex;
372 const void *pointer_color;
373 size_t pointer_vertex_offset;
374 size_t pointer_color_offset;
375 int pointer_vertex_buffer;
376 int pointer_color_buffer;
380 static void GL_BindVBO(int bufferobject)
382 if (gl_state.vertexbufferobject != bufferobject)
384 gl_state.vertexbufferobject = bufferobject;
386 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);
391 static void GL_BindEBO(int bufferobject)
393 if (gl_state.elementbufferobject != bufferobject)
395 gl_state.elementbufferobject = bufferobject;
397 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);
402 void GL_SetupTextureState(void)
405 gltextureunit_t *unit;
407 gl_state.unit = MAX_TEXTUREUNITS;
408 gl_state.clientunit = MAX_TEXTUREUNITS;
409 for (i = 0;i < MAX_TEXTUREUNITS;i++)
411 unit = gl_state.units + i;
416 unit->arrayenabled = false;
417 unit->arraycomponents = 0;
418 unit->pointer_texcoord = NULL;
419 unit->pointer_texcoord_buffer = 0;
420 unit->pointer_texcoord_offset = 0;
422 unit->alphascale = 1;
423 unit->combinergb = GL_MODULATE;
424 unit->combinealpha = GL_MODULATE;
425 unit->texmatrixenabled = false;
426 unit->matrix = identitymatrix;
429 for (i = 0;i < backendimageunits;i++)
432 qglBindTexture(GL_TEXTURE_1D, 0);CHECKGLERROR
433 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
436 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
438 if (gl_texturecubemap)
440 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
444 for (i = 0;i < backendarrayunits;i++)
446 GL_ClientActiveTexture(i);
448 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
449 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
452 for (i = 0;i < backendunits;i++)
455 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
456 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
459 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
461 if (gl_texturecubemap)
463 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
465 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
466 qglLoadIdentity();CHECKGLERROR
467 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
468 if (gl_combine.integer)
470 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
471 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);CHECKGLERROR
472 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);CHECKGLERROR
473 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
474 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
475 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
476 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
477 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);CHECKGLERROR
478 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);CHECKGLERROR
479 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);CHECKGLERROR
480 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
481 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);CHECKGLERROR
482 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
483 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
484 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
485 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
486 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
490 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
497 void GL_Backend_ResetState(void)
499 memset(&gl_state, 0, sizeof(gl_state));
500 gl_state.depthtest = true;
501 gl_state.alphatest = false;
502 gl_state.blendfunc1 = GL_ONE;
503 gl_state.blendfunc2 = GL_ZERO;
504 gl_state.blend = false;
505 gl_state.depthmask = GL_TRUE;
506 gl_state.colormask = 15;
507 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
508 gl_state.lockrange_first = 0;
509 gl_state.lockrange_count = 0;
510 gl_state.cullface = GL_FRONT; // quake is backwards, this culls back faces
511 gl_state.cullfaceenable = true;
515 qglColorMask(1, 1, 1, 1);
516 qglAlphaFunc(GL_GEQUAL, 0.5);CHECKGLERROR
517 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
518 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
519 qglDisable(GL_BLEND);CHECKGLERROR
520 qglCullFace(gl_state.cullface);CHECKGLERROR
521 qglEnable(GL_CULL_FACE);CHECKGLERROR
522 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
523 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
524 qglDepthMask(gl_state.depthmask);CHECKGLERROR
526 if (gl_support_arb_vertex_buffer_object)
528 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
529 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
532 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
533 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
535 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
536 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
538 GL_Color(0, 0, 0, 0);
539 GL_Color(1, 1, 1, 1);
541 GL_SetupTextureState();
544 void GL_ActiveTexture(unsigned int num)
546 if (gl_state.unit != num)
549 if (qglActiveTexture)
552 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
558 void GL_ClientActiveTexture(unsigned int num)
560 if (gl_state.clientunit != num)
562 gl_state.clientunit = num;
563 if (qglActiveTexture)
566 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
572 void GL_BlendFunc(int blendfunc1, int blendfunc2)
574 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
577 qglBlendFunc(gl_state.blendfunc1 = blendfunc1, gl_state.blendfunc2 = blendfunc2);CHECKGLERROR
578 if (gl_state.blendfunc2 == GL_ZERO)
580 if (gl_state.blendfunc1 == GL_ONE)
585 qglDisable(GL_BLEND);CHECKGLERROR
593 qglEnable(GL_BLEND);CHECKGLERROR
602 qglEnable(GL_BLEND);CHECKGLERROR
608 void GL_DepthMask(int state)
610 if (gl_state.depthmask != state)
613 qglDepthMask(gl_state.depthmask = state);CHECKGLERROR
617 void GL_DepthTest(int state)
619 if (gl_state.depthtest != state)
621 gl_state.depthtest = state;
623 if (gl_state.depthtest)
625 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
629 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
634 void GL_CullFace(int state)
637 if (state != GL_NONE)
639 if (!gl_state.cullfaceenable)
641 gl_state.cullfaceenable = true;
642 qglEnable(GL_CULL_FACE);CHECKGLERROR
644 if (gl_state.cullface != state)
646 gl_state.cullface = state;
647 qglCullFace(gl_state.cullface);CHECKGLERROR
652 if (gl_state.cullfaceenable)
654 gl_state.cullfaceenable = false;
655 qglDisable(GL_CULL_FACE);CHECKGLERROR
660 void GL_AlphaTest(int state)
662 if (gl_state.alphatest != state)
664 gl_state.alphatest = state;
666 if (gl_state.alphatest)
668 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
672 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
677 void GL_ColorMask(int r, int g, int b, int a)
679 int state = r*8 + g*4 + b*2 + a*1;
680 if (gl_state.colormask != state)
682 gl_state.colormask = state;
684 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
688 void GL_Color(float cr, float cg, float cb, float ca)
690 if (gl_state.pointer_color_enabled || gl_state.color4f[0] != cr || gl_state.color4f[1] != cg || gl_state.color4f[2] != cb || gl_state.color4f[3] != ca)
692 gl_state.color4f[0] = cr;
693 gl_state.color4f[1] = cg;
694 gl_state.color4f[2] = cb;
695 gl_state.color4f[3] = ca;
697 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
702 void GL_LockArrays(int first, int count)
704 if (count < gl_lockarrays_minimumvertices.integer)
709 if (gl_state.lockrange_count != count || gl_state.lockrange_first != first)
711 if (gl_state.lockrange_count)
713 gl_state.lockrange_count = 0;
715 qglUnlockArraysEXT();
718 if (count && gl_supportslockarrays && gl_lockarrays.integer && r_render.integer)
720 gl_state.lockrange_first = first;
721 gl_state.lockrange_count = count;
723 qglLockArraysEXT(first, count);
729 void GL_Scissor (int x, int y, int width, int height)
732 qglScissor(x, vid.height - (y + height),width,height);
736 void GL_ScissorTest(int state)
738 if(gl_state.scissortest == state)
742 if((gl_state.scissortest = state))
743 qglEnable(GL_SCISSOR_TEST);
745 qglDisable(GL_SCISSOR_TEST);
749 void GL_Clear(int mask)
752 qglClear(mask);CHECKGLERROR
755 void GL_TransformToScreen(const vec4_t in, vec4_t out)
759 Matrix4x4_Transform4 (&backend_viewmatrix, in, temp);
760 Matrix4x4_Transform4 (&backend_projectmatrix, temp, out);
762 out[0] = r_view.x + (out[0] * iw + 1.0f) * r_view.width * 0.5f;
763 out[1] = r_view.y + r_view.height - (out[1] * iw + 1.0f) * r_view.height * 0.5f;
764 out[2] = r_view.z + (out[2] * iw + 1.0f) * r_view.depth * 0.5f;
767 // called at beginning of frame
768 void R_Mesh_Start(void)
772 if (gl_printcheckerror.integer && !gl_paranoid.integer)
774 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
775 Cvar_SetValueQuick(&gl_paranoid, 1);
777 GL_Backend_ResetState();
780 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
784 char compilelog[MAX_INPUTLINE];
785 shaderobject = qglCreateShaderObjectARB(shadertypeenum);CHECKGLERROR
788 qglShaderSourceARB(shaderobject, numstrings, strings, NULL);CHECKGLERROR
789 qglCompileShaderARB(shaderobject);CHECKGLERROR
790 qglGetObjectParameterivARB(shaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &shadercompiled);CHECKGLERROR
791 qglGetInfoLogARB(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
793 Con_DPrintf("%s shader compile log:\n%s\n", shadertype, compilelog);
796 qglDeleteObjectARB(shaderobject);CHECKGLERROR
799 qglAttachObjectARB(programobject, shaderobject);CHECKGLERROR
800 qglDeleteObjectARB(shaderobject);CHECKGLERROR
804 unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **vertexstrings_list, int geometrystrings_count, const char **geometrystrings_list, int fragmentstrings_count, const char **fragmentstrings_list)
807 GLuint programobject = 0;
808 char linklog[MAX_INPUTLINE];
811 programobject = qglCreateProgramObjectARB();CHECKGLERROR
815 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER_ARB, "vertex", vertexstrings_count, vertexstrings_list))
818 #ifdef GL_GEOMETRY_SHADER_ARB
819 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER_ARB, "geometry", geometrystrings_count, geometrystrings_list))
823 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER_ARB, "fragment", fragmentstrings_count, fragmentstrings_list))
826 qglLinkProgramARB(programobject);CHECKGLERROR
827 qglGetObjectParameterivARB(programobject, GL_OBJECT_LINK_STATUS_ARB, &programlinked);CHECKGLERROR
828 qglGetInfoLogARB(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
831 Con_DPrintf("program link log:\n%s\n", linklog);
832 // software vertex shader is ok but software fragment shader is WAY
833 // too slow, fail program if so.
834 // NOTE: this string might be ATI specific, but that's ok because the
835 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
836 // software fragment shader due to low instruction and dependent
838 if (strstr(linklog, "fragment shader will run in software"))
839 programlinked = false;
843 return programobject;
845 qglDeleteObjectARB(programobject);CHECKGLERROR
849 void GL_Backend_FreeProgram(unsigned int prog)
852 qglDeleteObjectARB(prog);
856 int gl_backend_rebindtextures;
858 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
863 for (i = 0;i < count;i++)
864 *out++ = *in++ + offset;
867 memcpy(out, in, sizeof(*out) * count);
870 // renders triangles using vertices from the active arrays
871 int paranoidblah = 0;
872 void R_Mesh_Draw(int firstvertex, int numvertices, int numtriangles, const int *elements, int bufferobject, size_t bufferoffset)
874 unsigned int numelements = numtriangles * 3;
875 if (numvertices < 3 || numtriangles < 1)
877 Con_Printf("R_Mesh_Draw(%d, %d, %d, %8p, %i, %p);\n", firstvertex, numvertices, numtriangles, elements, bufferobject, (void *)bufferoffset);
883 r_refdef.stats.meshes++;
884 r_refdef.stats.meshes_elements += numelements;
885 if (gl_paranoid.integer)
887 unsigned int i, j, size;
889 // note: there's no validation done here on buffer objects because it
890 // is somewhat difficult to get at the data, and gl_paranoid can be
891 // used without buffer objects if the need arises
892 // (the data could be gotten using glMapBuffer but it would be very
893 // slow due to uncachable video memory reads)
894 if (!qglIsEnabled(GL_VERTEX_ARRAY))
895 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
897 if (gl_state.pointer_vertex)
898 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
900 if (gl_state.pointer_color_enabled)
902 if (!qglIsEnabled(GL_COLOR_ARRAY))
903 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
905 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
906 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
909 for (i = 0;i < backendarrayunits;i++)
911 if (gl_state.units[i].arrayenabled)
913 GL_ClientActiveTexture(i);
914 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
915 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
917 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
918 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++)
922 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
924 if (elements[i] < firstvertex || elements[i] >= firstvertex + numvertices)
926 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in elements list\n", elements[i], firstvertex, firstvertex + numvertices);
932 if (r_render.integer)
935 if (gl_mesh_testmanualfeeding.integer)
939 qglBegin(GL_TRIANGLES);
940 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
942 for (j = 0;j < backendarrayunits;j++)
944 if (gl_state.units[j].pointer_texcoord && gl_state.units[j].arrayenabled)
946 if (backendarrayunits > 1)
948 if (gl_state.units[j].arraycomponents == 4)
950 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
951 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
953 else if (gl_state.units[j].arraycomponents == 3)
955 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
956 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
958 else if (gl_state.units[j].arraycomponents == 2)
960 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
961 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
965 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
966 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
971 if (gl_state.units[j].arraycomponents == 4)
973 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
974 qglTexCoord4f(p[0], p[1], p[2], p[3]);
976 else if (gl_state.units[j].arraycomponents == 3)
978 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
979 qglTexCoord3f(p[0], p[1], p[2]);
981 else if (gl_state.units[j].arraycomponents == 2)
983 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
984 qglTexCoord2f(p[0], p[1]);
988 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
994 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
996 p = ((const GLfloat *)(gl_state.pointer_color)) + elements[i] * 4;
997 qglColor4f(p[0], p[1], p[2], p[3]);
999 p = ((const GLfloat *)(gl_state.pointer_vertex)) + elements[i] * 3;
1000 qglVertex3f(p[0], p[1], p[2]);
1005 else if (gl_mesh_testarrayelement.integer)
1008 qglBegin(GL_TRIANGLES);
1009 for (i = 0;i < numtriangles * 3;i++)
1011 qglArrayElement(elements[i]);
1016 else if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
1018 GL_BindEBO(bufferobject);
1019 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_INT, bufferobject ? (void *)bufferoffset : elements);
1024 GL_BindEBO(bufferobject);
1025 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, bufferobject ? (void *)bufferoffset : elements);
1031 // restores backend state, used when done with 3D rendering
1032 void R_Mesh_Finish(void)
1037 GL_LockArrays(0, 0);
1040 for (i = 0;i < backendimageunits;i++)
1042 GL_ActiveTexture(i);
1043 qglBindTexture(GL_TEXTURE_1D, 0);CHECKGLERROR
1044 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1047 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1049 if (gl_texturecubemap)
1051 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1054 for (i = 0;i < backendarrayunits;i++)
1056 GL_ActiveTexture(backendarrayunits - 1 - i);
1057 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1059 for (i = 0;i < backendunits;i++)
1061 GL_ActiveTexture(backendunits - 1 - i);
1062 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1063 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1066 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1068 if (gl_texturecubemap)
1070 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1072 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1073 if (gl_combine.integer)
1075 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
1076 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
1079 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1080 qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1082 qglDisable(GL_BLEND);CHECKGLERROR
1083 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1084 qglDepthMask(GL_TRUE);CHECKGLERROR
1085 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);CHECKGLERROR
1088 int R_Mesh_CreateStaticEBO(void *data, size_t size)
1090 GLuint bufferobject;
1091 if (!gl_vbo.integer)
1093 qglGenBuffersARB(1, &bufferobject);
1094 GL_BindEBO(bufferobject);
1095 qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, size, data, GL_STATIC_DRAW_ARB);
1096 return (int)bufferobject;
1099 void R_Mesh_DestroyEBO(int bufferobject)
1101 qglDeleteBuffersARB(1, (GLuint *)&bufferobject);
1104 int R_Mesh_CreateStaticVBO(void *data, size_t size)
1106 GLuint bufferobject;
1107 if (!gl_vbo.integer)
1109 qglGenBuffersARB(1, &bufferobject);
1110 GL_BindVBO(bufferobject);
1111 qglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, data, GL_STATIC_DRAW_ARB);
1112 return (int)bufferobject;
1115 void R_Mesh_DestroyVBO(int bufferobject)
1117 qglDeleteBuffersARB(1, (GLuint *)&bufferobject);
1120 void R_Mesh_Matrix(const matrix4x4_t *matrix)
1122 if (memcmp(matrix, &backend_modelmatrix, sizeof(matrix4x4_t)))
1124 double glmatrix[16];
1125 backend_modelmatrix = *matrix;
1126 Matrix4x4_Concat(&backend_modelviewmatrix, &backend_viewmatrix, matrix);
1127 Matrix4x4_ToArrayDoubleGL(&backend_modelviewmatrix, glmatrix);
1129 qglLoadMatrixd(glmatrix);CHECKGLERROR
1133 void R_Mesh_VertexPointer(const float *vertex3f, int bufferobject, size_t bufferoffset)
1135 if (!gl_vbo.integer)
1137 if (gl_state.pointer_vertex != vertex3f || gl_state.pointer_vertex_buffer != bufferobject || gl_state.pointer_vertex_offset != bufferoffset)
1139 gl_state.pointer_vertex = vertex3f;
1140 gl_state.pointer_vertex_buffer = bufferobject;
1141 gl_state.pointer_vertex_offset = bufferoffset;
1143 GL_BindVBO(bufferobject);
1144 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), bufferobject ? (void *)bufferoffset : vertex3f);CHECKGLERROR
1148 void R_Mesh_ColorPointer(const float *color4f, int bufferobject, size_t bufferoffset)
1150 // note: this can not rely on bufferobject to decide whether a color array
1151 // is supplied, because surfmesh_t shares one vbo for all arrays, which
1152 // means that a valid vbo may be supplied even if there is no color array.
1155 if (!gl_vbo.integer)
1157 // caller wants color array enabled
1158 if (!gl_state.pointer_color_enabled)
1160 gl_state.pointer_color_enabled = true;
1162 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1164 if (gl_state.pointer_color != color4f || gl_state.pointer_color_buffer != bufferobject || gl_state.pointer_color_offset != bufferoffset)
1166 gl_state.pointer_color = color4f;
1167 gl_state.pointer_color_buffer = bufferobject;
1168 gl_state.pointer_color_offset = bufferoffset;
1170 GL_BindVBO(bufferobject);
1171 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), bufferobject ? (void *)bufferoffset : color4f);CHECKGLERROR
1176 // caller wants color array disabled
1177 if (gl_state.pointer_color_enabled)
1179 gl_state.pointer_color_enabled = false;
1181 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1182 // when color array is on the glColor gets trashed, set it again
1183 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
1188 void R_Mesh_TexCoordPointer(unsigned int unitnum, unsigned int numcomponents, const float *texcoord, int bufferobject, size_t bufferoffset)
1190 gltextureunit_t *unit = gl_state.units + unitnum;
1191 // update array settings
1193 // note: there is no need to check bufferobject here because all cases
1194 // that involve a valid bufferobject also supply a texcoord array
1197 if (!gl_vbo.integer)
1199 // texture array unit is enabled, enable the array
1200 if (!unit->arrayenabled)
1202 unit->arrayenabled = true;
1203 GL_ClientActiveTexture(unitnum);
1204 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1207 if (unit->pointer_texcoord != texcoord || unit->pointer_texcoord_buffer != bufferobject || unit->pointer_texcoord_offset != bufferoffset || unit->arraycomponents != numcomponents)
1209 unit->pointer_texcoord = texcoord;
1210 unit->pointer_texcoord_buffer = bufferobject;
1211 unit->pointer_texcoord_offset = bufferoffset;
1212 unit->arraycomponents = numcomponents;
1213 GL_ClientActiveTexture(unitnum);
1214 GL_BindVBO(bufferobject);
1215 qglTexCoordPointer(unit->arraycomponents, GL_FLOAT, sizeof(float) * unit->arraycomponents, bufferobject ? (void *)bufferoffset : texcoord);CHECKGLERROR
1220 // texture array unit is disabled, disable the array
1221 if (unit->arrayenabled)
1223 unit->arrayenabled = false;
1224 GL_ClientActiveTexture(unitnum);
1225 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1230 void R_Mesh_TexBindAll(unsigned int unitnum, int tex1d, int tex2d, int tex3d, int texcubemap)
1232 gltextureunit_t *unit = gl_state.units + unitnum;
1233 if (unitnum >= backendimageunits)
1235 // update 1d texture binding
1236 if (unit->t1d != tex1d)
1238 GL_ActiveTexture(unitnum);
1239 if (unitnum < backendunits)
1245 qglEnable(GL_TEXTURE_1D);CHECKGLERROR
1252 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1257 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1259 // update 2d texture binding
1260 if (unit->t2d != tex2d)
1262 GL_ActiveTexture(unitnum);
1263 if (unitnum < backendunits)
1269 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
1276 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1281 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1283 // update 3d texture binding
1284 if (unit->t3d != tex3d)
1286 GL_ActiveTexture(unitnum);
1287 if (unitnum < backendunits)
1293 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
1300 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1305 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1307 // update cubemap texture binding
1308 if (unit->tcubemap != texcubemap)
1310 GL_ActiveTexture(unitnum);
1311 if (unitnum < backendunits)
1315 if (unit->tcubemap == 0)
1317 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1324 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1328 unit->tcubemap = texcubemap;
1329 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1333 void R_Mesh_TexBind1D(unsigned int unitnum, int texnum)
1335 gltextureunit_t *unit = gl_state.units + unitnum;
1336 if (unitnum >= backendimageunits)
1338 // update 1d texture binding
1339 if (unit->t1d != texnum)
1341 GL_ActiveTexture(unitnum);
1342 if (unitnum < backendunits)
1348 qglEnable(GL_TEXTURE_1D);CHECKGLERROR
1355 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1360 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1362 // update 2d texture binding
1365 GL_ActiveTexture(unitnum);
1366 if (unitnum < backendunits)
1370 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1374 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1376 // update 3d texture binding
1379 GL_ActiveTexture(unitnum);
1380 if (unitnum < backendunits)
1384 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1388 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1390 // update cubemap texture binding
1393 GL_ActiveTexture(unitnum);
1394 if (unitnum < backendunits)
1398 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1402 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1406 void R_Mesh_TexBind(unsigned int unitnum, int texnum)
1408 gltextureunit_t *unit = gl_state.units + unitnum;
1409 if (unitnum >= backendimageunits)
1411 // update 1d texture binding
1414 GL_ActiveTexture(unitnum);
1415 if (unitnum < backendunits)
1419 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1423 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1425 // update 2d texture binding
1426 if (unit->t2d != texnum)
1428 GL_ActiveTexture(unitnum);
1429 if (unitnum < backendunits)
1435 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
1442 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1447 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1449 // update 3d texture binding
1452 GL_ActiveTexture(unitnum);
1453 if (unitnum < backendunits)
1457 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1461 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1463 // update cubemap texture binding
1464 if (unit->tcubemap != 0)
1466 GL_ActiveTexture(unitnum);
1467 if (unitnum < backendunits)
1471 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1475 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1479 void R_Mesh_TexBind3D(unsigned int unitnum, int texnum)
1481 gltextureunit_t *unit = gl_state.units + unitnum;
1482 if (unitnum >= backendimageunits)
1484 // update 1d texture binding
1487 GL_ActiveTexture(unitnum);
1488 if (unitnum < backendunits)
1492 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1496 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1498 // update 2d texture binding
1501 GL_ActiveTexture(unitnum);
1502 if (unitnum < backendunits)
1506 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1510 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1512 // update 3d texture binding
1513 if (unit->t3d != texnum)
1515 GL_ActiveTexture(unitnum);
1516 if (unitnum < backendunits)
1522 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
1529 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1534 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1536 // update cubemap texture binding
1537 if (unit->tcubemap != 0)
1539 GL_ActiveTexture(unitnum);
1540 if (unitnum < backendunits)
1544 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1548 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1552 void R_Mesh_TexBindCubeMap(unsigned int unitnum, int texnum)
1554 gltextureunit_t *unit = gl_state.units + unitnum;
1555 if (unitnum >= backendimageunits)
1557 // update 1d texture binding
1560 GL_ActiveTexture(unitnum);
1561 if (unitnum < backendunits)
1565 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1569 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1571 // update 2d texture binding
1574 GL_ActiveTexture(unitnum);
1575 if (unitnum < backendunits)
1579 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1583 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1585 // update 3d texture binding
1588 GL_ActiveTexture(unitnum);
1589 if (unitnum < backendunits)
1593 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1597 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1599 // update cubemap texture binding
1600 if (unit->tcubemap != texnum)
1602 GL_ActiveTexture(unitnum);
1603 if (unitnum < backendunits)
1607 if (unit->tcubemap == 0)
1609 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1616 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1620 unit->tcubemap = texnum;
1621 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1625 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
1627 gltextureunit_t *unit = gl_state.units + unitnum;
1628 if (matrix->m[3][3])
1630 // texmatrix specified, check if it is different
1631 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
1633 double glmatrix[16];
1634 unit->texmatrixenabled = true;
1635 unit->matrix = *matrix;
1637 Matrix4x4_ToArrayDoubleGL(&unit->matrix, glmatrix);
1638 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1639 GL_ActiveTexture(unitnum);
1640 qglLoadMatrixd(glmatrix);CHECKGLERROR
1641 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1646 // no texmatrix specified, revert to identity
1647 if (unit->texmatrixenabled)
1649 unit->texmatrixenabled = false;
1651 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1652 GL_ActiveTexture(unitnum);
1653 qglLoadIdentity();CHECKGLERROR
1654 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1659 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
1661 gltextureunit_t *unit = gl_state.units + unitnum;
1663 if (gl_combine.integer)
1665 // GL_ARB_texture_env_combine
1667 combinergb = GL_MODULATE;
1669 combinealpha = GL_MODULATE;
1674 if (unit->combinergb != combinergb)
1676 unit->combinergb = combinergb;
1677 GL_ActiveTexture(unitnum);
1678 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1680 if (unit->combinealpha != combinealpha)
1682 unit->combinealpha = combinealpha;
1683 GL_ActiveTexture(unitnum);
1684 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1686 if (unit->rgbscale != rgbscale)
1688 GL_ActiveTexture(unitnum);
1689 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = rgbscale));CHECKGLERROR
1691 if (unit->alphascale != alphascale)
1693 GL_ActiveTexture(unitnum);
1694 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = alphascale));CHECKGLERROR
1701 combinergb = GL_MODULATE;
1702 if (unit->combinergb != combinergb)
1704 unit->combinergb = combinergb;
1705 GL_ActiveTexture(unitnum);
1706 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
1711 void R_Mesh_TextureState(const rmeshstate_t *m)
1718 if (gl_backend_rebindtextures)
1720 gl_backend_rebindtextures = false;
1721 GL_SetupTextureState();
1725 for (i = 0;i < backendimageunits;i++)
1726 R_Mesh_TexBindAll(i, m->tex1d[i], m->tex[i], m->tex3d[i], m->texcubemap[i]);
1727 for (i = 0;i < backendarrayunits;i++)
1729 if (m->pointer_texcoord3f[i])
1730 R_Mesh_TexCoordPointer(i, 3, m->pointer_texcoord3f[i], m->pointer_texcoord_bufferobject[i], m->pointer_texcoord_bufferoffset[i]);
1732 R_Mesh_TexCoordPointer(i, 2, m->pointer_texcoord[i], m->pointer_texcoord_bufferobject[i], m->pointer_texcoord_bufferoffset[i]);
1734 for (i = 0;i < backendunits;i++)
1736 R_Mesh_TexMatrix(i, &m->texmatrix[i]);
1737 R_Mesh_TexCombine(i, m->texcombinergb[i], m->texcombinealpha[i], m->texrgbscale[i], m->texalphascale[i]);
1742 void R_Mesh_ResetTextureState(void)
1744 unsigned int unitnum;
1749 if (gl_backend_rebindtextures)
1751 gl_backend_rebindtextures = false;
1752 GL_SetupTextureState();
1756 for (unitnum = 0;unitnum < backendimageunits;unitnum++)
1758 gltextureunit_t *unit = gl_state.units + unitnum;
1759 // update 1d texture binding
1762 GL_ActiveTexture(unitnum);
1763 if (unitnum < backendunits)
1765 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1768 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1770 // update 2d texture binding
1773 GL_ActiveTexture(unitnum);
1774 if (unitnum < backendunits)
1776 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1779 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1781 // update 3d texture binding
1784 GL_ActiveTexture(unitnum);
1785 if (unitnum < backendunits)
1787 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1790 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1792 // update cubemap texture binding
1795 GL_ActiveTexture(unitnum);
1796 if (unitnum < backendunits)
1798 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1801 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1804 for (unitnum = 0;unitnum < backendarrayunits;unitnum++)
1806 gltextureunit_t *unit = gl_state.units + unitnum;
1807 // texture array unit is disabled, disable the array
1808 if (unit->arrayenabled)
1810 unit->arrayenabled = false;
1811 GL_ClientActiveTexture(unitnum);
1812 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1815 for (unitnum = 0;unitnum < backendunits;unitnum++)
1817 gltextureunit_t *unit = gl_state.units + unitnum;
1818 // no texmatrix specified, revert to identity
1819 if (unit->texmatrixenabled)
1821 unit->texmatrixenabled = false;
1823 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1824 GL_ActiveTexture(unitnum);
1825 qglLoadIdentity();CHECKGLERROR
1826 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1828 if (gl_combine.integer)
1830 // GL_ARB_texture_env_combine
1831 if (unit->combinergb != GL_MODULATE)
1833 unit->combinergb = GL_MODULATE;
1834 GL_ActiveTexture(unitnum);
1835 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1837 if (unit->combinealpha != GL_MODULATE)
1839 unit->combinealpha = GL_MODULATE;
1840 GL_ActiveTexture(unitnum);
1841 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1843 if (unit->rgbscale != 1)
1845 GL_ActiveTexture(unitnum);
1846 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = 1));CHECKGLERROR
1848 if (unit->alphascale != 1)
1850 GL_ActiveTexture(unitnum);
1851 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = 1));CHECKGLERROR
1857 if (unit->combinergb != GL_MODULATE)
1859 unit->combinergb = GL_MODULATE;
1860 GL_ActiveTexture(unitnum);
1861 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
1867 void R_Mesh_Draw_ShowTris(int firstvertex, int numvertices, int numtriangles, const int *elements)
1871 for (;numtriangles;numtriangles--, elements += 3)
1873 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
1874 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
1875 qglArrayElement(elements[2]);qglArrayElement(elements[0]);