4 cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "1024"};
5 cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "1"};
6 cvar_t gl_mesh_drawmode = {CVAR_SAVE, "gl_mesh_drawmode", "3"};
8 cvar_t r_render = {0, "r_render", "1"};
9 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1"}; // whether or not to use dithering
10 cvar_t gl_lockarrays = {0, "gl_lockarrays", "1"};
12 // this is used to increase gl_mesh_maxtriangles automatically if a mesh was
13 // too large for the buffers in the previous frame
14 int overflowedverts = 0;
16 int gl_maxdrawrangeelementsvertices;
17 int gl_maxdrawrangeelementsindices;
22 void GL_PrintError(int errornumber, char *filename, int linenumber)
26 #ifdef GL_INVALID_ENUM
28 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
31 #ifdef GL_INVALID_VALUE
32 case GL_INVALID_VALUE:
33 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
36 #ifdef GL_INVALID_OPERATION
37 case GL_INVALID_OPERATION:
38 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
41 #ifdef GL_STACK_OVERFLOW
42 case GL_STACK_OVERFLOW:
43 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
46 #ifdef GL_STACK_UNDERFLOW
47 case GL_STACK_UNDERFLOW:
48 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
51 #ifdef GL_OUT_OF_MEMORY
52 case GL_OUT_OF_MEMORY:
53 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
56 #ifdef GL_TABLE_TOO_LARGE
57 case GL_TABLE_TOO_LARGE:
58 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
62 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
68 #define BACKENDACTIVECHECK if (!backendactive) Sys_Error("GL backend function called when backend is not active\n");
72 static float viewdist;
73 // sign bits (true if negative) for vpn[] entries, so quick integer compares can be used instead of float compares
74 static int vpnbit0, vpnbit1, vpnbit2;
76 int c_meshs, c_meshtris;
80 float overbrightscale;
82 void SCR_ScreenShot_f (void);
84 // these are externally accessible
85 float mesh_colorscale;
89 float *varray_texcoord[MAX_TEXTUREUNITS];
91 int mesh_maxverts; // always mesh_maxtris * 3
93 static matrix4x4_t backend_viewmatrix;
94 static matrix4x4_t backend_modelmatrix;
95 static matrix4x4_t backend_modelviewmatrix;
96 static matrix4x4_t backend_glmodelviewmatrix;
98 static int backendunits, backendactive;
99 static qbyte *varray_bcolor;
100 static mempool_t *gl_backend_mempool;
102 void GL_Backend_AllocArrays(void)
106 if (!gl_backend_mempool)
107 gl_backend_mempool = Mem_AllocPool("GL_Backend");
109 mesh_maxverts = mesh_maxtris * 3;
111 varray_element = Mem_Alloc(gl_backend_mempool, mesh_maxtris * sizeof(int[3]));
112 varray_vertex = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(float[4]));
113 varray_color = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(float[4]));
114 varray_bcolor = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(qbyte[4]));
115 for (i = 0;i < backendunits;i++)
116 varray_texcoord[i] = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(float[2]));
117 for (;i < MAX_TEXTUREUNITS;i++)
118 varray_texcoord[i] = NULL;
121 void GL_Backend_FreeArrays(int resizingbuffers)
125 Mem_EmptyPool(gl_backend_mempool);
127 Mem_FreePool(&gl_backend_mempool);
128 varray_element = NULL;
129 varray_vertex = NULL;
131 varray_bcolor = NULL;
132 for (i = 0;i < MAX_TEXTUREUNITS;i++)
133 varray_texcoord[i] = NULL;
136 static void gl_backend_start(void)
138 Con_Printf("OpenGL Backend started with gl_mesh_maxtriangles %i\n", gl_mesh_maxtriangles.integer);
139 if (qglDrawRangeElements != NULL)
141 qglGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &gl_maxdrawrangeelementsvertices);
142 qglGetIntegerv(GL_MAX_ELEMENTS_INDICES, &gl_maxdrawrangeelementsindices);
144 Con_Printf("glDrawRangeElements detected (max vertices %i, max indices %i)\n", gl_maxdrawrangeelementsvertices, gl_maxdrawrangeelementsindices);
146 if (strstr(gl_renderer, "3Dfx"))
148 Con_Printf("3Dfx driver detected, forcing gl_mesh_floatcolors to 0 to prevent crashs\n");
149 Cvar_SetValueQuick(&gl_mesh_floatcolors, 0);
152 backendunits = min(MAX_TEXTUREUNITS, gl_textureunits);
154 GL_Backend_AllocArrays();
156 backendactive = true;
159 static void gl_backend_shutdown(void)
162 backendactive = false;
164 Con_Printf("OpenGL Backend shutting down\n");
166 GL_Backend_FreeArrays(false);
169 void GL_Backend_CheckCvars(void)
171 if (gl_mesh_drawmode.integer < 0)
172 Cvar_SetValueQuick(&gl_mesh_drawmode, 0);
173 if (gl_mesh_drawmode.integer > 3)
174 Cvar_SetValueQuick(&gl_mesh_drawmode, 3);
176 // change drawmode 3 to 2 if 3 won't work
177 if (gl_mesh_drawmode.integer >= 3 && qglDrawRangeElements == NULL)
178 Cvar_SetValueQuick(&gl_mesh_drawmode, 2);
180 // 21760 is (65536 / 3) rounded off to a multiple of 128
181 if (gl_mesh_maxtriangles.integer < 1024)
182 Cvar_SetValueQuick(&gl_mesh_maxtriangles, 1024);
183 if (gl_mesh_maxtriangles.integer > 21760)
184 Cvar_SetValueQuick(&gl_mesh_maxtriangles, 21760);
187 void GL_Backend_ResizeArrays(int numtriangles)
189 Cvar_SetValueQuick(&gl_mesh_maxtriangles, numtriangles);
190 GL_Backend_CheckCvars();
191 mesh_maxtris = gl_mesh_maxtriangles.integer;
192 GL_Backend_FreeArrays(true);
193 GL_Backend_AllocArrays();
196 static void gl_backend_newmap(void)
200 void gl_backend_init(void)
202 Cvar_RegisterVariable(&r_render);
203 Cvar_RegisterVariable(&gl_dither);
204 Cvar_RegisterVariable(&gl_lockarrays);
206 Cvar_SetValue("r_render", 0);
209 Cvar_RegisterVariable(&gl_mesh_maxtriangles);
210 Cvar_RegisterVariable(&gl_mesh_floatcolors);
211 Cvar_RegisterVariable(&gl_mesh_drawmode);
212 GL_Backend_CheckCvars();
213 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
216 int arraylocked = false;
218 void GL_LockArray(int first, int count)
220 if (!arraylocked && gl_supportslockarrays && gl_lockarrays.integer && gl_mesh_drawmode.integer > 0)
222 qglLockArraysEXT(first, count);
228 void GL_UnlockArray(void)
232 qglUnlockArraysEXT();
243 static void GL_SetupFrame (void)
246 double fovx, fovy, zNear, zFar, aspect;
248 if (!r_render.integer)
251 qglDepthFunc (GL_LEQUAL);CHECKGLERROR
254 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
255 qglLoadIdentity ();CHECKGLERROR
257 // y is weird beause OpenGL is bottom to top, we use top to bottom
258 qglViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height);CHECKGLERROR
262 zFar = r_mesh_farclip;
267 fovx = r_refdef.fov_x;
268 fovy = r_refdef.fov_y;
269 aspect = r_refdef.width / r_refdef.height;
272 xmax = zNear * tan(fovx * M_PI / 360.0) * aspect;
273 ymax = zNear * tan(fovy * M_PI / 360.0);
276 qglFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar);CHECKGLERROR
278 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
280 Matrix4x4_CreateRotate(&backend_viewmatrix, -90, 1, 0, 0);
281 Matrix4x4_ConcatRotate(&backend_viewmatrix, 90, 0, 0, 1);
282 Matrix4x4_ConcatRotate(&backend_viewmatrix, -r_refdef.viewangles[2], 1, 0, 0);
283 Matrix4x4_ConcatRotate(&backend_viewmatrix, -r_refdef.viewangles[0], 0, 1, 0);
284 Matrix4x4_ConcatRotate(&backend_viewmatrix, -r_refdef.viewangles[1], 0, 0, 1);
285 Matrix4x4_ConcatTranslate(&backend_viewmatrix, -r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
286 //Con_Printf("Our Matrix:\n");
287 //Matrix4x4_Print(&backend_viewmatrix);
289 //Matrix4x4_Transpose(&backend_glmodelviewmatrix, &backend_viewmatrix);
290 //qglLoadMatrixf(&backend_glmodelviewmatrix.m[0][0]);CHECKGLERROR
291 memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
295 qglLoadIdentity ();CHECKGLERROR
296 qglRotatef (-90, 1, 0, 0);CHECKGLERROR
297 qglRotatef (90, 0, 0, 1);CHECKGLERROR
299 qglRotatef (-r_refdef.viewangles[2], 1, 0, 0);CHECKGLERROR
300 qglRotatef (-r_refdef.viewangles[0], 0, 1, 0);CHECKGLERROR
301 qglRotatef (-r_refdef.viewangles[1], 0, 0, 1);CHECKGLERROR
303 qglTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);CHECKGLERROR
304 qglGetFloatv (GL_MODELVIEW_MATRIX, &gl_viewmatrix.m[0][0]);
305 Matrix4x4_Transpose(&backend_viewmatrix, &gl_viewmatrix);
306 Con_Printf("GL Matrix:\n");
307 Matrix4x4_Print(&backend_viewmatrix);
320 int texture[MAX_TEXTUREUNITS];
321 float texturergbscale[MAX_TEXTUREUNITS];
325 void GL_SetupTextureState(void)
328 if (backendunits > 1)
330 for (i = 0;i < backendunits;i++)
332 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
333 qglBindTexture(GL_TEXTURE_2D, gl_state.texture[i]);CHECKGLERROR
334 if (gl_combine.integer)
336 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
337 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);CHECKGLERROR
338 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);CHECKGLERROR
339 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
340 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB);CHECKGLERROR
341 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
342 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
343 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);CHECKGLERROR
344 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);CHECKGLERROR
345 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);CHECKGLERROR
346 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
347 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);CHECKGLERROR
348 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
349 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
350 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
351 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, gl_state.texturergbscale[i]);CHECKGLERROR
352 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
356 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
358 if (gl_state.texture[i])
360 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
364 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
366 if (gl_mesh_drawmode.integer > 0)
368 qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR
369 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), varray_texcoord[i]);CHECKGLERROR
370 if (gl_state.texture[i])
372 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
376 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
383 qglBindTexture(GL_TEXTURE_2D, gl_state.texture[0]);CHECKGLERROR
384 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
385 if (gl_state.texture[0])
387 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
391 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
393 if (gl_mesh_drawmode.integer > 0)
395 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), varray_texcoord[0]);CHECKGLERROR
396 if (gl_state.texture[0])
398 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
402 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
409 void GL_Backend_ResetState(void)
413 gl_state.clientunit = 0;
415 for (i = 0;i < backendunits;i++)
417 gl_state.texture[i] = 0;
418 gl_state.texturergbscale[i] = 1;
421 qglEnable(GL_CULL_FACE);CHECKGLERROR
422 qglCullFace(GL_FRONT);CHECKGLERROR
424 gl_state.depthdisable = false;
425 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
427 gl_state.blendfunc1 = GL_ONE;
428 gl_state.blendfunc2 = GL_ZERO;
429 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
432 qglDisable(GL_BLEND);CHECKGLERROR
434 gl_state.depthmask = GL_TRUE;
435 qglDepthMask(gl_state.depthmask);CHECKGLERROR
438 if (gl_mesh_drawmode.integer > 0)
441 qglVertexPointer(3, GL_FLOAT, sizeof(float[4]), varray_vertex);CHECKGLERROR
442 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
443 if (gl_mesh_floatcolors.integer)
445 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), varray_color);CHECKGLERROR
449 qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(qbyte[4]), varray_bcolor);CHECKGLERROR
451 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
454 GL_SetupTextureState();
457 // called at beginning of frame
458 void R_Mesh_Start(float farclip)
464 r_mesh_farclip = farclip;
465 viewdist = DotProduct(r_origin, vpn);
466 vpnbit0 = vpn[0] < 0;
467 vpnbit1 = vpn[1] < 0;
468 vpnbit2 = vpn[2] < 0;
473 GL_Backend_CheckCvars();
474 if (mesh_maxtris != gl_mesh_maxtriangles.integer)
475 GL_Backend_ResizeArrays(gl_mesh_maxtriangles.integer);
479 GL_Backend_ResetState();
482 int gl_backend_rebindtextures;
484 void GL_ConvertColorsFloatToByte(int numverts)
487 // LordHavoc: to avoid problems with aliasing (treating memory as two
488 // different types - exactly what this is doing), these must be volatile
490 volatile int *icolor;
491 volatile float *fcolor;
494 total = numverts * 4;
496 // shift float to have 8bit fraction at base of number
497 fcolor = varray_color;
498 for (i = 0;i < total;)
500 fcolor[i ] += 32768.0f;
501 fcolor[i + 1] += 32768.0f;
502 fcolor[i + 2] += 32768.0f;
503 fcolor[i + 3] += 32768.0f;
507 // then read as integer and kill float bits...
508 icolor = (int *)varray_color;
509 bcolor = varray_bcolor;
510 for (i = 0;i < total;)
512 k = icolor[i ] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i ] = (qbyte) k;
513 k = icolor[i + 1] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i + 1] = (qbyte) k;
514 k = icolor[i + 2] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i + 2] = (qbyte) k;
515 k = icolor[i + 3] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i + 3] = (qbyte) k;
521 void GL_TransformVertices(int numverts)
524 float m[12], tempv[4], *v;
525 m[0] = backendmatrix.m[0][0];
526 m[1] = backendmatrix.m[0][1];
527 m[2] = backendmatrix.m[0][2];
528 m[3] = backendmatrix.m[0][3];
529 m[4] = backendmatrix.m[1][0];
530 m[5] = backendmatrix.m[1][1];
531 m[6] = backendmatrix.m[1][2];
532 m[7] = backendmatrix.m[1][3];
533 m[8] = backendmatrix.m[2][0];
534 m[9] = backendmatrix.m[2][1];
535 m[10] = backendmatrix.m[2][2];
536 m[11] = backendmatrix.m[2][3];
537 for (i = 0, v = varray_vertex;i < numverts;i++, v += 4)
539 VectorCopy(v, tempv);
540 v[0] = tempv[0] * m[0] + tempv[1] * m[1] + tempv[2] * m[2] + m[3];
541 v[1] = tempv[0] * m[4] + tempv[1] * m[5] + tempv[2] * m[6] + m[7];
542 v[2] = tempv[0] * m[8] + tempv[1] * m[9] + tempv[2] * m[10] + m[11];
547 void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, GLuint *index)
549 unsigned int i, j, in;
552 GL_LockArray(firstvert, endvert - firstvert);
553 if (gl_mesh_drawmode.integer >= 3/* && (endvert - firstvert) <= gl_maxdrawrangeelementsvertices && (indexcount) <= gl_maxdrawrangeelementsindices*/)
555 // GL 1.2 or GL 1.1 with extension
556 qglDrawRangeElements(GL_TRIANGLES, firstvert, endvert, indexcount, GL_UNSIGNED_INT, index);
559 else if (gl_mesh_drawmode.integer >= 2)
562 qglDrawElements(GL_TRIANGLES, indexcount, GL_UNSIGNED_INT, index);
565 else if (gl_mesh_drawmode.integer >= 1)
568 // feed it manually using glArrayElement
569 qglBegin(GL_TRIANGLES);
570 for (i = 0;i < indexcount;i++)
571 qglArrayElement(index[i]);
577 // GL 1.1 but not using vertex arrays - 3dfx glquake minigl driver
579 qglBegin(GL_TRIANGLES);
580 if (gl_state.texture[1]) // if the mesh uses multiple textures
582 // the minigl doesn't have this (because it does not have ARB_multitexture)
583 for (i = 0;i < indexcount;i++)
586 c = varray_bcolor + in * 4;
587 qglColor4ub(c[0], c[1], c[2], c[3]);
588 for (j = 0;j < backendunits;j++)
590 if (gl_state.texture[j])
592 v = varray_texcoord[j] + in * 2;
593 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, v[0], v[1]);
596 v = varray_vertex + in * 4;
597 qglVertex3f(v[0], v[1], v[2]);
602 for (i = 0;i < indexcount;i++)
605 c = varray_bcolor + in * 4;
606 qglColor4ub(c[0], c[1], c[2], c[3]);
607 if (gl_state.texture[0])
609 v = varray_texcoord[0] + in * 2;
610 qglTexCoord2f(v[0], v[1]);
612 v = varray_vertex + in * 4;
613 qglVertex3f(v[0], v[1], v[2]);
622 // enlarges geometry buffers if they are too small
623 void _R_Mesh_ResizeCheck(int numverts, int numtriangles)
625 if (numtriangles > mesh_maxtris || numverts > mesh_maxverts)
628 GL_Backend_ResizeArrays(max(numtriangles, (numverts + 2) / 3) + 100);
629 GL_Backend_ResetState();
634 void R_Mesh_Draw(int numverts, int numtriangles)
639 c_meshtris += numtriangles;
643 // drawmode 0 always uses byte colors
644 if (!gl_mesh_floatcolors.integer || gl_mesh_drawmode.integer <= 0)
645 GL_ConvertColorsFloatToByte(numverts);
646 //GL_TransformVertices(numverts);
647 if (!r_render.integer)
649 GL_DrawRangeElements(0, numverts, numtriangles * 3, varray_element);
652 // restores backend state, used when done with 3D rendering
653 void R_Mesh_Finish(void)
658 if (backendunits > 1)
660 for (i = backendunits - 1;i >= 0;i--)
662 qglActiveTexture(GL_TEXTURE0_ARB + i);CHECKGLERROR
663 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
664 if (gl_combine.integer)
666 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
670 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
674 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
676 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
680 qglClientActiveTexture(GL_TEXTURE0_ARB + i);CHECKGLERROR
681 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
687 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
688 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
691 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
696 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
697 qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
700 qglDisable(GL_BLEND);CHECKGLERROR
701 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
702 qglDepthMask(GL_TRUE);CHECKGLERROR
703 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);CHECKGLERROR
706 void R_Mesh_ClearDepth(void)
711 qglClear(GL_DEPTH_BUFFER_BIT);
712 R_Mesh_Start(r_mesh_farclip);
715 void R_Mesh_Matrix(const matrix4x4_t *matrix)
717 if (memcmp(matrix, &backend_modelmatrix, sizeof(matrix4x4_t)))
719 backend_modelmatrix = *matrix;
720 Matrix4x4_Concat(&backend_modelviewmatrix, &backend_viewmatrix, matrix);
721 Matrix4x4_Transpose(&backend_glmodelviewmatrix, &backend_modelviewmatrix);
722 qglLoadMatrixf(&backend_glmodelviewmatrix.m[0][0]);
726 // sets up the requested state
727 void R_Mesh_State(const rmeshstate_t *m)
730 int texturergbscale[MAX_TEXTUREUNITS];
735 if (gl_backend_rebindtextures)
737 gl_backend_rebindtextures = false;
738 GL_SetupTextureState();
743 if (m->blendfunc1 == GL_DST_COLOR)
745 // check if it is a 2x modulate with framebuffer
746 if (m->blendfunc2 == GL_SRC_COLOR)
749 else if (m->blendfunc2 != GL_SRC_COLOR)
753 overbright = m->wantoverbright && gl_combine.integer;
757 scaler *= overbrightscale;
759 mesh_colorscale = scaler;
761 if (gl_state.blendfunc1 != m->blendfunc1 || gl_state.blendfunc2 != m->blendfunc2)
763 qglBlendFunc(gl_state.blendfunc1 = m->blendfunc1, gl_state.blendfunc2 = m->blendfunc2);CHECKGLERROR
764 if (gl_state.blendfunc2 == GL_ZERO)
766 if (gl_state.blendfunc1 == GL_ONE)
771 qglDisable(GL_BLEND);CHECKGLERROR
779 qglEnable(GL_BLEND);CHECKGLERROR
788 qglEnable(GL_BLEND);CHECKGLERROR
792 if (gl_state.depthdisable != m->depthdisable)
794 gl_state.depthdisable = m->depthdisable;
795 if (gl_state.depthdisable)
796 qglDisable(GL_DEPTH_TEST);
798 qglEnable(GL_DEPTH_TEST);
800 if (gl_state.depthmask != (m->blendfunc2 == GL_ZERO || m->depthwrite))
802 qglDepthMask(gl_state.depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite));CHECKGLERROR
805 for (i = 0;i < backendunits;i++)
807 if (m->texrgbscale[i])
808 texturergbscale[i] = m->texrgbscale[i];
810 texturergbscale[i] = 1;
814 for (i = backendunits - 1;i >= 0;i--)
818 texturergbscale[i] = 4;
824 if (backendunits > 1)
826 for (i = 0;i < backendunits;i++)
828 if (gl_state.texture[i] != m->tex[i])
830 if (gl_state.unit != i)
832 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
834 if (gl_state.texture[i] == 0)
836 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
837 if (gl_state.clientunit != i)
839 qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR
841 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
843 qglBindTexture(GL_TEXTURE_2D, (gl_state.texture[i] = m->tex[i]));CHECKGLERROR
844 if (gl_state.texture[i] == 0)
846 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
847 if (gl_state.clientunit != i)
849 qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR
851 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
854 if (gl_state.texturergbscale[i] != texturergbscale[i])
856 if (gl_state.unit != i)
858 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
860 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (gl_state.texturergbscale[i] = texturergbscale[i]));CHECKGLERROR
866 if (gl_state.texture[0] != m->tex[0])
868 if (gl_state.texture[0] == 0)
870 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
871 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
873 qglBindTexture(GL_TEXTURE_2D, (gl_state.texture[0] = m->tex[0]));CHECKGLERROR
874 if (gl_state.texture[0] == 0)
876 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
877 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
884 ==============================================================================
888 ==============================================================================
891 qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height)
897 if (!r_render.integer)
900 buffer = Mem_Alloc(tempmempool, width*height*3);
901 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
904 // LordHavoc: compensate for v_overbrightbits when using hardware gamma
905 if (v_hwgamma.integer)
906 for (i = 0;i < width * height * 3;i++)
907 buffer[i] <<= v_overbrightbits.integer;
909 ret = Image_WriteTGARGB_preflipped(filename, width, height, buffer);
915 //=============================================================================
917 void R_ClearScreen(void)
919 if (r_render.integer)
922 qglClearColor(0,0,0,0);CHECKGLERROR
924 qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);CHECKGLERROR
925 // set dithering mode
926 if (gl_dither.integer)
928 qglEnable(GL_DITHER);CHECKGLERROR
932 qglDisable(GL_DITHER);CHECKGLERROR
941 This is called every frame, and can also be called explicitly to flush
945 void SCR_UpdateScreen (void)
949 R_TimeReport("finish");
951 if (r_textureunits.integer > gl_textureunits)
952 Cvar_SetValueQuick(&r_textureunits, gl_textureunits);
953 if (r_textureunits.integer < 1)
954 Cvar_SetValueQuick(&r_textureunits, 1);
956 if (gl_combine.integer && (!gl_combine_extension || r_textureunits.integer < 2))
957 Cvar_SetValueQuick(&gl_combine, 0);
960 overbrightscale = 1.0f / (float) (1 << v_overbrightbits.integer);
963 lightscalebit = v_overbrightbits.integer;
964 if (gl_combine.integer && r_textureunits.integer > 1)
966 lightscale = 1.0f / (float) (1 << lightscalebit);
968 R_TimeReport("setup");
972 R_TimeReport("clear");
974 if (scr_conlines < vid.conheight && cls.signon == SIGNONS)
980 // tell driver to commit it's partially full geometry queue to the rendering queue
981 // (this doesn't wait for the commands themselves to complete)