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_floatcolors = {0, "gl_mesh_floatcolors", "0"};
24 typedef struct buf_mesh_s
28 int blendfunc1, blendfunc2;
29 int textures[MAX_TEXTUREUNITS];
30 float texturergbscale[MAX_TEXTUREUNITS];
35 struct buf_mesh_s *chain;
36 struct buf_transtri_s *transchain;
40 typedef struct buf_transtri_s
42 struct buf_transtri_s *next;
43 struct buf_transtri_s *meshsortchain;
49 typedef struct buf_tri_s
79 static float meshfarclip;
80 static int currentmesh, currenttriangle, currentvertex, backendunits, backendactive, transranout;
81 static buf_mesh_t *buf_mesh;
82 static buf_tri_t *buf_tri;
83 static buf_vertex_t *buf_vertex;
84 static buf_fcolor_t *buf_fcolor;
85 static buf_bcolor_t *buf_bcolor;
86 static buf_texcoord_t *buf_texcoord[MAX_TEXTUREUNITS];
88 static int currenttransmesh, currenttransvertex, currenttranstriangle;
89 static buf_mesh_t *buf_transmesh;
90 static buf_transtri_t *buf_sorttranstri;
91 static buf_transtri_t **buf_sorttranstri_list;
92 static buf_tri_t *buf_transtri;
93 static buf_vertex_t *buf_transvertex;
94 static buf_fcolor_t *buf_transfcolor;
95 static buf_texcoord_t *buf_transtexcoord[MAX_TEXTUREUNITS];
97 static mempool_t *gl_backend_mempool;
98 static int resizingbuffers = false;
100 static void gl_backend_start(void)
104 max_verts = max_meshs * 3;
106 if (!gl_backend_mempool)
107 gl_backend_mempool = Mem_AllocPool("GL_Backend");
109 #define BACKENDALLOC(var, count, sizeofstruct)\
111 var = Mem_Alloc(gl_backend_mempool, count * sizeof(sizeofstruct));\
113 Sys_Error("gl_backend_start: unable to allocate memory\n");\
114 memset(var, 0, count * sizeof(sizeofstruct));\
117 BACKENDALLOC(buf_mesh, max_meshs, buf_mesh_t)
118 BACKENDALLOC(buf_tri, max_meshs, buf_tri_t)
119 BACKENDALLOC(buf_vertex, max_verts, buf_vertex_t)
120 BACKENDALLOC(buf_fcolor, max_verts, buf_fcolor_t)
121 BACKENDALLOC(buf_bcolor, max_verts, buf_bcolor_t)
123 BACKENDALLOC(buf_transmesh, max_meshs, buf_mesh_t)
124 BACKENDALLOC(buf_sorttranstri, max_meshs, buf_transtri_t)
125 BACKENDALLOC(buf_sorttranstri_list, TRANSDEPTHRES, buf_transtri_t *)
126 BACKENDALLOC(buf_transtri, max_meshs, buf_tri_t)
127 BACKENDALLOC(buf_transvertex, max_verts, buf_vertex_t)
128 BACKENDALLOC(buf_transfcolor, max_verts, buf_fcolor_t)
130 for (i = 0;i < MAX_TEXTUREUNITS;i++)
132 // only allocate as many texcoord arrays as we need
133 if (i < gl_textureunits)
135 BACKENDALLOC(buf_texcoord[i], max_verts, buf_texcoord_t)
136 BACKENDALLOC(buf_transtexcoord[i], max_verts, buf_texcoord_t)
140 buf_texcoord[i] = NULL;
141 buf_transtexcoord[i] = NULL;
144 backendunits = min(MAX_TEXTUREUNITS, gl_textureunits);
145 backendactive = true;
148 static void gl_backend_shutdown(void)
151 Mem_EmptyPool(gl_backend_mempool);
153 Mem_FreePool(&gl_backend_mempool);
156 backendactive = false;
159 static void gl_backend_bufferchanges(int init)
161 // 21760 is (65536 / 3) rounded off to a multiple of 128
162 if (gl_mesh_maxtriangles.integer < 256)
163 Cvar_SetValue("gl_mesh_maxtriangles", 256);
164 if (gl_mesh_maxtriangles.integer > 21760)
165 Cvar_SetValue("gl_mesh_maxtriangles", 21760);
167 if (gl_mesh_batchtriangles.integer < 0)
168 Cvar_SetValue("gl_mesh_batchtriangles", 0);
169 if (gl_mesh_batchtriangles.integer > gl_mesh_maxtriangles.integer)
170 Cvar_SetValue("gl_mesh_batchtriangles", gl_mesh_maxtriangles.integer);
172 max_batch = gl_mesh_batchtriangles.integer;
174 if (max_meshs != gl_mesh_maxtriangles.integer)
176 max_meshs = gl_mesh_maxtriangles.integer;
180 resizingbuffers = true;
181 gl_backend_shutdown();
183 resizingbuffers = false;
188 float r_farclip, r_newfarclip;
190 static void gl_backend_newmap(void)
192 r_farclip = r_newfarclip = 2048.0f;
195 int polyindexarray[768];
197 void gl_backend_init(void)
201 Cvar_RegisterVariable (&r_render);
202 Cvar_RegisterVariable (&gl_dither);
204 Cvar_SetValue("r_render", 0);
207 Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
208 Cmd_AddCommand ("envmap", R_Envmap_f);
210 Cvar_RegisterVariable(&gl_mesh_maxtriangles);
211 Cvar_RegisterVariable(&gl_mesh_batchtriangles);
212 Cvar_RegisterVariable(&gl_mesh_floatcolors);
213 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
214 gl_backend_bufferchanges(true);
215 for (i = 0;i < 256;i++)
217 polyindexarray[i*3+0] = 0;
218 polyindexarray[i*3+1] = i + 1;
219 polyindexarray[i*3+2] = i + 2;
223 static void MYgluPerspective(GLdouble fovx, GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar )
227 xmax = zNear * tan( fovx * M_PI / 360.0 ) * aspect;
228 ymax = zNear * tan( fovy * M_PI / 360.0 );
230 glFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar );
239 static void GL_SetupFrame (void)
241 if (!r_render.integer)
244 // glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: moved to SCR_UpdateScreen
247 glDepthFunc (GL_LEQUAL);
249 glDepthRange (gldepthmin, gldepthmax);
251 // update farclip based on previous frame
252 r_farclip = r_newfarclip;
255 glMatrixMode(GL_PROJECTION);
258 // y is weird beause OpenGL is bottom to top, we use top to bottom
259 glViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height);
260 // yfov = 2*atan((float)r_refdef.height/r_refdef.width)*180/M_PI;
261 MYgluPerspective (r_refdef.fov_x, r_refdef.fov_y, r_refdef.width/r_refdef.height, 4.0 / 3.0, r_farclip);
263 glCullFace(GL_FRONT);
265 glMatrixMode(GL_MODELVIEW);
268 glRotatef (-90, 1, 0, 0); // put Z going up
269 glRotatef (90, 0, 0, 1); // put Z going up
270 glRotatef (-r_refdef.viewangles[2], 1, 0, 0);
271 glRotatef (-r_refdef.viewangles[0], 0, 1, 0);
272 glRotatef (-r_refdef.viewangles[1], 0, 0, 1);
273 glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
275 // glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
280 // if (gl_cull.integer)
281 glEnable(GL_CULL_FACE);
283 // glDisable(GL_CULL_FACE);
285 glEnable(GL_BLEND); // was Disable
286 glEnable(GL_DEPTH_TEST);
290 static float viewdist;
292 int c_meshs, c_meshtris, c_transmeshs, c_transtris;
294 // called at beginning of frame
295 void R_Mesh_Clear(void)
298 Sys_Error("R_Mesh_Clear: called when backend is not active\n");
300 gl_backend_bufferchanges(false);
305 currenttransmesh = 0;
306 currenttranstriangle = 0;
307 currenttransvertex = 0;
310 viewdist = DotProduct(r_origin, vpn);
321 void GL_PrintError(int errornumber, char *filename, int linenumber)
325 case GL_INVALID_ENUM:
326 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
328 case GL_INVALID_VALUE:
329 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
331 case GL_INVALID_OPERATION:
332 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
334 case GL_STACK_OVERFLOW:
335 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
337 case GL_STACK_UNDERFLOW:
338 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
340 case GL_OUT_OF_MEMORY:
341 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
343 #ifdef GL_TABLE_TOO_LARGE
344 case GL_TABLE_TOO_LARGE:
345 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
349 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
357 // renders mesh buffers, called to flush buffers when full
358 void R_Mesh_Render(void)
360 int i, k, blendfunc1, blendfunc2, blend, depthmask, depthtest, unit = 0, clientunit = 0, firsttriangle, endtriangle, indexcount, firstvert, endvert, texture[MAX_TEXTUREUNITS];
361 float farclip, texturergbscale[MAX_TEXTUREUNITS];
364 // float to byte color conversion
369 Sys_Error("R_Mesh_Render: called when backend is not active\n");
375 // push out farclip based on vertices
376 for (i = 0;i < currentvertex;i++)
378 farclip = DotProduct(buf_vertex[i].v, vpn);
379 if (meshfarclip < farclip)
380 meshfarclip = farclip;
383 farclip = meshfarclip + 256.0f - viewdist; // + 256 just to be safe
385 // push out farclip for next frame
386 if (farclip > r_newfarclip)
387 r_newfarclip = ceil((farclip + 255) / 256) * 256 + 256;
389 for (i = 0;i < backendunits;i++)
390 texturergbscale[i] = 1;
392 glEnable(GL_CULL_FACE);
394 glCullFace(GL_FRONT);
397 glEnable(GL_DEPTH_TEST);
400 blendfunc2 = GL_ZERO;
401 glBlendFunc(blendfunc1, blendfunc2);
407 glDepthMask((GLboolean) depthmask);
410 glVertexPointer(3, GL_FLOAT, sizeof(buf_vertex_t), &buf_vertex[0].v[0]);
412 glEnableClientState(GL_VERTEX_ARRAY);
414 if (gl_mesh_floatcolors.integer)
416 glColorPointer(4, GL_FLOAT, sizeof(buf_fcolor_t), &buf_fcolor[0].c[0]);
421 // shift float to have 8bit fraction at base of number
422 for (i = 0, fcolor = &buf_fcolor->c[0];i < currentvertex;i++)
424 *fcolor++ += 32768.0f;
425 *fcolor++ += 32768.0f;
426 *fcolor++ += 32768.0f;
427 *fcolor++ += 32768.0f;
429 // then read as integer and kill float bits...
430 for (i = 0, icolor = (int *)&buf_fcolor->c[0], bcolor = &buf_bcolor->c[0];i < currentvertex;i++)
432 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
433 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
434 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
435 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
437 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(buf_bcolor_t), &buf_bcolor[0].c[0]);
440 glEnableClientState(GL_COLOR_ARRAY);
443 if (backendunits > 1)
445 for (i = 0;i < backendunits;i++)
447 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
449 glBindTexture(GL_TEXTURE_2D, (texture[i] = 0));
451 glDisable(GL_TEXTURE_2D);
453 if (gl_combine.integer)
455 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
457 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
459 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
461 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
463 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB);
465 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
467 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
469 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
471 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
473 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
475 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
477 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);
479 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
481 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
483 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
485 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
487 glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0f);
492 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
496 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
498 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[i]);
500 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
506 glBindTexture(GL_TEXTURE_2D, (texture[0] = 0));
508 glDisable(GL_TEXTURE_2D);
510 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
513 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[0]);
515 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
519 // lock as early as possible
520 GL_LockArray(0, currentvertex);
523 for (k = 0, mesh = buf_mesh;k < currentmesh;k++, mesh++)
525 if (backendunits > 1)
528 for (i = 0;i < backendunits;i++)
530 if (texture[i] != mesh->textures[i])
534 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
539 glEnable(GL_TEXTURE_2D);
541 // have to disable texcoord array on disabled texture
542 // units due to NVIDIA driver bug with
543 // compiled_vertex_array
546 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
549 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
552 glBindTexture(GL_TEXTURE_2D, (texture[i] = mesh->textures[i]));
556 glDisable(GL_TEXTURE_2D);
558 // have to disable texcoord array on disabled texture
559 // units due to NVIDIA driver bug with
560 // compiled_vertex_array
563 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
566 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
570 if (texturergbscale[i] != mesh->texturergbscale[i])
574 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
577 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (texturergbscale[i] = mesh->texturergbscale[i]));
583 // if (unit != topunit)
585 // qglActiveTexture(GL_TEXTURE0_ARB + (unit = topunit));
591 if (texture[0] != mesh->textures[0])
595 glEnable(GL_TEXTURE_2D);
597 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
600 glBindTexture(GL_TEXTURE_2D, (texture[0] = mesh->textures[0]));
604 glDisable(GL_TEXTURE_2D);
606 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
611 if (blendfunc1 != mesh->blendfunc1 || blendfunc2 != mesh->blendfunc2)
613 blendfunc1 = mesh->blendfunc1;
614 blendfunc2 = mesh->blendfunc2;
615 glBlendFunc(blendfunc1, blendfunc2);
617 if (blendfunc2 == GL_ZERO)
619 if (blendfunc1 == GL_ONE)
648 if (depthtest != mesh->depthtest)
650 depthtest = mesh->depthtest;
652 glEnable(GL_DEPTH_TEST);
654 glDisable(GL_DEPTH_TEST);
656 if (depthmask != mesh->depthmask)
658 depthmask = mesh->depthmask;
659 glDepthMask((GLboolean) depthmask);
663 firsttriangle = mesh->firsttriangle;
664 firstvert = mesh->firstvert;
665 endtriangle = firsttriangle + mesh->triangles;
666 endvert = firstvert + mesh->verts;
668 indexcount = (endtriangle - firsttriangle) * 3;
669 index = (unsigned int *)&buf_tri[firsttriangle].index[0];
670 for (i = 0;i < indexcount;i++)
671 index[i] += firstvert;
674 // FIXME: dynamic link to GL so we can get DrawRangeElements on WIN32
675 glDrawElements(GL_TRIANGLES, indexcount, GL_UNSIGNED_INT, index);
677 glDrawRangeElements(GL_TRIANGLES, firstvert, endvert, indexcount, GL_UNSIGNED_INT, index);
689 if (backendunits > 1)
691 for (i = backendunits - 1;i >= 0;i--)
693 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
695 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
697 if (gl_combine.integer)
699 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
704 glDisable(GL_TEXTURE_2D);
709 glEnable(GL_TEXTURE_2D);
712 glBindTexture(GL_TEXTURE_2D, 0);
715 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
717 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
723 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
725 glEnable(GL_TEXTURE_2D);
727 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
730 glDisableClientState(GL_COLOR_ARRAY);
732 glDisableClientState(GL_VERTEX_ARRAY);
737 glEnable(GL_DEPTH_TEST);
741 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
745 void R_Mesh_AddTransparent(void)
748 float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
749 buf_vertex_t *vert1, *vert2, *vert3;
751 buf_mesh_t *mesh, *transmesh;
753 if (!currenttransmesh)
756 // convert index data to transtris for sorting
757 for (j = 0;j < currenttransmesh;j++)
759 mesh = buf_transmesh + j;
760 k = mesh->firsttriangle;
761 index = &buf_transtri[k].index[0];
762 for (i = 0;i < mesh->triangles;i++)
764 tri = &buf_sorttranstri[k++];
766 tri->index[0] = *index++;
767 tri->index[1] = *index++;
768 tri->index[2] = *index++;
772 // map farclip to 0-4095 list range
773 centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
774 viewdistcompare = viewdist + 4.0f;
776 memset(buf_sorttranstri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
779 for (j = 0;j < currenttranstriangle;j++)
781 tri = &buf_sorttranstri[j];
782 i = tri->mesh->firstvert;
784 vert1 = &buf_transvertex[tri->index[0] + i];
785 vert2 = &buf_transvertex[tri->index[1] + i];
786 vert3 = &buf_transvertex[tri->index[2] + i];
788 dist1 = DotProduct(vert1->v, vpn);
789 dist2 = DotProduct(vert2->v, vpn);
790 dist3 = DotProduct(vert3->v, vpn);
792 maxdist = max(dist1, max(dist2, dist3));
793 if (maxdist < viewdistcompare)
796 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
799 i = bound(0, i, (TRANSDEPTHRES - 1));
803 center += 8388608.0f;
804 i = *((long *)¢er) & 0x7FFFFF;
805 i = min(i, (TRANSDEPTHRES - 1));
807 tri->next = buf_sorttranstri_list[i];
808 buf_sorttranstri_list[i] = tri;
812 for (i = 0;i < currenttransmesh;i++)
813 buf_transmesh[i].transchain = NULL;
815 for (j = 0;j < TRANSDEPTHRES;j++)
817 if ((tri = buf_sorttranstri_list[j]))
819 for (;tri;tri = tri->next)
821 if (!tri->mesh->transchain)
823 tri->mesh->chain = transmesh;
824 transmesh = tri->mesh;
826 tri->meshsortchain = tri->mesh->transchain;
827 tri->mesh->transchain = tri;
832 for (;transmesh;transmesh = transmesh->chain)
834 if (currentmesh >= max_meshs || currenttriangle + transmesh->triangles > max_batch || currentvertex + transmesh->verts > max_verts)
837 mesh = &buf_mesh[currentmesh++];
838 *mesh = *transmesh; // copy mesh properties
840 mesh->firstvert = currentvertex;
841 memcpy(&buf_vertex[currentvertex], &buf_transvertex[transmesh->firstvert], transmesh->verts * sizeof(buf_vertex_t));
842 memcpy(&buf_fcolor[currentvertex], &buf_transfcolor[transmesh->firstvert], transmesh->verts * sizeof(buf_fcolor_t));
843 for (i = 0;i < backendunits && transmesh->textures[i];i++)
844 memcpy(&buf_texcoord[i][currentvertex], &buf_transtexcoord[i][transmesh->firstvert], transmesh->verts * sizeof(buf_texcoord_t));
845 currentvertex += mesh->verts;
847 mesh->firsttriangle = currenttriangle;
848 for (tri = transmesh->transchain;tri;tri = tri->meshsortchain)
850 buf_tri[currenttriangle].index[0] = tri->index[0];
851 buf_tri[currenttriangle].index[1] = tri->index[1];
852 buf_tri[currenttriangle].index[2] = tri->index[2];
855 mesh->triangles = currenttriangle - mesh->firsttriangle;
858 currenttransmesh = 0;
859 currenttranstriangle = 0;
860 currenttransvertex = 0;
863 void R_Mesh_Draw(const rmeshinfo_t *m)
865 // these are static because gcc runs out of virtual registers otherwise
866 static int i, j, overbright, *index;
867 static float *in, scaler;
868 static float cr, cg, cb, ca;
869 static buf_mesh_t *mesh;
870 static buf_vertex_t *vert;
871 static buf_fcolor_t *fcolor;
872 static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
875 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
881 Host_Error("R_Mesh_Draw: no triangles or verts\n");
883 // ignore meaningless alpha meshs
884 if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
888 for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
891 if (i == m->numverts)
894 else if (m->ca < 0.01f)
899 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
902 for (i = 0;i < m->numtriangles * 3;i++)
903 if ((unsigned int) m->index[i] >= (unsigned int) m->numverts)
904 Host_Error("R_Mesh_Draw: invalid index (%i of %i verts)\n", m->index, m->numverts);
909 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
913 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
920 c_transtris += m->numtriangles;
921 vert = &buf_transvertex[currenttransvertex];
922 fcolor = &buf_transfcolor[currenttransvertex];
923 for (i = 0;i < backendunits;i++)
924 texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
926 // transmesh is only for storage of transparent meshs until they
927 // are inserted into the main mesh array
928 mesh = &buf_transmesh[currenttransmesh++];
929 mesh->firsttriangle = currenttranstriangle;
930 mesh->firstvert = currenttransvertex;
931 index = &buf_transtri[currenttranstriangle].index[0];
933 currenttranstriangle += m->numtriangles;
934 currenttransvertex += m->numverts;
938 if (m->numtriangles > max_meshs || m->numverts > max_verts)
940 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
944 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
948 c_meshtris += m->numtriangles;
949 vert = &buf_vertex[currentvertex];
950 fcolor = &buf_fcolor[currentvertex];
951 for (i = 0;i < backendunits;i++)
952 texcoord[i] = &buf_texcoord[i][currentvertex];
954 // opaque meshs are rendered directly
955 mesh = &buf_mesh[currentmesh++];
956 mesh->firsttriangle = currenttriangle;
957 mesh->firstvert = currentvertex;
958 index = &buf_tri[currenttriangle].index[0];
960 currenttriangle += m->numtriangles;
961 currentvertex += m->numverts;
964 // code shared for transparent and opaque meshs
965 memcpy(index, m->index, sizeof(int[3]) * m->numtriangles);
966 mesh->blendfunc1 = m->blendfunc1;
967 mesh->blendfunc2 = m->blendfunc2;
968 mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
969 mesh->depthtest = !m->depthdisable;
970 mesh->triangles = m->numtriangles;
971 mesh->verts = m->numverts;
975 if (m->blendfunc2 == GL_SRC_COLOR)
977 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
984 overbright = gl_combine.integer;
988 scaler *= overbrightscale;
993 for (i = 0;i < backendunits;i++)
995 if ((mesh->textures[i] = m->tex[i]))
997 mesh->texturergbscale[i] = m->texrgbscale[i];
998 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
999 mesh->texturergbscale[i] = 1;
1001 if (overbright && j >= 0)
1002 mesh->texturergbscale[j] = 4;
1004 if (m->vertexstep != sizeof(buf_vertex_t))
1006 for (i = 0, in = m->vertex;i < m->numverts;i++, (int)in += m->vertexstep)
1008 vert[i].v[0] = in[0];
1009 vert[i].v[1] = in[1];
1010 vert[i].v[2] = in[2];
1014 memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
1018 for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep)
1020 fcolor[i].c[0] = in[0] * scaler;
1021 fcolor[i].c[1] = in[1] * scaler;
1022 fcolor[i].c[2] = in[2] * scaler;
1023 fcolor[i].c[3] = in[3];
1028 cr = m->cr * scaler;
1029 cg = m->cg * scaler;
1030 cb = m->cb * scaler;
1032 for (i = 0;i < m->numverts;i++)
1034 fcolor[i].c[0] = cr;
1035 fcolor[i].c[1] = cg;
1036 fcolor[i].c[2] = cb;
1037 fcolor[i].c[3] = ca;
1041 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1043 if (j >= backendunits)
1044 Sys_Error("R_Mesh_Draw: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1045 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1047 for (i = 0, in = m->texcoords[j];i < m->numverts;i++, (int)in += m->texcoordstep[j])
1049 texcoord[j][i].t[0] = in[0];
1050 texcoord[j][i].t[1] = in[1];
1054 memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1057 for (;j < backendunits;j++)
1058 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1062 void R_Mesh_Draw_NativeOnly(const rmeshinfo_t *m)
1064 // these are static because gcc runs out of virtual registers otherwise
1065 static int i, j, overbright, *index;
1066 static float *in, scaler;
1067 static buf_mesh_t *mesh;
1068 static buf_vertex_t *vert;
1069 static buf_fcolor_t *fcolor;
1070 static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
1073 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1075 if (m->index == NULL
1077 || m->vertex == NULL
1079 Host_Error("R_Mesh_Draw: no triangles or verts\n");
1081 // ignore meaningless alpha meshs
1082 if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
1086 for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
1089 if (i == m->numverts)
1092 else if (m->ca < 0.01f)
1098 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
1102 Con_Printf("R_Mesh_Draw_NativeOnly: ran out of room for transparent meshs\n");
1109 c_transtris += m->numtriangles;
1110 vert = &buf_transvertex[currenttransvertex];
1111 fcolor = &buf_transfcolor[currenttransvertex];
1112 for (i = 0;i < backendunits;i++)
1113 texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
1115 // transmesh is only for storage of transparent meshs until they
1116 // are inserted into the main mesh array
1117 mesh = &buf_transmesh[currenttransmesh++];
1118 mesh->firsttriangle = currenttranstriangle;
1119 mesh->firstvert = currenttransvertex;
1120 index = &buf_transtri[currenttranstriangle].index[0];
1121 currenttranstriangle += m->numtriangles;
1122 currenttransvertex += m->numverts;
1126 if (m->numtriangles > max_meshs || m->numverts > max_verts)
1128 Con_Printf("R_Mesh_Draw_NativeOnly: mesh too big for buffers\n");
1132 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
1136 c_meshtris += m->numtriangles;
1137 vert = &buf_vertex[currentvertex];
1138 fcolor = &buf_fcolor[currentvertex];
1139 for (i = 0;i < backendunits;i++)
1140 texcoord[i] = &buf_texcoord[i][currentvertex];
1142 // opaque meshs are rendered directly
1143 mesh = &buf_mesh[currentmesh++];
1144 mesh->firsttriangle = currenttriangle;
1145 mesh->firstvert = currentvertex;
1146 index = &buf_tri[currenttriangle].index[0];
1147 currenttriangle += m->numtriangles;
1148 currentvertex += m->numverts;
1151 // code shared for transparent and opaque meshs
1152 memcpy(index, m->index, sizeof(int[3]) * m->numtriangles);
1153 mesh->blendfunc1 = m->blendfunc1;
1154 mesh->blendfunc2 = m->blendfunc2;
1155 mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
1156 mesh->depthtest = !m->depthdisable;
1157 mesh->triangles = m->numtriangles;
1158 mesh->verts = m->numverts;
1162 if (m->blendfunc2 == GL_SRC_COLOR)
1164 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
1171 overbright = gl_combine.integer;
1175 scaler *= overbrightscale;
1179 for (i = 0;i < backendunits;i++)
1181 if ((mesh->textures[i] = m->tex[i]))
1183 mesh->texturergbscale[i] = m->texrgbscale[i];
1184 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1185 mesh->texturergbscale[i] = 1;
1187 if (overbright && j >= 0)
1188 mesh->texturergbscale[j] = 4;
1190 if (m->vertexstep != sizeof(buf_vertex_t))
1191 Host_Error("R_Mesh_Draw_NativeOnly: unsupported vertexstep\n");
1192 if (m->colorstep != sizeof(buf_fcolor_t))
1193 Host_Error("R_Mesh_Draw_NativeOnly: unsupported colorstep\n");
1194 if (m->color == NULL)
1195 Host_Error("R_Mesh_Draw_NativeOnly: must provide color array\n");
1196 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1198 if (j >= backendunits)
1199 Sys_Error("R_Mesh_Draw_NativeOnly: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1200 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1201 Host_Error("R_Mesh_Draw_NativeOnly: unsupported texcoordstep\n");
1204 memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
1205 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1206 memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1208 for (;j < backendunits;j++)
1209 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1212 memcpy(fcolor, m->color, m->numverts * sizeof(buf_fcolor_t));
1214 // do this as a second step because memcpy preloaded the cache, which we can't easily do
1217 for (i = 0;i < m->numverts;i++)
1219 fcolor[i].c[0] *= scaler;
1220 fcolor[i].c[1] *= scaler;
1221 fcolor[i].c[2] *= scaler;
1226 // allocates space in geometry buffers, and fills in pointers to the buffers in passsed struct
1227 // (this is used for very high speed rendering, no copying)
1228 int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m)
1230 // these are static because gcc runs out of virtual registers otherwise
1231 int i, j, overbright;
1236 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1238 if (!m->numtriangles
1240 Host_Error("R_Mesh_Draw: no triangles or verts\n");
1244 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
1248 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1255 c_transtris += m->numtriangles;
1256 m->index = &buf_transtri[currenttranstriangle].index[0];
1257 m->vertex = &buf_transvertex[currenttransvertex].v[0];
1258 m->color = &buf_transfcolor[currenttransvertex].c[0];
1259 for (i = 0;i < backendunits;i++)
1260 m->texcoords[i] = &buf_transtexcoord[i][currenttransvertex].t[0];
1262 // transmesh is only for storage of transparent meshs until they
1263 // are inserted into the main mesh array
1264 mesh = &buf_transmesh[currenttransmesh++];
1265 mesh->firsttriangle = currenttranstriangle;
1266 mesh->firstvert = currenttransvertex;
1267 currenttranstriangle += m->numtriangles;
1268 currenttransvertex += m->numverts;
1272 if (m->numtriangles > max_meshs || m->numverts > max_verts)
1274 Con_Printf("R_Mesh_Draw_GetBuffer: mesh too big for buffers\n");
1278 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
1282 c_meshtris += m->numtriangles;
1283 m->index = &buf_tri[currenttriangle].index[0];
1284 m->vertex = &buf_vertex[currentvertex].v[0];
1285 m->color = &buf_fcolor[currentvertex].c[0];
1286 for (i = 0;i < backendunits;i++)
1287 m->texcoords[i] = &buf_texcoord[i][currentvertex].t[0];
1289 // opaque meshs are rendered directly
1290 mesh = &buf_mesh[currentmesh++];
1291 mesh->firsttriangle = currenttriangle;
1292 mesh->firstvert = currentvertex;
1293 currenttriangle += m->numtriangles;
1294 currentvertex += m->numverts;
1297 // code shared for transparent and opaque meshs
1298 mesh->blendfunc1 = m->blendfunc1;
1299 mesh->blendfunc2 = m->blendfunc2;
1300 mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
1301 mesh->depthtest = !m->depthdisable;
1302 mesh->triangles = m->numtriangles;
1303 mesh->verts = m->numverts;
1307 if (m->blendfunc2 == GL_SRC_COLOR)
1309 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
1316 overbright = gl_combine.integer;
1320 scaler *= overbrightscale;
1322 m->colorscale = scaler;
1325 for (i = 0;i < MAX_TEXTUREUNITS;i++)
1327 if ((mesh->textures[i] = m->tex[i]))
1330 if (i >= backendunits)
1331 Sys_Error("R_Mesh_Draw_GetBuffer: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1333 mesh->texturergbscale[i] = m->texrgbscale[i];
1334 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1335 mesh->texturergbscale[i] = 1;
1337 if (overbright && j >= 0)
1338 mesh->texturergbscale[j] = 4;
1343 void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts)
1345 m->index = polyindexarray;
1346 m->numverts = numverts;
1347 m->numtriangles = numverts - 2;
1348 if (m->numtriangles < 1)
1350 Con_Printf("R_Mesh_DrawPolygon: invalid vertex count\n");
1353 if (m->numtriangles >= 256)
1355 Con_Printf("R_Mesh_DrawPolygon: only up to 256 triangles (258 verts) supported\n");
1362 ==============================================================================
1366 ==============================================================================
1369 float CalcFov (float fov_x, float width, float height);
1370 void R_ClearScreen(void);
1372 void SCR_ScreenShot(char *filename, int x, int y, int width, int height)
1377 buffer = Mem_Alloc(tempmempool, width*height*3);
1378 glReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
1381 // LordHavoc: compensate for v_overbrightbits when using hardware gamma
1382 if (v_hwgamma.integer)
1383 for (i = 0;i < width * height * 3;i++)
1384 buffer[i] <<= v_overbrightbits.integer;
1386 Image_WriteTGARGB_preflipped(filename, width, height, buffer);
1396 void SCR_ScreenShot_f (void)
1400 char checkname[MAX_OSPATH];
1402 // find a file name to save it to
1404 strcpy(filename, "dp0000.tga");
1406 for (i=0 ; i<=9999 ; i++)
1408 filename[2] = (i/1000)%10 + '0';
1409 filename[3] = (i/ 100)%10 + '0';
1410 filename[4] = (i/ 10)%10 + '0';
1411 filename[5] = (i/ 1)%10 + '0';
1412 sprintf (checkname, "%s/%s", com_gamedir, filename);
1413 if (Sys_FileTime(checkname) == -1)
1414 break; // file doesn't exist
1418 Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n");
1422 SCR_ScreenShot(filename, vid.realx, vid.realy, vid.realwidth, vid.realheight);
1423 Con_Printf ("Wrote %s\n", filename);
1430 Grab six views for environment mapping tests
1441 {{ 0, 90, 0}, "rt"},
1442 {{ 0, 180, 0}, "bk"},
1443 {{ 0, 270, 0}, "lf"},
1444 {{-90, 90, 0}, "up"},
1445 {{ 90, 90, 0}, "dn"}
1447 static void R_Envmap_f (void)
1450 char filename[256], basename[256];
1452 if (Cmd_Argc() != 3)
1454 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");
1458 if (!r_render.integer)
1461 strcpy(basename, Cmd_Argv(1));
1462 size = atoi(Cmd_Argv(2));
1463 if (size != 128 && size != 256 && size != 512 && size != 1024)
1465 Con_Printf("envmap: size must be one of 128, 256, 512, or 1024\n");
1468 if (size > vid.realwidth || size > vid.realheight)
1470 Con_Printf("envmap: your resolution is not big enough to render that size\n");
1478 r_refdef.width = size;
1479 r_refdef.height = size;
1481 r_refdef.fov_x = 90;
1482 r_refdef.fov_y = 90;
1484 for (j = 0;j < 6;j++)
1486 sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name);
1487 VectorCopy(envmapinfo[j].angles, r_refdef.viewangles);
1490 SCR_ScreenShot(filename, vid.realx, vid.realy, size, size);
1496 //=============================================================================
1498 void R_ClearScreen(void)
1500 if (r_render.integer)
1502 glClearColor(0,0,0,0);
1504 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
1506 if (gl_dither.integer)
1507 glEnable(GL_DITHER);
1509 glDisable(GL_DITHER);
1518 This is called every frame, and can also be called explicitly to flush
1522 void SCR_UpdateScreen (void)
1524 //Mem_CheckSentinelsGlobal();
1525 //R_TimeReport("memtest");
1529 R_TimeReport("finish");
1531 if (gl_combine.integer && !gl_combine_extension)
1532 Cvar_SetValue("gl_combine", 0);
1534 lightscalebit = v_overbrightbits.integer;
1535 if (gl_combine.integer && r_multitexture.integer)
1538 lightscale = 1.0f / (float) (1 << lightscalebit);
1539 overbrightscale = 1.0f / (float) (1 << v_overbrightbits.integer);
1541 R_TimeReport("setup");
1545 R_TimeReport("clear");
1547 if (scr_conlines < vid.conheight)
1553 // tell driver to commit it's partially full geometry queue to the rendering queue
1554 // (this doesn't wait for the commands themselves to complete)