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"};
24 static cvar_t gl_mesh_dupetransverts = {0, "gl_mesh_dupetransverts", "0"};
25 static cvar_t gl_mesh_sorttransbymesh = {0, "gl_mesh_sorttransbymesh", "1"};
27 typedef struct buf_mesh_s
29 //struct buf_mesh_s *next;
32 int blendfunc1, blendfunc2;
33 int textures[MAX_TEXTUREUNITS];
34 float texturergbscale[MAX_TEXTUREUNITS];
39 struct buf_mesh_s *chain;
40 struct buf_transtri_s *transchain;
41 //struct buf_transtri_s **transchainpointer;
45 typedef struct buf_transtri_s
47 struct buf_transtri_s *next;
48 struct buf_transtri_s *meshsortchain;
54 typedef struct buf_tri_s
84 static float meshfarclip;
85 static int currentmesh, currenttriangle, currentvertex, backendunits, backendactive, meshmerge, transranout;
86 static buf_mesh_t *buf_mesh;
87 static buf_tri_t *buf_tri;
88 static buf_vertex_t *buf_vertex;
89 static buf_fcolor_t *buf_fcolor;
90 static buf_bcolor_t *buf_bcolor;
91 static buf_texcoord_t *buf_texcoord[MAX_TEXTUREUNITS];
93 static int currenttransmesh, currenttransvertex, currenttranstriangle;
94 static buf_mesh_t *buf_transmesh;
95 static buf_transtri_t *buf_transtri;
96 static buf_transtri_t **buf_transtri_list;
97 static buf_vertex_t *buf_transvertex;
98 static buf_fcolor_t *buf_transfcolor;
99 static buf_texcoord_t *buf_transtexcoord[MAX_TEXTUREUNITS];
101 static mempool_t *gl_backend_mempool;
102 static int resizingbuffers = false;
104 static void gl_backend_start(void)
108 max_verts = max_meshs * 3;
110 if (!gl_backend_mempool)
111 gl_backend_mempool = Mem_AllocPool("GL_Backend");
113 #define BACKENDALLOC(var, count, sizeofstruct)\
115 var = Mem_Alloc(gl_backend_mempool, count * sizeof(sizeofstruct));\
117 Sys_Error("gl_backend_start: unable to allocate memory\n");\
118 memset(var, 0, count * sizeof(sizeofstruct));\
121 BACKENDALLOC(buf_mesh, max_meshs, buf_mesh_t)
122 BACKENDALLOC(buf_tri, max_meshs, buf_tri_t)
123 BACKENDALLOC(buf_vertex, max_verts, buf_vertex_t)
124 BACKENDALLOC(buf_fcolor, max_verts, buf_fcolor_t)
125 BACKENDALLOC(buf_bcolor, max_verts, buf_bcolor_t)
127 BACKENDALLOC(buf_transmesh, max_meshs, buf_mesh_t)
128 BACKENDALLOC(buf_transtri, max_meshs, buf_transtri_t)
129 BACKENDALLOC(buf_transtri_list, TRANSDEPTHRES, buf_transtri_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)
155 #define BACKENDFREE(var)\
163 #define BACKENDFREE(var) var = NULL;
165 BACKENDFREE(buf_mesh)
167 BACKENDFREE(buf_vertex)
168 BACKENDFREE(buf_fcolor)
169 BACKENDFREE(buf_bcolor)
171 BACKENDFREE(buf_transmesh)
172 BACKENDFREE(buf_transtri)
173 BACKENDFREE(buf_transtri_list)
174 BACKENDFREE(buf_transvertex)
175 BACKENDFREE(buf_transfcolor)
177 for (i = 0;i < MAX_TEXTUREUNITS;i++)
179 BACKENDFREE(buf_texcoord[i])
180 BACKENDFREE(buf_transtexcoord[i])
185 Mem_EmptyPool(gl_backend_mempool);
187 Mem_FreePool(&gl_backend_mempool);
190 backendactive = false;
193 static void gl_backend_bufferchanges(int init)
195 // 21760 is (65536 / 3) rounded off to a multiple of 128
196 if (gl_mesh_maxtriangles.integer < 256)
197 Cvar_SetValue("gl_mesh_maxtriangles", 256);
198 if (gl_mesh_maxtriangles.integer > 21760)
199 Cvar_SetValue("gl_mesh_maxtriangles", 21760);
201 if (gl_mesh_batchtriangles.integer < 0)
202 Cvar_SetValue("gl_mesh_batchtriangles", 0);
203 if (gl_mesh_batchtriangles.integer > gl_mesh_maxtriangles.integer)
204 Cvar_SetValue("gl_mesh_batchtriangles", gl_mesh_maxtriangles.integer);
206 max_batch = gl_mesh_batchtriangles.integer;
208 if (max_meshs != gl_mesh_maxtriangles.integer)
210 max_meshs = gl_mesh_maxtriangles.integer;
214 resizingbuffers = true;
215 gl_backend_shutdown();
217 resizingbuffers = false;
222 float r_farclip, r_newfarclip;
224 static void gl_backend_newmap(void)
226 r_farclip = r_newfarclip = 2048.0f;
229 int polyindexarray[768];
231 void gl_backend_init(void)
235 Cvar_RegisterVariable (&r_render);
236 Cvar_RegisterVariable (&gl_dither);
238 Cvar_SetValue("r_render", 0);
241 Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
242 Cmd_AddCommand ("envmap", R_Envmap_f);
244 Cvar_RegisterVariable(&gl_mesh_maxtriangles);
245 Cvar_RegisterVariable(&gl_mesh_batchtriangles);
246 Cvar_RegisterVariable(&gl_mesh_merge);
247 Cvar_RegisterVariable(&gl_mesh_floatcolors);
248 Cvar_RegisterVariable(&gl_mesh_dupetransverts);
249 Cvar_RegisterVariable(&gl_mesh_sorttransbymesh);
250 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
251 gl_backend_bufferchanges(true);
252 for (i = 0;i < 256;i++)
254 polyindexarray[i*3+0] = 0;
255 polyindexarray[i*3+1] = i + 1;
256 polyindexarray[i*3+2] = i + 2;
260 static void MYgluPerspective(GLdouble fovx, GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar )
264 xmax = zNear * tan( fovx * M_PI / 360.0 ) * aspect;
265 ymax = zNear * tan( fovy * M_PI / 360.0 );
267 glFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar );
276 static void GL_SetupFrame (void)
278 if (!r_render.integer)
281 // glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: moved to SCR_UpdateScreen
284 glDepthFunc (GL_LEQUAL);
286 glDepthRange (gldepthmin, gldepthmax);
288 // update farclip based on previous frame
289 r_farclip = r_newfarclip;
292 glMatrixMode(GL_PROJECTION);
295 // y is weird beause OpenGL is bottom to top, we use top to bottom
296 glViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height);
297 // yfov = 2*atan((float)r_refdef.height/r_refdef.width)*180/M_PI;
298 MYgluPerspective (r_refdef.fov_x, r_refdef.fov_y, r_refdef.width/r_refdef.height, 4, r_farclip);
300 glCullFace(GL_FRONT);
302 glMatrixMode(GL_MODELVIEW);
305 glRotatef (-90, 1, 0, 0); // put Z going up
306 glRotatef (90, 0, 0, 1); // put Z going up
307 glRotatef (-r_refdef.viewangles[2], 1, 0, 0);
308 glRotatef (-r_refdef.viewangles[0], 0, 1, 0);
309 glRotatef (-r_refdef.viewangles[1], 0, 0, 1);
310 glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
312 // glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
317 // if (gl_cull.integer)
318 glEnable(GL_CULL_FACE);
320 // glDisable(GL_CULL_FACE);
322 glEnable(GL_BLEND); // was Disable
323 glEnable(GL_DEPTH_TEST);
327 static float viewdist;
329 int c_meshs, c_meshtris, c_transmeshs, c_transtris;
331 // called at beginning of frame
332 void R_Mesh_Clear(void)
335 Sys_Error("R_Mesh_Clear: called when backend is not active\n");
337 gl_backend_bufferchanges(false);
342 currenttransmesh = 0;
343 currenttranstriangle = 0;
344 currenttransvertex = 0;
346 meshmerge = gl_mesh_merge.integer;
348 viewdist = DotProduct(r_origin, vpn);
359 void GL_PrintError(int errornumber, char *filename, int linenumber)
363 case GL_INVALID_ENUM:
364 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
366 case GL_INVALID_VALUE:
367 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
369 case GL_INVALID_OPERATION:
370 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
372 case GL_STACK_OVERFLOW:
373 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
375 case GL_STACK_UNDERFLOW:
376 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
378 case GL_OUT_OF_MEMORY:
379 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
381 #ifdef GL_TABLE_TOO_LARGE
382 case GL_TABLE_TOO_LARGE:
383 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
387 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
395 // renders mesh buffers, called to flush buffers when full
396 void R_Mesh_Render(void)
398 int i, k, blendfunc1, blendfunc2, blend, depthmask, depthtest, unit = 0, clientunit = 0, firsttriangle, triangles, firstvert, lastvert, texture[MAX_TEXTUREUNITS];
399 float farclip, texturergbscale[MAX_TEXTUREUNITS];
401 // float to byte color conversion
406 Sys_Error("R_Mesh_Render: called when backend is not active\n");
412 // push out farclip based on vertices
413 for (i = 0;i < currentvertex;i++)
415 farclip = DotProduct(buf_vertex[i].v, vpn);
416 if (meshfarclip < farclip)
417 meshfarclip = farclip;
420 farclip = meshfarclip + 256.0f - viewdist; // + 256 just to be safe
422 // push out farclip for next frame
423 if (farclip > r_newfarclip)
424 r_newfarclip = ceil((farclip + 255) / 256) * 256 + 256;
426 for (i = 0;i < backendunits;i++)
427 texturergbscale[i] = 1;
429 glEnable(GL_CULL_FACE);
431 glCullFace(GL_FRONT);
434 glEnable(GL_DEPTH_TEST);
437 blendfunc2 = GL_ZERO;
438 glBlendFunc(blendfunc1, blendfunc2);
444 glDepthMask((GLboolean) depthmask);
447 glVertexPointer(3, GL_FLOAT, sizeof(buf_vertex_t), buf_vertex);
449 glEnableClientState(GL_VERTEX_ARRAY);
451 if (gl_mesh_floatcolors.integer)
453 glColorPointer(4, GL_FLOAT, sizeof(buf_fcolor_t), buf_fcolor);
458 // shift float to have 8bit fraction at base of number
459 for (i = 0, fcolor = &buf_fcolor->c[0];i < currentvertex;i++)
461 *fcolor++ += 32768.0f;
462 *fcolor++ += 32768.0f;
463 *fcolor++ += 32768.0f;
464 *fcolor++ += 32768.0f;
466 // then read as integer and kill float bits...
467 for (i = 0, icolor = (int *)&buf_fcolor->c[0], bcolor = &buf_bcolor->c[0];i < currentvertex;i++)
469 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
470 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
471 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
472 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
474 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(buf_bcolor_t), buf_bcolor);
477 glEnableClientState(GL_COLOR_ARRAY);
480 if (backendunits > 1)
482 for (i = 0;i < backendunits;i++)
484 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
486 glBindTexture(GL_TEXTURE_2D, (texture[i] = 0));
488 glDisable(GL_TEXTURE_2D);
490 if (gl_combine.integer)
492 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
494 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
496 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
498 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
500 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB);
502 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
504 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
506 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
508 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
510 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
512 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
514 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);
516 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
518 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
520 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
522 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
524 glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0f);
529 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
533 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
535 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[i]);
537 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
543 glBindTexture(GL_TEXTURE_2D, (texture[0] = 0));
545 glDisable(GL_TEXTURE_2D);
547 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
550 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[0]);
552 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
556 // lock as early as possible
557 GL_LockArray(0, currentvertex);
560 for (k = 0;k < currentmesh;)
564 if (backendunits > 1)
567 for (i = 0;i < backendunits;i++)
569 if (texture[i] != mesh->textures[i])
573 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
578 glEnable(GL_TEXTURE_2D);
580 // have to disable texcoord array on disabled texture
581 // units due to NVIDIA driver bug with
582 // compiled_vertex_array
585 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
588 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
591 glBindTexture(GL_TEXTURE_2D, (texture[i] = mesh->textures[i]));
595 glDisable(GL_TEXTURE_2D);
597 // have to disable texcoord array on disabled texture
598 // units due to NVIDIA driver bug with
599 // compiled_vertex_array
602 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
605 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
609 if (texturergbscale[i] != mesh->texturergbscale[i])
613 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
616 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (texturergbscale[i] = mesh->texturergbscale[i]));
622 // if (unit != topunit)
624 // qglActiveTexture(GL_TEXTURE0_ARB + (unit = topunit));
630 if (texture[0] != mesh->textures[0])
634 glEnable(GL_TEXTURE_2D);
636 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
639 glBindTexture(GL_TEXTURE_2D, (texture[0] = mesh->textures[0]));
643 glDisable(GL_TEXTURE_2D);
645 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
650 if (blendfunc1 != mesh->blendfunc1 || blendfunc2 != mesh->blendfunc2)
652 blendfunc1 = mesh->blendfunc1;
653 blendfunc2 = mesh->blendfunc2;
654 glBlendFunc(blendfunc1, blendfunc2);
656 if (blendfunc2 == GL_ZERO)
658 if (blendfunc1 == GL_ONE)
687 if (depthtest != mesh->depthtest)
689 depthtest = mesh->depthtest;
691 glEnable(GL_DEPTH_TEST);
693 glDisable(GL_DEPTH_TEST);
695 if (depthmask != mesh->depthmask)
697 depthmask = mesh->depthmask;
698 glDepthMask((GLboolean) depthmask);
702 firsttriangle = mesh->firsttriangle;
703 triangles = mesh->triangles;
704 firstvert = mesh->firstvert;
705 lastvert = mesh->lastvert;
706 mesh = &buf_mesh[++k];
710 #if MAX_TEXTUREUNITS != 4
711 #error update this code
713 while (k < currentmesh
714 && mesh->blendfunc1 == blendfunc1
715 && mesh->blendfunc2 == blendfunc2
716 && mesh->depthtest == depthtest
717 && mesh->depthmask == depthmask
718 && mesh->textures[0] == texture[0]
719 && mesh->textures[1] == texture[1]
720 && mesh->textures[2] == texture[2]
721 && mesh->textures[3] == texture[3]
722 && mesh->texturergbscale[0] == texturergbscale[0]
723 && mesh->texturergbscale[1] == texturergbscale[1]
724 && mesh->texturergbscale[2] == texturergbscale[2]
725 && mesh->texturergbscale[3] == texturergbscale[3])
727 triangles += mesh->triangles;
728 if (firstvert > mesh->firstvert)
729 firstvert = mesh->firstvert;
730 if (lastvert < mesh->lastvert)
731 lastvert = mesh->lastvert;
732 mesh = &buf_mesh[++k];
737 // FIXME: dynamic link to GL so we can get DrawRangeElements on WIN32
738 glDrawElements(GL_TRIANGLES, triangles * 3, GL_UNSIGNED_INT, (unsigned int *)&buf_tri[firsttriangle]);
740 glDrawRangeElements(GL_TRIANGLES, firstvert, lastvert + 1, triangles * 3, GL_UNSIGNED_INT, (unsigned int *)&buf_tri[firsttriangle]);
752 if (backendunits > 1)
754 for (i = backendunits - 1;i >= 0;i--)
756 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
758 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
760 if (gl_combine.integer)
762 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
767 glDisable(GL_TEXTURE_2D);
772 glEnable(GL_TEXTURE_2D);
775 glBindTexture(GL_TEXTURE_2D, 0);
778 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
780 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
786 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
788 glEnable(GL_TEXTURE_2D);
790 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
793 glDisableClientState(GL_COLOR_ARRAY);
795 glDisableClientState(GL_VERTEX_ARRAY);
800 glEnable(GL_DEPTH_TEST);
804 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
808 void R_Mesh_AddTransparent(void)
810 if (gl_mesh_sorttransbymesh.integer)
813 float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
814 buf_vertex_t *vert1, *vert2, *vert3;
816 buf_mesh_t *mesh, *transmesh;
818 // process and add transparent mesh triangles
819 if (!currenttranstriangle)
822 // map farclip to 0-4095 list range
823 centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
824 viewdistcompare = viewdist + 4.0f;
826 memset(buf_transtri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
829 for (j = 0;j < currenttranstriangle;j++)
831 tri = &buf_transtri[j];
833 vert1 = &buf_transvertex[tri->index[0]];
834 vert2 = &buf_transvertex[tri->index[1]];
835 vert3 = &buf_transvertex[tri->index[2]];
837 dist1 = DotProduct(vert1->v, vpn);
838 dist2 = DotProduct(vert2->v, vpn);
839 dist3 = DotProduct(vert3->v, vpn);
841 maxdist = max(dist1, max(dist2, dist3));
842 if (maxdist < viewdistcompare)
845 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
848 i = bound(0, i, (TRANSDEPTHRES - 1));
852 center += 8388608.0f;
853 i = *((long *)¢er) & 0x7FFFFF;
854 i = min(i, (TRANSDEPTHRES - 1));
856 tri->next = buf_transtri_list[i];
857 buf_transtri_list[i] = tri;
862 if (currentmesh + k > max_meshs || currenttriangle + k > max_batch || currentvertex + currenttransvertex > max_verts)
865 // note: can't batch these because they can be rendered in any order
866 // there can never be more transparent triangles than fit in main buffers
867 memcpy(&buf_vertex[currentvertex], &buf_transvertex[0], currenttransvertex * sizeof(buf_vertex_t));
868 memcpy(&buf_fcolor[currentvertex], &buf_transfcolor[0], currenttransvertex * sizeof(buf_fcolor_t));
869 for (i = 0;i < backendunits;i++)
870 memcpy(&buf_texcoord[i][currentvertex], &buf_transtexcoord[i][0], currenttransvertex * sizeof(buf_texcoord_t));
873 for (i = 0;i < currenttransmesh;i++)
875 buf_transmesh[i].transchain = NULL;
876 //buf_transmesh[i].transchainpointer = &buf_transmesh[i].transchain;
877 buf_transmesh[i].triangles = 0;
880 for (j = 0;j < TRANSDEPTHRES;j++)
882 if ((tri = buf_transtri_list[j]))
884 for (;tri;tri = tri->next)
886 if (!tri->mesh->transchain)
888 tri->mesh->chain = transmesh;
889 transmesh = tri->mesh;
891 tri->meshsortchain = tri->mesh->transchain;
892 tri->mesh->transchain = tri;
894 *tri->mesh->transchainpointer = tri;
895 tri->meshsortchain = NULL;
896 tri->mesh->transchainpointer = &tri->meshsortchain;
898 tri->mesh->triangles++;
904 for (;transmesh;transmesh = transmesh->chain)
906 int meshvertexadjust;
907 int numverts = transmesh->lastvert - transmesh->firstvert + 1;
908 if (currentmesh >= max_meshs || currenttriangle + transmesh->triangles > max_batch || currentvertex + numverts > max_verts)
911 memcpy(&buf_vertex[currentvertex], &buf_transvertex[transmesh->firstvert], numverts * sizeof(buf_vertex_t));
912 memcpy(&buf_fcolor[currentvertex], &buf_transfcolor[transmesh->firstvert], numverts * sizeof(buf_fcolor_t));
913 for (i = 0;i < backendunits && transmesh->textures[i];i++)
914 memcpy(&buf_texcoord[i][currentvertex], &buf_transtexcoord[i][transmesh->firstvert], numverts * sizeof(buf_texcoord_t));
916 mesh = &buf_mesh[currentmesh++];
917 *mesh = *transmesh; // copy mesh properties
918 mesh->firstvert = currentvertex;
919 mesh->lastvert = currentvertex + numverts - 1;
920 currentvertex += numverts;
921 meshvertexadjust = mesh->firstvert - transmesh->firstvert;
922 mesh->firsttriangle = currenttriangle;
923 for (tri = transmesh->transchain;tri;tri = tri->meshsortchain)
925 buf_tri[currenttriangle].index[0] = tri->index[0] + meshvertexadjust;
926 buf_tri[currenttriangle].index[1] = tri->index[1] + meshvertexadjust;
927 buf_tri[currenttriangle].index[2] = tri->index[2] + meshvertexadjust;
929 if (tri->mesh != transmesh)
931 if ((unsigned int) buf_tri[currenttriangle].index[0] < (unsigned int) mesh->firstvert
932 || (unsigned int) buf_tri[currenttriangle].index[0] > (unsigned int) mesh->lastvert
933 || (unsigned int) buf_tri[currenttriangle].index[1] < (unsigned int) mesh->firstvert
934 || (unsigned int) buf_tri[currenttriangle].index[1] > (unsigned int) mesh->lastvert
935 || (unsigned int) buf_tri[currenttriangle].index[2] < (unsigned int) mesh->firstvert
936 || (unsigned int) buf_tri[currenttriangle].index[2] > (unsigned int) mesh->lastvert)
942 if (mesh->triangles != currenttriangle - mesh->firsttriangle)
947 for (;transmesh;transmesh = transmesh->chain)
949 mesh = &buf_mesh[currentmesh++];
950 *mesh = *transmesh; // copy mesh properties
951 mesh->firstvert += currentvertex;
952 mesh->lastvert += currentvertex;
953 mesh->firsttriangle = currenttriangle;
954 for (tri = transmesh->transchain;tri;tri = tri->meshsortchain)
956 buf_tri[currenttriangle].index[0] = tri->index[0] + currentvertex;
957 buf_tri[currenttriangle].index[1] = tri->index[1] + currentvertex;
958 buf_tri[currenttriangle].index[2] = tri->index[2] + currentvertex;
960 if (tri->mesh != transmesh)
962 if ((unsigned int) buf_tri[currenttriangle].index[0] < (unsigned int) mesh->firstvert
963 || (unsigned int) buf_tri[currenttriangle].index[0] > (unsigned int) mesh->lastvert
964 || (unsigned int) buf_tri[currenttriangle].index[1] < (unsigned int) mesh->firstvert
965 || (unsigned int) buf_tri[currenttriangle].index[1] > (unsigned int) mesh->lastvert
966 || (unsigned int) buf_tri[currenttriangle].index[2] < (unsigned int) mesh->firstvert
967 || (unsigned int) buf_tri[currenttriangle].index[2] > (unsigned int) mesh->lastvert)
973 if (mesh->triangles != currenttriangle - mesh->firsttriangle)
977 currentvertex += currenttransvertex;
980 currenttransmesh = 0;
981 currenttranstriangle = 0;
982 currenttransvertex = 0;
984 else if (gl_mesh_dupetransverts.integer)
987 float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
988 buf_vertex_t *vert1, *vert2, *vert3;
992 // process and add transparent mesh triangles
993 if (!currenttranstriangle)
996 // map farclip to 0-4095 list range
997 centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
998 viewdistcompare = viewdist + 4.0f;
1000 memset(buf_transtri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
1002 // process in reverse because transtri_list adding code is in reverse as well
1004 for (j = currenttranstriangle - 1;j >= 0;j--)
1006 tri = &buf_transtri[j];
1008 vert1 = &buf_transvertex[tri->index[0]];
1009 vert2 = &buf_transvertex[tri->index[1]];
1010 vert3 = &buf_transvertex[tri->index[2]];
1012 dist1 = DotProduct(vert1->v, vpn);
1013 dist2 = DotProduct(vert2->v, vpn);
1014 dist3 = DotProduct(vert3->v, vpn);
1016 maxdist = max(dist1, max(dist2, dist3));
1017 if (maxdist < viewdistcompare)
1020 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
1023 i = bound(0, i, (TRANSDEPTHRES - 1));
1027 center += 8388608.0f;
1028 i = *((long *)¢er) & 0x7FFFFF;
1029 i = min(i, (TRANSDEPTHRES - 1));
1031 tri->next = buf_transtri_list[i];
1032 buf_transtri_list[i] = tri;
1036 if (currentmesh + k > max_meshs || currenttriangle + k > max_batch || currentvertex + k * 3 > max_verts)
1039 currenttransmesh = 0;
1040 currenttranstriangle = 0;
1041 currenttransvertex = 0;
1043 // note: can't batch these because they can be rendered in any order
1044 // there can never be more transparent triangles than fit in main buffers
1045 for (j = TRANSDEPTHRES - 1;j >= 0;j--)
1047 if ((tri = buf_transtri_list[j]))
1051 mesh = &buf_mesh[currentmesh++];
1052 *mesh = *tri->mesh; // copy mesh properties
1053 mesh->firstvert = currentvertex;
1054 mesh->lastvert = currentvertex + 2;
1055 mesh->firsttriangle = currenttriangle;
1056 mesh->triangles = 1;
1057 for (k = 0;k < 3;k++)
1059 index = tri->index[k];
1060 buf_tri[currenttriangle].index[k] = currentvertex;
1061 memcpy(buf_vertex[currentvertex].v, buf_transvertex[index].v, sizeof(buf_vertex_t));
1062 memcpy(buf_fcolor[currentvertex].c, buf_transfcolor[index].c, sizeof(buf_fcolor_t));
1063 for (i = 0;i < backendunits && tri->mesh->textures[i];i++)
1064 memcpy(buf_texcoord[i][currentvertex].t, buf_transtexcoord[i][index].t, sizeof(buf_texcoord_t));
1076 float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
1077 buf_vertex_t *vert1, *vert2, *vert3;
1078 buf_transtri_t *tri;
1081 // process and add transparent mesh triangles
1082 if (!currenttranstriangle)
1085 // map farclip to 0-4095 list range
1086 centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
1087 viewdistcompare = viewdist + 4.0f;
1089 memset(buf_transtri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
1091 // process in reverse because transtri_list adding code is in reverse as well
1093 for (j = currenttranstriangle - 1;j >= 0;j--)
1095 tri = &buf_transtri[j];
1097 vert1 = &buf_transvertex[tri->index[0]];
1098 vert2 = &buf_transvertex[tri->index[1]];
1099 vert3 = &buf_transvertex[tri->index[2]];
1101 dist1 = DotProduct(vert1->v, vpn);
1102 dist2 = DotProduct(vert2->v, vpn);
1103 dist3 = DotProduct(vert3->v, vpn);
1105 maxdist = max(dist1, max(dist2, dist3));
1106 if (maxdist < viewdistcompare)
1109 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
1112 i = bound(0, i, (TRANSDEPTHRES - 1));
1116 center += 8388608.0f;
1117 i = *((long *)¢er) & 0x7FFFFF;
1118 i = min(i, (TRANSDEPTHRES - 1));
1120 tri->next = buf_transtri_list[i];
1121 buf_transtri_list[i] = tri;
1125 if (currentmesh + k > max_meshs || currenttriangle + k > max_batch || currentvertex + currenttransvertex > max_verts)
1128 // note: can't batch these because they can be rendered in any order
1129 // there can never be more transparent triangles than fit in main buffers
1130 memcpy(&buf_vertex[currentvertex], &buf_transvertex[0], currenttransvertex * sizeof(buf_vertex_t));
1131 memcpy(&buf_fcolor[currentvertex], &buf_transfcolor[0], currenttransvertex * sizeof(buf_fcolor_t));
1132 for (i = 0;i < backendunits;i++)
1133 memcpy(&buf_texcoord[i][currentvertex], &buf_transtexcoord[i][0], currenttransvertex * sizeof(buf_texcoord_t));
1135 for (j = TRANSDEPTHRES - 1;j >= 0;j--)
1137 if ((tri = buf_transtri_list[j]))
1141 mesh = &buf_mesh[currentmesh++];
1142 *mesh = *tri->mesh; // copy mesh properties
1143 buf_tri[currenttriangle].index[0] = tri->index[0] + currentvertex;
1144 buf_tri[currenttriangle].index[1] = tri->index[1] + currentvertex;
1145 buf_tri[currenttriangle].index[2] = tri->index[2] + currentvertex;
1146 mesh->firstvert = min(buf_tri[currenttriangle].index[0], min(buf_tri[currenttriangle].index[1], buf_tri[currenttriangle].index[2]));
1147 mesh->lastvert = max(buf_tri[currenttriangle].index[0], max(buf_tri[currenttriangle].index[1], buf_tri[currenttriangle].index[2]));
1148 mesh->firsttriangle = currenttriangle++;
1149 mesh->triangles = 1;
1154 currentvertex += currenttransvertex;
1155 currenttransmesh = 0;
1156 currenttranstriangle = 0;
1157 currenttransvertex = 0;
1161 void R_Mesh_Draw(const rmeshinfo_t *m)
1163 // these are static because gcc runs out of virtual registers otherwise
1164 static int i, j, *index, overbright;
1165 static float *in, scaler;
1166 static float cr, cg, cb, ca;
1167 static buf_mesh_t *mesh;
1168 static buf_vertex_t *vert;
1169 static buf_fcolor_t *fcolor;
1170 static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
1171 static buf_transtri_t *tri;
1173 if (m->index == NULL
1175 || m->vertex == NULL
1178 // ignore meaningless alpha meshs
1179 if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
1183 for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
1186 if (i == m->numverts)
1189 else if (m->ca < 0.01f)
1194 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1197 if (m->blendfunc2 == GL_SRC_COLOR)
1199 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
1206 overbright = gl_combine.integer;
1210 scaler *= overbrightscale;
1215 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
1219 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1226 c_transtris += m->numtriangles;
1227 vert = &buf_transvertex[currenttransvertex];
1228 fcolor = &buf_transfcolor[currenttransvertex];
1229 for (i = 0;i < backendunits;i++)
1230 texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
1232 // transmesh is only for storage of transparent meshs until they
1233 // are inserted into the main mesh array
1234 mesh = &buf_transmesh[currenttransmesh++];
1236 // transparent meshs are broken up into individual triangles which can
1237 // be sorted by depth
1239 for (i = 0;i < m->numtriangles;i++)
1241 tri = &buf_transtri[currenttranstriangle++];
1243 tri->index[0] = *index++ + currenttransvertex;
1244 tri->index[1] = *index++ + currenttransvertex;
1245 tri->index[2] = *index++ + currenttransvertex;
1248 mesh->firstvert = currenttransvertex;
1249 mesh->lastvert = currenttransvertex + m->numverts - 1;
1250 currenttransvertex += m->numverts;
1254 if (m->numtriangles > max_meshs || m->numverts > max_verts)
1256 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
1260 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
1264 c_meshtris += m->numtriangles;
1265 vert = &buf_vertex[currentvertex];
1266 fcolor = &buf_fcolor[currentvertex];
1267 for (i = 0;i < backendunits;i++)
1268 texcoord[i] = &buf_texcoord[i][currentvertex];
1270 mesh = &buf_mesh[currentmesh++];
1271 // opaque meshs are rendered directly
1272 index = (int *)&buf_tri[currenttriangle];
1273 mesh->firsttriangle = currenttriangle;
1274 currenttriangle += m->numtriangles;
1275 for (i = 0;i < m->numtriangles * 3;i++)
1276 index[i] = m->index[i] + currentvertex;
1278 mesh->firstvert = currentvertex;
1279 mesh->lastvert = currentvertex + m->numverts - 1;
1280 currentvertex += m->numverts;
1283 // code shared for transparent and opaque meshs
1284 mesh->blendfunc1 = m->blendfunc1;
1285 mesh->blendfunc2 = m->blendfunc2;
1286 mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
1287 mesh->depthtest = !m->depthdisable;
1288 mesh->triangles = m->numtriangles;
1290 for (i = 0;i < backendunits;i++)
1292 if ((mesh->textures[i] = m->tex[i]))
1294 mesh->texturergbscale[i] = m->texrgbscale[i];
1295 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1296 mesh->texturergbscale[i] = 1;
1298 if (overbright && j >= 0)
1299 mesh->texturergbscale[j] = 4;
1301 if (m->vertexstep != sizeof(buf_vertex_t))
1303 for (i = 0, in = m->vertex;i < m->numverts;i++, (int)in += m->vertexstep)
1305 vert[i].v[0] = in[0];
1306 vert[i].v[1] = in[1];
1307 vert[i].v[2] = in[2];
1311 memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
1315 for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep)
1317 fcolor[i].c[0] = in[0] * scaler;
1318 fcolor[i].c[1] = in[1] * scaler;
1319 fcolor[i].c[2] = in[2] * scaler;
1320 fcolor[i].c[3] = in[3];
1325 cr = m->cr * scaler;
1326 cg = m->cg * scaler;
1327 cb = m->cb * scaler;
1329 for (i = 0;i < m->numverts;i++)
1331 fcolor[i].c[0] = cr;
1332 fcolor[i].c[1] = cg;
1333 fcolor[i].c[2] = cb;
1334 fcolor[i].c[3] = ca;
1338 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1340 if (j >= backendunits)
1341 Sys_Error("R_Mesh_Draw: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1342 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1344 for (i = 0, in = m->texcoords[j];i < m->numverts;i++, (int)in += m->texcoordstep[j])
1346 texcoord[j][i].t[0] = in[0];
1347 texcoord[j][i].t[1] = in[1];
1351 memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1354 for (;j < backendunits;j++)
1355 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1359 void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts)
1361 m->index = polyindexarray;
1362 m->numverts = numverts;
1363 m->numtriangles = numverts - 2;
1364 if (m->numtriangles < 1)
1366 Con_Printf("R_Mesh_DrawPolygon: invalid vertex count\n");
1369 if (m->numtriangles >= 256)
1371 Con_Printf("R_Mesh_DrawPolygon: only up to 256 triangles (258 verts) supported\n");
1377 // LordHavoc: this thing is evil, but necessary because decals account for so much overhead
1378 void R_Mesh_DrawDecal(const rmeshinfo_t *m)
1380 // these are static because gcc runs out of virtual registers otherwise
1381 static int i, *index, overbright;
1382 static float scaler;
1383 static float cr, cg, cb, ca;
1384 static buf_mesh_t *mesh;
1385 static buf_vertex_t *vert;
1386 static buf_fcolor_t *fcolor;
1387 static buf_texcoord_t *texcoord;
1388 static buf_transtri_t *tri;
1391 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1396 overbright = gl_combine.integer;
1400 scaler *= overbrightscale;
1404 if (currenttransmesh >= max_meshs || (currenttranstriangle + 2) > max_meshs || (currenttransvertex + 4) > max_verts)
1408 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1416 vert = &buf_transvertex[currenttransvertex];
1417 fcolor = &buf_transfcolor[currenttransvertex];
1418 texcoord = &buf_transtexcoord[0][currenttransvertex];
1420 // transmesh is only for storage of transparent meshs until they
1421 // are inserted into the main mesh array
1422 mesh = &buf_transmesh[currenttransmesh++];
1423 mesh->blendfunc1 = m->blendfunc1;
1424 mesh->blendfunc2 = m->blendfunc2;
1425 mesh->depthmask = false;
1426 mesh->depthtest = true;
1427 mesh->triangles = 2;
1428 mesh->textures[0] = m->tex[0];
1429 mesh->texturergbscale[0] = overbright ? 4 : 1;
1430 for (i = 1;i < backendunits;i++)
1432 mesh->textures[i] = 0;
1433 mesh->texturergbscale[i] = 1;
1437 // transparent meshs are broken up into individual triangles which can
1438 // be sorted by depth
1440 tri = &buf_transtri[currenttranstriangle++];
1442 tri->index[0] = 0 + currenttransvertex;
1443 tri->index[1] = 1 + currenttransvertex;
1444 tri->index[2] = 2 + currenttransvertex;
1445 tri = &buf_transtri[currenttranstriangle++];
1447 tri->index[0] = 0 + currenttransvertex;
1448 tri->index[1] = 2 + currenttransvertex;
1449 tri->index[2] = 3 + currenttransvertex;
1451 mesh->firstvert = currenttransvertex;
1452 mesh->lastvert = currenttransvertex + 3;
1453 currenttransvertex += 4;
1457 if (2 > max_meshs || 4 > max_verts)
1459 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
1463 if (currentmesh >= max_meshs || (currenttriangle + 2) > max_batch || (currentvertex + 4) > max_verts)
1468 vert = &buf_vertex[currentvertex];
1469 fcolor = &buf_fcolor[currentvertex];
1470 texcoord = &buf_texcoord[0][currentvertex];
1472 mesh = &buf_mesh[currentmesh++];
1473 mesh->blendfunc1 = m->blendfunc1;
1474 mesh->blendfunc2 = m->blendfunc2;
1475 mesh->depthmask = false;
1476 mesh->depthtest = !m->depthdisable;
1477 mesh->firsttriangle = currenttriangle;
1478 mesh->triangles = 2;
1479 mesh->textures[0] = m->tex[0];
1480 mesh->texturergbscale[0] = overbright ? 4 : 1;
1481 for (i = 1;i < backendunits;i++)
1483 mesh->textures[i] = 0;
1484 mesh->texturergbscale[i] = 1;
1487 // opaque meshs are rendered directly
1488 index = (int *)&buf_tri[currenttriangle];
1489 index[0] = 0 + currentvertex;
1490 index[1] = 1 + currentvertex;
1491 index[2] = 2 + currentvertex;
1492 index[3] = 0 + currentvertex;
1493 index[4] = 2 + currentvertex;
1494 index[5] = 3 + currentvertex;
1495 mesh->firstvert = currentvertex;
1496 mesh->lastvert = currentvertex + 3;
1497 currenttriangle += 2;
1501 // buf_vertex_t must match the size of the decal vertex array (or vice versa)
1502 memcpy(vert, m->vertex, 4 * sizeof(buf_vertex_t));
1504 cr = m->cr * scaler;
1505 cg = m->cg * scaler;
1506 cb = m->cb * scaler;
1508 fcolor[0].c[0] = cr;
1509 fcolor[0].c[1] = cg;
1510 fcolor[0].c[2] = cb;
1511 fcolor[0].c[3] = ca;
1512 fcolor[1].c[0] = cr;
1513 fcolor[1].c[1] = cg;
1514 fcolor[1].c[2] = cb;
1515 fcolor[1].c[3] = ca;
1516 fcolor[2].c[0] = cr;
1517 fcolor[2].c[1] = cg;
1518 fcolor[2].c[2] = cb;
1519 fcolor[2].c[3] = ca;
1520 fcolor[3].c[0] = cr;
1521 fcolor[3].c[1] = cg;
1522 fcolor[3].c[2] = cb;
1523 fcolor[3].c[3] = ca;
1525 // buf_texcoord_t must be the same size as the decal texcoord array (or vice versa)
1526 memcpy(&texcoord[0].t[0], m->texcoords[0], 4 * sizeof(buf_texcoord_t));
1530 ==============================================================================
1534 ==============================================================================
1537 float CalcFov (float fov_x, float width, float height);
1538 void R_ClearScreen(void);
1540 void SCR_ScreenShot(char *filename, int x, int y, int width, int height)
1545 buffer = Mem_Alloc(tempmempool, width*height*3);
1546 glReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
1549 // LordHavoc: compensate for v_overbrightbits when using hardware gamma
1550 if (v_hwgamma.integer)
1551 for (i = 0;i < width * height * 3;i++)
1552 buffer[i] <<= v_overbrightbits.integer;
1554 Image_WriteTGARGB_preflipped(filename, width, height, buffer);
1564 void SCR_ScreenShot_f (void)
1568 char checkname[MAX_OSPATH];
1570 // find a file name to save it to
1572 strcpy(filename, "dp0000.tga");
1574 for (i=0 ; i<=9999 ; i++)
1576 filename[2] = (i/1000)%10 + '0';
1577 filename[3] = (i/ 100)%10 + '0';
1578 filename[4] = (i/ 10)%10 + '0';
1579 filename[5] = (i/ 1)%10 + '0';
1580 sprintf (checkname, "%s/%s", com_gamedir, filename);
1581 if (Sys_FileTime(checkname) == -1)
1582 break; // file doesn't exist
1586 Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n");
1590 SCR_ScreenShot(filename, vid.realx, vid.realy, vid.realwidth, vid.realheight);
1591 Con_Printf ("Wrote %s\n", filename);
1598 Grab six views for environment mapping tests
1609 {{ 0, 90, 0}, "rt"},
1610 {{ 0, 180, 0}, "bk"},
1611 {{ 0, 270, 0}, "lf"},
1612 {{-90, 90, 0}, "up"},
1613 {{ 90, 90, 0}, "dn"}
1615 static void R_Envmap_f (void)
1618 char filename[256], basename[256];
1620 if (Cmd_Argc() != 3)
1622 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");
1626 if (!r_render.integer)
1629 strcpy(basename, Cmd_Argv(1));
1630 size = atoi(Cmd_Argv(2));
1631 if (size != 128 && size != 256 && size != 512 && size != 1024)
1633 Con_Printf("envmap: size must be one of 128, 256, 512, or 1024\n");
1636 if (size > vid.realwidth || size > vid.realheight)
1638 Con_Printf("envmap: your resolution is not big enough to render that size\n");
1646 r_refdef.width = size;
1647 r_refdef.height = size;
1649 r_refdef.fov_x = 90;
1650 r_refdef.fov_y = 90;
1652 for (j = 0;j < 6;j++)
1654 sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name);
1655 VectorCopy(envmapinfo[j].angles, r_refdef.viewangles);
1658 SCR_ScreenShot(filename, vid.realx, vid.realy, size, size);
1664 //=============================================================================
1666 void R_ClearScreen(void)
1668 if (r_render.integer)
1670 glClearColor(0,0,0,0);
1672 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
1674 if (gl_dither.integer)
1675 glEnable(GL_DITHER);
1677 glDisable(GL_DITHER);
1686 This is called every frame, and can also be called explicitly to flush
1690 void SCR_UpdateScreen (void)
1692 //Mem_CheckSentinelsGlobal();
1693 //R_TimeReport("memtest");
1700 R_TimeReport("finish");
1702 if (gl_combine.integer && !gl_combine_extension)
1703 Cvar_SetValue("gl_combine", 0);
1705 lightscalebit = v_overbrightbits.integer;
1706 if (gl_combine.integer && r_multitexture.integer)
1709 lightscale = 1.0f / (float) (1 << lightscalebit);
1710 overbrightscale = 1.0f / (float) (1 << v_overbrightbits.integer);
1712 R_TimeReport("setup");
1716 R_TimeReport("clear");
1718 if (scr_conlines < vid.conheight)