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 void GL_VBOStats_f(void)
149 GL_Mesh_ListVBOs(true);
152 typedef struct gl_bufferobjectinfo_s
157 char name[MAX_QPATH];
159 gl_bufferobjectinfo_t;
161 memexpandablearray_t gl_bufferobjectinfoarray;
163 static void gl_backend_start(void)
165 Con_Print("OpenGL Backend starting...\n");
168 if (qglDrawRangeElements != NULL)
171 qglGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &gl_maxdrawrangeelementsvertices);
173 qglGetIntegerv(GL_MAX_ELEMENTS_INDICES, &gl_maxdrawrangeelementsindices);
175 Con_Printf("glDrawRangeElements detected (max vertices %i, max indices %i)\n", gl_maxdrawrangeelementsvertices, gl_maxdrawrangeelementsindices);
178 backendunits = bound(1, gl_textureunits, MAX_TEXTUREUNITS);
179 backendimageunits = backendunits;
180 backendarrayunits = backendunits;
181 if (gl_support_fragment_shader)
184 qglGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, (int *)&backendimageunits);
186 qglGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, (int *)&backendarrayunits);
188 Con_Printf("GLSL shader support detected: texture units = %i texenv, %i image, %i array\n", backendunits, backendimageunits, backendarrayunits);
189 backendimageunits = bound(1, backendimageunits, MAX_TEXTUREUNITS);
190 backendarrayunits = bound(1, backendarrayunits, MAX_TEXTUREUNITS);
192 else if (backendunits > 1)
193 Con_Printf("multitexture detected: texture units = %i\n", backendunits);
195 Con_Printf("singletexture\n");
197 GL_Backend_AllocArrays();
199 Mem_ExpandableArray_NewArray(&gl_bufferobjectinfoarray, r_main_mempool, sizeof(gl_bufferobjectinfo_t), 128);
201 Con_Printf("OpenGL backend started.\n");
205 backendactive = true;
208 static void gl_backend_shutdown(void)
211 backendimageunits = 0;
212 backendarrayunits = 0;
213 backendactive = false;
215 Con_Print("OpenGL Backend shutting down\n");
217 Mem_ExpandableArray_FreeArray(&gl_bufferobjectinfoarray);
219 GL_Backend_FreeArrays();
222 static void gl_backend_newmap(void)
226 void gl_backend_init(void)
230 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
232 polygonelements[i * 3 + 0] = 0;
233 polygonelements[i * 3 + 1] = i + 1;
234 polygonelements[i * 3 + 2] = i + 2;
236 // elements for rendering a series of quads as triangles
237 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
239 quadelements[i * 6 + 0] = i * 4;
240 quadelements[i * 6 + 1] = i * 4 + 1;
241 quadelements[i * 6 + 2] = i * 4 + 2;
242 quadelements[i * 6 + 3] = i * 4;
243 quadelements[i * 6 + 4] = i * 4 + 2;
244 quadelements[i * 6 + 5] = i * 4 + 3;
247 Cvar_RegisterVariable(&r_render);
248 Cvar_RegisterVariable(&r_waterwarp);
249 Cvar_RegisterVariable(&gl_polyblend);
250 Cvar_RegisterVariable(&gl_dither);
251 Cvar_RegisterVariable(&gl_lockarrays);
252 Cvar_RegisterVariable(&gl_lockarrays_minimumvertices);
253 Cvar_RegisterVariable(&gl_vbo);
254 Cvar_RegisterVariable(&gl_paranoid);
255 Cvar_RegisterVariable(&gl_printcheckerror);
257 Cvar_SetValue("r_render", 0);
260 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
261 Cvar_RegisterVariable(&gl_mesh_testarrayelement);
262 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
264 Cmd_AddCommand("gl_vbostats", GL_VBOStats_f, "prints a list of all buffer objects (vertex data and triangle elements) and total video memory used by them\n");
266 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
269 void GL_SetupView_Orientation_Identity (void)
271 backend_viewmatrix = identitymatrix;
272 memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
275 void GL_SetupView_Orientation_FromEntity(const matrix4x4_t *matrix)
277 matrix4x4_t tempmatrix, basematrix;
278 Matrix4x4_Invert_Simple(&tempmatrix, matrix);
279 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
280 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
281 Matrix4x4_Concat(&backend_viewmatrix, &basematrix, &tempmatrix);
282 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[2], 1, 0, 0);
283 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[0], 0, 1, 0);
284 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[1], 0, 0, 1);
285 //Matrix4x4_ConcatTranslate(&backend_viewmatrix, -origin[0], -origin[1], -origin[2]);
286 memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
289 void GL_SetupView_Mode_Perspective (double frustumx, double frustumy, double zNear, double zFar)
295 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
296 qglLoadIdentity();CHECKGLERROR
298 qglFrustum(-frustumx * zNear, frustumx * zNear, -frustumy * zNear, frustumy * zNear, zNear, zFar);CHECKGLERROR
299 qglGetDoublev(GL_PROJECTION_MATRIX, m);CHECKGLERROR
300 Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
301 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
302 GL_SetupView_Orientation_Identity();
306 void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double frustumx, double frustumy, double zNear)
312 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
313 qglLoadIdentity();CHECKGLERROR
315 nudge = 1.0 - 1.0 / (1<<23);
316 m[ 0] = 1.0 / frustumx;
321 m[ 5] = 1.0 / frustumy;
330 m[14] = -2 * zNear * nudge;
332 qglLoadMatrixd(m);CHECKGLERROR
333 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
334 GL_SetupView_Orientation_Identity();
336 Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
339 void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double zNear, double zFar)
345 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
346 qglLoadIdentity();CHECKGLERROR
347 qglOrtho(x1, x2, y2, y1, zNear, zFar);CHECKGLERROR
348 qglGetDoublev(GL_PROJECTION_MATRIX, m);CHECKGLERROR
349 Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
350 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
351 GL_SetupView_Orientation_Identity();
355 typedef struct gltextureunit_s
357 const void *pointer_texcoord;
358 size_t pointer_texcoord_offset;
359 int pointer_texcoord_buffer;
360 int t1d, t2d, t3d, tcubemap;
362 unsigned int arraycomponents;
363 int rgbscale, alphascale;
364 int combinergb, combinealpha;
365 // FIXME: add more combine stuff
366 // texmatrixenabled exists only to avoid unnecessary texmatrix compares
367 int texmatrixenabled;
372 static struct gl_state_s
380 int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
386 unsigned int clientunit;
387 gltextureunit_t units[MAX_TEXTUREUNITS];
391 int vertexbufferobject;
392 int elementbufferobject;
393 qboolean pointer_color_enabled;
394 const void *pointer_vertex;
395 const void *pointer_color;
396 size_t pointer_vertex_offset;
397 size_t pointer_color_offset;
398 int pointer_vertex_buffer;
399 int pointer_color_buffer;
403 static void GL_BindVBO(int bufferobject)
405 if (gl_state.vertexbufferobject != bufferobject)
407 gl_state.vertexbufferobject = bufferobject;
409 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);
414 static void GL_BindEBO(int bufferobject)
416 if (gl_state.elementbufferobject != bufferobject)
418 gl_state.elementbufferobject = bufferobject;
420 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);
425 void GL_SetupTextureState(void)
428 gltextureunit_t *unit;
430 gl_state.unit = MAX_TEXTUREUNITS;
431 gl_state.clientunit = MAX_TEXTUREUNITS;
432 for (i = 0;i < MAX_TEXTUREUNITS;i++)
434 unit = gl_state.units + i;
439 unit->arrayenabled = false;
440 unit->arraycomponents = 0;
441 unit->pointer_texcoord = NULL;
442 unit->pointer_texcoord_buffer = 0;
443 unit->pointer_texcoord_offset = 0;
445 unit->alphascale = 1;
446 unit->combinergb = GL_MODULATE;
447 unit->combinealpha = GL_MODULATE;
448 unit->texmatrixenabled = false;
449 unit->matrix = identitymatrix;
452 for (i = 0;i < backendimageunits;i++)
455 qglBindTexture(GL_TEXTURE_1D, 0);CHECKGLERROR
456 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
459 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
461 if (gl_texturecubemap)
463 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
467 for (i = 0;i < backendarrayunits;i++)
469 GL_ClientActiveTexture(i);
471 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
472 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
475 for (i = 0;i < backendunits;i++)
478 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
479 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
482 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
484 if (gl_texturecubemap)
486 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
488 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
489 qglLoadIdentity();CHECKGLERROR
490 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
491 if (gl_combine.integer)
493 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
494 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);CHECKGLERROR
495 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);CHECKGLERROR
496 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
497 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
498 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
499 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
500 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);CHECKGLERROR
501 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);CHECKGLERROR
502 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);CHECKGLERROR
503 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
504 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);CHECKGLERROR
505 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
506 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
507 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
508 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
509 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
513 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
520 void GL_Backend_ResetState(void)
522 memset(&gl_state, 0, sizeof(gl_state));
523 gl_state.depthtest = true;
524 gl_state.alphatest = false;
525 gl_state.blendfunc1 = GL_ONE;
526 gl_state.blendfunc2 = GL_ZERO;
527 gl_state.blend = false;
528 gl_state.depthmask = GL_TRUE;
529 gl_state.colormask = 15;
530 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
531 gl_state.lockrange_first = 0;
532 gl_state.lockrange_count = 0;
533 gl_state.cullface = GL_FRONT; // quake is backwards, this culls back faces
534 gl_state.cullfaceenable = true;
538 qglColorMask(1, 1, 1, 1);
539 qglAlphaFunc(GL_GEQUAL, 0.5);CHECKGLERROR
540 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
541 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
542 qglDisable(GL_BLEND);CHECKGLERROR
543 qglCullFace(gl_state.cullface);CHECKGLERROR
544 qglEnable(GL_CULL_FACE);CHECKGLERROR
545 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
546 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
547 qglDepthMask(gl_state.depthmask);CHECKGLERROR
549 if (gl_support_arb_vertex_buffer_object)
551 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
552 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
555 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
556 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
558 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
559 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
561 GL_Color(0, 0, 0, 0);
562 GL_Color(1, 1, 1, 1);
564 GL_SetupTextureState();
567 void GL_ActiveTexture(unsigned int num)
569 if (gl_state.unit != num)
572 if (qglActiveTexture)
575 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
581 void GL_ClientActiveTexture(unsigned int num)
583 if (gl_state.clientunit != num)
585 gl_state.clientunit = num;
586 if (qglActiveTexture)
589 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
595 void GL_BlendFunc(int blendfunc1, int blendfunc2)
597 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
600 qglBlendFunc(gl_state.blendfunc1 = blendfunc1, gl_state.blendfunc2 = blendfunc2);CHECKGLERROR
601 if (gl_state.blendfunc2 == GL_ZERO)
603 if (gl_state.blendfunc1 == GL_ONE)
608 qglDisable(GL_BLEND);CHECKGLERROR
616 qglEnable(GL_BLEND);CHECKGLERROR
625 qglEnable(GL_BLEND);CHECKGLERROR
631 void GL_DepthMask(int state)
633 if (gl_state.depthmask != state)
636 qglDepthMask(gl_state.depthmask = state);CHECKGLERROR
640 void GL_DepthTest(int state)
642 if (gl_state.depthtest != state)
644 gl_state.depthtest = state;
646 if (gl_state.depthtest)
648 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
652 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
657 void GL_DepthRange(float nearfrac, float farfrac)
659 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
661 gl_state.depthrange[0] = nearfrac;
662 gl_state.depthrange[1] = farfrac;
663 qglDepthRange(nearfrac, farfrac);
667 void GL_CullFace(int state)
670 if (state != GL_NONE)
672 if (!gl_state.cullfaceenable)
674 gl_state.cullfaceenable = true;
675 qglEnable(GL_CULL_FACE);CHECKGLERROR
677 if (gl_state.cullface != state)
679 gl_state.cullface = state;
680 qglCullFace(gl_state.cullface);CHECKGLERROR
685 if (gl_state.cullfaceenable)
687 gl_state.cullfaceenable = false;
688 qglDisable(GL_CULL_FACE);CHECKGLERROR
693 void GL_AlphaTest(int state)
695 if (gl_state.alphatest != state)
697 gl_state.alphatest = state;
699 if (gl_state.alphatest)
701 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
705 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
710 void GL_ColorMask(int r, int g, int b, int a)
712 int state = r*8 + g*4 + b*2 + a*1;
713 if (gl_state.colormask != state)
715 gl_state.colormask = state;
717 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
721 void GL_Color(float cr, float cg, float cb, float ca)
723 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)
725 gl_state.color4f[0] = cr;
726 gl_state.color4f[1] = cg;
727 gl_state.color4f[2] = cb;
728 gl_state.color4f[3] = ca;
730 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
735 void GL_LockArrays(int first, int count)
737 if (count < gl_lockarrays_minimumvertices.integer)
742 if (gl_state.lockrange_count != count || gl_state.lockrange_first != first)
744 if (gl_state.lockrange_count)
746 gl_state.lockrange_count = 0;
748 qglUnlockArraysEXT();
751 if (count && gl_supportslockarrays && gl_lockarrays.integer && r_render.integer)
753 gl_state.lockrange_first = first;
754 gl_state.lockrange_count = count;
756 qglLockArraysEXT(first, count);
762 void GL_Scissor (int x, int y, int width, int height)
765 qglScissor(x, vid.height - (y + height),width,height);
769 void GL_ScissorTest(int state)
771 if(gl_state.scissortest == state)
775 if((gl_state.scissortest = state))
776 qglEnable(GL_SCISSOR_TEST);
778 qglDisable(GL_SCISSOR_TEST);
782 void GL_Clear(int mask)
785 qglClear(mask);CHECKGLERROR
788 void GL_TransformToScreen(const vec4_t in, vec4_t out)
792 Matrix4x4_Transform4 (&backend_viewmatrix, in, temp);
793 Matrix4x4_Transform4 (&backend_projectmatrix, temp, out);
795 out[0] = r_view.x + (out[0] * iw + 1.0f) * r_view.width * 0.5f;
796 out[1] = r_view.y + r_view.height - (out[1] * iw + 1.0f) * r_view.height * 0.5f;
797 out[2] = r_view.z + (out[2] * iw + 1.0f) * r_view.depth * 0.5f;
800 // called at beginning of frame
801 void R_Mesh_Start(void)
805 if (gl_printcheckerror.integer && !gl_paranoid.integer)
807 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
808 Cvar_SetValueQuick(&gl_paranoid, 1);
810 GL_Backend_ResetState();
813 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
817 char compilelog[MAX_INPUTLINE];
818 shaderobject = qglCreateShaderObjectARB(shadertypeenum);CHECKGLERROR
821 qglShaderSourceARB(shaderobject, numstrings, strings, NULL);CHECKGLERROR
822 qglCompileShaderARB(shaderobject);CHECKGLERROR
823 qglGetObjectParameterivARB(shaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &shadercompiled);CHECKGLERROR
824 qglGetInfoLogARB(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
826 Con_DPrintf("%s shader compile log:\n%s\n", shadertype, compilelog);
829 qglDeleteObjectARB(shaderobject);CHECKGLERROR
832 qglAttachObjectARB(programobject, shaderobject);CHECKGLERROR
833 qglDeleteObjectARB(shaderobject);CHECKGLERROR
837 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)
840 GLuint programobject = 0;
841 char linklog[MAX_INPUTLINE];
844 programobject = qglCreateProgramObjectARB();CHECKGLERROR
848 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER_ARB, "vertex", vertexstrings_count, vertexstrings_list))
851 #ifdef GL_GEOMETRY_SHADER_ARB
852 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER_ARB, "geometry", geometrystrings_count, geometrystrings_list))
856 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER_ARB, "fragment", fragmentstrings_count, fragmentstrings_list))
859 qglLinkProgramARB(programobject);CHECKGLERROR
860 qglGetObjectParameterivARB(programobject, GL_OBJECT_LINK_STATUS_ARB, &programlinked);CHECKGLERROR
861 qglGetInfoLogARB(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
864 Con_DPrintf("program link log:\n%s\n", linklog);
865 // software vertex shader is ok but software fragment shader is WAY
866 // too slow, fail program if so.
867 // NOTE: this string might be ATI specific, but that's ok because the
868 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
869 // software fragment shader due to low instruction and dependent
871 if (strstr(linklog, "fragment shader will run in software"))
872 programlinked = false;
876 return programobject;
878 qglDeleteObjectARB(programobject);CHECKGLERROR
882 void GL_Backend_FreeProgram(unsigned int prog)
885 qglDeleteObjectARB(prog);
889 int gl_backend_rebindtextures;
891 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
896 for (i = 0;i < count;i++)
897 *out++ = *in++ + offset;
900 memcpy(out, in, sizeof(*out) * count);
903 // renders triangles using vertices from the active arrays
904 int paranoidblah = 0;
905 void R_Mesh_Draw(int firstvertex, int numvertices, int numtriangles, const int *elements, int bufferobject, size_t bufferoffset)
907 unsigned int numelements = numtriangles * 3;
908 if (numvertices < 3 || numtriangles < 1)
910 Con_Printf("R_Mesh_Draw(%d, %d, %d, %8p, %i, %p);\n", firstvertex, numvertices, numtriangles, elements, bufferobject, (void *)bufferoffset);
916 r_refdef.stats.meshes++;
917 r_refdef.stats.meshes_elements += numelements;
918 if (gl_paranoid.integer)
920 unsigned int i, j, size;
922 // note: there's no validation done here on buffer objects because it
923 // is somewhat difficult to get at the data, and gl_paranoid can be
924 // used without buffer objects if the need arises
925 // (the data could be gotten using glMapBuffer but it would be very
926 // slow due to uncachable video memory reads)
927 if (!qglIsEnabled(GL_VERTEX_ARRAY))
928 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
930 if (gl_state.pointer_vertex)
931 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
933 if (gl_state.pointer_color_enabled)
935 if (!qglIsEnabled(GL_COLOR_ARRAY))
936 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
938 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
939 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
942 for (i = 0;i < backendarrayunits;i++)
944 if (gl_state.units[i].arrayenabled)
946 GL_ClientActiveTexture(i);
947 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
948 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
950 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
951 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++)
955 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
957 if (elements[i] < firstvertex || elements[i] >= firstvertex + numvertices)
959 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in elements list\n", elements[i], firstvertex, firstvertex + numvertices);
965 if (r_render.integer)
968 if (gl_mesh_testmanualfeeding.integer)
972 qglBegin(GL_TRIANGLES);
973 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
975 for (j = 0;j < backendarrayunits;j++)
977 if (gl_state.units[j].pointer_texcoord && gl_state.units[j].arrayenabled)
979 if (backendarrayunits > 1)
981 if (gl_state.units[j].arraycomponents == 4)
983 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
984 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
986 else if (gl_state.units[j].arraycomponents == 3)
988 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
989 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
991 else if (gl_state.units[j].arraycomponents == 2)
993 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
994 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
998 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
999 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
1004 if (gl_state.units[j].arraycomponents == 4)
1006 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
1007 qglTexCoord4f(p[0], p[1], p[2], p[3]);
1009 else if (gl_state.units[j].arraycomponents == 3)
1011 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
1012 qglTexCoord3f(p[0], p[1], p[2]);
1014 else if (gl_state.units[j].arraycomponents == 2)
1016 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
1017 qglTexCoord2f(p[0], p[1]);
1021 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
1022 qglTexCoord1f(p[0]);
1027 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
1029 p = ((const GLfloat *)(gl_state.pointer_color)) + elements[i] * 4;
1030 qglColor4f(p[0], p[1], p[2], p[3]);
1032 p = ((const GLfloat *)(gl_state.pointer_vertex)) + elements[i] * 3;
1033 qglVertex3f(p[0], p[1], p[2]);
1038 else if (gl_mesh_testarrayelement.integer)
1041 qglBegin(GL_TRIANGLES);
1042 for (i = 0;i < numtriangles * 3;i++)
1044 qglArrayElement(elements[i]);
1049 else if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
1051 GL_BindEBO(bufferobject);
1052 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_INT, bufferobject ? (void *)bufferoffset : elements);
1057 GL_BindEBO(bufferobject);
1058 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, bufferobject ? (void *)bufferoffset : elements);
1064 // restores backend state, used when done with 3D rendering
1065 void R_Mesh_Finish(void)
1070 GL_LockArrays(0, 0);
1073 for (i = 0;i < backendimageunits;i++)
1075 GL_ActiveTexture(i);
1076 qglBindTexture(GL_TEXTURE_1D, 0);CHECKGLERROR
1077 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1080 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1082 if (gl_texturecubemap)
1084 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1087 for (i = 0;i < backendarrayunits;i++)
1089 GL_ActiveTexture(backendarrayunits - 1 - i);
1090 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1092 for (i = 0;i < backendunits;i++)
1094 GL_ActiveTexture(backendunits - 1 - i);
1095 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1096 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1099 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1101 if (gl_texturecubemap)
1103 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1105 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1106 if (gl_combine.integer)
1108 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
1109 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
1112 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1113 qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1115 qglDisable(GL_BLEND);CHECKGLERROR
1116 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1117 qglDepthMask(GL_TRUE);CHECKGLERROR
1118 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);CHECKGLERROR
1121 int R_Mesh_CreateStaticBufferObject(unsigned int target, void *data, size_t size, const char *name)
1123 gl_bufferobjectinfo_t *info;
1124 GLuint bufferobject;
1126 if (!gl_vbo.integer)
1129 qglGenBuffersARB(1, &bufferobject);
1132 case GL_ELEMENT_ARRAY_BUFFER_ARB: GL_BindEBO(bufferobject);break;
1133 case GL_ARRAY_BUFFER_ARB: GL_BindVBO(bufferobject);break;
1134 default: Sys_Error("R_Mesh_CreateStaticBufferObject: unknown target type %i\n", target);return 0;
1136 qglBufferDataARB(target, size, data, GL_STATIC_DRAW_ARB);
1138 info = Mem_ExpandableArray_AllocRecord(&gl_bufferobjectinfoarray);
1139 memset(info, 0, sizeof(*info));
1140 info->target = target;
1141 info->object = bufferobject;
1143 strlcpy(info->name, name, sizeof(info->name));
1145 return (int)bufferobject;
1148 void R_Mesh_DestroyBufferObject(int bufferobject)
1151 gl_bufferobjectinfo_t *info;
1153 qglDeleteBuffersARB(1, (GLuint *)&bufferobject);
1155 endindex = Mem_ExpandableArray_IndexRange(&gl_bufferobjectinfoarray);
1156 for (i = 0;i < endindex;i++)
1158 info = Mem_ExpandableArray_RecordAtIndex(&gl_bufferobjectinfoarray, i);
1161 if (info->object == bufferobject)
1163 Mem_ExpandableArray_FreeRecord(&gl_bufferobjectinfoarray, (void *)info);
1169 void GL_Mesh_ListVBOs(qboolean printeach)
1172 size_t ebocount = 0, ebomemory = 0;
1173 size_t vbocount = 0, vbomemory = 0;
1174 gl_bufferobjectinfo_t *info;
1175 endindex = Mem_ExpandableArray_IndexRange(&gl_bufferobjectinfoarray);
1176 for (i = 0;i < endindex;i++)
1178 info = Mem_ExpandableArray_RecordAtIndex(&gl_bufferobjectinfoarray, i);
1181 switch(info->target)
1183 case GL_ELEMENT_ARRAY_BUFFER_ARB: ebocount++;ebomemory += info->size;if (printeach) Con_Printf("EBO #%i %s = %i bytes\n", info->object, info->name, (int)info->size);break;
1184 case GL_ARRAY_BUFFER_ARB: vbocount++;vbomemory += info->size;if (printeach) Con_Printf("VBO #%i %s = %i bytes\n", info->object, info->name, (int)info->size);break;
1185 default: Con_Printf("gl_vbostats: unknown target type %i\n", info->target);break;
1188 Con_Printf("vertex buffers: %i element buffers totalling %i bytes (%.3f MB), %i vertex buffers totalling %i bytes (%.3f MB), combined %i bytes (%.3fMB)\n", (int)ebocount, (int)ebomemory, ebomemory / 1048576.0, (int)vbocount, (int)vbomemory, vbomemory / 1048576.0, (int)(ebomemory + vbomemory), (ebomemory + vbomemory) / 1048576.0);
1191 void R_Mesh_Matrix(const matrix4x4_t *matrix)
1193 if (memcmp(matrix, &backend_modelmatrix, sizeof(matrix4x4_t)))
1195 double glmatrix[16];
1196 backend_modelmatrix = *matrix;
1197 Matrix4x4_Concat(&backend_modelviewmatrix, &backend_viewmatrix, matrix);
1198 Matrix4x4_ToArrayDoubleGL(&backend_modelviewmatrix, glmatrix);
1200 qglLoadMatrixd(glmatrix);CHECKGLERROR
1204 void R_Mesh_VertexPointer(const float *vertex3f, int bufferobject, size_t bufferoffset)
1206 if (!gl_vbo.integer)
1208 if (gl_state.pointer_vertex != vertex3f || gl_state.pointer_vertex_buffer != bufferobject || gl_state.pointer_vertex_offset != bufferoffset)
1210 gl_state.pointer_vertex = vertex3f;
1211 gl_state.pointer_vertex_buffer = bufferobject;
1212 gl_state.pointer_vertex_offset = bufferoffset;
1214 GL_BindVBO(bufferobject);
1215 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), bufferobject ? (void *)bufferoffset : vertex3f);CHECKGLERROR
1219 void R_Mesh_ColorPointer(const float *color4f, int bufferobject, size_t bufferoffset)
1221 // note: this can not rely on bufferobject to decide whether a color array
1222 // is supplied, because surfmesh_t shares one vbo for all arrays, which
1223 // means that a valid vbo may be supplied even if there is no color array.
1226 if (!gl_vbo.integer)
1228 // caller wants color array enabled
1229 if (!gl_state.pointer_color_enabled)
1231 gl_state.pointer_color_enabled = true;
1233 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1235 if (gl_state.pointer_color != color4f || gl_state.pointer_color_buffer != bufferobject || gl_state.pointer_color_offset != bufferoffset)
1237 gl_state.pointer_color = color4f;
1238 gl_state.pointer_color_buffer = bufferobject;
1239 gl_state.pointer_color_offset = bufferoffset;
1241 GL_BindVBO(bufferobject);
1242 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), bufferobject ? (void *)bufferoffset : color4f);CHECKGLERROR
1247 // caller wants color array disabled
1248 if (gl_state.pointer_color_enabled)
1250 gl_state.pointer_color_enabled = false;
1252 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1253 // when color array is on the glColor gets trashed, set it again
1254 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
1259 void R_Mesh_TexCoordPointer(unsigned int unitnum, unsigned int numcomponents, const float *texcoord, int bufferobject, size_t bufferoffset)
1261 gltextureunit_t *unit = gl_state.units + unitnum;
1262 // update array settings
1264 // note: there is no need to check bufferobject here because all cases
1265 // that involve a valid bufferobject also supply a texcoord array
1268 if (!gl_vbo.integer)
1270 // texture array unit is enabled, enable the array
1271 if (!unit->arrayenabled)
1273 unit->arrayenabled = true;
1274 GL_ClientActiveTexture(unitnum);
1275 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1278 if (unit->pointer_texcoord != texcoord || unit->pointer_texcoord_buffer != bufferobject || unit->pointer_texcoord_offset != bufferoffset || unit->arraycomponents != numcomponents)
1280 unit->pointer_texcoord = texcoord;
1281 unit->pointer_texcoord_buffer = bufferobject;
1282 unit->pointer_texcoord_offset = bufferoffset;
1283 unit->arraycomponents = numcomponents;
1284 GL_ClientActiveTexture(unitnum);
1285 GL_BindVBO(bufferobject);
1286 qglTexCoordPointer(unit->arraycomponents, GL_FLOAT, sizeof(float) * unit->arraycomponents, bufferobject ? (void *)bufferoffset : texcoord);CHECKGLERROR
1291 // texture array unit is disabled, disable the array
1292 if (unit->arrayenabled)
1294 unit->arrayenabled = false;
1295 GL_ClientActiveTexture(unitnum);
1296 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1301 void R_Mesh_TexBindAll(unsigned int unitnum, int tex1d, int tex2d, int tex3d, int texcubemap)
1303 gltextureunit_t *unit = gl_state.units + unitnum;
1304 if (unitnum >= backendimageunits)
1306 // update 1d texture binding
1307 if (unit->t1d != tex1d)
1309 GL_ActiveTexture(unitnum);
1310 if (unitnum < backendunits)
1316 qglEnable(GL_TEXTURE_1D);CHECKGLERROR
1323 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1328 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1330 // update 2d texture binding
1331 if (unit->t2d != tex2d)
1333 GL_ActiveTexture(unitnum);
1334 if (unitnum < backendunits)
1340 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
1347 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1352 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1354 // update 3d texture binding
1355 if (unit->t3d != tex3d)
1357 GL_ActiveTexture(unitnum);
1358 if (unitnum < backendunits)
1364 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
1371 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1376 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1378 // update cubemap texture binding
1379 if (unit->tcubemap != texcubemap)
1381 GL_ActiveTexture(unitnum);
1382 if (unitnum < backendunits)
1386 if (unit->tcubemap == 0)
1388 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1395 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1399 unit->tcubemap = texcubemap;
1400 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1404 void R_Mesh_TexBind1D(unsigned int unitnum, int texnum)
1406 gltextureunit_t *unit = gl_state.units + unitnum;
1407 if (unitnum >= backendimageunits)
1409 // update 1d texture binding
1410 if (unit->t1d != texnum)
1412 GL_ActiveTexture(unitnum);
1413 if (unitnum < backendunits)
1419 qglEnable(GL_TEXTURE_1D);CHECKGLERROR
1426 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1431 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1433 // update 2d texture binding
1436 GL_ActiveTexture(unitnum);
1437 if (unitnum < backendunits)
1441 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1445 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1447 // update 3d texture binding
1450 GL_ActiveTexture(unitnum);
1451 if (unitnum < backendunits)
1455 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1459 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1461 // update cubemap texture binding
1464 GL_ActiveTexture(unitnum);
1465 if (unitnum < backendunits)
1469 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1473 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1477 void R_Mesh_TexBind(unsigned int unitnum, int texnum)
1479 gltextureunit_t *unit = gl_state.units + unitnum;
1480 if (unitnum >= backendimageunits)
1482 // update 1d texture binding
1485 GL_ActiveTexture(unitnum);
1486 if (unitnum < backendunits)
1490 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1494 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1496 // update 2d texture binding
1497 if (unit->t2d != texnum)
1499 GL_ActiveTexture(unitnum);
1500 if (unitnum < backendunits)
1506 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
1513 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1518 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1520 // update 3d texture binding
1523 GL_ActiveTexture(unitnum);
1524 if (unitnum < backendunits)
1528 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1532 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1534 // update cubemap texture binding
1535 if (unit->tcubemap != 0)
1537 GL_ActiveTexture(unitnum);
1538 if (unitnum < backendunits)
1542 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1546 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1550 void R_Mesh_TexBind3D(unsigned int unitnum, int texnum)
1552 gltextureunit_t *unit = gl_state.units + unitnum;
1553 if (unitnum >= backendimageunits)
1555 // update 1d texture binding
1558 GL_ActiveTexture(unitnum);
1559 if (unitnum < backendunits)
1563 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1567 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1569 // update 2d texture binding
1572 GL_ActiveTexture(unitnum);
1573 if (unitnum < backendunits)
1577 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1581 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1583 // update 3d texture binding
1584 if (unit->t3d != texnum)
1586 GL_ActiveTexture(unitnum);
1587 if (unitnum < backendunits)
1593 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
1600 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1605 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1607 // update cubemap texture binding
1608 if (unit->tcubemap != 0)
1610 GL_ActiveTexture(unitnum);
1611 if (unitnum < backendunits)
1615 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1619 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1623 void R_Mesh_TexBindCubeMap(unsigned int unitnum, int texnum)
1625 gltextureunit_t *unit = gl_state.units + unitnum;
1626 if (unitnum >= backendimageunits)
1628 // update 1d texture binding
1631 GL_ActiveTexture(unitnum);
1632 if (unitnum < backendunits)
1636 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1640 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1642 // update 2d texture binding
1645 GL_ActiveTexture(unitnum);
1646 if (unitnum < backendunits)
1650 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1654 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1656 // update 3d texture binding
1659 GL_ActiveTexture(unitnum);
1660 if (unitnum < backendunits)
1664 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1668 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1670 // update cubemap texture binding
1671 if (unit->tcubemap != texnum)
1673 GL_ActiveTexture(unitnum);
1674 if (unitnum < backendunits)
1678 if (unit->tcubemap == 0)
1680 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1687 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1691 unit->tcubemap = texnum;
1692 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1696 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
1698 gltextureunit_t *unit = gl_state.units + unitnum;
1699 if (matrix->m[3][3])
1701 // texmatrix specified, check if it is different
1702 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
1704 double glmatrix[16];
1705 unit->texmatrixenabled = true;
1706 unit->matrix = *matrix;
1708 Matrix4x4_ToArrayDoubleGL(&unit->matrix, glmatrix);
1709 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1710 GL_ActiveTexture(unitnum);
1711 qglLoadMatrixd(glmatrix);CHECKGLERROR
1712 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1717 // no texmatrix specified, revert to identity
1718 if (unit->texmatrixenabled)
1720 unit->texmatrixenabled = false;
1722 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1723 GL_ActiveTexture(unitnum);
1724 qglLoadIdentity();CHECKGLERROR
1725 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1730 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
1732 gltextureunit_t *unit = gl_state.units + unitnum;
1734 if (gl_combine.integer)
1736 // GL_ARB_texture_env_combine
1738 combinergb = GL_MODULATE;
1740 combinealpha = GL_MODULATE;
1745 if (unit->combinergb != combinergb)
1747 unit->combinergb = combinergb;
1748 GL_ActiveTexture(unitnum);
1749 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1751 if (unit->combinealpha != combinealpha)
1753 unit->combinealpha = combinealpha;
1754 GL_ActiveTexture(unitnum);
1755 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1757 if (unit->rgbscale != rgbscale)
1759 GL_ActiveTexture(unitnum);
1760 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = rgbscale));CHECKGLERROR
1762 if (unit->alphascale != alphascale)
1764 GL_ActiveTexture(unitnum);
1765 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = alphascale));CHECKGLERROR
1772 combinergb = GL_MODULATE;
1773 if (unit->combinergb != combinergb)
1775 unit->combinergb = combinergb;
1776 GL_ActiveTexture(unitnum);
1777 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
1782 void R_Mesh_TextureState(const rmeshstate_t *m)
1789 if (gl_backend_rebindtextures)
1791 gl_backend_rebindtextures = false;
1792 GL_SetupTextureState();
1796 for (i = 0;i < backendimageunits;i++)
1797 R_Mesh_TexBindAll(i, m->tex1d[i], m->tex[i], m->tex3d[i], m->texcubemap[i]);
1798 for (i = 0;i < backendarrayunits;i++)
1800 if (m->pointer_texcoord3f[i])
1801 R_Mesh_TexCoordPointer(i, 3, m->pointer_texcoord3f[i], m->pointer_texcoord_bufferobject[i], m->pointer_texcoord_bufferoffset[i]);
1803 R_Mesh_TexCoordPointer(i, 2, m->pointer_texcoord[i], m->pointer_texcoord_bufferobject[i], m->pointer_texcoord_bufferoffset[i]);
1805 for (i = 0;i < backendunits;i++)
1807 R_Mesh_TexMatrix(i, &m->texmatrix[i]);
1808 R_Mesh_TexCombine(i, m->texcombinergb[i], m->texcombinealpha[i], m->texrgbscale[i], m->texalphascale[i]);
1813 void R_Mesh_ResetTextureState(void)
1815 unsigned int unitnum;
1820 if (gl_backend_rebindtextures)
1822 gl_backend_rebindtextures = false;
1823 GL_SetupTextureState();
1827 for (unitnum = 0;unitnum < backendimageunits;unitnum++)
1829 gltextureunit_t *unit = gl_state.units + unitnum;
1830 // update 1d texture binding
1833 GL_ActiveTexture(unitnum);
1834 if (unitnum < backendunits)
1836 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1839 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1841 // update 2d texture binding
1844 GL_ActiveTexture(unitnum);
1845 if (unitnum < backendunits)
1847 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1850 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1852 // update 3d texture binding
1855 GL_ActiveTexture(unitnum);
1856 if (unitnum < backendunits)
1858 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1861 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1863 // update cubemap texture binding
1866 GL_ActiveTexture(unitnum);
1867 if (unitnum < backendunits)
1869 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1872 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1875 for (unitnum = 0;unitnum < backendarrayunits;unitnum++)
1877 gltextureunit_t *unit = gl_state.units + unitnum;
1878 // texture array unit is disabled, disable the array
1879 if (unit->arrayenabled)
1881 unit->arrayenabled = false;
1882 GL_ClientActiveTexture(unitnum);
1883 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1886 for (unitnum = 0;unitnum < backendunits;unitnum++)
1888 gltextureunit_t *unit = gl_state.units + unitnum;
1889 // no texmatrix specified, revert to identity
1890 if (unit->texmatrixenabled)
1892 unit->texmatrixenabled = false;
1894 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1895 GL_ActiveTexture(unitnum);
1896 qglLoadIdentity();CHECKGLERROR
1897 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1899 if (gl_combine.integer)
1901 // GL_ARB_texture_env_combine
1902 if (unit->combinergb != GL_MODULATE)
1904 unit->combinergb = GL_MODULATE;
1905 GL_ActiveTexture(unitnum);
1906 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1908 if (unit->combinealpha != GL_MODULATE)
1910 unit->combinealpha = GL_MODULATE;
1911 GL_ActiveTexture(unitnum);
1912 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1914 if (unit->rgbscale != 1)
1916 GL_ActiveTexture(unitnum);
1917 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = 1));CHECKGLERROR
1919 if (unit->alphascale != 1)
1921 GL_ActiveTexture(unitnum);
1922 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = 1));CHECKGLERROR
1928 if (unit->combinergb != GL_MODULATE)
1930 unit->combinergb = GL_MODULATE;
1931 GL_ActiveTexture(unitnum);
1932 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
1938 void R_Mesh_Draw_ShowTris(int firstvertex, int numvertices, int numtriangles, const int *elements)
1942 for (;numtriangles;numtriangles--, elements += 3)
1944 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
1945 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
1946 qglArrayElement(elements[2]);qglArrayElement(elements[0]);