4 cvar_t r_render = {0, "r_render", "1"};
5 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1"}; // whether or not to use dithering
11 void SCR_ScreenShot_f (void);
12 static void R_Envmap_f (void);
16 static int max_verts; // always max_meshs * 3
17 #define TRANSDEPTHRES 4096
19 //static cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "21760"};
20 static cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "8192"};
21 static cvar_t gl_mesh_batchtriangles = {0, "gl_mesh_batchtriangles", "1024"};
22 static cvar_t gl_mesh_merge = {0, "gl_mesh_merge", "1"};
23 static cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "0"};
25 typedef struct buf_mesh_s
27 //struct buf_mesh_s *next;
30 int blendfunc1, blendfunc2;
31 int textures[MAX_TEXTUREUNITS];
32 float texturergbscale[MAX_TEXTUREUNITS];
37 struct buf_mesh_s *chain;
38 struct buf_transtri_s *transchain;
39 //struct buf_transtri_s **transchainpointer;
43 typedef struct buf_transtri_s
45 struct buf_transtri_s *next;
46 struct buf_transtri_s *meshsortchain;
52 typedef struct buf_tri_s
82 static float meshfarclip;
83 static int currentmesh, currenttriangle, currentvertex, backendunits, backendactive, meshmerge, transranout;
84 static buf_mesh_t *buf_mesh;
85 static buf_tri_t *buf_tri;
86 static buf_vertex_t *buf_vertex;
87 static buf_fcolor_t *buf_fcolor;
88 static buf_bcolor_t *buf_bcolor;
89 static buf_texcoord_t *buf_texcoord[MAX_TEXTUREUNITS];
91 static int currenttransmesh, currenttransvertex, currenttranstriangle;
92 static buf_mesh_t *buf_transmesh;
93 static buf_transtri_t *buf_transtri;
94 static buf_transtri_t **buf_transtri_list;
95 static buf_vertex_t *buf_transvertex;
96 static buf_fcolor_t *buf_transfcolor;
97 static buf_texcoord_t *buf_transtexcoord[MAX_TEXTUREUNITS];
99 static mempool_t *gl_backend_mempool;
100 static int resizingbuffers = false;
102 static void gl_backend_start(void)
106 max_verts = max_meshs * 3;
108 if (!gl_backend_mempool)
109 gl_backend_mempool = Mem_AllocPool("GL_Backend");
111 #define BACKENDALLOC(var, count, sizeofstruct)\
113 var = Mem_Alloc(gl_backend_mempool, count * sizeof(sizeofstruct));\
115 Sys_Error("gl_backend_start: unable to allocate memory\n");\
116 memset(var, 0, count * sizeof(sizeofstruct));\
119 BACKENDALLOC(buf_mesh, max_meshs, buf_mesh_t)
120 BACKENDALLOC(buf_tri, max_meshs, buf_tri_t)
121 BACKENDALLOC(buf_vertex, max_verts, buf_vertex_t)
122 BACKENDALLOC(buf_fcolor, max_verts, buf_fcolor_t)
123 BACKENDALLOC(buf_bcolor, max_verts, buf_bcolor_t)
125 BACKENDALLOC(buf_transmesh, max_meshs, buf_mesh_t)
126 BACKENDALLOC(buf_transtri, max_meshs, buf_transtri_t)
127 BACKENDALLOC(buf_transtri_list, TRANSDEPTHRES, buf_transtri_t *)
128 BACKENDALLOC(buf_transvertex, max_verts, buf_vertex_t)
129 BACKENDALLOC(buf_transfcolor, max_verts, buf_fcolor_t)
131 for (i = 0;i < MAX_TEXTUREUNITS;i++)
133 // only allocate as many texcoord arrays as we need
134 if (i < gl_textureunits)
136 BACKENDALLOC(buf_texcoord[i], max_verts, buf_texcoord_t)
137 BACKENDALLOC(buf_transtexcoord[i], max_verts, buf_texcoord_t)
141 buf_texcoord[i] = NULL;
142 buf_transtexcoord[i] = NULL;
145 backendunits = min(MAX_TEXTUREUNITS, gl_textureunits);
146 backendactive = true;
149 static void gl_backend_shutdown(void)
153 #define BACKENDFREE(var)\
161 #define BACKENDFREE(var) var = NULL;
163 BACKENDFREE(buf_mesh)
165 BACKENDFREE(buf_vertex)
166 BACKENDFREE(buf_fcolor)
167 BACKENDFREE(buf_bcolor)
169 BACKENDFREE(buf_transmesh)
170 BACKENDFREE(buf_transtri)
171 BACKENDFREE(buf_transtri_list)
172 BACKENDFREE(buf_transvertex)
173 BACKENDFREE(buf_transfcolor)
175 for (i = 0;i < MAX_TEXTUREUNITS;i++)
177 BACKENDFREE(buf_texcoord[i])
178 BACKENDFREE(buf_transtexcoord[i])
183 Mem_EmptyPool(gl_backend_mempool);
185 Mem_FreePool(&gl_backend_mempool);
188 backendactive = false;
191 static void gl_backend_bufferchanges(int init)
193 // 21760 is (65536 / 3) rounded off to a multiple of 128
194 if (gl_mesh_maxtriangles.integer < 256)
195 Cvar_SetValue("gl_mesh_maxtriangles", 256);
196 if (gl_mesh_maxtriangles.integer > 21760)
197 Cvar_SetValue("gl_mesh_maxtriangles", 21760);
199 if (gl_mesh_batchtriangles.integer < 0)
200 Cvar_SetValue("gl_mesh_batchtriangles", 0);
201 if (gl_mesh_batchtriangles.integer > gl_mesh_maxtriangles.integer)
202 Cvar_SetValue("gl_mesh_batchtriangles", gl_mesh_maxtriangles.integer);
204 max_batch = gl_mesh_batchtriangles.integer;
206 if (max_meshs != gl_mesh_maxtriangles.integer)
208 max_meshs = gl_mesh_maxtriangles.integer;
212 resizingbuffers = true;
213 gl_backend_shutdown();
215 resizingbuffers = false;
220 float r_farclip, r_newfarclip;
222 static void gl_backend_newmap(void)
224 r_farclip = r_newfarclip = 2048.0f;
227 int polyindexarray[768];
229 void gl_backend_init(void)
233 Cvar_RegisterVariable (&r_render);
234 Cvar_RegisterVariable (&gl_dither);
236 Cvar_SetValue("r_render", 0);
239 Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
240 Cmd_AddCommand ("envmap", R_Envmap_f);
242 Cvar_RegisterVariable(&gl_mesh_maxtriangles);
243 Cvar_RegisterVariable(&gl_mesh_batchtriangles);
244 Cvar_RegisterVariable(&gl_mesh_merge);
245 Cvar_RegisterVariable(&gl_mesh_floatcolors);
246 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
247 gl_backend_bufferchanges(true);
248 for (i = 0;i < 256;i++)
250 polyindexarray[i*3+0] = 0;
251 polyindexarray[i*3+1] = i + 1;
252 polyindexarray[i*3+2] = i + 2;
256 static void MYgluPerspective(GLdouble fovx, GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar )
260 xmax = zNear * tan( fovx * M_PI / 360.0 ) * aspect;
261 ymax = zNear * tan( fovy * M_PI / 360.0 );
263 glFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar );
272 static void GL_SetupFrame (void)
274 if (!r_render.integer)
277 // glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: moved to SCR_UpdateScreen
280 glDepthFunc (GL_LEQUAL);
282 glDepthRange (gldepthmin, gldepthmax);
284 // update farclip based on previous frame
285 r_farclip = r_newfarclip;
288 glMatrixMode(GL_PROJECTION);
291 // y is weird beause OpenGL is bottom to top, we use top to bottom
292 glViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height);
293 // yfov = 2*atan((float)r_refdef.height/r_refdef.width)*180/M_PI;
294 MYgluPerspective (r_refdef.fov_x, r_refdef.fov_y, r_refdef.width/r_refdef.height, 4, r_farclip);
296 glCullFace(GL_FRONT);
298 glMatrixMode(GL_MODELVIEW);
301 glRotatef (-90, 1, 0, 0); // put Z going up
302 glRotatef (90, 0, 0, 1); // put Z going up
303 glRotatef (-r_refdef.viewangles[2], 1, 0, 0);
304 glRotatef (-r_refdef.viewangles[0], 0, 1, 0);
305 glRotatef (-r_refdef.viewangles[1], 0, 0, 1);
306 glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
308 // glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
313 // if (gl_cull.integer)
314 glEnable(GL_CULL_FACE);
316 // glDisable(GL_CULL_FACE);
318 glEnable(GL_BLEND); // was Disable
319 glEnable(GL_DEPTH_TEST);
323 static float viewdist;
325 int c_meshs, c_meshtris, c_transmeshs, c_transtris;
327 // called at beginning of frame
328 void R_Mesh_Clear(void)
331 Sys_Error("R_Mesh_Clear: called when backend is not active\n");
333 gl_backend_bufferchanges(false);
338 currenttransmesh = 0;
339 currenttranstriangle = 0;
340 currenttransvertex = 0;
342 meshmerge = gl_mesh_merge.integer;
344 viewdist = DotProduct(r_origin, vpn);
355 void GL_PrintError(int errornumber, char *filename, int linenumber)
359 case GL_INVALID_ENUM:
360 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
362 case GL_INVALID_VALUE:
363 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
365 case GL_INVALID_OPERATION:
366 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
368 case GL_STACK_OVERFLOW:
369 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
371 case GL_STACK_UNDERFLOW:
372 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
374 case GL_OUT_OF_MEMORY:
375 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
377 #ifdef GL_TABLE_TOO_LARGE
378 case GL_TABLE_TOO_LARGE:
379 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
383 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
391 // renders mesh buffers, called to flush buffers when full
392 void R_Mesh_Render(void)
394 int i, k, blendfunc1, blendfunc2, blend, depthmask, depthtest, unit = 0, clientunit = 0, firsttriangle, triangles, firstvert, lastvert, texture[MAX_TEXTUREUNITS];
395 float farclip, texturergbscale[MAX_TEXTUREUNITS];
398 // float to byte color conversion
403 Sys_Error("R_Mesh_Render: called when backend is not active\n");
409 // push out farclip based on vertices
410 for (i = 0;i < currentvertex;i++)
412 farclip = DotProduct(buf_vertex[i].v, vpn);
413 if (meshfarclip < farclip)
414 meshfarclip = farclip;
417 farclip = meshfarclip + 256.0f - viewdist; // + 256 just to be safe
419 // push out farclip for next frame
420 if (farclip > r_newfarclip)
421 r_newfarclip = ceil((farclip + 255) / 256) * 256 + 256;
423 for (i = 0;i < backendunits;i++)
424 texturergbscale[i] = 1;
426 glEnable(GL_CULL_FACE);
428 glCullFace(GL_FRONT);
431 glEnable(GL_DEPTH_TEST);
434 blendfunc2 = GL_ZERO;
435 glBlendFunc(blendfunc1, blendfunc2);
441 glDepthMask((GLboolean) depthmask);
444 glVertexPointer(3, GL_FLOAT, sizeof(buf_vertex_t), buf_vertex);
446 glEnableClientState(GL_VERTEX_ARRAY);
448 if (gl_mesh_floatcolors.integer)
450 glColorPointer(4, GL_FLOAT, sizeof(buf_fcolor_t), buf_fcolor);
455 // shift float to have 8bit fraction at base of number
456 for (i = 0, fcolor = &buf_fcolor->c[0];i < currentvertex;i++)
458 *fcolor++ += 32768.0f;
459 *fcolor++ += 32768.0f;
460 *fcolor++ += 32768.0f;
461 *fcolor++ += 32768.0f;
463 // then read as integer and kill float bits...
464 for (i = 0, icolor = (int *)&buf_fcolor->c[0], bcolor = &buf_bcolor->c[0];i < currentvertex;i++)
466 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
467 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
468 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
469 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
471 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(buf_bcolor_t), buf_bcolor);
474 glEnableClientState(GL_COLOR_ARRAY);
477 if (backendunits > 1)
479 for (i = 0;i < backendunits;i++)
481 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
483 glBindTexture(GL_TEXTURE_2D, (texture[i] = 0));
485 glDisable(GL_TEXTURE_2D);
487 if (gl_combine.integer)
489 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
491 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
493 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
495 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
497 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB);
499 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
501 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
503 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
505 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
507 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
509 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
511 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);
513 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
515 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
517 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
519 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
521 glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0f);
526 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
530 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
532 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[i]);
534 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
540 glBindTexture(GL_TEXTURE_2D, (texture[0] = 0));
542 glDisable(GL_TEXTURE_2D);
544 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
547 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[0]);
549 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
553 // lock as early as possible
554 GL_LockArray(0, currentvertex);
557 for (k = 0;k < currentmesh;)
561 if (backendunits > 1)
564 for (i = 0;i < backendunits;i++)
566 if (texture[i] != mesh->textures[i])
570 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
575 glEnable(GL_TEXTURE_2D);
577 // have to disable texcoord array on disabled texture
578 // units due to NVIDIA driver bug with
579 // compiled_vertex_array
582 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
585 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
588 glBindTexture(GL_TEXTURE_2D, (texture[i] = mesh->textures[i]));
592 glDisable(GL_TEXTURE_2D);
594 // have to disable texcoord array on disabled texture
595 // units due to NVIDIA driver bug with
596 // compiled_vertex_array
599 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
602 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
606 if (texturergbscale[i] != mesh->texturergbscale[i])
610 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
613 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (texturergbscale[i] = mesh->texturergbscale[i]));
619 // if (unit != topunit)
621 // qglActiveTexture(GL_TEXTURE0_ARB + (unit = topunit));
627 if (texture[0] != mesh->textures[0])
631 glEnable(GL_TEXTURE_2D);
633 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
636 glBindTexture(GL_TEXTURE_2D, (texture[0] = mesh->textures[0]));
640 glDisable(GL_TEXTURE_2D);
642 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
647 if (blendfunc1 != mesh->blendfunc1 || blendfunc2 != mesh->blendfunc2)
649 blendfunc1 = mesh->blendfunc1;
650 blendfunc2 = mesh->blendfunc2;
651 glBlendFunc(blendfunc1, blendfunc2);
653 if (blendfunc2 == GL_ZERO)
655 if (blendfunc1 == GL_ONE)
684 if (depthtest != mesh->depthtest)
686 depthtest = mesh->depthtest;
688 glEnable(GL_DEPTH_TEST);
690 glDisable(GL_DEPTH_TEST);
692 if (depthmask != mesh->depthmask)
694 depthmask = mesh->depthmask;
695 glDepthMask((GLboolean) depthmask);
699 firsttriangle = mesh->firsttriangle;
700 triangles = mesh->triangles;
701 firstvert = mesh->firstvert;
702 lastvert = mesh->lastvert;
703 mesh = &buf_mesh[++k];
707 #if MAX_TEXTUREUNITS != 4
708 #error update this code
710 while (k < currentmesh
711 && mesh->blendfunc1 == blendfunc1
712 && mesh->blendfunc2 == blendfunc2
713 && mesh->depthtest == depthtest
714 && mesh->depthmask == depthmask
715 && mesh->textures[0] == texture[0]
716 && mesh->textures[1] == texture[1]
717 && mesh->textures[2] == texture[2]
718 && mesh->textures[3] == texture[3]
719 && mesh->texturergbscale[0] == texturergbscale[0]
720 && mesh->texturergbscale[1] == texturergbscale[1]
721 && mesh->texturergbscale[2] == texturergbscale[2]
722 && mesh->texturergbscale[3] == texturergbscale[3])
724 triangles += mesh->triangles;
725 if (firstvert > mesh->firstvert)
726 firstvert = mesh->firstvert;
727 if (lastvert < mesh->lastvert)
728 lastvert = mesh->lastvert;
729 mesh = &buf_mesh[++k];
733 index = (unsigned int *)&buf_tri[firsttriangle].index[0];
734 for (i = 0;i < triangles * 3;i++)
735 index[i] += firstvert;
738 // FIXME: dynamic link to GL so we can get DrawRangeElements on WIN32
739 glDrawElements(GL_TRIANGLES, triangles * 3, GL_UNSIGNED_INT, index);
741 glDrawRangeElements(GL_TRIANGLES, firstvert, lastvert + 1, triangles * 3, GL_UNSIGNED_INT, index);
753 if (backendunits > 1)
755 for (i = backendunits - 1;i >= 0;i--)
757 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
759 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
761 if (gl_combine.integer)
763 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
768 glDisable(GL_TEXTURE_2D);
773 glEnable(GL_TEXTURE_2D);
776 glBindTexture(GL_TEXTURE_2D, 0);
779 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
781 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
787 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
789 glEnable(GL_TEXTURE_2D);
791 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
794 glDisableClientState(GL_COLOR_ARRAY);
796 glDisableClientState(GL_VERTEX_ARRAY);
801 glEnable(GL_DEPTH_TEST);
805 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
809 void R_Mesh_AddTransparent(void)
812 float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
813 buf_vertex_t *vert1, *vert2, *vert3;
815 buf_mesh_t *mesh, *transmesh;
817 if (!currenttransmesh)
821 // convert index data to transtris for sorting
822 for (i = 0;i < currenttransmesh;i++)
824 mesh = buf_transmesh + i;
827 for (i = 0;i < mesh->numtriangles;i++)
829 tri = &buf_transtri[currenttranstriangle++];
831 tri->index[0] = *index++ + j;
832 tri->index[1] = *index++ + j;
833 tri->index[2] = *index++ + j;
838 // map farclip to 0-4095 list range
839 centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
840 viewdistcompare = viewdist + 4.0f;
842 memset(buf_transtri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
845 for (j = 0;j < currenttranstriangle;j++)
847 tri = &buf_transtri[j];
848 i = tri->mesh->firstvert;
850 vert1 = &buf_transvertex[tri->index[0] + i];
851 vert2 = &buf_transvertex[tri->index[1] + i];
852 vert3 = &buf_transvertex[tri->index[2] + i];
854 dist1 = DotProduct(vert1->v, vpn);
855 dist2 = DotProduct(vert2->v, vpn);
856 dist3 = DotProduct(vert3->v, vpn);
858 maxdist = max(dist1, max(dist2, dist3));
859 if (maxdist < viewdistcompare)
862 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
865 i = bound(0, i, (TRANSDEPTHRES - 1));
869 center += 8388608.0f;
870 i = *((long *)¢er) & 0x7FFFFF;
871 i = min(i, (TRANSDEPTHRES - 1));
873 tri->next = buf_transtri_list[i];
874 buf_transtri_list[i] = tri;
878 if (currentmesh + k > max_meshs || currenttriangle + k > max_batch || currentvertex + currenttransvertex > max_verts)
881 for (i = 0;i < currenttransmesh;i++)
882 buf_transmesh[i].transchain = NULL;
884 for (j = 0;j < TRANSDEPTHRES;j++)
886 if ((tri = buf_transtri_list[j]))
888 for (;tri;tri = tri->next)
890 if (!tri->mesh->transchain)
892 tri->mesh->chain = transmesh;
893 transmesh = tri->mesh;
895 tri->meshsortchain = tri->mesh->transchain;
896 tri->mesh->transchain = tri;
901 for (;transmesh;transmesh = transmesh->chain)
903 int numverts = transmesh->lastvert - transmesh->firstvert + 1;
904 //if (currentmesh >= max_meshs || currenttriangle + transmesh->triangles > max_batch || currentvertex + numverts > max_verts)
907 memcpy(&buf_vertex[currentvertex], &buf_transvertex[transmesh->firstvert], numverts * sizeof(buf_vertex_t));
908 memcpy(&buf_fcolor[currentvertex], &buf_transfcolor[transmesh->firstvert], numverts * sizeof(buf_fcolor_t));
909 for (i = 0;i < backendunits && transmesh->textures[i];i++)
910 memcpy(&buf_texcoord[i][currentvertex], &buf_transtexcoord[i][transmesh->firstvert], numverts * sizeof(buf_texcoord_t));
912 mesh = &buf_mesh[currentmesh++];
913 *mesh = *transmesh; // copy mesh properties
914 mesh->firstvert = currentvertex;
915 mesh->lastvert = currentvertex + numverts - 1;
916 currentvertex += numverts;
917 mesh->firsttriangle = currenttriangle;
918 for (tri = transmesh->transchain;tri;tri = tri->meshsortchain)
920 buf_tri[currenttriangle].index[0] = tri->index[0];
921 buf_tri[currenttriangle].index[1] = tri->index[1];
922 buf_tri[currenttriangle].index[2] = tri->index[2];
925 mesh->triangles = currenttriangle - mesh->firsttriangle;
928 currenttransmesh = 0;
929 currenttranstriangle = 0;
930 currenttransvertex = 0;
933 void R_Mesh_Draw(const rmeshinfo_t *m)
935 // these are static because gcc runs out of virtual registers otherwise
936 static int i, j, *index, overbright;
937 static float *in, scaler;
938 static float cr, cg, cb, ca;
939 static buf_mesh_t *mesh;
940 static buf_vertex_t *vert;
941 static buf_fcolor_t *fcolor;
942 static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
943 static buf_transtri_t *tri;
946 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
952 Host_Error("R_Mesh_Draw: no triangles or verts\n");
954 // ignore meaningless alpha meshs
955 if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
959 for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
962 if (i == m->numverts)
965 else if (m->ca < 0.01f)
970 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
973 if (m->blendfunc2 == GL_SRC_COLOR)
975 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
982 overbright = gl_combine.integer;
986 scaler *= overbrightscale;
991 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
995 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1002 c_transtris += m->numtriangles;
1003 vert = &buf_transvertex[currenttransvertex];
1004 fcolor = &buf_transfcolor[currenttransvertex];
1005 for (i = 0;i < backendunits;i++)
1006 texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
1008 // transmesh is only for storage of transparent meshs until they
1009 // are inserted into the main mesh array
1010 mesh = &buf_transmesh[currenttransmesh++];
1012 // transparent meshs are broken up into individual triangles which can
1013 // be sorted by depth
1015 for (i = 0;i < m->numtriangles;i++)
1017 tri = &buf_transtri[currenttranstriangle++];
1019 tri->index[0] = *index++;
1020 tri->index[1] = *index++;
1021 tri->index[2] = *index++;
1024 mesh->firstvert = currenttransvertex;
1025 mesh->lastvert = currenttransvertex + m->numverts - 1;
1026 currenttransvertex += m->numverts;
1030 if (m->numtriangles > max_meshs || m->numverts > max_verts)
1032 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
1036 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
1040 c_meshtris += m->numtriangles;
1041 vert = &buf_vertex[currentvertex];
1042 fcolor = &buf_fcolor[currentvertex];
1043 for (i = 0;i < backendunits;i++)
1044 texcoord[i] = &buf_texcoord[i][currentvertex];
1046 mesh = &buf_mesh[currentmesh++];
1047 // opaque meshs are rendered directly
1048 mesh->firsttriangle = currenttriangle;
1049 memcpy(&buf_tri[currenttriangle].index[0], m->index, sizeof(float[3]) * m->numtriangles);
1050 currenttriangle += m->numtriangles;
1052 mesh->firstvert = currentvertex;
1053 mesh->lastvert = currentvertex + m->numverts - 1;
1054 currentvertex += m->numverts;
1057 // code shared for transparent and opaque meshs
1058 mesh->blendfunc1 = m->blendfunc1;
1059 mesh->blendfunc2 = m->blendfunc2;
1060 mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
1061 mesh->depthtest = !m->depthdisable;
1062 mesh->triangles = m->numtriangles;
1064 for (i = 0;i < backendunits;i++)
1066 if ((mesh->textures[i] = m->tex[i]))
1068 mesh->texturergbscale[i] = m->texrgbscale[i];
1069 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1070 mesh->texturergbscale[i] = 1;
1072 if (overbright && j >= 0)
1073 mesh->texturergbscale[j] = 4;
1075 if (m->vertexstep != sizeof(buf_vertex_t))
1077 for (i = 0, in = m->vertex;i < m->numverts;i++, (int)in += m->vertexstep)
1079 vert[i].v[0] = in[0];
1080 vert[i].v[1] = in[1];
1081 vert[i].v[2] = in[2];
1085 memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
1089 for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep)
1091 fcolor[i].c[0] = in[0] * scaler;
1092 fcolor[i].c[1] = in[1] * scaler;
1093 fcolor[i].c[2] = in[2] * scaler;
1094 fcolor[i].c[3] = in[3];
1099 cr = m->cr * scaler;
1100 cg = m->cg * scaler;
1101 cb = m->cb * scaler;
1103 for (i = 0;i < m->numverts;i++)
1105 fcolor[i].c[0] = cr;
1106 fcolor[i].c[1] = cg;
1107 fcolor[i].c[2] = cb;
1108 fcolor[i].c[3] = ca;
1112 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1114 if (j >= backendunits)
1115 Sys_Error("R_Mesh_Draw: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1116 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1118 for (i = 0, in = m->texcoords[j];i < m->numverts;i++, (int)in += m->texcoordstep[j])
1120 texcoord[j][i].t[0] = in[0];
1121 texcoord[j][i].t[1] = in[1];
1125 memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1128 for (;j < backendunits;j++)
1129 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1132 if (currenttriangle >= max_batch)
1136 void R_Mesh_Draw_NativeOnly(const rmeshinfo_t *m)
1138 // these are static because gcc runs out of virtual registers otherwise
1139 static int i, j, *index, overbright;
1140 static float *in, scaler;
1141 static buf_mesh_t *mesh;
1142 static buf_vertex_t *vert;
1143 static buf_fcolor_t *fcolor;
1144 static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
1145 static buf_transtri_t *tri;
1148 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1150 if (m->index == NULL
1152 || m->vertex == NULL
1154 Host_Error("R_Mesh_Draw: no triangles or verts\n");
1156 // ignore meaningless alpha meshs
1157 if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
1161 for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
1164 if (i == m->numverts)
1167 else if (m->ca < 0.01f)
1172 if (m->blendfunc2 == GL_SRC_COLOR)
1174 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
1181 overbright = gl_combine.integer;
1185 scaler *= overbrightscale;
1190 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
1194 Con_Printf("R_Mesh_Draw_NativeOnly: ran out of room for transparent meshs\n");
1201 c_transtris += m->numtriangles;
1202 vert = &buf_transvertex[currenttransvertex];
1203 fcolor = &buf_transfcolor[currenttransvertex];
1204 for (i = 0;i < backendunits;i++)
1205 texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
1207 // transmesh is only for storage of transparent meshs until they
1208 // are inserted into the main mesh array
1209 mesh = &buf_transmesh[currenttransmesh++];
1211 // transparent meshs are broken up into individual triangles which can
1212 // be sorted by depth
1214 for (i = 0;i < m->numtriangles;i++)
1216 tri = &buf_transtri[currenttranstriangle++];
1218 tri->index[0] = *index++;
1219 tri->index[1] = *index++;
1220 tri->index[2] = *index++;
1223 mesh->firstvert = currenttransvertex;
1224 mesh->lastvert = currenttransvertex + m->numverts - 1;
1225 currenttransvertex += m->numverts;
1229 if (m->numtriangles > max_meshs || m->numverts > max_verts)
1231 Con_Printf("R_Mesh_Draw_NativeOnly: mesh too big for buffers\n");
1235 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
1239 c_meshtris += m->numtriangles;
1240 vert = &buf_vertex[currentvertex];
1241 fcolor = &buf_fcolor[currentvertex];
1242 for (i = 0;i < backendunits;i++)
1243 texcoord[i] = &buf_texcoord[i][currentvertex];
1245 mesh = &buf_mesh[currentmesh++];
1246 // opaque meshs are rendered directly
1247 mesh->firsttriangle = currenttriangle;
1248 memcpy(&buf_tri[currenttriangle].index[0], m->index, sizeof(float[3]) * m->numtriangles);
1249 currenttriangle += m->numtriangles;
1251 mesh->firstvert = currentvertex;
1252 mesh->lastvert = currentvertex + m->numverts - 1;
1253 currentvertex += m->numverts;
1256 // code shared for transparent and opaque meshs
1257 mesh->blendfunc1 = m->blendfunc1;
1258 mesh->blendfunc2 = m->blendfunc2;
1259 mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
1260 mesh->depthtest = !m->depthdisable;
1261 mesh->triangles = m->numtriangles;
1263 for (i = 0;i < backendunits;i++)
1265 if ((mesh->textures[i] = m->tex[i]))
1267 mesh->texturergbscale[i] = m->texrgbscale[i];
1268 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1269 mesh->texturergbscale[i] = 1;
1271 if (overbright && j >= 0)
1272 mesh->texturergbscale[j] = 4;
1274 if (m->vertexstep != sizeof(buf_vertex_t))
1275 Host_Error("R_Mesh_Draw_NativeOnly: unsupported vertexstep\n");
1276 if (m->colorstep != sizeof(buf_fcolor_t))
1277 Host_Error("R_Mesh_Draw_NativeOnly: unsupported colorstep\n");
1278 if (m->color == NULL)
1279 Host_Error("R_Mesh_Draw_NativeOnly: must provide color array\n");
1280 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1282 if (j >= backendunits)
1283 Sys_Error("R_Mesh_Draw_NativeOnly: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1284 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1285 Host_Error("R_Mesh_Draw_NativeOnly: unsupported texcoordstep\n");
1288 memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
1289 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1290 memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1292 for (;j < backendunits;j++)
1293 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1296 memcpy(fcolor, m->color, m->numverts * sizeof(buf_fcolor_t));
1298 // do this as a second step because memcpy preloaded the cache, which we can't easily do
1301 for (i = 0;i < m->numverts;i++)
1303 fcolor[i].c[0] *= scaler;
1304 fcolor[i].c[1] *= scaler;
1305 fcolor[i].c[2] *= scaler;
1309 if (currenttriangle >= max_batch)
1314 void R_Mesh_Draw_GetBuffer(volatile rmeshinfo_t *m)
1316 // these are static because gcc runs out of virtual registers otherwise
1317 static int i, j, *index, overbright;
1318 static float *in, scaler;
1319 static buf_transtri_t *tri;
1322 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1324 if (!m->numtriangles
1326 Host_Error("R_Mesh_Draw: no triangles or verts\n");
1329 if (m->blendfunc2 == GL_SRC_COLOR)
1331 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
1338 overbright = gl_combine.integer;
1342 scaler *= overbrightscale;
1347 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
1351 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1358 c_transtris += m->numtriangles;
1359 m->vertex = &buf_transvertex[currenttransvertex].v[0];
1360 m->color = &buf_transfcolor[currenttransvertex].c[0];
1361 for (i = 0;i < backendunits;i++)
1362 m->texcoords[i] = &buf_transtexcoord[i][currenttransvertex].tc[0];
1364 // transmesh is only for storage of transparent meshs until they
1365 // are inserted into the main mesh array
1366 mesh = &buf_transmesh[currenttransmesh++];
1368 // transparent meshs are broken up into individual triangles which can
1369 // be sorted by depth
1371 for (i = 0;i < m->numtriangles;i++)
1373 tri = &buf_transtri[currenttranstriangle++];
1375 tri->index[0] = *index++;
1376 tri->index[1] = *index++;
1377 tri->index[2] = *index++;
1380 mesh->firstvert = currenttransvertex;
1381 mesh->lastvert = currenttransvertex + m->numverts - 1;
1382 currenttransvertex += m->numverts;
1386 if (m->numtriangles > max_meshs || m->numverts > max_verts)
1388 Con_Printf("R_Mesh_Draw_NativeOnly: mesh too big for buffers\n");
1392 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
1396 c_meshtris += m->numtriangles;
1397 vert = &buf_vertex[currentvertex];
1398 fcolor = &buf_fcolor[currentvertex];
1399 for (i = 0;i < backendunits;i++)
1400 texcoord[i] = &buf_texcoord[i][currentvertex];
1402 mesh = &buf_mesh[currentmesh++];
1403 // opaque meshs are rendered directly
1404 mesh->firsttriangle = currenttriangle;
1405 memcpy(&buf_tri[currenttriangle].index[0], m->index, sizeof(float[3]) * m->numtriangles);
1406 currenttriangle += m->numtriangles;
1408 mesh->firstvert = currentvertex;
1409 mesh->lastvert = currentvertex + m->numverts - 1;
1410 currentvertex += m->numverts;
1413 // code shared for transparent and opaque meshs
1414 mesh->blendfunc1 = m->blendfunc1;
1415 mesh->blendfunc2 = m->blendfunc2;
1416 mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
1417 mesh->depthtest = !m->depthdisable;
1418 mesh->triangles = m->numtriangles;
1420 for (i = 0;i < backendunits;i++)
1422 if ((mesh->textures[i] = m->tex[i]))
1424 mesh->texturergbscale[i] = m->texrgbscale[i];
1425 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1426 mesh->texturergbscale[i] = 1;
1428 if (overbright && j >= 0)
1429 mesh->texturergbscale[j] = 4;
1431 if (m->vertexstep != sizeof(buf_vertex_t))
1432 Host_Error("R_Mesh_Draw_NativeOnly: unsupported vertexstep\n");
1433 if (m->colorstep != sizeof(buf_fcolor_t))
1434 Host_Error("R_Mesh_Draw_NativeOnly: unsupported colorstep\n");
1435 if (m->color == NULL)
1436 Host_Error("R_Mesh_Draw_NativeOnly: must provide color array\n");
1437 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1439 if (j >= backendunits)
1440 Sys_Error("R_Mesh_Draw_NativeOnly: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1441 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1442 Host_Error("R_Mesh_Draw_NativeOnly: unsupported texcoordstep\n");
1445 memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
1446 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1447 memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1449 for (;j < backendunits;j++)
1450 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1453 memcpy(fcolor, m->color, m->numverts * sizeof(buf_fcolor_t));
1455 // do this as a second step because memcpy preloaded the cache, which we can't easily do
1458 for (i = 0;i < m->numverts;i++)
1460 fcolor[i].c[0] *= scaler;
1461 fcolor[i].c[1] *= scaler;
1462 fcolor[i].c[2] *= scaler;
1466 if (currenttriangle >= max_batch)
1471 void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts)
1473 m->index = polyindexarray;
1474 m->numverts = numverts;
1475 m->numtriangles = numverts - 2;
1476 if (m->numtriangles < 1)
1478 Con_Printf("R_Mesh_DrawPolygon: invalid vertex count\n");
1481 if (m->numtriangles >= 256)
1483 Con_Printf("R_Mesh_DrawPolygon: only up to 256 triangles (258 verts) supported\n");
1489 // LordHavoc: this thing is evil, but necessary because decals account for so much overhead
1490 void R_Mesh_DrawDecal(const rmeshinfo_t *m)
1492 // these are static because gcc runs out of virtual registers otherwise
1493 static int i, *index, overbright;
1494 static float scaler;
1495 static float cr, cg, cb, ca;
1496 static buf_mesh_t *mesh;
1497 static buf_vertex_t *vert;
1498 static buf_fcolor_t *fcolor;
1499 static buf_texcoord_t *texcoord;
1500 static buf_transtri_t *tri;
1503 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1508 overbright = gl_combine.integer;
1512 scaler *= overbrightscale;
1516 if (currenttransmesh >= max_meshs || (currenttranstriangle + 2) > max_meshs || (currenttransvertex + 4) > max_verts)
1520 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1528 vert = &buf_transvertex[currenttransvertex];
1529 fcolor = &buf_transfcolor[currenttransvertex];
1530 texcoord = &buf_transtexcoord[0][currenttransvertex];
1532 // transmesh is only for storage of transparent meshs until they
1533 // are inserted into the main mesh array
1534 mesh = &buf_transmesh[currenttransmesh++];
1535 mesh->blendfunc1 = m->blendfunc1;
1536 mesh->blendfunc2 = m->blendfunc2;
1537 mesh->depthmask = false;
1538 mesh->depthtest = true;
1539 mesh->triangles = 2;
1540 mesh->textures[0] = m->tex[0];
1541 mesh->texturergbscale[0] = overbright ? 4 : 1;
1542 for (i = 1;i < backendunits;i++)
1544 mesh->textures[i] = 0;
1545 mesh->texturergbscale[i] = 1;
1549 // transparent meshs are broken up into individual triangles which can
1550 // be sorted by depth
1552 tri = &buf_transtri[currenttranstriangle++];
1557 tri = &buf_transtri[currenttranstriangle++];
1563 mesh->firstvert = currenttransvertex;
1564 mesh->lastvert = currenttransvertex + 3;
1565 currenttransvertex += 4;
1569 if (2 > max_meshs || 4 > max_verts)
1571 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
1575 if (currentmesh >= max_meshs || (currenttriangle + 2) > max_batch || (currentvertex + 4) > max_verts)
1580 vert = &buf_vertex[currentvertex];
1581 fcolor = &buf_fcolor[currentvertex];
1582 texcoord = &buf_texcoord[0][currentvertex];
1584 mesh = &buf_mesh[currentmesh++];
1585 mesh->blendfunc1 = m->blendfunc1;
1586 mesh->blendfunc2 = m->blendfunc2;
1587 mesh->depthmask = false;
1588 mesh->depthtest = !m->depthdisable;
1589 mesh->firsttriangle = currenttriangle;
1590 mesh->triangles = 2;
1591 mesh->textures[0] = m->tex[0];
1592 mesh->texturergbscale[0] = overbright ? 4 : 1;
1593 for (i = 1;i < backendunits;i++)
1595 mesh->textures[i] = 0;
1596 mesh->texturergbscale[i] = 1;
1599 // opaque meshs are rendered directly
1600 index = &buf_tri[currenttriangle].index[0];
1607 mesh->firstvert = currentvertex;
1608 mesh->lastvert = currentvertex + 3;
1609 currenttriangle += 2;
1613 // buf_vertex_t must match the size of the decal vertex array (or vice versa)
1614 memcpy(vert, m->vertex, 4 * sizeof(buf_vertex_t));
1616 cr = m->cr * scaler;
1617 cg = m->cg * scaler;
1618 cb = m->cb * scaler;
1620 fcolor[0].c[0] = cr;
1621 fcolor[0].c[1] = cg;
1622 fcolor[0].c[2] = cb;
1623 fcolor[0].c[3] = ca;
1624 fcolor[1].c[0] = cr;
1625 fcolor[1].c[1] = cg;
1626 fcolor[1].c[2] = cb;
1627 fcolor[1].c[3] = ca;
1628 fcolor[2].c[0] = cr;
1629 fcolor[2].c[1] = cg;
1630 fcolor[2].c[2] = cb;
1631 fcolor[2].c[3] = ca;
1632 fcolor[3].c[0] = cr;
1633 fcolor[3].c[1] = cg;
1634 fcolor[3].c[2] = cb;
1635 fcolor[3].c[3] = ca;
1637 // buf_texcoord_t must be the same size as the decal texcoord array (or vice versa)
1638 memcpy(&texcoord[0].t[0], m->texcoords[0], 4 * sizeof(buf_texcoord_t));
1640 if (currenttriangle >= max_batch)
1645 ==============================================================================
1649 ==============================================================================
1652 float CalcFov (float fov_x, float width, float height);
1653 void R_ClearScreen(void);
1655 void SCR_ScreenShot(char *filename, int x, int y, int width, int height)
1660 buffer = Mem_Alloc(tempmempool, width*height*3);
1661 glReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
1664 // LordHavoc: compensate for v_overbrightbits when using hardware gamma
1665 if (v_hwgamma.integer)
1666 for (i = 0;i < width * height * 3;i++)
1667 buffer[i] <<= v_overbrightbits.integer;
1669 Image_WriteTGARGB_preflipped(filename, width, height, buffer);
1679 void SCR_ScreenShot_f (void)
1683 char checkname[MAX_OSPATH];
1685 // find a file name to save it to
1687 strcpy(filename, "dp0000.tga");
1689 for (i=0 ; i<=9999 ; i++)
1691 filename[2] = (i/1000)%10 + '0';
1692 filename[3] = (i/ 100)%10 + '0';
1693 filename[4] = (i/ 10)%10 + '0';
1694 filename[5] = (i/ 1)%10 + '0';
1695 sprintf (checkname, "%s/%s", com_gamedir, filename);
1696 if (Sys_FileTime(checkname) == -1)
1697 break; // file doesn't exist
1701 Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n");
1705 SCR_ScreenShot(filename, vid.realx, vid.realy, vid.realwidth, vid.realheight);
1706 Con_Printf ("Wrote %s\n", filename);
1713 Grab six views for environment mapping tests
1724 {{ 0, 90, 0}, "rt"},
1725 {{ 0, 180, 0}, "bk"},
1726 {{ 0, 270, 0}, "lf"},
1727 {{-90, 90, 0}, "up"},
1728 {{ 90, 90, 0}, "dn"}
1730 static void R_Envmap_f (void)
1733 char filename[256], basename[256];
1735 if (Cmd_Argc() != 3)
1737 Con_Printf ("envmap <basename> <size>: save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n");
1741 if (!r_render.integer)
1744 strcpy(basename, Cmd_Argv(1));
1745 size = atoi(Cmd_Argv(2));
1746 if (size != 128 && size != 256 && size != 512 && size != 1024)
1748 Con_Printf("envmap: size must be one of 128, 256, 512, or 1024\n");
1751 if (size > vid.realwidth || size > vid.realheight)
1753 Con_Printf("envmap: your resolution is not big enough to render that size\n");
1761 r_refdef.width = size;
1762 r_refdef.height = size;
1764 r_refdef.fov_x = 90;
1765 r_refdef.fov_y = 90;
1767 for (j = 0;j < 6;j++)
1769 sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name);
1770 VectorCopy(envmapinfo[j].angles, r_refdef.viewangles);
1773 SCR_ScreenShot(filename, vid.realx, vid.realy, size, size);
1779 //=============================================================================
1781 void R_ClearScreen(void)
1783 if (r_render.integer)
1785 glClearColor(0,0,0,0);
1787 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
1789 if (gl_dither.integer)
1790 glEnable(GL_DITHER);
1792 glDisable(GL_DITHER);
1801 This is called every frame, and can also be called explicitly to flush
1805 void SCR_UpdateScreen (void)
1807 //Mem_CheckSentinelsGlobal();
1808 //R_TimeReport("memtest");
1815 R_TimeReport("finish");
1817 if (gl_combine.integer && !gl_combine_extension)
1818 Cvar_SetValue("gl_combine", 0);
1820 lightscalebit = v_overbrightbits.integer;
1821 if (gl_combine.integer && r_multitexture.integer)
1824 lightscale = 1.0f / (float) (1 << lightscalebit);
1825 overbrightscale = 1.0f / (float) (1 << v_overbrightbits.integer);
1827 R_TimeReport("setup");
1831 R_TimeReport("clear");
1833 if (scr_conlines < vid.conheight)