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);
70 static float viewdist;
71 // sign bits (true if negative) for vpn[] entries, so quick integer compares can be used instead of float compares
72 static int vpnbit0, vpnbit1, vpnbit2;
74 int c_meshs, c_meshtris;
78 float overbrightscale;
80 void SCR_ScreenShot_f (void);
83 static int max_verts; // always max_tris * 3
85 typedef struct buf_mesh_s
89 int blendfunc1, blendfunc2;
90 int textures[MAX_TEXTUREUNITS];
91 int texturergbscale[MAX_TEXTUREUNITS];
95 struct buf_mesh_s *chain;
99 typedef struct buf_tri_s
129 static int backendunits, backendactive;
130 static buf_mesh_t buf_mesh;
131 static buf_tri_t *buf_tri;
132 static buf_vertex_t *buf_vertex;
133 static buf_fcolor_t *buf_fcolor;
134 static buf_bcolor_t *buf_bcolor;
135 static buf_texcoord_t *buf_texcoord[MAX_TEXTUREUNITS];
137 static mempool_t *gl_backend_mempool;
138 static int resizingbuffers = false;
140 static void gl_backend_start(void)
144 qglGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &gl_maxdrawrangeelementsvertices);
145 qglGetIntegerv(GL_MAX_ELEMENTS_INDICES, &gl_maxdrawrangeelementsindices);
147 Con_Printf("OpenGL Backend started with gl_mesh_maxtriangles %i\n", gl_mesh_maxtriangles.integer);
148 if (qglDrawRangeElements != NULL)
149 Con_Printf("glDrawRangeElements detected (max vertices %i, max indices %i)\n", gl_maxdrawrangeelementsvertices, gl_maxdrawrangeelementsindices);
150 if (strstr(gl_renderer, "3Dfx"))
152 Con_Printf("3Dfx driver detected, forcing gl_mesh_floatcolors to 0 to prevent crashs\n");
153 Cvar_SetValueQuick(&gl_mesh_floatcolors, 0);
157 max_verts = max_tris * 3;
159 if (!gl_backend_mempool)
160 gl_backend_mempool = Mem_AllocPool("GL_Backend");
162 #define BACKENDALLOC(var, count, sizeofstruct, varname)\
164 var = Mem_Alloc(gl_backend_mempool, count * sizeof(sizeofstruct));\
166 Sys_Error("gl_backend_start: unable to allocate memory for %s (%d bytes)\n", (varname), count * sizeof(sizeofstruct));\
167 memset(var, 0, count * sizeof(sizeofstruct));\
170 BACKENDALLOC(buf_tri, max_tris, buf_tri_t, "buf_tri")
171 BACKENDALLOC(buf_vertex, max_verts, buf_vertex_t, "buf_vertex")
172 BACKENDALLOC(buf_fcolor, max_verts, buf_fcolor_t, "buf_fcolor")
173 BACKENDALLOC(buf_bcolor, max_verts, buf_bcolor_t, "buf_bcolor")
175 for (i = 0;i < MAX_TEXTUREUNITS;i++)
177 // only allocate as many texcoord arrays as we need
178 if (i < gl_textureunits)
180 BACKENDALLOC(buf_texcoord[i], max_verts, buf_texcoord_t, va("buf_texcoord[%d]", i))
184 buf_texcoord[i] = NULL;
187 backendunits = min(MAX_TEXTUREUNITS, gl_textureunits);
188 backendactive = true;
191 static void gl_backend_shutdown(void)
193 Con_Printf("OpenGL Backend shutting down\n");
196 Mem_EmptyPool(gl_backend_mempool);
198 Mem_FreePool(&gl_backend_mempool);
201 backendactive = false;
204 static void gl_backend_bufferchanges(int init)
206 if (overflowedverts > gl_mesh_maxtriangles.integer * 3)
207 Cvar_SetValueQuick(&gl_mesh_maxtriangles, (int) ((overflowedverts + 2) / 3));
210 if (gl_mesh_drawmode.integer < 0)
211 Cvar_SetValueQuick(&gl_mesh_drawmode, 0);
212 if (gl_mesh_drawmode.integer > 3)
213 Cvar_SetValueQuick(&gl_mesh_drawmode, 3);
215 if (gl_mesh_drawmode.integer >= 3 && qglDrawRangeElements == NULL)
217 // change drawmode 3 to 2 if 3 won't work at all
218 Cvar_SetValueQuick(&gl_mesh_drawmode, 2);
221 // 21760 is (65536 / 3) rounded off to a multiple of 128
222 if (gl_mesh_maxtriangles.integer < 1024)
223 Cvar_SetValueQuick(&gl_mesh_maxtriangles, 1024);
224 if (gl_mesh_maxtriangles.integer > 21760)
225 Cvar_SetValueQuick(&gl_mesh_maxtriangles, 21760);
227 if (max_tris != gl_mesh_maxtriangles.integer)
229 max_tris = gl_mesh_maxtriangles.integer;
233 resizingbuffers = true;
234 gl_backend_shutdown();
236 resizingbuffers = false;
241 static void gl_backend_newmap(void)
245 void gl_backend_init(void)
247 Cvar_RegisterVariable(&r_render);
248 Cvar_RegisterVariable(&gl_dither);
249 Cvar_RegisterVariable(&gl_lockarrays);
251 Cvar_SetValue("r_render", 0);
254 Cvar_RegisterVariable(&gl_mesh_maxtriangles);
255 Cvar_RegisterVariable(&gl_mesh_floatcolors);
256 Cvar_RegisterVariable(&gl_mesh_drawmode);
257 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
258 gl_backend_bufferchanges(true);
261 int arraylocked = false;
263 void GL_LockArray(int first, int count)
265 if (!arraylocked && gl_supportslockarrays && gl_lockarrays.integer && gl_mesh_drawmode.integer > 0)
267 qglLockArraysEXT(first, count);
273 void GL_UnlockArray(void)
277 qglUnlockArraysEXT();
288 static void GL_SetupFrame (void)
291 double fovx, fovy, zNear, zFar, aspect;
293 if (!r_render.integer)
296 qglDepthFunc (GL_LEQUAL);CHECKGLERROR
299 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
300 qglLoadIdentity ();CHECKGLERROR
302 // y is weird beause OpenGL is bottom to top, we use top to bottom
303 qglViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height);CHECKGLERROR
307 zFar = r_mesh_farclip;
312 fovx = r_refdef.fov_x;
313 fovy = r_refdef.fov_y;
314 aspect = r_refdef.width / r_refdef.height;
317 xmax = zNear * tan(fovx * M_PI / 360.0) * aspect;
318 ymax = zNear * tan(fovy * M_PI / 360.0);
321 qglFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar);CHECKGLERROR
323 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
324 qglLoadIdentity ();CHECKGLERROR
327 qglRotatef (-90, 1, 0, 0);CHECKGLERROR
328 qglRotatef (90, 0, 0, 1);CHECKGLERROR
330 qglRotatef (-r_refdef.viewangles[2], 1, 0, 0);CHECKGLERROR
331 qglRotatef (-r_refdef.viewangles[0], 0, 1, 0);CHECKGLERROR
332 qglRotatef (-r_refdef.viewangles[1], 0, 0, 1);CHECKGLERROR
334 qglTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);CHECKGLERROR
346 int texture[MAX_TEXTUREUNITS];
347 float texturergbscale[MAX_TEXTUREUNITS];
351 void GL_SetupTextureState(void)
354 if (backendunits > 1)
356 for (i = 0;i < backendunits;i++)
358 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
359 qglBindTexture(GL_TEXTURE_2D, gl_state.texture[i]);CHECKGLERROR
360 if (gl_combine.integer)
362 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
363 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);CHECKGLERROR
364 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);CHECKGLERROR
365 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
366 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB);CHECKGLERROR
367 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
368 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
369 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);CHECKGLERROR
370 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);CHECKGLERROR
371 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);CHECKGLERROR
372 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
373 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);CHECKGLERROR
374 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
375 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
376 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
377 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, gl_state.texturergbscale[i]);CHECKGLERROR
378 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
382 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
384 if (gl_state.texture[i])
386 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
390 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
392 if (gl_mesh_drawmode.integer > 0)
394 qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR
395 qglTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[i]);CHECKGLERROR
396 if (gl_state.texture[i])
398 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
402 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
409 qglBindTexture(GL_TEXTURE_2D, gl_state.texture[0]);CHECKGLERROR
410 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
411 if (gl_state.texture[0])
413 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
417 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
419 if (gl_mesh_drawmode.integer > 0)
421 qglTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[0]);CHECKGLERROR
422 if (gl_state.texture[0])
424 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
428 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
434 // called at beginning of frame
436 void R_Mesh_Start(float farclip)
440 Sys_Error("R_Mesh_Clear: called when backend is not active\n");
444 gl_backend_bufferchanges(false);
446 r_mesh_farclip = farclip;
447 viewdist = DotProduct(r_origin, vpn);
448 vpnbit0 = vpn[0] < 0;
449 vpnbit1 = vpn[1] < 0;
450 vpnbit2 = vpn[2] < 0;
458 gl_state.clientunit = 0;
460 for (i = 0;i < backendunits;i++)
462 gl_state.texture[i] = 0;
463 gl_state.texturergbscale[i] = 1;
466 qglEnable(GL_CULL_FACE);CHECKGLERROR
467 qglCullFace(GL_FRONT);CHECKGLERROR
469 gl_state.depthtest = true;
470 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
472 gl_state.blendfunc1 = GL_ONE;
473 gl_state.blendfunc2 = GL_ZERO;
474 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
477 qglDisable(GL_BLEND);CHECKGLERROR
479 gl_state.depthmask = GL_TRUE;
480 qglDepthMask(gl_state.depthmask);CHECKGLERROR
483 if (gl_mesh_drawmode.integer > 0)
486 qglVertexPointer(3, GL_FLOAT, sizeof(buf_vertex_t), &buf_vertex[0].v[0]);CHECKGLERROR
487 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
488 if (gl_mesh_floatcolors.integer)
490 qglColorPointer(4, GL_FLOAT, sizeof(buf_fcolor_t), &buf_fcolor[0].c[0]);CHECKGLERROR
494 qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(buf_bcolor_t), &buf_bcolor[0].c[0]);CHECKGLERROR
496 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
499 GL_SetupTextureState();
502 int gl_backend_rebindtextures;
504 void GL_ConvertColorsFloatToByte(int numverts)
507 // LordHavoc: to avoid problems with aliasing (treating memory as two
508 // different types - exactly what this is doing), these must be volatile
510 volatile int *icolor;
511 volatile float *fcolor;
514 total = numverts * 4;
516 // shift float to have 8bit fraction at base of number
517 fcolor = &buf_fcolor->c[0];
518 for (i = 0;i < total;)
520 fcolor[i ] += 32768.0f;
521 fcolor[i + 1] += 32768.0f;
522 fcolor[i + 2] += 32768.0f;
523 fcolor[i + 3] += 32768.0f;
527 // then read as integer and kill float bits...
528 icolor = (int *)&buf_fcolor->c[0];
529 bcolor = &buf_bcolor->c[0];
530 for (i = 0;i < total;)
532 k = icolor[i ] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i ] = (qbyte) k;
533 k = icolor[i + 1] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i + 1] = (qbyte) k;
534 k = icolor[i + 2] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i + 2] = (qbyte) k;
535 k = icolor[i + 3] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i + 3] = (qbyte) k;
540 void GL_TransformVertices(int numverts)
543 float m[12], tempv[4], *v;
544 m[0] = buf_mesh.matrix.m[0][0];
545 m[1] = buf_mesh.matrix.m[0][1];
546 m[2] = buf_mesh.matrix.m[0][2];
547 m[3] = buf_mesh.matrix.m[0][3];
548 m[4] = buf_mesh.matrix.m[1][0];
549 m[5] = buf_mesh.matrix.m[1][1];
550 m[6] = buf_mesh.matrix.m[1][2];
551 m[7] = buf_mesh.matrix.m[1][3];
552 m[8] = buf_mesh.matrix.m[2][0];
553 m[9] = buf_mesh.matrix.m[2][1];
554 m[10] = buf_mesh.matrix.m[2][2];
555 m[11] = buf_mesh.matrix.m[2][3];
556 for (i = 0, v = buf_vertex[0].v;i < numverts;i++, v += 4)
558 VectorCopy(v, tempv);
559 v[0] = tempv[0] * m[0] + tempv[1] * m[1] + tempv[2] * m[2] + m[3];
560 v[1] = tempv[0] * m[4] + tempv[1] * m[5] + tempv[2] * m[6] + m[7];
561 v[2] = tempv[0] * m[8] + tempv[1] * m[9] + tempv[2] * m[10] + m[11];
565 void GL_MeshState(void)
568 if (backendunits > 1)
570 for (i = 0;i < backendunits;i++)
572 if (gl_state.texture[i] != buf_mesh.textures[i])
574 if (gl_state.unit != i)
576 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
578 if (gl_state.texture[i] == 0)
580 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
581 // have to disable texcoord array on disabled texture
582 // units due to NVIDIA driver bug with
583 // compiled_vertex_array
584 if (gl_state.clientunit != i)
586 qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR
588 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
590 qglBindTexture(GL_TEXTURE_2D, (gl_state.texture[i] = buf_mesh.textures[i]));CHECKGLERROR
591 if (gl_state.texture[i] == 0)
593 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
594 // have to disable texcoord array on disabled texture
595 // units due to NVIDIA driver bug with
596 // compiled_vertex_array
597 if (gl_state.clientunit != i)
599 qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR
601 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
604 if (gl_state.texturergbscale[i] != buf_mesh.texturergbscale[i])
606 if (gl_state.unit != i)
608 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
610 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (gl_state.texturergbscale[i] = buf_mesh.texturergbscale[i]));CHECKGLERROR
616 if (gl_state.texture[0] != buf_mesh.textures[0])
618 if (gl_state.texture[0] == 0)
620 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
621 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
623 qglBindTexture(GL_TEXTURE_2D, (gl_state.texture[0] = buf_mesh.textures[0]));CHECKGLERROR
624 if (gl_state.texture[0] == 0)
626 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
627 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
631 if (gl_state.blendfunc1 != buf_mesh.blendfunc1 || gl_state.blendfunc2 != buf_mesh.blendfunc2)
633 qglBlendFunc(gl_state.blendfunc1 = buf_mesh.blendfunc1, gl_state.blendfunc2 = buf_mesh.blendfunc2);CHECKGLERROR
634 if (gl_state.blendfunc2 == GL_ZERO)
636 if (gl_state.blendfunc1 == GL_ONE)
641 qglDisable(GL_BLEND);CHECKGLERROR
649 qglEnable(GL_BLEND);CHECKGLERROR
658 qglEnable(GL_BLEND);CHECKGLERROR
662 if (gl_state.depthtest != buf_mesh.depthtest)
664 gl_state.depthtest = buf_mesh.depthtest;
665 if (gl_state.depthtest)
666 qglEnable(GL_DEPTH_TEST);
668 qglDisable(GL_DEPTH_TEST);
670 if (gl_state.depthmask != buf_mesh.depthmask)
672 qglDepthMask(gl_state.depthmask = buf_mesh.depthmask);CHECKGLERROR
676 void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, GLuint *index)
678 unsigned int i, j, in;
679 if (gl_mesh_drawmode.integer >= 3/* && (endvert - firstvert) <= gl_maxdrawrangeelementsvertices && (indexcount) <= gl_maxdrawrangeelementsindices*/)
681 // GL 1.2 or GL 1.1 with extension
682 qglDrawRangeElements(GL_TRIANGLES, firstvert, endvert, indexcount, GL_UNSIGNED_INT, index);
684 else if (gl_mesh_drawmode.integer >= 2)
687 qglDrawElements(GL_TRIANGLES, indexcount, GL_UNSIGNED_INT, index);
689 else if (gl_mesh_drawmode.integer >= 1)
692 // feed it manually using glArrayElement
693 qglBegin(GL_TRIANGLES);
694 for (i = 0;i < indexcount;i++)
695 qglArrayElement(index[i]);
700 // GL 1.1 but not using vertex arrays - 3dfx glquake minigl driver
702 qglBegin(GL_TRIANGLES);
703 if (gl_state.texture[1]) // if the mesh uses multiple textures
705 // the minigl doesn't have this (because it does not have ARB_multitexture)
706 for (i = 0;i < indexcount;i++)
709 qglColor4ub(buf_bcolor[in].c[0], buf_bcolor[in].c[1], buf_bcolor[in].c[2], buf_bcolor[in].c[3]);
710 for (j = 0;j < backendunits;j++)
711 if (gl_state.texture[j])
712 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, buf_texcoord[j][in].t[0], buf_texcoord[j][in].t[1]);
713 qglVertex3f(buf_vertex[in].v[0], buf_vertex[in].v[1], buf_vertex[in].v[2]);
718 for (i = 0;i < indexcount;i++)
721 qglColor4ub(buf_bcolor[in].c[0], buf_bcolor[in].c[1], buf_bcolor[in].c[2], buf_bcolor[in].c[3]);
722 if (gl_state.texture[0])
723 qglTexCoord2f(buf_texcoord[0][in].t[0], buf_texcoord[0][in].t[1]);
724 qglVertex3f(buf_vertex[in].v[0], buf_vertex[in].v[1], buf_vertex[in].v[2]);
731 // renders mesh buffers, called to flush buffers when full
732 void R_Mesh_Render(void)
735 Sys_Error("R_Mesh_Render: called when backend is not active\n");
737 if (!r_render.integer)
742 // drawmode 0 always uses byte colors
743 if (!gl_mesh_floatcolors.integer || gl_mesh_drawmode.integer <= 0)
744 GL_ConvertColorsFloatToByte(buf_mesh.verts);
745 GL_TransformVertices(buf_mesh.verts);
746 GL_LockArray(0, buf_mesh.verts);CHECKGLERROR
747 GL_DrawRangeElements(0, buf_mesh.verts, buf_mesh.triangles * 3, &buf_tri[0].index[0]);CHECKGLERROR
748 GL_UnlockArray();CHECKGLERROR
751 // restores backend state, used when done with 3D rendering
752 void R_Mesh_Finish(void)
755 if (backendunits > 1)
757 for (i = backendunits - 1;i >= 0;i--)
759 qglActiveTexture(GL_TEXTURE0_ARB + i);CHECKGLERROR
760 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
761 if (gl_combine.integer)
763 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
767 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
771 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
773 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
777 qglClientActiveTexture(GL_TEXTURE0_ARB + i);CHECKGLERROR
778 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
784 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
785 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
788 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
793 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
794 qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
797 qglDisable(GL_BLEND);CHECKGLERROR
798 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
799 qglDepthMask(GL_TRUE);CHECKGLERROR
800 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);CHECKGLERROR
803 void R_Mesh_ClearDepth(void)
806 qglClear(GL_DEPTH_BUFFER_BIT);
807 R_Mesh_Start(r_mesh_farclip);
810 // allocates space in geometry buffers, and fills in pointers to the buffers in passsed struct
811 // (this is used for very high speed rendering, no copying)
812 int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m, int wantoverbright)
814 // these are static because gcc runs out of virtual registers otherwise
815 int i, j, overbright;
819 Sys_Error("R_Mesh_Draw_GetBuffer: called when backend is not active\n");
823 Host_Error("R_Mesh_Draw_GetBuffer: no triangles or verts\n");
825 i = max(m->numtriangles * 3, m->numverts);
826 if (overflowedverts < i)
829 if (m->numtriangles > max_tris || m->numverts > max_verts)
831 Con_Printf("R_Mesh_Draw_GetBuffer: mesh too big for current gl_mesh_maxtriangles setting, increasing limits\n");
836 c_meshtris += m->numtriangles;
837 m->index = &buf_tri[0].index[0];
838 m->vertex = &buf_vertex[0].v[0];
839 m->color = &buf_fcolor[0].c[0];
840 for (i = 0;i < backendunits;i++)
841 m->texcoords[i] = &buf_texcoord[i][0].t[0];
843 buf_mesh.blendfunc1 = m->blendfunc1;
844 buf_mesh.blendfunc2 = m->blendfunc2;
845 buf_mesh.depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
846 buf_mesh.depthtest = !m->depthdisable;
847 buf_mesh.triangles = m->numtriangles;
848 buf_mesh.verts = m->numverts;
849 buf_mesh.matrix = m->matrix; // this copies the struct
853 if (m->blendfunc1 == GL_DST_COLOR)
855 // check if it is a 2x modulate with framebuffer
856 if (m->blendfunc2 == GL_SRC_COLOR)
859 else if (m->blendfunc2 != GL_SRC_COLOR)
863 overbright = wantoverbright && gl_combine.integer;
867 scaler *= overbrightscale;
869 m->colorscale = scaler;
872 for (i = 0;i < MAX_TEXTUREUNITS;i++)
874 if ((buf_mesh.textures[i] = m->tex[i]))
877 if (i >= backendunits)
878 Sys_Error("R_Mesh_Draw_GetBuffer: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
880 buf_mesh.texturergbscale[i] = m->texrgbscale[i];
881 if (buf_mesh.texturergbscale[i] != 1 && buf_mesh.texturergbscale[i] != 2 && buf_mesh.texturergbscale[i] != 4)
882 buf_mesh.texturergbscale[i] = 1;
884 if (overbright && j >= 0)
885 buf_mesh.texturergbscale[j] = 4;
887 if (gl_backend_rebindtextures)
889 gl_backend_rebindtextures = false;
890 GL_SetupTextureState();
899 ==============================================================================
903 ==============================================================================
906 qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height)
912 if (!r_render.integer)
915 buffer = Mem_Alloc(tempmempool, width*height*3);
916 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
919 // LordHavoc: compensate for v_overbrightbits when using hardware gamma
920 if (v_hwgamma.integer)
921 for (i = 0;i < width * height * 3;i++)
922 buffer[i] <<= v_overbrightbits.integer;
924 ret = Image_WriteTGARGB_preflipped(filename, width, height, buffer);
930 //=============================================================================
932 void R_ClearScreen(void)
934 if (r_render.integer)
937 qglClearColor(0,0,0,0);CHECKGLERROR
939 qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);CHECKGLERROR
940 // set dithering mode
941 if (gl_dither.integer)
943 qglEnable(GL_DITHER);CHECKGLERROR
947 qglDisable(GL_DITHER);CHECKGLERROR
956 This is called every frame, and can also be called explicitly to flush
960 void SCR_UpdateScreen (void)
964 R_TimeReport("finish");
966 if (r_textureunits.integer > gl_textureunits)
967 Cvar_SetValueQuick(&r_textureunits, gl_textureunits);
968 if (r_textureunits.integer < 1)
969 Cvar_SetValueQuick(&r_textureunits, 1);
971 if (gl_combine.integer && (!gl_combine_extension || r_textureunits.integer < 2))
972 Cvar_SetValueQuick(&gl_combine, 0);
975 overbrightscale = 1.0f / (float) (1 << v_overbrightbits.integer);
978 lightscalebit = v_overbrightbits.integer;
979 if (gl_combine.integer && r_textureunits.integer > 1)
981 lightscale = 1.0f / (float) (1 << lightscalebit);
983 R_TimeReport("setup");
987 R_TimeReport("clear");
989 if (scr_conlines < vid.conheight && cls.signon == SIGNONS)
995 // tell driver to commit it's partially full geometry queue to the rendering queue
996 // (this doesn't wait for the commands themselves to complete)