6 static int max_verts; // always max_meshs * 3
7 #define TRANSDEPTHRES 4096
11 //static cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "21760"};
12 static cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "8192"};
13 static cvar_t gl_mesh_batchtriangles = {0, "gl_mesh_batchtriangles", "1024"};
14 static cvar_t gl_mesh_merge = {0, "gl_mesh_merge", "1"};
16 static cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "1"};
18 static cvar_t gl_mesh_dupetransverts = {0, "gl_mesh_dupetransverts", "0"};
19 static cvar_t gl_mesh_sorttransbymesh = {0, "gl_mesh_sorttransbymesh", "1"};
21 typedef struct buf_mesh_s
23 //struct buf_mesh_s *next;
26 int blendfunc1, blendfunc2;
27 int textures[MAX_TEXTUREUNITS];
28 float texturergbscale[MAX_TEXTUREUNITS];
33 struct buf_mesh_s *chain;
34 struct buf_transtri_s *transchain;
35 //struct buf_transtri_s **transchainpointer;
39 typedef struct buf_transtri_s
41 struct buf_transtri_s *next;
42 struct buf_transtri_s *meshsortchain;
48 typedef struct buf_tri_s
80 static float meshfarclip;
81 static int currentmesh, currenttriangle, currentvertex, backendunits, backendactive, meshmerge, transranout;
83 static int floatcolors;
85 static buf_mesh_t *buf_mesh;
86 static buf_tri_t *buf_tri;
87 static buf_vertex_t *buf_vertex;
89 static buf_fcolor_t *buf_fcolor;
91 static buf_bcolor_t *buf_bcolor;
92 static buf_texcoord_t *buf_texcoord[MAX_TEXTUREUNITS];
94 static int currenttransmesh, currenttransvertex, currenttranstriangle;
95 static buf_mesh_t *buf_transmesh;
96 static buf_transtri_t *buf_transtri;
97 static buf_transtri_t **buf_transtri_list;
98 static buf_vertex_t *buf_transvertex;
100 static buf_fcolor_t *buf_transfcolor;
102 static buf_bcolor_t *buf_transbcolor;
103 static buf_texcoord_t *buf_transtexcoord[MAX_TEXTUREUNITS];
105 static mempool_t *gl_backend_mempool;
106 static int resizingbuffers = false;
108 static void gl_backend_start(void)
112 max_verts = max_meshs * 3;
114 if (!gl_backend_mempool)
115 gl_backend_mempool = Mem_AllocPool("GL_Backend");
117 #define BACKENDALLOC(var, count, sizeofstruct)\
119 var = Mem_Alloc(gl_backend_mempool, count * sizeof(sizeofstruct));\
121 Sys_Error("gl_backend_start: unable to allocate memory\n");\
122 memset(var, 0, count * sizeof(sizeofstruct));\
125 BACKENDALLOC(buf_mesh, max_meshs, buf_mesh_t)
126 BACKENDALLOC(buf_tri, max_meshs, buf_tri_t)
127 BACKENDALLOC(buf_vertex, max_verts, buf_vertex_t)
129 BACKENDALLOC(buf_fcolor, max_verts, buf_fcolor_t)
131 BACKENDALLOC(buf_bcolor, max_verts, buf_bcolor_t)
133 BACKENDALLOC(buf_transmesh, max_meshs, buf_mesh_t)
134 BACKENDALLOC(buf_transtri, max_meshs, buf_transtri_t)
135 BACKENDALLOC(buf_transtri_list, TRANSDEPTHRES, buf_transtri_t *)
136 BACKENDALLOC(buf_transvertex, max_verts, buf_vertex_t)
138 BACKENDALLOC(buf_transfcolor, max_verts, buf_fcolor_t)
140 BACKENDALLOC(buf_transbcolor, max_verts, buf_bcolor_t)
142 for (i = 0;i < MAX_TEXTUREUNITS;i++)
144 // only allocate as many texcoord arrays as we need
145 if (i < gl_textureunits)
147 BACKENDALLOC(buf_texcoord[i], max_verts, buf_texcoord_t)
148 BACKENDALLOC(buf_transtexcoord[i], max_verts, buf_texcoord_t)
152 buf_texcoord[i] = NULL;
153 buf_transtexcoord[i] = NULL;
156 backendunits = min(MAX_TEXTUREUNITS, gl_textureunits);
157 backendactive = true;
160 static void gl_backend_shutdown(void)
164 #define BACKENDFREE(var)\
172 #define BACKENDFREE(var) var = NULL;
174 BACKENDFREE(buf_mesh)
176 BACKENDFREE(buf_vertex)
178 BACKENDFREE(buf_fcolor)
180 BACKENDFREE(buf_bcolor)
182 BACKENDFREE(buf_transmesh)
183 BACKENDFREE(buf_transtri)
184 BACKENDFREE(buf_transtri_list)
185 BACKENDFREE(buf_transvertex)
187 BACKENDFREE(buf_transfcolor)
189 BACKENDFREE(buf_transbcolor)
191 for (i = 0;i < MAX_TEXTUREUNITS;i++)
193 BACKENDFREE(buf_texcoord[i])
194 BACKENDFREE(buf_transtexcoord[i])
199 Mem_EmptyPool(gl_backend_mempool);
201 Mem_FreePool(&gl_backend_mempool);
204 backendactive = false;
207 static void gl_backend_bufferchanges(int init)
209 // 21760 is (65536 / 3) rounded off to a multiple of 128
210 if (gl_mesh_maxtriangles.integer < 256)
211 Cvar_SetValue("gl_mesh_maxtriangles", 256);
212 if (gl_mesh_maxtriangles.integer > 21760)
213 Cvar_SetValue("gl_mesh_maxtriangles", 21760);
215 if (gl_mesh_batchtriangles.integer < 0)
216 Cvar_SetValue("gl_mesh_batchtriangles", 0);
217 if (gl_mesh_batchtriangles.integer > gl_mesh_maxtriangles.integer)
218 Cvar_SetValue("gl_mesh_batchtriangles", gl_mesh_maxtriangles.integer);
220 max_batch = gl_mesh_batchtriangles.integer;
222 if (max_meshs != gl_mesh_maxtriangles.integer)
224 max_meshs = gl_mesh_maxtriangles.integer;
228 resizingbuffers = true;
229 gl_backend_shutdown();
231 resizingbuffers = false;
236 float r_farclip, r_newfarclip;
238 static void gl_backend_newmap(void)
240 r_farclip = r_newfarclip = 2048.0f;
243 int polyindexarray[768];
245 void gl_backend_init(void)
248 Cvar_RegisterVariable(&gl_mesh_maxtriangles);
249 Cvar_RegisterVariable(&gl_mesh_batchtriangles);
250 Cvar_RegisterVariable(&gl_mesh_merge);
252 Cvar_RegisterVariable(&gl_mesh_floatcolors);
254 Cvar_RegisterVariable(&gl_mesh_dupetransverts);
255 Cvar_RegisterVariable(&gl_mesh_sorttransbymesh);
256 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
257 gl_backend_bufferchanges(true);
258 for (i = 0;i < 256;i++)
260 polyindexarray[i*3+0] = 0;
261 polyindexarray[i*3+1] = i + 1;
262 polyindexarray[i*3+2] = i + 2;
266 static float viewdist;
268 int c_meshs, c_meshtris, c_transmeshs, c_transtris;
270 // called at beginning of frame
271 void R_Mesh_Clear(void)
274 Sys_Error("R_Mesh_Clear: called when backend is not active\n");
276 gl_backend_bufferchanges(false);
281 currenttransmesh = 0;
282 currenttranstriangle = 0;
283 currenttransvertex = 0;
285 meshmerge = gl_mesh_merge.integer;
287 floatcolors = gl_mesh_floatcolors.integer;
290 viewdist = DotProduct(r_origin, vpn);
299 void GL_PrintError(int errornumber, char *filename, int linenumber)
303 case GL_INVALID_ENUM:
304 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
306 case GL_INVALID_VALUE:
307 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
309 case GL_INVALID_OPERATION:
310 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
312 case GL_STACK_OVERFLOW:
313 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
315 case GL_STACK_UNDERFLOW:
316 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
318 case GL_OUT_OF_MEMORY:
319 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
321 #ifdef GL_TABLE_TOO_LARGE
322 case GL_TABLE_TOO_LARGE:
323 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
327 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
335 // renders mesh buffers, called to flush buffers when full
336 void R_Mesh_Render(void)
338 int i, k, blendfunc1, blendfunc2, blend, depthmask, depthtest, unit = 0, clientunit = 0, firsttriangle, triangles, firstvert, lastvert, texture[MAX_TEXTUREUNITS];
339 float farclip, texturergbscale[MAX_TEXTUREUNITS];
342 Sys_Error("R_Mesh_Render: called when backend is not active\n");
348 // push out farclip based on vertices
349 for (i = 0;i < currentvertex;i++)
351 farclip = DotProduct(buf_vertex[i].v, vpn);
352 if (meshfarclip < farclip)
353 meshfarclip = farclip;
356 farclip = meshfarclip + 256.0f - viewdist; // + 256 just to be safe
358 // push out farclip for next frame
359 if (farclip > r_newfarclip)
360 r_newfarclip = ceil((farclip + 255) / 256) * 256 + 256;
362 for (i = 0;i < backendunits;i++)
363 texturergbscale[i] = 1;
365 glEnable(GL_CULL_FACE);
367 glCullFace(GL_FRONT);
370 glEnable(GL_DEPTH_TEST);
373 blendfunc2 = GL_ZERO;
374 glBlendFunc(blendfunc1, blendfunc2);
380 glDepthMask((GLboolean) depthmask);
383 glVertexPointer(3, GL_FLOAT, sizeof(buf_vertex_t), buf_vertex);
385 glEnableClientState(GL_VERTEX_ARRAY);
390 glColorPointer(4, GL_FLOAT, sizeof(buf_fcolor_t), buf_fcolor);
396 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(buf_bcolor_t), buf_bcolor);
401 glEnableClientState(GL_COLOR_ARRAY);
404 if (backendunits > 1)
406 for (i = 0;i < backendunits;i++)
408 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
410 glBindTexture(GL_TEXTURE_2D, (texture[i] = 0));
412 glDisable(GL_TEXTURE_2D);
414 if (gl_combine.integer)
416 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
418 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
420 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
422 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
424 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB);
426 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
428 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
430 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
432 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
434 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
436 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
438 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);
440 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
442 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
444 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
446 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
448 glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0f);
453 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
457 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
459 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[i]);
461 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
467 glBindTexture(GL_TEXTURE_2D, (texture[0] = 0));
469 glDisable(GL_TEXTURE_2D);
471 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
474 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[0]);
476 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
480 // lock as early as possible
481 GL_LockArray(0, currentvertex);
484 for (k = 0;k < currentmesh;)
488 if (backendunits > 1)
491 for (i = 0;i < backendunits;i++)
493 if (texture[i] != mesh->textures[i])
497 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
502 glEnable(GL_TEXTURE_2D);
504 // have to disable texcoord array on disabled texture
505 // units due to NVIDIA driver bug with
506 // compiled_vertex_array
509 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
512 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
515 glBindTexture(GL_TEXTURE_2D, (texture[i] = mesh->textures[i]));
519 glDisable(GL_TEXTURE_2D);
521 // have to disable texcoord array on disabled texture
522 // units due to NVIDIA driver bug with
523 // compiled_vertex_array
526 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
529 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
533 if (texturergbscale[i] != mesh->texturergbscale[i])
537 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
540 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (texturergbscale[i] = mesh->texturergbscale[i]));
546 // if (unit != topunit)
548 // qglActiveTexture(GL_TEXTURE0_ARB + (unit = topunit));
554 if (texture[0] != mesh->textures[0])
558 glEnable(GL_TEXTURE_2D);
560 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
563 glBindTexture(GL_TEXTURE_2D, (texture[0] = mesh->textures[0]));
567 glDisable(GL_TEXTURE_2D);
569 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
574 if (blendfunc1 != mesh->blendfunc1 || blendfunc2 != mesh->blendfunc2)
576 blendfunc1 = mesh->blendfunc1;
577 blendfunc2 = mesh->blendfunc2;
578 glBlendFunc(blendfunc1, blendfunc2);
580 if (blendfunc2 == GL_ZERO)
582 if (blendfunc1 == GL_ONE)
611 if (depthtest != mesh->depthtest)
613 depthtest = mesh->depthtest;
615 glEnable(GL_DEPTH_TEST);
617 glDisable(GL_DEPTH_TEST);
619 if (depthmask != mesh->depthmask)
621 depthmask = mesh->depthmask;
622 glDepthMask((GLboolean) depthmask);
626 firsttriangle = mesh->firsttriangle;
627 triangles = mesh->triangles;
628 firstvert = mesh->firstvert;
629 lastvert = mesh->lastvert;
630 mesh = &buf_mesh[++k];
634 #if MAX_TEXTUREUNITS != 4
635 #error update this code
637 while (k < currentmesh
638 && mesh->blendfunc1 == blendfunc1
639 && mesh->blendfunc2 == blendfunc2
640 && mesh->depthtest == depthtest
641 && mesh->depthmask == depthmask
642 && mesh->textures[0] == texture[0]
643 && mesh->textures[1] == texture[1]
644 && mesh->textures[2] == texture[2]
645 && mesh->textures[3] == texture[3]
646 && mesh->texturergbscale[0] == texturergbscale[0]
647 && mesh->texturergbscale[1] == texturergbscale[1]
648 && mesh->texturergbscale[2] == texturergbscale[2]
649 && mesh->texturergbscale[3] == texturergbscale[3])
651 triangles += mesh->triangles;
652 if (firstvert > mesh->firstvert)
653 firstvert = mesh->firstvert;
654 if (lastvert < mesh->lastvert)
655 lastvert = mesh->lastvert;
656 mesh = &buf_mesh[++k];
661 // FIXME: dynamic link to GL so we can get DrawRangeElements on WIN32
662 glDrawElements(GL_TRIANGLES, triangles * 3, GL_UNSIGNED_INT, (unsigned int *)&buf_tri[firsttriangle]);
664 glDrawRangeElements(GL_TRIANGLES, firstvert, lastvert + 1, triangles * 3, GL_UNSIGNED_INT, (unsigned int *)&buf_tri[firsttriangle]);
676 if (backendunits > 1)
678 for (i = backendunits - 1;i >= 0;i--)
680 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
682 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
684 if (gl_combine.integer)
686 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
691 glDisable(GL_TEXTURE_2D);
696 glEnable(GL_TEXTURE_2D);
699 glBindTexture(GL_TEXTURE_2D, 0);
702 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
704 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
710 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
712 glEnable(GL_TEXTURE_2D);
714 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
717 glDisableClientState(GL_COLOR_ARRAY);
719 glDisableClientState(GL_VERTEX_ARRAY);
724 glEnable(GL_DEPTH_TEST);
728 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
732 void R_Mesh_AddTransparent(void)
734 if (gl_mesh_sorttransbymesh.integer)
737 float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
738 buf_vertex_t *vert1, *vert2, *vert3;
740 buf_mesh_t *mesh, *transmesh;
742 // process and add transparent mesh triangles
743 if (!currenttranstriangle)
746 // map farclip to 0-4095 list range
747 centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
748 viewdistcompare = viewdist + 4.0f;
750 memset(buf_transtri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
753 for (j = 0;j < currenttranstriangle;j++)
755 tri = &buf_transtri[j];
757 vert1 = &buf_transvertex[tri->index[0]];
758 vert2 = &buf_transvertex[tri->index[1]];
759 vert3 = &buf_transvertex[tri->index[2]];
761 dist1 = DotProduct(vert1->v, vpn);
762 dist2 = DotProduct(vert2->v, vpn);
763 dist3 = DotProduct(vert3->v, vpn);
765 maxdist = max(dist1, max(dist2, dist3));
766 if (maxdist < viewdistcompare)
769 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
772 i = bound(0, i, (TRANSDEPTHRES - 1));
776 center += 8388608.0f;
777 i = *((long *)¢er) & 0x7FFFFF;
778 i = min(i, (TRANSDEPTHRES - 1));
780 tri->next = buf_transtri_list[i];
781 buf_transtri_list[i] = tri;
786 if (currentmesh + k > max_meshs || currenttriangle + k > max_batch || currentvertex + currenttransvertex > max_verts)
789 // note: can't batch these because they can be rendered in any order
790 // there can never be more transparent triangles than fit in main buffers
791 memcpy(&buf_vertex[currentvertex], &buf_transvertex[0], currenttransvertex * sizeof(buf_vertex_t));
794 memcpy(&buf_fcolor[currentvertex], &buf_transfcolor[0], currenttransvertex * sizeof(buf_fcolor_t));
797 memcpy(&buf_bcolor[currentvertex], &buf_transbcolor[0], currenttransvertex * sizeof(buf_bcolor_t));
798 for (i = 0;i < backendunits;i++)
799 memcpy(&buf_texcoord[i][currentvertex], &buf_transtexcoord[i][0], currenttransvertex * sizeof(buf_texcoord_t));
802 for (i = 0;i < currenttransmesh;i++)
804 buf_transmesh[i].transchain = NULL;
805 //buf_transmesh[i].transchainpointer = &buf_transmesh[i].transchain;
806 buf_transmesh[i].triangles = 0;
809 for (j = 0;j < TRANSDEPTHRES;j++)
811 if ((tri = buf_transtri_list[j]))
813 for (;tri;tri = tri->next)
815 if (!tri->mesh->transchain)
817 tri->mesh->chain = transmesh;
818 transmesh = tri->mesh;
820 tri->meshsortchain = tri->mesh->transchain;
821 tri->mesh->transchain = tri;
823 *tri->mesh->transchainpointer = tri;
824 tri->meshsortchain = NULL;
825 tri->mesh->transchainpointer = &tri->meshsortchain;
827 tri->mesh->triangles++;
833 for (;transmesh;transmesh = transmesh->chain)
835 int meshvertexadjust;
836 int numverts = transmesh->lastvert - transmesh->firstvert + 1;
837 if (currentmesh >= max_meshs || currenttriangle + transmesh->triangles > max_batch || currentvertex + numverts > max_verts)
840 memcpy(&buf_vertex[currentvertex], &buf_transvertex[transmesh->firstvert], numverts * sizeof(buf_vertex_t));
843 memcpy(&buf_fcolor[currentvertex], &buf_transfcolor[transmesh->firstvert], numverts * sizeof(buf_fcolor_t));
846 memcpy(&buf_bcolor[currentvertex], &buf_transbcolor[transmesh->firstvert], numverts * sizeof(buf_bcolor_t));
847 for (i = 0;i < backendunits && transmesh->textures[i];i++)
848 memcpy(&buf_texcoord[i][currentvertex], &buf_transtexcoord[i][transmesh->firstvert], numverts * sizeof(buf_texcoord_t));
850 mesh = &buf_mesh[currentmesh++];
851 *mesh = *transmesh; // copy mesh properties
852 mesh->firstvert = currentvertex;
853 mesh->lastvert = currentvertex + numverts - 1;
854 currentvertex += numverts;
855 meshvertexadjust = mesh->firstvert - transmesh->firstvert;
856 mesh->firsttriangle = currenttriangle;
857 for (tri = transmesh->transchain;tri;tri = tri->meshsortchain)
859 buf_tri[currenttriangle].index[0] = tri->index[0] + meshvertexadjust;
860 buf_tri[currenttriangle].index[1] = tri->index[1] + meshvertexadjust;
861 buf_tri[currenttriangle].index[2] = tri->index[2] + meshvertexadjust;
863 if (tri->mesh != transmesh)
865 if ((unsigned int) buf_tri[currenttriangle].index[0] < (unsigned int) mesh->firstvert
866 || (unsigned int) buf_tri[currenttriangle].index[0] > (unsigned int) mesh->lastvert
867 || (unsigned int) buf_tri[currenttriangle].index[1] < (unsigned int) mesh->firstvert
868 || (unsigned int) buf_tri[currenttriangle].index[1] > (unsigned int) mesh->lastvert
869 || (unsigned int) buf_tri[currenttriangle].index[2] < (unsigned int) mesh->firstvert
870 || (unsigned int) buf_tri[currenttriangle].index[2] > (unsigned int) mesh->lastvert)
876 if (mesh->triangles != currenttriangle - mesh->firsttriangle)
881 for (;transmesh;transmesh = transmesh->chain)
883 mesh = &buf_mesh[currentmesh++];
884 *mesh = *transmesh; // copy mesh properties
885 mesh->firstvert += currentvertex;
886 mesh->lastvert += currentvertex;
887 mesh->firsttriangle = currenttriangle;
888 for (tri = transmesh->transchain;tri;tri = tri->meshsortchain)
890 buf_tri[currenttriangle].index[0] = tri->index[0] + currentvertex;
891 buf_tri[currenttriangle].index[1] = tri->index[1] + currentvertex;
892 buf_tri[currenttriangle].index[2] = tri->index[2] + currentvertex;
894 if (tri->mesh != transmesh)
896 if ((unsigned int) buf_tri[currenttriangle].index[0] < (unsigned int) mesh->firstvert
897 || (unsigned int) buf_tri[currenttriangle].index[0] > (unsigned int) mesh->lastvert
898 || (unsigned int) buf_tri[currenttriangle].index[1] < (unsigned int) mesh->firstvert
899 || (unsigned int) buf_tri[currenttriangle].index[1] > (unsigned int) mesh->lastvert
900 || (unsigned int) buf_tri[currenttriangle].index[2] < (unsigned int) mesh->firstvert
901 || (unsigned int) buf_tri[currenttriangle].index[2] > (unsigned int) mesh->lastvert)
907 if (mesh->triangles != currenttriangle - mesh->firsttriangle)
911 currentvertex += currenttransvertex;
914 currenttransmesh = 0;
915 currenttranstriangle = 0;
916 currenttransvertex = 0;
918 else if (gl_mesh_dupetransverts.integer)
921 float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
922 buf_vertex_t *vert1, *vert2, *vert3;
926 // process and add transparent mesh triangles
927 if (!currenttranstriangle)
930 // map farclip to 0-4095 list range
931 centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
932 viewdistcompare = viewdist + 4.0f;
934 memset(buf_transtri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
936 // process in reverse because transtri_list adding code is in reverse as well
938 for (j = currenttranstriangle - 1;j >= 0;j--)
940 tri = &buf_transtri[j];
942 vert1 = &buf_transvertex[tri->index[0]];
943 vert2 = &buf_transvertex[tri->index[1]];
944 vert3 = &buf_transvertex[tri->index[2]];
946 dist1 = DotProduct(vert1->v, vpn);
947 dist2 = DotProduct(vert2->v, vpn);
948 dist3 = DotProduct(vert3->v, vpn);
950 maxdist = max(dist1, max(dist2, dist3));
951 if (maxdist < viewdistcompare)
954 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
957 i = bound(0, i, (TRANSDEPTHRES - 1));
961 center += 8388608.0f;
962 i = *((long *)¢er) & 0x7FFFFF;
963 i = min(i, (TRANSDEPTHRES - 1));
965 tri->next = buf_transtri_list[i];
966 buf_transtri_list[i] = tri;
970 if (currentmesh + k > max_meshs || currenttriangle + k > max_batch || currentvertex + k * 3 > max_verts)
973 currenttransmesh = 0;
974 currenttranstriangle = 0;
975 currenttransvertex = 0;
977 // note: can't batch these because they can be rendered in any order
978 // there can never be more transparent triangles than fit in main buffers
979 for (j = TRANSDEPTHRES - 1;j >= 0;j--)
981 if ((tri = buf_transtri_list[j]))
985 mesh = &buf_mesh[currentmesh++];
986 *mesh = *tri->mesh; // copy mesh properties
987 mesh->firstvert = currentvertex;
988 mesh->lastvert = currentvertex + 2;
989 mesh->firsttriangle = currenttriangle;
991 for (k = 0;k < 3;k++)
993 index = tri->index[k];
994 buf_tri[currenttriangle].index[k] = currentvertex;
995 memcpy(buf_vertex[currentvertex].v, buf_transvertex[index].v, sizeof(buf_vertex_t));
998 memcpy(buf_fcolor[currentvertex].c, buf_transfcolor[index].c, sizeof(buf_fcolor_t));
1001 memcpy(buf_bcolor[currentvertex].c, buf_transbcolor[index].c, sizeof(buf_bcolor_t));
1002 for (i = 0;i < backendunits && tri->mesh->textures[i];i++)
1003 memcpy(buf_texcoord[i][currentvertex].t, buf_transtexcoord[i][index].t, sizeof(buf_texcoord_t));
1015 float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
1016 buf_vertex_t *vert1, *vert2, *vert3;
1017 buf_transtri_t *tri;
1020 // process and add transparent mesh triangles
1021 if (!currenttranstriangle)
1024 // map farclip to 0-4095 list range
1025 centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
1026 viewdistcompare = viewdist + 4.0f;
1028 memset(buf_transtri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
1030 // process in reverse because transtri_list adding code is in reverse as well
1032 for (j = currenttranstriangle - 1;j >= 0;j--)
1034 tri = &buf_transtri[j];
1036 vert1 = &buf_transvertex[tri->index[0]];
1037 vert2 = &buf_transvertex[tri->index[1]];
1038 vert3 = &buf_transvertex[tri->index[2]];
1040 dist1 = DotProduct(vert1->v, vpn);
1041 dist2 = DotProduct(vert2->v, vpn);
1042 dist3 = DotProduct(vert3->v, vpn);
1044 maxdist = max(dist1, max(dist2, dist3));
1045 if (maxdist < viewdistcompare)
1048 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
1051 i = bound(0, i, (TRANSDEPTHRES - 1));
1055 center += 8388608.0f;
1056 i = *((long *)¢er) & 0x7FFFFF;
1057 i = min(i, (TRANSDEPTHRES - 1));
1059 tri->next = buf_transtri_list[i];
1060 buf_transtri_list[i] = tri;
1064 if (currentmesh + k > max_meshs || currenttriangle + k > max_batch || currentvertex + currenttransvertex > max_verts)
1067 // note: can't batch these because they can be rendered in any order
1068 // there can never be more transparent triangles than fit in main buffers
1069 memcpy(&buf_vertex[currentvertex], &buf_transvertex[0], currenttransvertex * sizeof(buf_vertex_t));
1072 memcpy(&buf_fcolor[currentvertex], &buf_transfcolor[0], currenttransvertex * sizeof(buf_fcolor_t));
1075 memcpy(&buf_bcolor[currentvertex], &buf_transbcolor[0], currenttransvertex * sizeof(buf_bcolor_t));
1076 for (i = 0;i < backendunits;i++)
1077 memcpy(&buf_texcoord[i][currentvertex], &buf_transtexcoord[i][0], currenttransvertex * sizeof(buf_texcoord_t));
1079 for (j = TRANSDEPTHRES - 1;j >= 0;j--)
1081 if ((tri = buf_transtri_list[j]))
1085 mesh = &buf_mesh[currentmesh++];
1086 *mesh = *tri->mesh; // copy mesh properties
1087 buf_tri[currenttriangle].index[0] = tri->index[0] + currentvertex;
1088 buf_tri[currenttriangle].index[1] = tri->index[1] + currentvertex;
1089 buf_tri[currenttriangle].index[2] = tri->index[2] + currentvertex;
1090 mesh->firstvert = min(buf_tri[currenttriangle].index[0], min(buf_tri[currenttriangle].index[1], buf_tri[currenttriangle].index[2]));
1091 mesh->lastvert = max(buf_tri[currenttriangle].index[0], max(buf_tri[currenttriangle].index[1], buf_tri[currenttriangle].index[2]));
1092 mesh->firsttriangle = currenttriangle++;
1093 mesh->triangles = 1;
1098 currentvertex += currenttransvertex;
1099 currenttransmesh = 0;
1100 currenttranstriangle = 0;
1101 currenttransvertex = 0;
1105 void R_Mesh_Draw(const rmeshinfo_t *m)
1107 // these are static because gcc runs out of virtual registers otherwise
1108 static int i, j, *index, overbright;
1109 static float c, *in, scaler;
1111 static float cr, cg, cb, ca;
1113 static buf_mesh_t *mesh;
1114 static buf_vertex_t *vert;
1116 static buf_fcolor_t *fcolor;
1118 static buf_bcolor_t *bcolor;
1119 static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
1120 static buf_transtri_t *tri;
1121 static buf_bcolor_t flatbcolor;
1123 if (m->index == NULL
1125 || m->vertex == NULL
1128 // ignore meaningless alpha meshs
1129 if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
1133 for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
1136 if (i == m->numverts)
1139 else if (m->ca < 0.01f)
1144 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1147 if (m->blendfunc2 == GL_SRC_COLOR)
1149 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
1156 overbright = gl_combine.integer;
1166 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
1170 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1177 c_transtris += m->numtriangles;
1178 vert = &buf_transvertex[currenttransvertex];
1180 fcolor = &buf_transfcolor[currenttransvertex];
1182 bcolor = &buf_transbcolor[currenttransvertex];
1183 for (i = 0;i < backendunits;i++)
1184 texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
1186 // transmesh is only for storage of transparent meshs until they
1187 // are inserted into the main mesh array
1188 mesh = &buf_transmesh[currenttransmesh++];
1190 // transparent meshs are broken up into individual triangles which can
1191 // be sorted by depth
1193 for (i = 0;i < m->numtriangles;i++)
1195 tri = &buf_transtri[currenttranstriangle++];
1197 tri->index[0] = *index++ + currenttransvertex;
1198 tri->index[1] = *index++ + currenttransvertex;
1199 tri->index[2] = *index++ + currenttransvertex;
1202 mesh->firstvert = currenttransvertex;
1203 mesh->lastvert = currenttransvertex + m->numverts - 1;
1204 currenttransvertex += m->numverts;
1208 if (m->numtriangles > max_meshs || m->numverts > max_verts)
1210 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
1214 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
1218 c_meshtris += m->numtriangles;
1219 vert = &buf_vertex[currentvertex];
1221 fcolor = &buf_fcolor[currentvertex];
1223 bcolor = &buf_bcolor[currentvertex];
1224 for (i = 0;i < backendunits;i++)
1225 texcoord[i] = &buf_texcoord[i][currentvertex];
1227 mesh = &buf_mesh[currentmesh++];
1228 // opaque meshs are rendered directly
1229 index = (int *)&buf_tri[currenttriangle];
1230 mesh->firsttriangle = currenttriangle;
1231 currenttriangle += m->numtriangles;
1232 for (i = 0;i < m->numtriangles * 3;i++)
1233 index[i] = m->index[i] + currentvertex;
1235 mesh->firstvert = currentvertex;
1236 mesh->lastvert = currentvertex + m->numverts - 1;
1237 currentvertex += m->numverts;
1240 // code shared for transparent and opaque meshs
1241 mesh->blendfunc1 = m->blendfunc1;
1242 mesh->blendfunc2 = m->blendfunc2;
1243 mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
1244 mesh->depthtest = !m->depthdisable;
1245 mesh->triangles = m->numtriangles;
1247 for (i = 0;i < backendunits;i++)
1249 if ((mesh->textures[i] = m->tex[i]))
1251 mesh->texturergbscale[i] = m->texrgbscale[i];
1252 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1253 mesh->texturergbscale[i] = 1;
1255 if (overbright && j >= 0)
1256 mesh->texturergbscale[j] = 4;
1258 if (m->vertexstep != sizeof(buf_vertex_t))
1260 for (i = 0, in = m->vertex;i < m->numverts;i++, (int)in += m->vertexstep)
1262 vert[i].v[0] = in[0];
1263 vert[i].v[1] = in[1];
1264 vert[i].v[2] = in[2];
1268 memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
1275 for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep)
1277 fcolor[i].c[0] = in[0] * scaler;
1278 fcolor[i].c[1] = in[1] * scaler;
1279 fcolor[i].c[2] = in[2] * scaler;
1280 fcolor[i].c[3] = in[3];
1285 cr = m->cr * scaler;
1286 cg = m->cg * scaler;
1287 cb = m->cb * scaler;
1289 for (i = 0;i < m->numverts;i++)
1291 fcolor[i].c[0] = cr;
1292 fcolor[i].c[1] = cg;
1293 fcolor[i].c[2] = cb;
1294 fcolor[i].c[3] = ca;
1303 for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep)
1305 // shift float to have 8bit fraction at base of number,
1306 // then read as integer and kill float bits...
1307 c = in[0] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[0] = (byte) j;
1308 c = in[1] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[1] = (byte) j;
1309 c = in[2] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[2] = (byte) j;
1310 c = in[3] + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[3] = (byte) j;
1315 c = m->cr * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;flatbcolor.c[0] = (byte) j;
1316 c = m->cg * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;flatbcolor.c[1] = (byte) j;
1317 c = m->cb * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;flatbcolor.c[2] = (byte) j;
1318 c = m->ca + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;flatbcolor.c[3] = (byte) j;
1319 for (i = 0;i < m->numverts;i++)
1320 bcolor[i] = flatbcolor;
1326 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1328 if (j >= backendunits)
1329 Sys_Error("R_Mesh_Draw: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1330 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1332 for (i = 0, in = m->texcoords[j];i < m->numverts;i++, (int)in += m->texcoordstep[j])
1334 texcoord[j][i].t[0] = in[0];
1335 texcoord[j][i].t[1] = in[1];
1339 memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1342 for (;j < backendunits;j++)
1343 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1347 void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts)
1349 m->index = polyindexarray;
1350 m->numverts = numverts;
1351 m->numtriangles = numverts - 2;
1352 if (m->numtriangles < 1)
1354 Con_Printf("R_Mesh_DrawPolygon: invalid vertex count\n");
1357 if (m->numtriangles >= 256)
1359 Con_Printf("R_Mesh_DrawPolygon: only up to 256 triangles (258 verts) supported\n");
1365 // LordHavoc: this thing is evil, but necessary because decals account for so much overhead
1366 void R_Mesh_DrawDecal(const rmeshinfo_t *m)
1368 // these are static because gcc runs out of virtual registers otherwise
1369 static int i, j, *index, overbright;
1370 static float c, scaler;
1372 static float cr, cg, cb, ca;
1374 static buf_mesh_t *mesh;
1375 static buf_vertex_t *vert;
1377 static buf_fcolor_t *fcolor;
1379 static buf_bcolor_t *bcolor;
1380 static buf_texcoord_t *texcoord;
1381 static buf_transtri_t *tri;
1382 static buf_bcolor_t flatbcolor;
1385 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1390 overbright = gl_combine.integer;
1399 if (currenttransmesh >= max_meshs || (currenttranstriangle + 2) > max_meshs || (currenttransvertex + 4) > max_verts)
1403 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1411 vert = &buf_transvertex[currenttransvertex];
1413 fcolor = &buf_transfcolor[currenttransvertex];
1415 bcolor = &buf_transbcolor[currenttransvertex];
1416 texcoord = &buf_transtexcoord[0][currenttransvertex];
1418 // transmesh is only for storage of transparent meshs until they
1419 // are inserted into the main mesh array
1420 mesh = &buf_transmesh[currenttransmesh++];
1421 mesh->blendfunc1 = m->blendfunc1;
1422 mesh->blendfunc2 = m->blendfunc2;
1423 mesh->depthmask = false;
1424 mesh->depthtest = true;
1425 mesh->triangles = 2;
1426 mesh->textures[0] = m->tex[0];
1427 mesh->texturergbscale[0] = overbright ? 4 : 1;
1428 for (i = 1;i < backendunits;i++)
1430 mesh->textures[i] = 0;
1431 mesh->texturergbscale[i] = 1;
1435 // transparent meshs are broken up into individual triangles which can
1436 // be sorted by depth
1438 tri = &buf_transtri[currenttranstriangle++];
1440 tri->index[0] = 0 + currenttransvertex;
1441 tri->index[1] = 1 + currenttransvertex;
1442 tri->index[2] = 2 + currenttransvertex;
1443 tri = &buf_transtri[currenttranstriangle++];
1445 tri->index[0] = 0 + currenttransvertex;
1446 tri->index[1] = 2 + currenttransvertex;
1447 tri->index[2] = 3 + currenttransvertex;
1449 mesh->firstvert = currenttransvertex;
1450 mesh->lastvert = currenttransvertex + 3;
1451 currenttransvertex += 4;
1455 if (2 > max_meshs || 4 > max_verts)
1457 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
1461 if (currentmesh >= max_meshs || (currenttriangle + 2) > max_batch || (currentvertex + 4) > max_verts)
1466 vert = &buf_vertex[currentvertex];
1468 fcolor = &buf_fcolor[currentvertex];
1470 bcolor = &buf_bcolor[currentvertex];
1471 texcoord = &buf_texcoord[0][currentvertex];
1473 mesh = &buf_mesh[currentmesh++];
1474 mesh->blendfunc1 = m->blendfunc1;
1475 mesh->blendfunc2 = m->blendfunc2;
1476 mesh->depthmask = false;
1477 mesh->depthtest = !m->depthdisable;
1478 mesh->firsttriangle = currenttriangle;
1479 mesh->triangles = 2;
1480 mesh->textures[0] = m->tex[0];
1481 mesh->texturergbscale[0] = overbright ? 4 : 1;
1482 for (i = 1;i < backendunits;i++)
1484 mesh->textures[i] = 0;
1485 mesh->texturergbscale[i] = 1;
1488 // opaque meshs are rendered directly
1489 index = (int *)&buf_tri[currenttriangle];
1490 index[0] = 0 + currentvertex;
1491 index[1] = 1 + currentvertex;
1492 index[2] = 2 + currentvertex;
1493 index[3] = 0 + currentvertex;
1494 index[4] = 2 + currentvertex;
1495 index[5] = 3 + currentvertex;
1496 mesh->firstvert = currentvertex;
1497 mesh->lastvert = currentvertex + 3;
1498 currenttriangle += 2;
1502 // buf_vertex_t must match the size of the decal vertex array (or vice versa)
1503 memcpy(vert, m->vertex, 4 * sizeof(buf_vertex_t));
1508 cr = m->cr * scaler;
1509 cg = m->cg * scaler;
1510 cb = m->cb * scaler;
1512 fcolor[0].c[0] = cr;
1513 fcolor[0].c[1] = cg;
1514 fcolor[0].c[2] = cb;
1515 fcolor[0].c[3] = ca;
1516 fcolor[1].c[0] = cr;
1517 fcolor[1].c[1] = cg;
1518 fcolor[1].c[2] = cb;
1519 fcolor[1].c[3] = ca;
1520 fcolor[2].c[0] = cr;
1521 fcolor[2].c[1] = cg;
1522 fcolor[2].c[2] = cb;
1523 fcolor[2].c[3] = ca;
1524 fcolor[3].c[0] = cr;
1525 fcolor[3].c[1] = cg;
1526 fcolor[3].c[2] = cb;
1527 fcolor[3].c[3] = ca;
1532 c = m->cr * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;flatbcolor.c[0] = (byte) j;
1533 c = m->cg * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;flatbcolor.c[1] = (byte) j;
1534 c = m->cb * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;flatbcolor.c[2] = (byte) j;
1535 c = m->ca + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;flatbcolor.c[3] = (byte) j;
1536 bcolor[0] = flatbcolor;
1537 bcolor[1] = flatbcolor;
1538 bcolor[2] = flatbcolor;
1539 bcolor[3] = flatbcolor;
1544 // buf_texcoord_t must be the same size as the decal texcoord array (or vice versa)
1545 memcpy(&texcoord[0].t[0], m->texcoords[0], 4 * sizeof(buf_texcoord_t));