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_sorttranstri;
94 static buf_transtri_t **buf_sorttranstri_list;
95 static buf_tri_t *buf_transtri;
96 static buf_vertex_t *buf_transvertex;
97 static buf_fcolor_t *buf_transfcolor;
98 static buf_texcoord_t *buf_transtexcoord[MAX_TEXTUREUNITS];
100 static mempool_t *gl_backend_mempool;
101 static int resizingbuffers = false;
103 static void gl_backend_start(void)
107 max_verts = max_meshs * 3;
109 if (!gl_backend_mempool)
110 gl_backend_mempool = Mem_AllocPool("GL_Backend");
112 #define BACKENDALLOC(var, count, sizeofstruct)\
114 var = Mem_Alloc(gl_backend_mempool, count * sizeof(sizeofstruct));\
116 Sys_Error("gl_backend_start: unable to allocate memory\n");\
117 memset(var, 0, count * sizeof(sizeofstruct));\
120 BACKENDALLOC(buf_mesh, max_meshs, buf_mesh_t)
121 BACKENDALLOC(buf_tri, max_meshs, buf_tri_t)
122 BACKENDALLOC(buf_vertex, max_verts, buf_vertex_t)
123 BACKENDALLOC(buf_fcolor, max_verts, buf_fcolor_t)
124 BACKENDALLOC(buf_bcolor, max_verts, buf_bcolor_t)
126 BACKENDALLOC(buf_transmesh, max_meshs, buf_mesh_t)
127 BACKENDALLOC(buf_sorttranstri, max_meshs, buf_transtri_t)
128 BACKENDALLOC(buf_sorttranstri_list, TRANSDEPTHRES, buf_transtri_t *)
129 BACKENDALLOC(buf_transtri, max_meshs, buf_tri_t)
130 BACKENDALLOC(buf_transvertex, max_verts, buf_vertex_t)
131 BACKENDALLOC(buf_transfcolor, max_verts, buf_fcolor_t)
133 for (i = 0;i < MAX_TEXTUREUNITS;i++)
135 // only allocate as many texcoord arrays as we need
136 if (i < gl_textureunits)
138 BACKENDALLOC(buf_texcoord[i], max_verts, buf_texcoord_t)
139 BACKENDALLOC(buf_transtexcoord[i], max_verts, buf_texcoord_t)
143 buf_texcoord[i] = NULL;
144 buf_transtexcoord[i] = NULL;
147 backendunits = min(MAX_TEXTUREUNITS, gl_textureunits);
148 backendactive = true;
151 static void gl_backend_shutdown(void)
154 Mem_EmptyPool(gl_backend_mempool);
156 Mem_FreePool(&gl_backend_mempool);
159 backendactive = false;
162 static void gl_backend_bufferchanges(int init)
164 // 21760 is (65536 / 3) rounded off to a multiple of 128
165 if (gl_mesh_maxtriangles.integer < 256)
166 Cvar_SetValue("gl_mesh_maxtriangles", 256);
167 if (gl_mesh_maxtriangles.integer > 21760)
168 Cvar_SetValue("gl_mesh_maxtriangles", 21760);
170 if (gl_mesh_batchtriangles.integer < 0)
171 Cvar_SetValue("gl_mesh_batchtriangles", 0);
172 if (gl_mesh_batchtriangles.integer > gl_mesh_maxtriangles.integer)
173 Cvar_SetValue("gl_mesh_batchtriangles", gl_mesh_maxtriangles.integer);
175 max_batch = gl_mesh_batchtriangles.integer;
177 if (max_meshs != gl_mesh_maxtriangles.integer)
179 max_meshs = gl_mesh_maxtriangles.integer;
183 resizingbuffers = true;
184 gl_backend_shutdown();
186 resizingbuffers = false;
191 float r_farclip, r_newfarclip;
193 static void gl_backend_newmap(void)
195 r_farclip = r_newfarclip = 2048.0f;
198 int polyindexarray[768];
200 void gl_backend_init(void)
204 Cvar_RegisterVariable (&r_render);
205 Cvar_RegisterVariable (&gl_dither);
207 Cvar_SetValue("r_render", 0);
210 Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
211 Cmd_AddCommand ("envmap", R_Envmap_f);
213 Cvar_RegisterVariable(&gl_mesh_maxtriangles);
214 Cvar_RegisterVariable(&gl_mesh_batchtriangles);
215 Cvar_RegisterVariable(&gl_mesh_merge);
216 Cvar_RegisterVariable(&gl_mesh_floatcolors);
217 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
218 gl_backend_bufferchanges(true);
219 for (i = 0;i < 256;i++)
221 polyindexarray[i*3+0] = 0;
222 polyindexarray[i*3+1] = i + 1;
223 polyindexarray[i*3+2] = i + 2;
227 static void MYgluPerspective(GLdouble fovx, GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar )
231 xmax = zNear * tan( fovx * M_PI / 360.0 ) * aspect;
232 ymax = zNear * tan( fovy * M_PI / 360.0 );
234 glFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar );
243 static void GL_SetupFrame (void)
245 if (!r_render.integer)
248 // glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: moved to SCR_UpdateScreen
251 glDepthFunc (GL_LEQUAL);
253 glDepthRange (gldepthmin, gldepthmax);
255 // update farclip based on previous frame
256 r_farclip = r_newfarclip;
259 glMatrixMode(GL_PROJECTION);
262 // y is weird beause OpenGL is bottom to top, we use top to bottom
263 glViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height);
264 // yfov = 2*atan((float)r_refdef.height/r_refdef.width)*180/M_PI;
265 MYgluPerspective (r_refdef.fov_x, r_refdef.fov_y, r_refdef.width/r_refdef.height, 4, r_farclip);
267 glCullFace(GL_FRONT);
269 glMatrixMode(GL_MODELVIEW);
272 glRotatef (-90, 1, 0, 0); // put Z going up
273 glRotatef (90, 0, 0, 1); // put Z going up
274 glRotatef (-r_refdef.viewangles[2], 1, 0, 0);
275 glRotatef (-r_refdef.viewangles[0], 0, 1, 0);
276 glRotatef (-r_refdef.viewangles[1], 0, 0, 1);
277 glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
279 // glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
284 // if (gl_cull.integer)
285 glEnable(GL_CULL_FACE);
287 // glDisable(GL_CULL_FACE);
289 glEnable(GL_BLEND); // was Disable
290 glEnable(GL_DEPTH_TEST);
294 static float viewdist;
296 int c_meshs, c_meshtris, c_transmeshs, c_transtris;
298 // called at beginning of frame
299 void R_Mesh_Clear(void)
302 Sys_Error("R_Mesh_Clear: called when backend is not active\n");
304 gl_backend_bufferchanges(false);
309 currenttransmesh = 0;
310 currenttranstriangle = 0;
311 currenttransvertex = 0;
313 meshmerge = gl_mesh_merge.integer;
315 viewdist = DotProduct(r_origin, vpn);
326 void GL_PrintError(int errornumber, char *filename, int linenumber)
330 case GL_INVALID_ENUM:
331 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
333 case GL_INVALID_VALUE:
334 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
336 case GL_INVALID_OPERATION:
337 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
339 case GL_STACK_OVERFLOW:
340 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
342 case GL_STACK_UNDERFLOW:
343 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
345 case GL_OUT_OF_MEMORY:
346 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
348 #ifdef GL_TABLE_TOO_LARGE
349 case GL_TABLE_TOO_LARGE:
350 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
354 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
362 // renders mesh buffers, called to flush buffers when full
363 void R_Mesh_Render(void)
365 int i, k, blendfunc1, blendfunc2, blend, depthmask, depthtest, unit = 0, clientunit = 0, firsttriangle, triangles, firstvert, lastvert, texture[MAX_TEXTUREUNITS];
366 float farclip, texturergbscale[MAX_TEXTUREUNITS];
369 // float to byte color conversion
374 Sys_Error("R_Mesh_Render: called when backend is not active\n");
380 // push out farclip based on vertices
381 for (i = 0;i < currentvertex;i++)
383 farclip = DotProduct(buf_vertex[i].v, vpn);
384 if (meshfarclip < farclip)
385 meshfarclip = farclip;
388 farclip = meshfarclip + 256.0f - viewdist; // + 256 just to be safe
390 // push out farclip for next frame
391 if (farclip > r_newfarclip)
392 r_newfarclip = ceil((farclip + 255) / 256) * 256 + 256;
394 for (i = 0;i < backendunits;i++)
395 texturergbscale[i] = 1;
397 glEnable(GL_CULL_FACE);
399 glCullFace(GL_FRONT);
402 glEnable(GL_DEPTH_TEST);
405 blendfunc2 = GL_ZERO;
406 glBlendFunc(blendfunc1, blendfunc2);
412 glDepthMask((GLboolean) depthmask);
415 glVertexPointer(3, GL_FLOAT, sizeof(buf_vertex_t), buf_vertex);
417 glEnableClientState(GL_VERTEX_ARRAY);
419 if (gl_mesh_floatcolors.integer)
421 glColorPointer(4, GL_FLOAT, sizeof(buf_fcolor_t), buf_fcolor);
426 // shift float to have 8bit fraction at base of number
427 for (i = 0, fcolor = &buf_fcolor->c[0];i < currentvertex;i++)
429 *fcolor++ += 32768.0f;
430 *fcolor++ += 32768.0f;
431 *fcolor++ += 32768.0f;
432 *fcolor++ += 32768.0f;
434 // then read as integer and kill float bits...
435 for (i = 0, icolor = (int *)&buf_fcolor->c[0], bcolor = &buf_bcolor->c[0];i < currentvertex;i++)
437 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
438 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
439 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
440 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
442 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(buf_bcolor_t), buf_bcolor);
445 glEnableClientState(GL_COLOR_ARRAY);
448 if (backendunits > 1)
450 for (i = 0;i < backendunits;i++)
452 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
454 glBindTexture(GL_TEXTURE_2D, (texture[i] = 0));
456 glDisable(GL_TEXTURE_2D);
458 if (gl_combine.integer)
460 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
462 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
464 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
466 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
468 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB);
470 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
472 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
474 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
476 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
478 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
480 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
482 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);
484 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
486 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
488 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
490 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
492 glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0f);
497 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
501 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
503 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[i]);
505 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
511 glBindTexture(GL_TEXTURE_2D, (texture[0] = 0));
513 glDisable(GL_TEXTURE_2D);
515 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
518 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[0]);
520 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
524 // lock as early as possible
525 GL_LockArray(0, currentvertex);
528 for (k = 0;k < currentmesh;)
532 if (backendunits > 1)
535 for (i = 0;i < backendunits;i++)
537 if (texture[i] != mesh->textures[i])
541 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
546 glEnable(GL_TEXTURE_2D);
548 // have to disable texcoord array on disabled texture
549 // units due to NVIDIA driver bug with
550 // compiled_vertex_array
553 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
556 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
559 glBindTexture(GL_TEXTURE_2D, (texture[i] = mesh->textures[i]));
563 glDisable(GL_TEXTURE_2D);
565 // have to disable texcoord array on disabled texture
566 // units due to NVIDIA driver bug with
567 // compiled_vertex_array
570 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
573 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
577 if (texturergbscale[i] != mesh->texturergbscale[i])
581 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
584 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (texturergbscale[i] = mesh->texturergbscale[i]));
590 // if (unit != topunit)
592 // qglActiveTexture(GL_TEXTURE0_ARB + (unit = topunit));
598 if (texture[0] != mesh->textures[0])
602 glEnable(GL_TEXTURE_2D);
604 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
607 glBindTexture(GL_TEXTURE_2D, (texture[0] = mesh->textures[0]));
611 glDisable(GL_TEXTURE_2D);
613 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
618 if (blendfunc1 != mesh->blendfunc1 || blendfunc2 != mesh->blendfunc2)
620 blendfunc1 = mesh->blendfunc1;
621 blendfunc2 = mesh->blendfunc2;
622 glBlendFunc(blendfunc1, blendfunc2);
624 if (blendfunc2 == GL_ZERO)
626 if (blendfunc1 == GL_ONE)
655 if (depthtest != mesh->depthtest)
657 depthtest = mesh->depthtest;
659 glEnable(GL_DEPTH_TEST);
661 glDisable(GL_DEPTH_TEST);
663 if (depthmask != mesh->depthmask)
665 depthmask = mesh->depthmask;
666 glDepthMask((GLboolean) depthmask);
670 firsttriangle = mesh->firsttriangle;
671 triangles = mesh->triangles;
672 firstvert = mesh->firstvert;
673 lastvert = mesh->lastvert;
674 mesh = &buf_mesh[++k];
678 #if MAX_TEXTUREUNITS != 4
679 #error update this code
681 while (k < currentmesh
682 && mesh->blendfunc1 == blendfunc1
683 && mesh->blendfunc2 == blendfunc2
684 && mesh->depthtest == depthtest
685 && mesh->depthmask == depthmask
686 && mesh->textures[0] == texture[0]
687 && mesh->textures[1] == texture[1]
688 && mesh->textures[2] == texture[2]
689 && mesh->textures[3] == texture[3]
690 && mesh->texturergbscale[0] == texturergbscale[0]
691 && mesh->texturergbscale[1] == texturergbscale[1]
692 && mesh->texturergbscale[2] == texturergbscale[2]
693 && mesh->texturergbscale[3] == texturergbscale[3])
695 triangles += mesh->triangles;
696 if (firstvert > mesh->firstvert)
697 firstvert = mesh->firstvert;
698 if (lastvert < mesh->lastvert)
699 lastvert = mesh->lastvert;
700 mesh = &buf_mesh[++k];
704 index = (unsigned int *)&buf_tri[firsttriangle].index[0];
705 for (i = 0;i < triangles * 3;i++)
706 index[i] += firstvert;
709 // FIXME: dynamic link to GL so we can get DrawRangeElements on WIN32
710 glDrawElements(GL_TRIANGLES, triangles * 3, GL_UNSIGNED_INT, index);
712 glDrawRangeElements(GL_TRIANGLES, firstvert, lastvert + 1, triangles * 3, GL_UNSIGNED_INT, index);
724 if (backendunits > 1)
726 for (i = backendunits - 1;i >= 0;i--)
728 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
730 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
732 if (gl_combine.integer)
734 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
739 glDisable(GL_TEXTURE_2D);
744 glEnable(GL_TEXTURE_2D);
747 glBindTexture(GL_TEXTURE_2D, 0);
750 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
752 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
758 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
760 glEnable(GL_TEXTURE_2D);
762 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
765 glDisableClientState(GL_COLOR_ARRAY);
767 glDisableClientState(GL_VERTEX_ARRAY);
772 glEnable(GL_DEPTH_TEST);
776 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
780 void R_Mesh_AddTransparent(void)
783 float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
784 buf_vertex_t *vert1, *vert2, *vert3;
786 buf_mesh_t *mesh, *transmesh;
788 if (!currenttransmesh)
791 // convert index data to transtris for sorting
792 for (j = 0;j < currenttransmesh;j++)
794 mesh = buf_transmesh + j;
795 k = mesh->firsttriangle;
796 index = &buf_transtri[k].index[0];
797 for (i = 0;i < mesh->triangles;i++)
799 tri = &buf_sorttranstri[k++];
801 tri->index[0] = *index++;
802 tri->index[1] = *index++;
803 tri->index[2] = *index++;
807 // map farclip to 0-4095 list range
808 centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
809 viewdistcompare = viewdist + 4.0f;
811 memset(buf_sorttranstri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
814 for (j = 0;j < currenttranstriangle;j++)
816 tri = &buf_sorttranstri[j];
817 i = tri->mesh->firstvert;
819 vert1 = &buf_transvertex[tri->index[0] + i];
820 vert2 = &buf_transvertex[tri->index[1] + i];
821 vert3 = &buf_transvertex[tri->index[2] + i];
823 dist1 = DotProduct(vert1->v, vpn);
824 dist2 = DotProduct(vert2->v, vpn);
825 dist3 = DotProduct(vert3->v, vpn);
827 maxdist = max(dist1, max(dist2, dist3));
828 if (maxdist < viewdistcompare)
831 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
834 i = bound(0, i, (TRANSDEPTHRES - 1));
838 center += 8388608.0f;
839 i = *((long *)¢er) & 0x7FFFFF;
840 i = min(i, (TRANSDEPTHRES - 1));
842 tri->next = buf_sorttranstri_list[i];
843 buf_sorttranstri_list[i] = tri;
847 //if (currentmesh + k > max_meshs || currenttriangle + k > max_batch || currentvertex + currenttransvertex > max_verts)
850 for (i = 0;i < currenttransmesh;i++)
851 buf_transmesh[i].transchain = NULL;
853 for (j = 0;j < TRANSDEPTHRES;j++)
855 if ((tri = buf_sorttranstri_list[j]))
857 for (;tri;tri = tri->next)
859 if (!tri->mesh->transchain)
861 tri->mesh->chain = transmesh;
862 transmesh = tri->mesh;
864 tri->meshsortchain = tri->mesh->transchain;
865 tri->mesh->transchain = tri;
870 for (;transmesh;transmesh = transmesh->chain)
872 int numverts = transmesh->lastvert - transmesh->firstvert + 1;
873 if (currentmesh >= max_meshs || currenttriangle + transmesh->triangles > max_batch || currentvertex + numverts > max_verts)
876 memcpy(&buf_vertex[currentvertex], &buf_transvertex[transmesh->firstvert], numverts * sizeof(buf_vertex_t));
877 memcpy(&buf_fcolor[currentvertex], &buf_transfcolor[transmesh->firstvert], numverts * sizeof(buf_fcolor_t));
878 for (i = 0;i < backendunits && transmesh->textures[i];i++)
879 memcpy(&buf_texcoord[i][currentvertex], &buf_transtexcoord[i][transmesh->firstvert], numverts * sizeof(buf_texcoord_t));
881 mesh = &buf_mesh[currentmesh++];
882 *mesh = *transmesh; // copy mesh properties
883 mesh->firstvert = currentvertex;
884 mesh->lastvert = currentvertex + numverts - 1;
885 currentvertex += numverts;
886 mesh->firsttriangle = currenttriangle;
887 for (tri = transmesh->transchain;tri;tri = tri->meshsortchain)
889 buf_tri[currenttriangle].index[0] = tri->index[0];
890 buf_tri[currenttriangle].index[1] = tri->index[1];
891 buf_tri[currenttriangle].index[2] = tri->index[2];
894 mesh->triangles = currenttriangle - mesh->firsttriangle;
897 currenttransmesh = 0;
898 currenttranstriangle = 0;
899 currenttransvertex = 0;
902 void R_Mesh_Draw(const rmeshinfo_t *m)
904 // these are static because gcc runs out of virtual registers otherwise
905 static int i, j, overbright;
906 static float *in, scaler;
907 static float cr, cg, cb, ca;
908 static buf_mesh_t *mesh;
909 static buf_vertex_t *vert;
910 static buf_fcolor_t *fcolor;
911 static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
914 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
920 Host_Error("R_Mesh_Draw: no triangles or verts\n");
922 // ignore meaningless alpha meshs
923 if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
927 for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
930 if (i == m->numverts)
933 else if (m->ca < 0.01f)
938 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
941 if (m->blendfunc2 == GL_SRC_COLOR)
943 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
950 overbright = gl_combine.integer;
954 scaler *= overbrightscale;
959 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
963 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
970 c_transtris += m->numtriangles;
971 vert = &buf_transvertex[currenttransvertex];
972 fcolor = &buf_transfcolor[currenttransvertex];
973 for (i = 0;i < backendunits;i++)
974 texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
976 // transmesh is only for storage of transparent meshs until they
977 // are inserted into the main mesh array
978 mesh = &buf_transmesh[currenttransmesh++];
979 mesh->firsttriangle = currenttranstriangle;
980 memcpy(&buf_transtri[currenttranstriangle].index[0], m->index, sizeof(int[3]) * m->numtriangles);
981 currenttranstriangle += m->numtriangles;
983 mesh->firstvert = currenttransvertex;
984 mesh->lastvert = currenttransvertex + m->numverts - 1;
985 currenttransvertex += m->numverts;
989 if (m->numtriangles > max_meshs || m->numverts > max_verts)
991 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
995 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
999 c_meshtris += m->numtriangles;
1000 vert = &buf_vertex[currentvertex];
1001 fcolor = &buf_fcolor[currentvertex];
1002 for (i = 0;i < backendunits;i++)
1003 texcoord[i] = &buf_texcoord[i][currentvertex];
1005 // opaque meshs are rendered directly
1006 mesh = &buf_mesh[currentmesh++];
1007 mesh->firsttriangle = currenttriangle;
1008 memcpy(&buf_tri[currenttriangle].index[0], m->index, sizeof(int[3]) * m->numtriangles);
1009 currenttriangle += m->numtriangles;
1011 mesh->firstvert = currentvertex;
1012 mesh->lastvert = currentvertex + m->numverts - 1;
1013 currentvertex += m->numverts;
1016 // code shared for transparent and opaque meshs
1017 mesh->blendfunc1 = m->blendfunc1;
1018 mesh->blendfunc2 = m->blendfunc2;
1019 mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
1020 mesh->depthtest = !m->depthdisable;
1021 mesh->triangles = m->numtriangles;
1023 for (i = 0;i < backendunits;i++)
1025 if ((mesh->textures[i] = m->tex[i]))
1027 mesh->texturergbscale[i] = m->texrgbscale[i];
1028 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1029 mesh->texturergbscale[i] = 1;
1031 if (overbright && j >= 0)
1032 mesh->texturergbscale[j] = 4;
1034 if (m->vertexstep != sizeof(buf_vertex_t))
1036 for (i = 0, in = m->vertex;i < m->numverts;i++, (int)in += m->vertexstep)
1038 vert[i].v[0] = in[0];
1039 vert[i].v[1] = in[1];
1040 vert[i].v[2] = in[2];
1044 memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
1048 for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep)
1050 fcolor[i].c[0] = in[0] * scaler;
1051 fcolor[i].c[1] = in[1] * scaler;
1052 fcolor[i].c[2] = in[2] * scaler;
1053 fcolor[i].c[3] = in[3];
1058 cr = m->cr * scaler;
1059 cg = m->cg * scaler;
1060 cb = m->cb * scaler;
1062 for (i = 0;i < m->numverts;i++)
1064 fcolor[i].c[0] = cr;
1065 fcolor[i].c[1] = cg;
1066 fcolor[i].c[2] = cb;
1067 fcolor[i].c[3] = ca;
1071 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1073 if (j >= backendunits)
1074 Sys_Error("R_Mesh_Draw: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1075 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1077 for (i = 0, in = m->texcoords[j];i < m->numverts;i++, (int)in += m->texcoordstep[j])
1079 texcoord[j][i].t[0] = in[0];
1080 texcoord[j][i].t[1] = in[1];
1084 memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1087 for (;j < backendunits;j++)
1088 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1091 if (currenttriangle >= max_batch)
1095 void R_Mesh_Draw_NativeOnly(const rmeshinfo_t *m)
1097 // these are static because gcc runs out of virtual registers otherwise
1098 static int i, j, overbright;
1099 static float *in, scaler;
1100 static buf_mesh_t *mesh;
1101 static buf_vertex_t *vert;
1102 static buf_fcolor_t *fcolor;
1103 static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
1106 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1108 if (m->index == NULL
1110 || m->vertex == NULL
1112 Host_Error("R_Mesh_Draw: no triangles or verts\n");
1114 // ignore meaningless alpha meshs
1115 if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
1119 for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
1122 if (i == m->numverts)
1125 else if (m->ca < 0.01f)
1130 if (m->blendfunc2 == GL_SRC_COLOR)
1132 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
1139 overbright = gl_combine.integer;
1143 scaler *= overbrightscale;
1148 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
1152 Con_Printf("R_Mesh_Draw_NativeOnly: ran out of room for transparent meshs\n");
1159 c_transtris += m->numtriangles;
1160 vert = &buf_transvertex[currenttransvertex];
1161 fcolor = &buf_transfcolor[currenttransvertex];
1162 for (i = 0;i < backendunits;i++)
1163 texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
1165 // transmesh is only for storage of transparent meshs until they
1166 // are inserted into the main mesh array
1167 mesh = &buf_transmesh[currenttransmesh++];
1168 mesh->firsttriangle = currenttranstriangle;
1169 memcpy(&buf_transtri[currenttranstriangle].index[0], m->index, sizeof(int[3]) * m->numtriangles);
1170 currenttranstriangle += m->numtriangles;
1172 mesh->firstvert = currenttransvertex;
1173 mesh->lastvert = currenttransvertex + m->numverts - 1;
1174 currenttransvertex += m->numverts;
1178 if (m->numtriangles > max_meshs || m->numverts > max_verts)
1180 Con_Printf("R_Mesh_Draw_NativeOnly: mesh too big for buffers\n");
1184 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
1188 c_meshtris += m->numtriangles;
1189 vert = &buf_vertex[currentvertex];
1190 fcolor = &buf_fcolor[currentvertex];
1191 for (i = 0;i < backendunits;i++)
1192 texcoord[i] = &buf_texcoord[i][currentvertex];
1194 mesh = &buf_mesh[currentmesh++];
1195 // opaque meshs are rendered directly
1196 mesh->firsttriangle = currenttriangle;
1197 memcpy(&buf_tri[currenttriangle].index[0], m->index, sizeof(int[3]) * m->numtriangles);
1198 currenttriangle += m->numtriangles;
1200 mesh->firstvert = currentvertex;
1201 mesh->lastvert = currentvertex + m->numverts - 1;
1202 currentvertex += m->numverts;
1205 // code shared for transparent and opaque meshs
1206 mesh->blendfunc1 = m->blendfunc1;
1207 mesh->blendfunc2 = m->blendfunc2;
1208 mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
1209 mesh->depthtest = !m->depthdisable;
1210 mesh->triangles = m->numtriangles;
1212 for (i = 0;i < backendunits;i++)
1214 if ((mesh->textures[i] = m->tex[i]))
1216 mesh->texturergbscale[i] = m->texrgbscale[i];
1217 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1218 mesh->texturergbscale[i] = 1;
1220 if (overbright && j >= 0)
1221 mesh->texturergbscale[j] = 4;
1223 if (m->vertexstep != sizeof(buf_vertex_t))
1224 Host_Error("R_Mesh_Draw_NativeOnly: unsupported vertexstep\n");
1225 if (m->colorstep != sizeof(buf_fcolor_t))
1226 Host_Error("R_Mesh_Draw_NativeOnly: unsupported colorstep\n");
1227 if (m->color == NULL)
1228 Host_Error("R_Mesh_Draw_NativeOnly: must provide color array\n");
1229 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1231 if (j >= backendunits)
1232 Sys_Error("R_Mesh_Draw_NativeOnly: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1233 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1234 Host_Error("R_Mesh_Draw_NativeOnly: unsupported texcoordstep\n");
1237 memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
1238 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1239 memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1241 for (;j < backendunits;j++)
1242 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1245 memcpy(fcolor, m->color, m->numverts * sizeof(buf_fcolor_t));
1247 // do this as a second step because memcpy preloaded the cache, which we can't easily do
1250 for (i = 0;i < m->numverts;i++)
1252 fcolor[i].c[0] *= scaler;
1253 fcolor[i].c[1] *= scaler;
1254 fcolor[i].c[2] *= scaler;
1258 if (currenttriangle >= max_batch)
1263 void R_Mesh_Draw_GetBuffer(volatile rmeshinfo_t *m)
1265 // these are static because gcc runs out of virtual registers otherwise
1266 static int i, j, *index, overbright;
1267 static float *in, scaler;
1270 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1272 if (!m->numtriangles
1274 Host_Error("R_Mesh_Draw: no triangles or verts\n");
1277 if (m->blendfunc2 == GL_SRC_COLOR)
1279 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
1286 overbright = gl_combine.integer;
1290 scaler *= overbrightscale;
1295 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
1299 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1306 c_transtris += m->numtriangles;
1307 m->vertex = &buf_transvertex[currenttransvertex].v[0];
1308 m->color = &buf_transfcolor[currenttransvertex].c[0];
1309 for (i = 0;i < backendunits;i++)
1310 m->texcoords[i] = &buf_transtexcoord[i][currenttransvertex].tc[0];
1312 // transmesh is only for storage of transparent meshs until they
1313 // are inserted into the main mesh array
1314 mesh = &buf_transmesh[currenttransmesh++];
1315 mesh->firsttriangle = currenttranstriangle;
1316 memcpy(&buf_transtri[currenttranstriangle].index[0], m->index, sizeof(int[3]) * m->numtriangles);
1317 currenttranstriangle += m->numtriangles;
1319 mesh->firstvert = currenttransvertex;
1320 mesh->lastvert = currenttransvertex + m->numverts - 1;
1321 currenttransvertex += m->numverts;
1325 if (m->numtriangles > max_meshs || m->numverts > max_verts)
1327 Con_Printf("R_Mesh_Draw_NativeOnly: mesh too big for buffers\n");
1331 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
1335 c_meshtris += m->numtriangles;
1336 vert = &buf_vertex[currentvertex];
1337 fcolor = &buf_fcolor[currentvertex];
1338 for (i = 0;i < backendunits;i++)
1339 texcoord[i] = &buf_texcoord[i][currentvertex];
1341 // opaque meshs are rendered directly
1342 mesh = &buf_mesh[currentmesh++];
1343 mesh->firsttriangle = currenttriangle;
1344 memcpy(&buf_tri[currenttriangle].index[0], m->index, sizeof(int[3]) * m->numtriangles);
1345 currenttriangle += m->numtriangles;
1347 mesh->firstvert = currentvertex;
1348 mesh->lastvert = currentvertex + m->numverts - 1;
1349 currentvertex += m->numverts;
1352 // code shared for transparent and opaque meshs
1353 mesh->blendfunc1 = m->blendfunc1;
1354 mesh->blendfunc2 = m->blendfunc2;
1355 mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
1356 mesh->depthtest = !m->depthdisable;
1357 mesh->triangles = m->numtriangles;
1359 for (i = 0;i < backendunits;i++)
1361 if ((mesh->textures[i] = m->tex[i]))
1363 mesh->texturergbscale[i] = m->texrgbscale[i];
1364 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1365 mesh->texturergbscale[i] = 1;
1367 if (overbright && j >= 0)
1368 mesh->texturergbscale[j] = 4;
1370 if (m->vertexstep != sizeof(buf_vertex_t))
1371 Host_Error("R_Mesh_Draw_NativeOnly: unsupported vertexstep\n");
1372 if (m->colorstep != sizeof(buf_fcolor_t))
1373 Host_Error("R_Mesh_Draw_NativeOnly: unsupported colorstep\n");
1374 if (m->color == NULL)
1375 Host_Error("R_Mesh_Draw_NativeOnly: must provide color array\n");
1376 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1378 if (j >= backendunits)
1379 Sys_Error("R_Mesh_Draw_NativeOnly: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1380 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1381 Host_Error("R_Mesh_Draw_NativeOnly: unsupported texcoordstep\n");
1384 memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
1385 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1386 memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1388 for (;j < backendunits;j++)
1389 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1392 memcpy(fcolor, m->color, m->numverts * sizeof(buf_fcolor_t));
1394 // do this as a second step because memcpy preloaded the cache, which we can't easily do
1397 for (i = 0;i < m->numverts;i++)
1399 fcolor[i].c[0] *= scaler;
1400 fcolor[i].c[1] *= scaler;
1401 fcolor[i].c[2] *= scaler;
1405 if (currenttriangle >= max_batch)
1410 void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts)
1412 m->index = polyindexarray;
1413 m->numverts = numverts;
1414 m->numtriangles = numverts - 2;
1415 if (m->numtriangles < 1)
1417 Con_Printf("R_Mesh_DrawPolygon: invalid vertex count\n");
1420 if (m->numtriangles >= 256)
1422 Con_Printf("R_Mesh_DrawPolygon: only up to 256 triangles (258 verts) supported\n");
1429 // LordHavoc: this thing is evil, but necessary because decals account for so much overhead
1430 void R_Mesh_DrawDecal(const rmeshinfo_t *m)
1432 // these are static because gcc runs out of virtual registers otherwise
1433 static int i, *index, overbright;
1434 static float scaler;
1435 static float cr, cg, cb, ca;
1436 static buf_mesh_t *mesh;
1437 static buf_vertex_t *vert;
1438 static buf_fcolor_t *fcolor;
1439 static buf_texcoord_t *texcoord;
1440 static buf_transtri_t *tri;
1443 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1448 overbright = gl_combine.integer;
1452 scaler *= overbrightscale;
1456 if (currenttransmesh >= max_meshs || (currenttranstriangle + 2) > max_meshs || (currenttransvertex + 4) > max_verts)
1460 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1468 vert = &buf_transvertex[currenttransvertex];
1469 fcolor = &buf_transfcolor[currenttransvertex];
1470 texcoord = &buf_transtexcoord[0][currenttransvertex];
1472 // transmesh is only for storage of transparent meshs until they
1473 // are inserted into the main mesh array
1474 mesh = &buf_transmesh[currenttransmesh++];
1475 mesh->blendfunc1 = m->blendfunc1;
1476 mesh->blendfunc2 = m->blendfunc2;
1477 mesh->depthmask = false;
1478 mesh->depthtest = true;
1479 mesh->firsttriangle = currenttranstriangle;
1480 mesh->triangles = 2;
1481 mesh->textures[0] = m->tex[0];
1482 mesh->texturergbscale[0] = overbright ? 4 : 1;
1483 for (i = 1;i < backendunits;i++)
1485 mesh->textures[i] = 0;
1486 mesh->texturergbscale[i] = 1;
1490 index = &buf_transtri[currenttranstriangle].index[0];
1491 mesh->firstvert = currenttransvertex;
1492 mesh->lastvert = currenttransvertex + 3;
1493 currenttranstriangle += 2;
1494 currenttransvertex += 4;
1498 if (2 > max_meshs || 4 > max_verts)
1500 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
1504 if (currentmesh >= max_meshs || (currenttriangle + 2) > max_batch || (currentvertex + 4) > max_verts)
1509 vert = &buf_vertex[currentvertex];
1510 fcolor = &buf_fcolor[currentvertex];
1511 texcoord = &buf_texcoord[0][currentvertex];
1513 mesh = &buf_mesh[currentmesh++];
1514 mesh->blendfunc1 = m->blendfunc1;
1515 mesh->blendfunc2 = m->blendfunc2;
1516 mesh->depthmask = false;
1517 mesh->depthtest = !m->depthdisable;
1518 mesh->firsttriangle = currenttriangle;
1519 mesh->triangles = 2;
1520 mesh->textures[0] = m->tex[0];
1521 mesh->texturergbscale[0] = overbright ? 4 : 1;
1522 for (i = 1;i < backendunits;i++)
1524 mesh->textures[i] = 0;
1525 mesh->texturergbscale[i] = 1;
1528 // opaque meshs are rendered directly
1529 index = &buf_tri[currenttriangle].index[0];
1530 mesh->firstvert = currentvertex;
1531 mesh->lastvert = currentvertex + 3;
1532 currenttriangle += 2;
1543 // buf_vertex_t must match the size of the decal vertex array (or vice versa)
1544 memcpy(vert, m->vertex, 4 * sizeof(buf_vertex_t));
1546 cr = m->cr * scaler;
1547 cg = m->cg * scaler;
1548 cb = m->cb * scaler;
1550 fcolor[0].c[0] = cr;
1551 fcolor[0].c[1] = cg;
1552 fcolor[0].c[2] = cb;
1553 fcolor[0].c[3] = ca;
1554 fcolor[1].c[0] = cr;
1555 fcolor[1].c[1] = cg;
1556 fcolor[1].c[2] = cb;
1557 fcolor[1].c[3] = ca;
1558 fcolor[2].c[0] = cr;
1559 fcolor[2].c[1] = cg;
1560 fcolor[2].c[2] = cb;
1561 fcolor[2].c[3] = ca;
1562 fcolor[3].c[0] = cr;
1563 fcolor[3].c[1] = cg;
1564 fcolor[3].c[2] = cb;
1565 fcolor[3].c[3] = ca;
1567 // buf_texcoord_t must be the same size as the decal texcoord array (or vice versa)
1568 memcpy(&texcoord[0].t[0], m->texcoords[0], 4 * sizeof(buf_texcoord_t));
1570 if (currenttriangle >= max_batch)
1576 ==============================================================================
1580 ==============================================================================
1583 float CalcFov (float fov_x, float width, float height);
1584 void R_ClearScreen(void);
1586 void SCR_ScreenShot(char *filename, int x, int y, int width, int height)
1591 buffer = Mem_Alloc(tempmempool, width*height*3);
1592 glReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
1595 // LordHavoc: compensate for v_overbrightbits when using hardware gamma
1596 if (v_hwgamma.integer)
1597 for (i = 0;i < width * height * 3;i++)
1598 buffer[i] <<= v_overbrightbits.integer;
1600 Image_WriteTGARGB_preflipped(filename, width, height, buffer);
1610 void SCR_ScreenShot_f (void)
1614 char checkname[MAX_OSPATH];
1616 // find a file name to save it to
1618 strcpy(filename, "dp0000.tga");
1620 for (i=0 ; i<=9999 ; i++)
1622 filename[2] = (i/1000)%10 + '0';
1623 filename[3] = (i/ 100)%10 + '0';
1624 filename[4] = (i/ 10)%10 + '0';
1625 filename[5] = (i/ 1)%10 + '0';
1626 sprintf (checkname, "%s/%s", com_gamedir, filename);
1627 if (Sys_FileTime(checkname) == -1)
1628 break; // file doesn't exist
1632 Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n");
1636 SCR_ScreenShot(filename, vid.realx, vid.realy, vid.realwidth, vid.realheight);
1637 Con_Printf ("Wrote %s\n", filename);
1644 Grab six views for environment mapping tests
1655 {{ 0, 90, 0}, "rt"},
1656 {{ 0, 180, 0}, "bk"},
1657 {{ 0, 270, 0}, "lf"},
1658 {{-90, 90, 0}, "up"},
1659 {{ 90, 90, 0}, "dn"}
1661 static void R_Envmap_f (void)
1664 char filename[256], basename[256];
1666 if (Cmd_Argc() != 3)
1668 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");
1672 if (!r_render.integer)
1675 strcpy(basename, Cmd_Argv(1));
1676 size = atoi(Cmd_Argv(2));
1677 if (size != 128 && size != 256 && size != 512 && size != 1024)
1679 Con_Printf("envmap: size must be one of 128, 256, 512, or 1024\n");
1682 if (size > vid.realwidth || size > vid.realheight)
1684 Con_Printf("envmap: your resolution is not big enough to render that size\n");
1692 r_refdef.width = size;
1693 r_refdef.height = size;
1695 r_refdef.fov_x = 90;
1696 r_refdef.fov_y = 90;
1698 for (j = 0;j < 6;j++)
1700 sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name);
1701 VectorCopy(envmapinfo[j].angles, r_refdef.viewangles);
1704 SCR_ScreenShot(filename, vid.realx, vid.realy, size, size);
1710 //=============================================================================
1712 void R_ClearScreen(void)
1714 if (r_render.integer)
1716 glClearColor(0,0,0,0);
1718 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
1720 if (gl_dither.integer)
1721 glEnable(GL_DITHER);
1723 glDisable(GL_DITHER);
1732 This is called every frame, and can also be called explicitly to flush
1736 void SCR_UpdateScreen (void)
1738 //Mem_CheckSentinelsGlobal();
1739 //R_TimeReport("memtest");
1746 R_TimeReport("finish");
1748 if (gl_combine.integer && !gl_combine_extension)
1749 Cvar_SetValue("gl_combine", 0);
1751 lightscalebit = v_overbrightbits.integer;
1752 if (gl_combine.integer && r_multitexture.integer)
1755 lightscale = 1.0f / (float) (1 << lightscalebit);
1756 overbrightscale = 1.0f / (float) (1 << v_overbrightbits.integer);
1758 R_TimeReport("setup");
1762 R_TimeReport("clear");
1764 if (scr_conlines < vid.conheight)