6 static int max_verts; // always max_meshs * 3
7 #define TRANSDEPTHRES 4096
9 //static cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "21760"};
10 static cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "4096"};
11 static cvar_t gl_mesh_batchtriangles = {0, "gl_mesh_batchtriangles", "1024"};
12 static cvar_t gl_mesh_merge = {0, "gl_mesh_merge", "1"};
13 static cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "1"};
14 static cvar_t gl_mesh_dupetransverts = {0, "gl_mesh_dupetransverts", "0"};
16 typedef struct buf_mesh_s
18 struct buf_mesh_s *next;
21 int blendfunc1, blendfunc2;
22 int textures[MAX_TEXTUREUNITS];
23 float texturergbscale[MAX_TEXTUREUNITS];
31 typedef struct buf_transtri_s
33 struct buf_transtri_s *next;
39 typedef struct buf_tri_s
69 static float meshfarclip;
70 static int currentmesh, currenttriangle, currentvertex, backendunits, backendactive, meshmerge, floatcolors, transranout;
71 static buf_mesh_t *buf_mesh;
72 static buf_tri_t *buf_tri;
73 static buf_vertex_t *buf_vertex;
74 static buf_fcolor_t *buf_fcolor;
75 static buf_bcolor_t *buf_bcolor;
76 static buf_texcoord_t *buf_texcoord[MAX_TEXTUREUNITS];
78 static int currenttransmesh, currenttransvertex, currenttranstriangle;
79 static buf_mesh_t *buf_transmesh;
80 static buf_transtri_t *buf_transtri;
81 static buf_transtri_t **buf_transtri_list;
82 static buf_vertex_t *buf_transvertex;
83 static buf_fcolor_t *buf_transfcolor;
84 static buf_bcolor_t *buf_transbcolor;
85 static buf_texcoord_t *buf_transtexcoord[MAX_TEXTUREUNITS];
87 static mempool_t *gl_backend_mempool;
88 static int resizingbuffers = false;
90 static void gl_backend_start(void)
94 max_verts = max_meshs * 3;
96 if (!gl_backend_mempool)
97 gl_backend_mempool = Mem_AllocPool("GL_Backend");
99 #define BACKENDALLOC(var, count, sizeofstruct)\
101 var = Mem_Alloc(gl_backend_mempool, count * sizeof(sizeofstruct));\
103 Sys_Error("gl_backend_start: unable to allocate memory\n");\
104 memset(var, 0, count * sizeof(sizeofstruct));\
107 BACKENDALLOC(buf_mesh, max_meshs, buf_mesh_t)
108 BACKENDALLOC(buf_tri, max_meshs, buf_tri_t)
109 BACKENDALLOC(buf_vertex, max_verts, buf_vertex_t)
110 BACKENDALLOC(buf_fcolor, max_verts, buf_fcolor_t)
111 BACKENDALLOC(buf_bcolor, max_verts, buf_bcolor_t)
113 BACKENDALLOC(buf_transmesh, max_meshs, buf_mesh_t)
114 BACKENDALLOC(buf_transtri, max_meshs, buf_transtri_t)
115 BACKENDALLOC(buf_transtri_list, TRANSDEPTHRES, buf_transtri_t *)
116 BACKENDALLOC(buf_transvertex, max_verts, buf_vertex_t)
117 BACKENDALLOC(buf_transfcolor, max_verts, buf_fcolor_t)
118 BACKENDALLOC(buf_transbcolor, max_verts, buf_bcolor_t)
120 for (i = 0;i < MAX_TEXTUREUNITS;i++)
122 // only allocate as many texcoord arrays as we need
123 if (i < gl_textureunits)
125 BACKENDALLOC(buf_texcoord[i], max_verts, buf_texcoord_t)
126 BACKENDALLOC(buf_transtexcoord[i], max_verts, buf_texcoord_t)
130 buf_texcoord[i] = NULL;
131 buf_transtexcoord[i] = NULL;
134 backendunits = min(MAX_TEXTUREUNITS, gl_textureunits);
135 backendactive = true;
138 static void gl_backend_shutdown(void)
142 #define BACKENDFREE(var)\
150 #define BACKENDFREE(var) var = NULL;
152 BACKENDFREE(buf_mesh)
154 BACKENDFREE(buf_vertex)
155 BACKENDFREE(buf_fcolor)
156 BACKENDFREE(buf_bcolor)
158 BACKENDFREE(buf_transmesh)
159 BACKENDFREE(buf_transtri)
160 BACKENDFREE(buf_transtri_list)
161 BACKENDFREE(buf_transvertex)
162 BACKENDFREE(buf_transfcolor)
163 BACKENDFREE(buf_transbcolor)
165 for (i = 0;i < MAX_TEXTUREUNITS;i++)
167 BACKENDFREE(buf_texcoord[i])
168 BACKENDFREE(buf_transtexcoord[i])
173 Mem_EmptyPool(gl_backend_mempool);
175 Mem_FreePool(&gl_backend_mempool);
178 backendactive = false;
181 static void gl_backend_bufferchanges(int init)
183 // 21760 is (65536 / 3) rounded off to a multiple of 128
184 if (gl_mesh_maxtriangles.integer < 256)
185 Cvar_SetValue("gl_mesh_maxtriangles", 256);
186 if (gl_mesh_maxtriangles.integer > 21760)
187 Cvar_SetValue("gl_mesh_maxtriangles", 21760);
189 if (gl_mesh_batchtriangles.integer < 0)
190 Cvar_SetValue("gl_mesh_batchtriangles", 0);
191 if (gl_mesh_batchtriangles.integer > gl_mesh_maxtriangles.integer)
192 Cvar_SetValue("gl_mesh_batchtriangles", gl_mesh_maxtriangles.integer);
194 max_batch = gl_mesh_batchtriangles.integer;
196 if (max_meshs != gl_mesh_maxtriangles.integer)
198 max_meshs = gl_mesh_maxtriangles.integer;
202 resizingbuffers = true;
203 gl_backend_shutdown();
205 resizingbuffers = false;
210 float r_farclip, r_newfarclip;
212 static void gl_backend_newmap(void)
214 r_farclip = r_newfarclip = 2048.0f;
217 int polyindexarray[768];
219 void gl_backend_init(void)
222 Cvar_RegisterVariable(&gl_mesh_maxtriangles);
223 Cvar_RegisterVariable(&gl_mesh_batchtriangles);
224 Cvar_RegisterVariable(&gl_mesh_merge);
225 Cvar_RegisterVariable(&gl_mesh_floatcolors);
226 Cvar_RegisterVariable(&gl_mesh_dupetransverts);
227 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
228 gl_backend_bufferchanges(true);
229 for (i = 0;i < 256;i++)
231 polyindexarray[i*3+0] = 0;
232 polyindexarray[i*3+1] = i + 1;
233 polyindexarray[i*3+2] = i + 2;
237 static float viewdist;
241 // called at beginning of frame
242 void R_Mesh_Clear(void)
245 Sys_Error("R_Mesh_Clear: called when backend is not active\n");
247 gl_backend_bufferchanges(false);
252 currenttransmesh = 0;
253 currenttranstriangle = 0;
254 currenttransvertex = 0;
256 meshmerge = gl_mesh_merge.integer;
257 floatcolors = gl_mesh_floatcolors.integer;
259 viewdist = DotProduct(r_origin, vpn);
265 void GL_PrintError(int errornumber, char *filename, int linenumber)
269 case GL_INVALID_ENUM:
270 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
272 case GL_INVALID_VALUE:
273 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
275 case GL_INVALID_OPERATION:
276 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
278 case GL_STACK_OVERFLOW:
279 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
281 case GL_STACK_UNDERFLOW:
282 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
284 case GL_OUT_OF_MEMORY:
285 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
287 #ifdef GL_TABLE_TOO_LARGE
288 case GL_TABLE_TOO_LARGE:
289 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
293 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
301 // renders mesh buffers, called to flush buffers when full
302 void R_Mesh_Render(void)
304 int i, k, blendfunc1, blendfunc2, blend, depthmask, depthtest, unit = 0, clientunit = 0, firsttriangle, triangles, firstvert, lastvert, texture[MAX_TEXTUREUNITS];
305 float farclip, texturergbscale[MAX_TEXTUREUNITS];
308 Sys_Error("R_Mesh_Render: called when backend is not active\n");
314 // push out farclip based on vertices
315 for (i = 0;i < currentvertex;i++)
317 farclip = DotProduct(buf_vertex[i].v, vpn);
318 if (meshfarclip < farclip)
319 meshfarclip = farclip;
322 farclip = meshfarclip + 256.0f - viewdist; // + 256 just to be safe
324 // push out farclip for next frame
325 if (farclip > r_newfarclip)
326 r_newfarclip = ceil((farclip + 255) / 256) * 256 + 256;
328 for (i = 0;i < backendunits;i++)
329 texturergbscale[i] = 1;
331 glEnable(GL_CULL_FACE);
333 glCullFace(GL_FRONT);
336 glEnable(GL_DEPTH_TEST);
339 blendfunc2 = GL_ZERO;
340 glBlendFunc(blendfunc1, blendfunc2);
346 glDepthMask((GLboolean) depthmask);
349 glVertexPointer(3, GL_FLOAT, sizeof(buf_vertex_t), buf_vertex);
351 glEnableClientState(GL_VERTEX_ARRAY);
355 glColorPointer(4, GL_FLOAT, sizeof(buf_fcolor_t), buf_fcolor);
360 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(buf_bcolor_t), buf_bcolor);
363 glEnableClientState(GL_COLOR_ARRAY);
366 if (backendunits > 1)
368 for (i = 0;i < backendunits;i++)
370 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
372 glBindTexture(GL_TEXTURE_2D, (texture[i] = 0));
374 glDisable(GL_TEXTURE_2D);
376 if (gl_combine.integer)
378 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
380 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
382 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
384 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
386 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB);
388 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
390 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
392 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
394 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
396 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
398 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
400 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);
402 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
404 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
406 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
408 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
410 glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0f);
415 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
419 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
421 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[i]);
423 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
429 glBindTexture(GL_TEXTURE_2D, (texture[0] = 0));
431 glDisable(GL_TEXTURE_2D);
433 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
436 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[0]);
438 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
442 // lock as early as possible
443 GL_LockArray(0, currentvertex);
446 for (k = 0;k < currentmesh;)
450 if (backendunits > 1)
453 for (i = 0;i < backendunits;i++)
455 if (texture[i] != mesh->textures[i])
459 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
464 glEnable(GL_TEXTURE_2D);
466 // have to disable texcoord array on disabled texture
467 // units due to NVIDIA driver bug with
468 // compiled_vertex_array
471 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
474 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
477 glBindTexture(GL_TEXTURE_2D, (texture[i] = mesh->textures[i]));
481 glDisable(GL_TEXTURE_2D);
483 // have to disable texcoord array on disabled texture
484 // units due to NVIDIA driver bug with
485 // compiled_vertex_array
488 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
491 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
495 if (texturergbscale[i] != mesh->texturergbscale[i])
499 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
502 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (texturergbscale[i] = mesh->texturergbscale[i]));
508 // if (unit != topunit)
510 // qglActiveTexture(GL_TEXTURE0_ARB + (unit = topunit));
516 if (texture[0] != mesh->textures[0])
520 glEnable(GL_TEXTURE_2D);
522 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
525 glBindTexture(GL_TEXTURE_2D, (texture[0] = mesh->textures[0]));
529 glDisable(GL_TEXTURE_2D);
531 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
536 if (blendfunc1 != mesh->blendfunc1 || blendfunc2 != mesh->blendfunc2)
538 blendfunc1 = mesh->blendfunc1;
539 blendfunc2 = mesh->blendfunc2;
540 glBlendFunc(blendfunc1, blendfunc2);
542 if (blendfunc2 == GL_ZERO)
544 if (blendfunc1 == GL_ONE)
573 if (depthtest != mesh->depthtest)
575 depthtest = mesh->depthtest;
577 glEnable(GL_DEPTH_TEST);
579 glDisable(GL_DEPTH_TEST);
581 if (depthmask != mesh->depthmask)
583 depthmask = mesh->depthmask;
584 glDepthMask((GLboolean) depthmask);
588 firsttriangle = mesh->firsttriangle;
589 triangles = mesh->triangles;
590 firstvert = mesh->firstvert;
591 lastvert = mesh->lastvert;
592 mesh = &buf_mesh[++k];
596 #if MAX_TEXTUREUNITS != 4
597 #error update this code
599 while (k < currentmesh
600 && mesh->blendfunc1 == blendfunc1
601 && mesh->blendfunc2 == blendfunc2
602 && mesh->depthtest == depthtest
603 && mesh->depthmask == depthmask
604 && mesh->textures[0] == texture[0]
605 && mesh->textures[1] == texture[1]
606 && mesh->textures[2] == texture[2]
607 && mesh->textures[3] == texture[3]
608 && mesh->texturergbscale[0] == texturergbscale[0]
609 && mesh->texturergbscale[1] == texturergbscale[1]
610 && mesh->texturergbscale[2] == texturergbscale[2]
611 && mesh->texturergbscale[3] == texturergbscale[3])
613 triangles += mesh->triangles;
614 if (firstvert > mesh->firstvert)
615 firstvert = mesh->firstvert;
616 if (lastvert < mesh->lastvert)
617 lastvert = mesh->lastvert;
618 mesh = &buf_mesh[++k];
623 // FIXME: dynamic link to GL so we can get DrawRangeElements on WIN32
624 glDrawElements(GL_TRIANGLES, triangles * 3, GL_UNSIGNED_INT, (unsigned int *)&buf_tri[firsttriangle]);
626 glDrawRangeElements(GL_TRIANGLES, firstvert, lastvert + 1, triangles * 3, GL_UNSIGNED_INT, (unsigned int *)&buf_tri[firsttriangle]);
638 if (backendunits > 1)
640 for (i = backendunits - 1;i >= 0;i--)
642 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
644 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
646 if (gl_combine.integer)
648 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
653 glDisable(GL_TEXTURE_2D);
658 glEnable(GL_TEXTURE_2D);
661 glBindTexture(GL_TEXTURE_2D, 0);
664 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
666 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
672 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
674 glEnable(GL_TEXTURE_2D);
676 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
679 glDisableClientState(GL_COLOR_ARRAY);
681 glDisableClientState(GL_VERTEX_ARRAY);
686 glEnable(GL_DEPTH_TEST);
690 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
694 void R_Mesh_AddTransparent(void)
696 if (gl_mesh_dupetransverts.integer)
699 float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
700 buf_vertex_t *vert1, *vert2, *vert3;
704 // process and add transparent mesh triangles
705 if (!currenttranstriangle)
708 // map farclip to 0-4095 list range
709 centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
710 viewdistcompare = viewdist + 4.0f;
712 memset(buf_transtri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
714 // process in reverse because transtri_list adding code is in reverse as well
716 for (j = currenttranstriangle - 1;j >= 0;j--)
718 tri = &buf_transtri[j];
720 vert1 = &buf_transvertex[tri->index[0]];
721 vert2 = &buf_transvertex[tri->index[1]];
722 vert3 = &buf_transvertex[tri->index[2]];
724 dist1 = DotProduct(vert1->v, vpn);
725 dist2 = DotProduct(vert2->v, vpn);
726 dist3 = DotProduct(vert3->v, vpn);
728 maxdist = max(dist1, max(dist2, dist3));
729 if (maxdist < viewdistcompare)
732 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
735 i = bound(0, i, (TRANSDEPTHRES - 1));
739 center += 8388608.0f;
740 i = *((long *)¢er) & 0x7FFFFF;
741 i = min(i, (TRANSDEPTHRES - 1));
743 tri->next = buf_transtri_list[i];
744 buf_transtri_list[i] = tri;
748 if (currentmesh + k > max_meshs || currenttriangle + k > max_batch || currentvertex + k * 3 > max_verts)
751 currenttransmesh = 0;
752 currenttranstriangle = 0;
753 currenttransvertex = 0;
755 // note: can't batch these because they can be rendered in any order
756 // there can never be more transparent triangles than fit in main buffers
757 for (j = TRANSDEPTHRES - 1;j >= 0;j--)
759 if ((tri = buf_transtri_list[j]))
763 mesh = &buf_mesh[currentmesh++];
764 *mesh = *tri->mesh; // copy mesh properties
765 mesh->firstvert = currentvertex;
766 mesh->lastvert = currentvertex + 2;
767 mesh->firsttriangle = currenttriangle;
769 for (k = 0;k < 3;k++)
771 index = tri->index[k];
772 buf_tri[currenttriangle].index[k] = currentvertex;
773 memcpy(buf_vertex[currentvertex].v, buf_transvertex[index].v, sizeof(buf_vertex_t));
775 memcpy(buf_fcolor[currentvertex].c, buf_transfcolor[index].c, sizeof(buf_fcolor_t));
777 memcpy(buf_bcolor[currentvertex].c, buf_transbcolor[index].c, sizeof(buf_bcolor_t));
778 for (i = 0;i < backendunits && tri->mesh->textures[i];i++)
779 memcpy(buf_texcoord[i][currentvertex].t, buf_transtexcoord[i][index].t, sizeof(buf_texcoord_t));
791 float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
792 buf_vertex_t *vert1, *vert2, *vert3;
796 // process and add transparent mesh triangles
797 if (!currenttranstriangle)
800 // map farclip to 0-4095 list range
801 centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
802 viewdistcompare = viewdist + 4.0f;
804 memset(buf_transtri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
806 // process in reverse because transtri_list adding code is in reverse as well
808 for (j = currenttranstriangle - 1;j >= 0;j--)
810 tri = &buf_transtri[j];
812 vert1 = &buf_transvertex[tri->index[0]];
813 vert2 = &buf_transvertex[tri->index[1]];
814 vert3 = &buf_transvertex[tri->index[2]];
816 dist1 = DotProduct(vert1->v, vpn);
817 dist2 = DotProduct(vert2->v, vpn);
818 dist3 = DotProduct(vert3->v, vpn);
820 maxdist = max(dist1, max(dist2, dist3));
821 if (maxdist < viewdistcompare)
824 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
827 i = bound(0, i, (TRANSDEPTHRES - 1));
831 center += 8388608.0f;
832 i = *((long *)¢er) & 0x7FFFFF;
833 i = min(i, (TRANSDEPTHRES - 1));
835 tri->next = buf_transtri_list[i];
836 buf_transtri_list[i] = tri;
840 if (currentmesh + k > max_meshs || currenttriangle + k > max_batch || currentvertex + currenttransvertex > max_verts)
843 // note: can't batch these because they can be rendered in any order
844 // there can never be more transparent triangles than fit in main buffers
845 memcpy(&buf_vertex[currentvertex], &buf_transvertex[0], currenttransvertex * sizeof(buf_vertex_t));
847 memcpy(&buf_fcolor[currentvertex], &buf_transfcolor[0], currenttransvertex * sizeof(buf_fcolor_t));
849 memcpy(&buf_fcolor[currentvertex], &buf_transbcolor[0], currenttransvertex * sizeof(buf_bcolor_t));
850 for (i = 0;i < backendunits;i++)
851 memcpy(&buf_texcoord[i][currentvertex], &buf_transtexcoord[i][0], currenttransvertex * sizeof(buf_texcoord_t));
853 for (j = TRANSDEPTHRES - 1;j >= 0;j--)
855 if ((tri = buf_transtri_list[j]))
859 mesh = &buf_mesh[currentmesh++];
860 *mesh = *tri->mesh; // copy mesh properties
861 buf_tri[currenttriangle].index[0] = tri->index[0] + currentvertex;
862 buf_tri[currenttriangle].index[1] = tri->index[1] + currentvertex;
863 buf_tri[currenttriangle].index[2] = tri->index[2] + currentvertex;
864 mesh->firstvert = min(buf_tri[currenttriangle].index[0], min(buf_tri[currenttriangle].index[1], buf_tri[currenttriangle].index[2]));
865 mesh->lastvert = max(buf_tri[currenttriangle].index[0], max(buf_tri[currenttriangle].index[1], buf_tri[currenttriangle].index[2]));
866 mesh->firsttriangle = currenttriangle++;
872 currentvertex += currenttransvertex;
873 currenttransmesh = 0;
874 currenttranstriangle = 0;
875 currenttransvertex = 0;
879 void R_Mesh_Draw(const rmeshinfo_t *m)
881 // these are static because gcc runs out of virtual registers otherwise
882 static int i, j, *index, overbright;
883 static float c, *in, scaler, cr, cg, cb, ca;
884 static buf_mesh_t *mesh;
885 static buf_vertex_t *vert;
886 static buf_fcolor_t *fcolor;
887 static buf_bcolor_t *bcolor;
888 static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
889 static buf_transtri_t *tri;
890 static byte br, bg, bb, ba;
897 // ignore meaningless alpha meshs
898 if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
902 for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
905 if (i == m->numverts)
908 else if (m->ca < 0.01f)
913 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
916 if (m->blendfunc2 == GL_SRC_COLOR)
918 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
925 overbright = gl_combine.integer;
935 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
939 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
945 vert = &buf_transvertex[currenttransvertex];
946 fcolor = &buf_transfcolor[currenttransvertex];
947 bcolor = &buf_transbcolor[currenttransvertex];
948 for (i = 0;i < backendunits;i++)
949 texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
951 // transmesh is only for storage of transparent meshs until they
952 // are inserted into the main mesh array
953 mesh = &buf_transmesh[currenttransmesh++];
954 mesh->blendfunc1 = m->blendfunc1;
955 mesh->blendfunc2 = m->blendfunc2;
956 mesh->depthmask = false;
957 mesh->depthtest = !m->depthdisable;
959 for (i = 0;i < backendunits;i++)
961 if ((mesh->textures[i] = m->tex[i]))
963 mesh->texturergbscale[i] = m->texrgbscale[i];
964 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
965 mesh->texturergbscale[i] = 1;
967 if (overbright && j >= 0)
968 mesh->texturergbscale[j] = 4;
970 // transparent meshs are broken up into individual triangles which can
971 // be sorted by depth
973 for (i = 0;i < m->numtriangles;i++)
975 tri = &buf_transtri[currenttranstriangle++];
977 tri->index[0] = *index++ + currenttransvertex;
978 tri->index[1] = *index++ + currenttransvertex;
979 tri->index[2] = *index++ + currenttransvertex;
982 currenttransvertex += m->numverts;
986 if (m->numtriangles > max_meshs || m->numverts > max_verts)
988 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
992 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
995 vert = &buf_vertex[currentvertex];
996 fcolor = &buf_fcolor[currentvertex];
997 bcolor = &buf_bcolor[currentvertex];
998 for (i = 0;i < backendunits;i++)
999 texcoord[i] = &buf_texcoord[i][currentvertex];
1001 mesh = &buf_mesh[currentmesh++];
1002 mesh->blendfunc1 = m->blendfunc1;
1003 mesh->blendfunc2 = m->blendfunc2;
1004 mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
1005 mesh->depthtest = !m->depthdisable;
1006 mesh->firsttriangle = currenttriangle;
1007 mesh->triangles = m->numtriangles;
1009 for (i = 0;i < backendunits;i++)
1011 if ((mesh->textures[i] = m->tex[i]))
1013 mesh->texturergbscale[i] = m->texrgbscale[i];
1014 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1015 mesh->texturergbscale[i] = 1;
1017 if (overbright && j >= 0)
1018 mesh->texturergbscale[j] = 4;
1020 // opaque meshs are rendered directly
1021 index = (int *)&buf_tri[currenttriangle];
1022 for (i = 0;i < m->numtriangles * 3;i++)
1023 index[i] = m->index[i] + currentvertex;
1024 mesh->firstvert = currentvertex;
1025 currenttriangle += m->numtriangles;
1026 currentvertex += m->numverts;
1027 mesh->lastvert = currentvertex - 1;
1030 // vertex array code is shared for transparent and opaque meshs
1032 c_meshtris += m->numtriangles;
1034 if (m->vertexstep != sizeof(buf_vertex_t))
1036 for (i = 0, in = m->vertex;i < m->numverts;i++, (int)in += m->vertexstep)
1038 vert[i].v[0] = in[0];
1039 vert[i].v[1] = in[1];
1040 vert[i].v[2] = in[2];
1044 memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
1050 for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep)
1052 fcolor[i].c[0] = in[0] * scaler;
1053 fcolor[i].c[1] = in[1] * scaler;
1054 fcolor[i].c[2] = in[2] * scaler;
1055 fcolor[i].c[3] = in[3];
1060 cr = m->cr * scaler;
1061 cg = m->cg * scaler;
1062 cb = m->cb * scaler;
1064 for (i = 0;i < m->numverts;i++)
1066 fcolor[i].c[0] = cr;
1067 fcolor[i].c[1] = cg;
1068 fcolor[i].c[2] = cb;
1069 fcolor[i].c[3] = ca;
1077 for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep)
1079 // shift float to have 8bit fraction at base of number,
1080 // then read as integer and kill float bits...
1081 c = in[0] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[0] = (byte) j;
1082 c = in[1] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[1] = (byte) j;
1083 c = in[2] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[2] = (byte) j;
1084 c = in[3] + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[3] = (byte) j;
1089 c = in[0] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;br = (byte) j;
1090 c = in[1] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bg = (byte) j;
1091 c = in[2] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bb = (byte) j;
1092 c = in[3] + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;ba = (byte) j;
1093 for (i = 0;i < m->numverts;i++)
1095 bcolor[i].c[0] = br;
1096 bcolor[i].c[1] = bg;
1097 bcolor[i].c[2] = bb;
1098 bcolor[i].c[3] = ba;
1103 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1105 if (j >= backendunits)
1106 Sys_Error("R_Mesh_Draw: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1107 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1109 for (i = 0, in = m->texcoords[j];i < m->numverts;i++, (int)in += m->texcoordstep[j])
1111 texcoord[j][i].t[0] = in[0];
1112 texcoord[j][i].t[1] = in[1];
1116 memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1119 for (;j < backendunits;j++)
1120 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1124 void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts)
1126 m->index = polyindexarray;
1127 m->numverts = numverts;
1128 m->numtriangles = numverts - 2;
1129 if (m->numtriangles < 1)
1131 Con_Printf("R_Mesh_DrawPolygon: invalid vertex count\n");
1134 if (m->numtriangles >= 256)
1136 Con_Printf("R_Mesh_DrawPolygon: only up to 256 triangles (258 verts) supported\n");
1142 // LordHavoc: this thing is evil, but necessary because decals account for so much overhead
1143 void R_Mesh_DrawDecal(const rmeshinfo_t *m)
1145 // these are static because gcc runs out of virtual registers otherwise
1146 static int i, j, *index, overbright;
1147 static float c, *in, scaler, cr, cg, cb, ca;
1148 static buf_mesh_t *mesh;
1149 static buf_vertex_t *vert;
1150 static buf_fcolor_t *fcolor;
1151 static buf_bcolor_t *bcolor;
1152 static buf_texcoord_t *texcoord;
1153 static buf_transtri_t *tri;
1154 static byte br, bg, bb, ba;
1157 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1162 overbright = gl_combine.integer;
1171 if (currenttransmesh >= max_meshs || (currenttranstriangle + 2) > max_meshs || (currenttransvertex + 4) > max_verts)
1175 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1181 vert = &buf_transvertex[currenttransvertex];
1182 fcolor = &buf_transfcolor[currenttransvertex];
1183 bcolor = &buf_transbcolor[currenttransvertex];
1184 texcoord = &buf_transtexcoord[0][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++];
1189 mesh->blendfunc1 = m->blendfunc1;
1190 mesh->blendfunc2 = m->blendfunc2;
1191 mesh->depthmask = false;
1192 mesh->depthtest = true;
1193 mesh->textures[0] = m->tex[0];
1194 mesh->texturergbscale[0] = overbright ? 4 : 1;
1195 for (i = 1;i < backendunits;i++)
1197 mesh->textures[i] = 0;
1198 mesh->texturergbscale[i] = 1;
1201 // transparent meshs are broken up into individual triangles which can
1202 // be sorted by depth
1204 tri = &buf_transtri[currenttranstriangle++];
1206 tri->index[0] = 0 + currenttransvertex;
1207 tri->index[1] = 1 + currenttransvertex;
1208 tri->index[2] = 2 + currenttransvertex;
1209 tri = &buf_transtri[currenttranstriangle++];
1211 tri->index[0] = 0 + currenttransvertex;
1212 tri->index[1] = 2 + currenttransvertex;
1213 tri->index[2] = 3 + currenttransvertex;
1215 currenttransvertex += 4;
1219 if (2 > max_meshs || 4 > max_verts)
1221 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
1225 if (currentmesh >= max_meshs || (currenttriangle + 2) > max_batch || (currentvertex + 4) > max_verts)
1228 vert = &buf_vertex[currentvertex];
1229 fcolor = &buf_fcolor[currentvertex];
1230 bcolor = &buf_bcolor[currentvertex];
1231 texcoord = &buf_texcoord[0][currentvertex];
1233 mesh = &buf_mesh[currentmesh++];
1234 mesh->blendfunc1 = m->blendfunc1;
1235 mesh->blendfunc2 = m->blendfunc2;
1236 mesh->depthmask = false;
1237 mesh->depthtest = !m->depthdisable;
1238 mesh->firsttriangle = currenttriangle;
1239 mesh->triangles = 2;
1240 mesh->textures[0] = m->tex[0];
1241 mesh->texturergbscale[0] = overbright ? 4 : 1;
1242 for (i = 1;i < backendunits;i++)
1244 mesh->textures[i] = 0;
1245 mesh->texturergbscale[i] = 1;
1248 // opaque meshs are rendered directly
1249 index = (int *)&buf_tri[currenttriangle];
1250 index[0] = 0 + currentvertex;
1251 index[1] = 1 + currentvertex;
1252 index[2] = 2 + currentvertex;
1253 index[3] = 0 + currentvertex;
1254 index[4] = 2 + currentvertex;
1255 index[5] = 3 + currentvertex;
1256 mesh->firstvert = currentvertex;
1257 currenttriangle += 2;
1259 mesh->lastvert = currentvertex - 1;
1262 // vertex array code is shared for transparent and opaque meshs
1266 // buf_vertex_t must match the size of the decal vertex array (or vice versa)
1267 memcpy(vert, m->vertex, 4 * sizeof(buf_vertex_t));
1271 cr = m->cr * scaler;
1272 cg = m->cg * scaler;
1273 cb = m->cb * scaler;
1275 fcolor[0].c[0] = cr;
1276 fcolor[0].c[1] = cg;
1277 fcolor[0].c[2] = cb;
1278 fcolor[0].c[3] = ca;
1279 fcolor[1].c[0] = cr;
1280 fcolor[1].c[1] = cg;
1281 fcolor[1].c[2] = cb;
1282 fcolor[1].c[3] = ca;
1283 fcolor[2].c[0] = cr;
1284 fcolor[2].c[1] = cg;
1285 fcolor[2].c[2] = cb;
1286 fcolor[2].c[3] = ca;
1287 fcolor[3].c[0] = cr;
1288 fcolor[3].c[1] = cg;
1289 fcolor[3].c[2] = cb;
1290 fcolor[3].c[3] = ca;
1294 c = in[0] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;br = (byte) j;
1295 c = in[1] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bg = (byte) j;
1296 c = in[2] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bb = (byte) j;
1297 c = in[3] + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;ba = (byte) j;
1298 bcolor[0].c[0] = br;
1299 bcolor[0].c[1] = bg;
1300 bcolor[0].c[2] = bb;
1301 bcolor[0].c[3] = ba;
1302 bcolor[1].c[0] = br;
1303 bcolor[1].c[1] = bg;
1304 bcolor[1].c[2] = bb;
1305 bcolor[1].c[3] = ba;
1306 bcolor[2].c[0] = br;
1307 bcolor[2].c[1] = bg;
1308 bcolor[2].c[2] = bb;
1309 bcolor[2].c[3] = ba;
1310 bcolor[3].c[0] = br;
1311 bcolor[3].c[1] = bg;
1312 bcolor[3].c[2] = bb;
1313 bcolor[3].c[3] = ba;
1316 // buf_texcoord_t must be the same size as the decal texcoord array (or vice versa)
1317 memcpy(&texcoord[0].t[0], m->texcoords[0], 4 * sizeof(buf_texcoord_t));