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_batchtriangles = {0, "gl_mesh_batchtriangles", "1024"};
11 static cvar_t gl_mesh_merge = {0, "gl_mesh_merge", "1"};
12 static cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "1"};
13 static cvar_t gl_mesh_dupetransverts = {0, "gl_mesh_dupetransverts", "0"};
15 typedef struct buf_mesh_s
17 struct buf_mesh_s *next;
20 int blendfunc1, blendfunc2;
21 int textures[MAX_TEXTUREUNITS];
22 float texturergbscale[MAX_TEXTUREUNITS];
30 typedef struct buf_transtri_s
32 struct buf_transtri_s *next;
38 typedef struct buf_tri_s
68 static float meshfarclip;
69 static int currentmesh, currenttriangle, currentvertex, backendunits, backendactive, meshmerge, floatcolors, transranout;
70 static buf_mesh_t *buf_mesh;
71 static buf_tri_t *buf_tri;
72 static buf_vertex_t *buf_vertex;
73 static buf_fcolor_t *buf_fcolor;
74 static buf_bcolor_t *buf_bcolor;
75 static buf_texcoord_t *buf_texcoord[MAX_TEXTUREUNITS];
77 static int currenttransmesh, currenttransvertex, currenttranstriangle;
78 static buf_mesh_t *buf_transmesh;
79 static buf_transtri_t *buf_transtri;
80 static buf_transtri_t **buf_transtri_list;
81 static buf_vertex_t *buf_transvertex;
82 static buf_fcolor_t *buf_transfcolor;
83 static buf_bcolor_t *buf_transbcolor;
84 static buf_texcoord_t *buf_transtexcoord[MAX_TEXTUREUNITS];
86 static mempool_t *gl_backend_mempool;
88 static void gl_backend_start(void)
92 max_verts = max_meshs * 3;
94 gl_backend_mempool = Mem_AllocPool("GL_Backend");
96 #define BACKENDALLOC(var, count, sizeofstruct)\
98 var = Mem_Alloc(gl_backend_mempool, count * sizeof(sizeofstruct));\
100 Sys_Error("gl_backend_start: unable to allocate memory\n");\
101 memset(var, 0, count * sizeof(sizeofstruct));\
104 BACKENDALLOC(buf_mesh, max_meshs, buf_mesh_t)
105 BACKENDALLOC(buf_tri, max_meshs, buf_tri_t)
106 BACKENDALLOC(buf_vertex, max_verts, buf_vertex_t)
107 BACKENDALLOC(buf_fcolor, max_verts, buf_fcolor_t)
108 BACKENDALLOC(buf_bcolor, max_verts, buf_bcolor_t)
110 BACKENDALLOC(buf_transmesh, max_meshs, buf_mesh_t)
111 BACKENDALLOC(buf_transtri, max_meshs, buf_transtri_t)
112 BACKENDALLOC(buf_transtri_list, TRANSDEPTHRES, buf_transtri_t *)
113 BACKENDALLOC(buf_transvertex, max_verts, buf_vertex_t)
114 BACKENDALLOC(buf_transfcolor, max_verts, buf_fcolor_t)
115 BACKENDALLOC(buf_transbcolor, max_verts, buf_bcolor_t)
117 for (i = 0;i < MAX_TEXTUREUNITS;i++)
119 // only allocate as many texcoord arrays as we need
120 if (i < gl_textureunits)
122 BACKENDALLOC(buf_texcoord[i], max_verts, buf_texcoord_t)
123 BACKENDALLOC(buf_transtexcoord[i], max_verts, buf_texcoord_t)
127 buf_texcoord[i] = NULL;
128 buf_transtexcoord[i] = NULL;
131 backendunits = min(MAX_TEXTUREUNITS, gl_textureunits);
132 backendactive = true;
135 static void gl_backend_shutdown(void)
139 #define BACKENDFREE(var)\
146 #define BACKENDFREE(var) var = NULL;
148 BACKENDFREE(buf_mesh)
150 BACKENDFREE(buf_vertex)
151 BACKENDFREE(buf_fcolor)
152 BACKENDFREE(buf_bcolor)
154 BACKENDFREE(buf_transmesh)
155 BACKENDFREE(buf_transtri)
156 BACKENDFREE(buf_transtri_list)
157 BACKENDFREE(buf_transvertex)
158 BACKENDFREE(buf_transfcolor)
159 BACKENDFREE(buf_transbcolor)
161 for (i = 0;i < MAX_TEXTUREUNITS;i++)
163 BACKENDFREE(buf_texcoord[i])
164 BACKENDFREE(buf_transtexcoord[i])
167 Mem_FreePool(&gl_backend_mempool);
170 backendactive = false;
173 static void gl_backend_bufferchanges(int init)
175 // 21760 is (65536 / 3) rounded off to a multiple of 128
176 if (gl_mesh_maxtriangles.integer < 256)
177 Cvar_SetValue("gl_mesh_maxtriangles", 256);
178 if (gl_mesh_maxtriangles.integer > 21760)
179 Cvar_SetValue("gl_mesh_maxtriangles", 21760);
181 if (gl_mesh_batchtriangles.integer < 0)
182 Cvar_SetValue("gl_mesh_batchtriangles", 0);
183 if (gl_mesh_batchtriangles.integer > gl_mesh_maxtriangles.integer)
184 Cvar_SetValue("gl_mesh_batchtriangles", gl_mesh_maxtriangles.integer);
186 max_batch = gl_mesh_batchtriangles.integer;
188 if (max_meshs != gl_mesh_maxtriangles.integer)
190 max_meshs = gl_mesh_maxtriangles.integer;
194 gl_backend_shutdown();
200 float r_farclip, r_newfarclip;
202 static void gl_backend_newmap(void)
204 r_farclip = r_newfarclip = 2048.0f;
207 int polyindexarray[768];
209 void gl_backend_init(void)
212 Cvar_RegisterVariable(&gl_mesh_maxtriangles);
213 Cvar_RegisterVariable(&gl_mesh_batchtriangles);
214 Cvar_RegisterVariable(&gl_mesh_merge);
215 Cvar_RegisterVariable(&gl_mesh_floatcolors);
216 Cvar_RegisterVariable(&gl_mesh_dupetransverts);
217 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
218 gl_backend_bufferchanges(true);
219 for (i = 0;i < 256;i++)
221 polyindexarray[i*3+0] = 0;
222 polyindexarray[i*3+1] = i + 1;
223 polyindexarray[i*3+2] = i + 2;
227 static float viewdist;
231 // called at beginning of frame
232 void R_Mesh_Clear(void)
235 Sys_Error("R_Mesh_Clear: called when backend is not active\n");
237 gl_backend_bufferchanges(false);
242 currenttransmesh = 0;
243 currenttranstriangle = 0;
244 currenttransvertex = 0;
246 meshmerge = gl_mesh_merge.integer;
247 floatcolors = gl_mesh_floatcolors.integer;
249 viewdist = DotProduct(r_origin, vpn);
255 void GL_PrintError(int errornumber, char *filename, int linenumber)
259 case GL_INVALID_ENUM:
260 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
262 case GL_INVALID_VALUE:
263 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
265 case GL_INVALID_OPERATION:
266 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
268 case GL_STACK_OVERFLOW:
269 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
271 case GL_STACK_UNDERFLOW:
272 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
274 case GL_OUT_OF_MEMORY:
275 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
277 #ifdef GL_TABLE_TOO_LARGE
278 case GL_TABLE_TOO_LARGE:
279 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
283 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
291 // renders mesh buffers, called to flush buffers when full
292 void R_Mesh_Render(void)
294 int i, k, blendfunc1, blendfunc2, blend, depthmask, depthtest, unit = 0, clientunit = 0, firsttriangle, triangles, firstvert, lastvert, texture[MAX_TEXTUREUNITS];
295 float farclip, texturergbscale[MAX_TEXTUREUNITS];
298 Sys_Error("R_Mesh_Render: called when backend is not active\n");
304 // push out farclip based on vertices
305 for (i = 0;i < currentvertex;i++)
307 farclip = DotProduct(buf_vertex[i].v, vpn);
308 if (meshfarclip < farclip)
309 meshfarclip = farclip;
312 farclip = meshfarclip + 256.0f - viewdist; // + 256 just to be safe
314 // push out farclip for next frame
315 if (farclip > r_newfarclip)
316 r_newfarclip = ceil((farclip + 255) / 256) * 256 + 256;
318 for (i = 0;i < backendunits;i++)
319 texturergbscale[i] = 1;
321 glEnable(GL_CULL_FACE);
323 glCullFace(GL_FRONT);
326 glEnable(GL_DEPTH_TEST);
329 blendfunc2 = GL_ZERO;
330 glBlendFunc(blendfunc1, blendfunc2);
336 glDepthMask((GLboolean) depthmask);
339 glVertexPointer(3, GL_FLOAT, sizeof(buf_vertex_t), buf_vertex);
341 glEnableClientState(GL_VERTEX_ARRAY);
345 glColorPointer(4, GL_FLOAT, sizeof(buf_fcolor_t), buf_fcolor);
350 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(buf_bcolor_t), buf_bcolor);
353 glEnableClientState(GL_COLOR_ARRAY);
356 if (backendunits > 1)
358 for (i = 0;i < backendunits;i++)
360 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
362 glBindTexture(GL_TEXTURE_2D, (texture[i] = 0));
364 glDisable(GL_TEXTURE_2D);
366 if (gl_combine.integer)
368 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
370 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
372 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
374 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
376 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB);
378 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
380 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
382 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
384 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
386 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
388 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
390 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);
392 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
394 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
396 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
398 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
400 glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0f);
405 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
409 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
411 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[i]);
413 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
419 glBindTexture(GL_TEXTURE_2D, (texture[0] = 0));
421 glDisable(GL_TEXTURE_2D);
423 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
426 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[0]);
428 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
432 // lock as early as possible
433 GL_LockArray(0, currentvertex);
436 for (k = 0;k < currentmesh;)
440 if (backendunits > 1)
443 for (i = 0;i < backendunits;i++)
445 if (texture[i] != mesh->textures[i])
449 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
454 glEnable(GL_TEXTURE_2D);
456 // have to disable texcoord array on disabled texture
457 // units due to NVIDIA driver bug with
458 // compiled_vertex_array
461 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
464 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
467 glBindTexture(GL_TEXTURE_2D, (texture[i] = mesh->textures[i]));
471 glDisable(GL_TEXTURE_2D);
473 // have to disable texcoord array on disabled texture
474 // units due to NVIDIA driver bug with
475 // compiled_vertex_array
478 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
481 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
485 if (texturergbscale[i] != mesh->texturergbscale[i])
489 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
492 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (texturergbscale[i] = mesh->texturergbscale[i]));
498 // if (unit != topunit)
500 // qglActiveTexture(GL_TEXTURE0_ARB + (unit = topunit));
506 if (texture[0] != mesh->textures[0])
510 glEnable(GL_TEXTURE_2D);
512 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
515 glBindTexture(GL_TEXTURE_2D, (texture[0] = mesh->textures[0]));
519 glDisable(GL_TEXTURE_2D);
521 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
526 if (blendfunc1 != mesh->blendfunc1 || blendfunc2 != mesh->blendfunc2)
528 blendfunc1 = mesh->blendfunc1;
529 blendfunc2 = mesh->blendfunc2;
530 glBlendFunc(blendfunc1, blendfunc2);
532 if (blendfunc2 == GL_ZERO)
534 if (blendfunc1 == GL_ONE)
563 if (depthtest != mesh->depthtest)
565 depthtest = mesh->depthtest;
567 glEnable(GL_DEPTH_TEST);
569 glDisable(GL_DEPTH_TEST);
571 if (depthmask != mesh->depthmask)
573 depthmask = mesh->depthmask;
574 glDepthMask((GLboolean) depthmask);
578 firsttriangle = mesh->firsttriangle;
579 triangles = mesh->triangles;
580 firstvert = mesh->firstvert;
581 lastvert = mesh->lastvert;
582 mesh = &buf_mesh[++k];
586 #if MAX_TEXTUREUNITS != 4
587 #error update this code
589 while (k < currentmesh
590 && mesh->blendfunc1 == blendfunc1
591 && mesh->blendfunc2 == blendfunc2
592 && mesh->depthtest == depthtest
593 && mesh->depthmask == depthmask
594 && mesh->textures[0] == texture[0]
595 && mesh->textures[1] == texture[1]
596 && mesh->textures[2] == texture[2]
597 && mesh->textures[3] == texture[3]
598 && mesh->texturergbscale[0] == texturergbscale[0]
599 && mesh->texturergbscale[1] == texturergbscale[1]
600 && mesh->texturergbscale[2] == texturergbscale[2]
601 && mesh->texturergbscale[3] == texturergbscale[3])
603 triangles += mesh->triangles;
604 if (firstvert > mesh->firstvert)
605 firstvert = mesh->firstvert;
606 if (lastvert < mesh->lastvert)
607 lastvert = mesh->lastvert;
608 mesh = &buf_mesh[++k];
613 // FIXME: dynamic link to GL so we can get DrawRangeElements on WIN32
614 glDrawElements(GL_TRIANGLES, triangles * 3, GL_UNSIGNED_INT, (unsigned int *)&buf_tri[firsttriangle]);
616 glDrawRangeElements(GL_TRIANGLES, firstvert, lastvert + 1, triangles * 3, GL_UNSIGNED_INT, (unsigned int *)&buf_tri[firsttriangle]);
628 if (backendunits > 1)
630 for (i = backendunits - 1;i >= 0;i--)
632 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
634 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
636 if (gl_combine.integer)
638 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
643 glDisable(GL_TEXTURE_2D);
648 glEnable(GL_TEXTURE_2D);
651 glBindTexture(GL_TEXTURE_2D, 0);
654 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
656 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
662 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
664 glEnable(GL_TEXTURE_2D);
666 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
669 glDisableClientState(GL_COLOR_ARRAY);
671 glDisableClientState(GL_VERTEX_ARRAY);
676 glEnable(GL_DEPTH_TEST);
680 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
684 void R_Mesh_AddTransparent(void)
686 if (gl_mesh_dupetransverts.integer)
689 float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
690 buf_vertex_t *vert1, *vert2, *vert3;
694 // process and add transparent mesh triangles
695 if (!currenttranstriangle)
698 // map farclip to 0-4095 list range
699 centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
700 viewdistcompare = viewdist + 4.0f;
702 memset(buf_transtri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
704 // process in reverse because transtri_list adding code is in reverse as well
706 for (j = currenttranstriangle - 1;j >= 0;j--)
708 tri = &buf_transtri[j];
710 vert1 = &buf_transvertex[tri->index[0]];
711 vert2 = &buf_transvertex[tri->index[1]];
712 vert3 = &buf_transvertex[tri->index[2]];
714 dist1 = DotProduct(vert1->v, vpn);
715 dist2 = DotProduct(vert2->v, vpn);
716 dist3 = DotProduct(vert3->v, vpn);
718 maxdist = max(dist1, max(dist2, dist3));
719 if (maxdist < viewdistcompare)
722 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
725 i = bound(0, i, (TRANSDEPTHRES - 1));
729 center += 8388608.0f;
730 i = *((long *)¢er) & 0x7FFFFF;
731 i = min(i, (TRANSDEPTHRES - 1));
733 tri->next = buf_transtri_list[i];
734 buf_transtri_list[i] = tri;
738 if (currentmesh + k > max_meshs || currenttriangle + k > max_batch || currentvertex + k * 3 > max_verts)
741 currenttransmesh = 0;
742 currenttranstriangle = 0;
743 currenttransvertex = 0;
745 // note: can't batch these because they can be rendered in any order
746 // there can never be more transparent triangles than fit in main buffers
747 for (j = TRANSDEPTHRES - 1;j >= 0;j--)
749 if ((tri = buf_transtri_list[j]))
753 mesh = &buf_mesh[currentmesh++];
754 *mesh = *tri->mesh; // copy mesh properties
755 mesh->firstvert = currentvertex;
756 mesh->lastvert = currentvertex + 2;
757 mesh->firsttriangle = currenttriangle;
759 for (k = 0;k < 3;k++)
761 index = tri->index[k];
762 buf_tri[currenttriangle].index[k] = currentvertex;
763 memcpy(buf_vertex[currentvertex].v, buf_transvertex[index].v, sizeof(buf_vertex_t));
765 memcpy(buf_fcolor[currentvertex].c, buf_transfcolor[index].c, sizeof(buf_fcolor_t));
767 memcpy(buf_bcolor[currentvertex].c, buf_transbcolor[index].c, sizeof(buf_bcolor_t));
768 for (i = 0;i < backendunits && tri->mesh->textures[i];i++)
769 memcpy(buf_texcoord[i][currentvertex].t, buf_transtexcoord[i][index].t, sizeof(buf_texcoord_t));
781 float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
782 buf_vertex_t *vert1, *vert2, *vert3;
786 // process and add transparent mesh triangles
787 if (!currenttranstriangle)
790 // map farclip to 0-4095 list range
791 centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
792 viewdistcompare = viewdist + 4.0f;
794 memset(buf_transtri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
796 // process in reverse because transtri_list adding code is in reverse as well
798 for (j = currenttranstriangle - 1;j >= 0;j--)
800 tri = &buf_transtri[j];
802 vert1 = &buf_transvertex[tri->index[0]];
803 vert2 = &buf_transvertex[tri->index[1]];
804 vert3 = &buf_transvertex[tri->index[2]];
806 dist1 = DotProduct(vert1->v, vpn);
807 dist2 = DotProduct(vert2->v, vpn);
808 dist3 = DotProduct(vert3->v, vpn);
810 maxdist = max(dist1, max(dist2, dist3));
811 if (maxdist < viewdistcompare)
814 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
817 i = bound(0, i, (TRANSDEPTHRES - 1));
821 center += 8388608.0f;
822 i = *((long *)¢er) & 0x7FFFFF;
823 i = min(i, (TRANSDEPTHRES - 1));
825 tri->next = buf_transtri_list[i];
826 buf_transtri_list[i] = tri;
830 if (currentmesh + k > max_meshs || currenttriangle + k > max_batch || currentvertex + currenttransvertex > max_verts)
833 // note: can't batch these because they can be rendered in any order
834 // there can never be more transparent triangles than fit in main buffers
835 memcpy(&buf_vertex[currentvertex], &buf_transvertex[0], currenttransvertex * sizeof(buf_vertex_t));
837 memcpy(&buf_fcolor[currentvertex], &buf_transfcolor[0], currenttransvertex * sizeof(buf_fcolor_t));
839 memcpy(&buf_fcolor[currentvertex], &buf_transbcolor[0], currenttransvertex * sizeof(buf_bcolor_t));
840 for (i = 0;i < backendunits;i++)
841 memcpy(&buf_texcoord[i][currentvertex], &buf_transtexcoord[i][0], currenttransvertex * sizeof(buf_texcoord_t));
843 for (j = TRANSDEPTHRES - 1;j >= 0;j--)
845 if ((tri = buf_transtri_list[j]))
849 mesh = &buf_mesh[currentmesh++];
850 *mesh = *tri->mesh; // copy mesh properties
851 buf_tri[currenttriangle].index[0] = tri->index[0] + currentvertex;
852 buf_tri[currenttriangle].index[1] = tri->index[1] + currentvertex;
853 buf_tri[currenttriangle].index[2] = tri->index[2] + currentvertex;
854 mesh->firstvert = min(buf_tri[currenttriangle].index[0], min(buf_tri[currenttriangle].index[1], buf_tri[currenttriangle].index[2]));
855 mesh->lastvert = max(buf_tri[currenttriangle].index[0], max(buf_tri[currenttriangle].index[1], buf_tri[currenttriangle].index[2]));
856 mesh->firsttriangle = currenttriangle++;
862 currentvertex += currenttransvertex;
863 currenttransmesh = 0;
864 currenttranstriangle = 0;
865 currenttransvertex = 0;
869 void R_Mesh_Draw(const rmeshinfo_t *m)
871 // these are static because gcc runs out of virtual registers otherwise
872 static int i, j, *index, overbright;
873 static float c, *in, scaler, cr, cg, cb, ca;
874 static buf_mesh_t *mesh;
875 static buf_vertex_t *vert;
876 static buf_fcolor_t *fcolor;
877 static buf_bcolor_t *bcolor;
878 static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
879 static buf_transtri_t *tri;
880 static byte br, bg, bb, ba;
887 // ignore meaningless alpha meshs
888 if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
892 for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
895 if (i == m->numverts)
898 else if (m->ca < 0.01f)
903 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
906 if (m->blendfunc2 == GL_SRC_COLOR)
908 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
915 overbright = gl_combine.integer;
925 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
929 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
935 vert = &buf_transvertex[currenttransvertex];
936 fcolor = &buf_transfcolor[currenttransvertex];
937 bcolor = &buf_transbcolor[currenttransvertex];
938 for (i = 0;i < backendunits;i++)
939 texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
941 // transmesh is only for storage of transparent meshs until they
942 // are inserted into the main mesh array
943 mesh = &buf_transmesh[currenttransmesh++];
944 mesh->blendfunc1 = m->blendfunc1;
945 mesh->blendfunc2 = m->blendfunc2;
946 mesh->depthmask = false;
947 mesh->depthtest = !m->depthdisable;
949 for (i = 0;i < backendunits;i++)
951 if ((mesh->textures[i] = m->tex[i]))
953 mesh->texturergbscale[i] = m->texrgbscale[i];
954 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
955 mesh->texturergbscale[i] = 1;
957 if (overbright && j >= 0)
958 mesh->texturergbscale[j] = 4;
960 // transparent meshs are broken up into individual triangles which can
961 // be sorted by depth
963 for (i = 0;i < m->numtriangles;i++)
965 tri = &buf_transtri[currenttranstriangle++];
967 tri->index[0] = *index++ + currenttransvertex;
968 tri->index[1] = *index++ + currenttransvertex;
969 tri->index[2] = *index++ + currenttransvertex;
972 currenttransvertex += m->numverts;
976 if (m->numtriangles > max_meshs || m->numverts > max_verts)
978 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
982 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
985 vert = &buf_vertex[currentvertex];
986 fcolor = &buf_fcolor[currentvertex];
987 bcolor = &buf_bcolor[currentvertex];
988 for (i = 0;i < backendunits;i++)
989 texcoord[i] = &buf_texcoord[i][currentvertex];
991 mesh = &buf_mesh[currentmesh++];
992 mesh->blendfunc1 = m->blendfunc1;
993 mesh->blendfunc2 = m->blendfunc2;
994 mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
995 mesh->depthtest = !m->depthdisable;
996 mesh->firsttriangle = currenttriangle;
997 mesh->triangles = m->numtriangles;
999 for (i = 0;i < backendunits;i++)
1001 if ((mesh->textures[i] = m->tex[i]))
1003 mesh->texturergbscale[i] = m->texrgbscale[i];
1004 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1005 mesh->texturergbscale[i] = 1;
1007 if (overbright && j >= 0)
1008 mesh->texturergbscale[j] = 4;
1010 // opaque meshs are rendered directly
1011 index = (int *)&buf_tri[currenttriangle];
1012 for (i = 0;i < m->numtriangles * 3;i++)
1013 index[i] = m->index[i] + currentvertex;
1014 mesh->firstvert = currentvertex;
1015 currenttriangle += m->numtriangles;
1016 currentvertex += m->numverts;
1017 mesh->lastvert = currentvertex - 1;
1020 // vertex array code is shared for transparent and opaque meshs
1022 c_meshtris += m->numtriangles;
1024 if (m->vertexstep != sizeof(buf_vertex_t))
1026 for (i = 0, in = m->vertex;i < m->numverts;i++, (int)in += m->vertexstep)
1028 vert[i].v[0] = in[0];
1029 vert[i].v[1] = in[1];
1030 vert[i].v[2] = in[2];
1034 memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
1040 for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep)
1042 fcolor[i].c[0] = in[0] * scaler;
1043 fcolor[i].c[1] = in[1] * scaler;
1044 fcolor[i].c[2] = in[2] * scaler;
1045 fcolor[i].c[3] = in[3];
1050 cr = m->cr * scaler;
1051 cg = m->cg * scaler;
1052 cb = m->cb * scaler;
1054 for (i = 0;i < m->numverts;i++)
1056 fcolor[i].c[0] = cr;
1057 fcolor[i].c[1] = cg;
1058 fcolor[i].c[2] = cb;
1059 fcolor[i].c[3] = ca;
1067 for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep)
1069 // shift float to have 8bit fraction at base of number,
1070 // then read as integer and kill float bits...
1071 c = in[0] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[0] = (byte) j;
1072 c = in[1] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[1] = (byte) j;
1073 c = in[2] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[2] = (byte) j;
1074 c = in[3] + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[3] = (byte) j;
1079 c = in[0] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;br = (byte) j;
1080 c = in[1] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bg = (byte) j;
1081 c = in[2] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bb = (byte) j;
1082 c = in[3] + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;ba = (byte) j;
1083 for (i = 0;i < m->numverts;i++)
1085 bcolor[i].c[0] = br;
1086 bcolor[i].c[1] = bg;
1087 bcolor[i].c[2] = bb;
1088 bcolor[i].c[3] = ba;
1093 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1095 if (j >= backendunits)
1096 Sys_Error("R_Mesh_Draw: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1097 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1099 for (i = 0, in = m->texcoords[j];i < m->numverts;i++, (int)in += m->texcoordstep[j])
1101 texcoord[j][i].t[0] = in[0];
1102 texcoord[j][i].t[1] = in[1];
1106 memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1109 for (;j < backendunits;j++)
1110 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1114 void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts)
1116 m->index = polyindexarray;
1117 m->numverts = numverts;
1118 m->numtriangles = numverts - 2;
1119 if (m->numtriangles < 1)
1121 Con_Printf("R_Mesh_DrawPolygon: invalid vertex count\n");
1124 if (m->numtriangles >= 256)
1126 Con_Printf("R_Mesh_DrawPolygon: only up to 256 triangles (258 verts) supported\n");
1132 // LordHavoc: this thing is evil, but necessary because decals account for so much overhead
1133 void R_Mesh_DrawDecal(const rmeshinfo_t *m)
1135 // these are static because gcc runs out of virtual registers otherwise
1136 static int i, j, *index, overbright;
1137 static float c, *in, scaler, cr, cg, cb, ca;
1138 static buf_mesh_t *mesh;
1139 static buf_vertex_t *vert;
1140 static buf_fcolor_t *fcolor;
1141 static buf_bcolor_t *bcolor;
1142 static buf_texcoord_t *texcoord;
1143 static buf_transtri_t *tri;
1144 static byte br, bg, bb, ba;
1147 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1152 overbright = gl_combine.integer;
1161 if (currenttransmesh >= max_meshs || (currenttranstriangle + 2) > max_meshs || (currenttransvertex + 4) > max_verts)
1165 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1171 vert = &buf_transvertex[currenttransvertex];
1172 fcolor = &buf_transfcolor[currenttransvertex];
1173 bcolor = &buf_transbcolor[currenttransvertex];
1174 texcoord = &buf_transtexcoord[0][currenttransvertex];
1176 // transmesh is only for storage of transparent meshs until they
1177 // are inserted into the main mesh array
1178 mesh = &buf_transmesh[currenttransmesh++];
1179 mesh->blendfunc1 = m->blendfunc1;
1180 mesh->blendfunc2 = m->blendfunc2;
1181 mesh->depthmask = false;
1182 mesh->depthtest = true;
1183 mesh->textures[0] = m->tex[0];
1184 mesh->texturergbscale[0] = overbright ? 4 : 1;
1185 for (i = 1;i < backendunits;i++)
1187 mesh->textures[i] = 0;
1188 mesh->texturergbscale[i] = 1;
1191 // transparent meshs are broken up into individual triangles which can
1192 // be sorted by depth
1194 tri = &buf_transtri[currenttranstriangle++];
1196 tri->index[0] = 0 + currenttransvertex;
1197 tri->index[1] = 1 + currenttransvertex;
1198 tri->index[2] = 2 + currenttransvertex;
1199 tri = &buf_transtri[currenttranstriangle++];
1201 tri->index[0] = 0 + currenttransvertex;
1202 tri->index[1] = 2 + currenttransvertex;
1203 tri->index[2] = 3 + currenttransvertex;
1205 currenttransvertex += 4;
1209 if (2 > max_meshs || 4 > max_verts)
1211 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
1215 if (currentmesh >= max_meshs || (currenttriangle + 2) > max_batch || (currentvertex + 4) > max_verts)
1218 vert = &buf_vertex[currentvertex];
1219 fcolor = &buf_fcolor[currentvertex];
1220 bcolor = &buf_bcolor[currentvertex];
1221 texcoord = &buf_texcoord[0][currentvertex];
1223 mesh = &buf_mesh[currentmesh++];
1224 mesh->blendfunc1 = m->blendfunc1;
1225 mesh->blendfunc2 = m->blendfunc2;
1226 mesh->depthmask = false;
1227 mesh->depthtest = !m->depthdisable;
1228 mesh->firsttriangle = currenttriangle;
1229 mesh->triangles = 2;
1230 mesh->textures[0] = m->tex[0];
1231 mesh->texturergbscale[0] = overbright ? 4 : 1;
1232 for (i = 1;i < backendunits;i++)
1234 mesh->textures[i] = 0;
1235 mesh->texturergbscale[i] = 1;
1238 // opaque meshs are rendered directly
1239 index = (int *)&buf_tri[currenttriangle];
1240 index[0] = 0 + currentvertex;
1241 index[1] = 1 + currentvertex;
1242 index[2] = 2 + currentvertex;
1243 index[3] = 0 + currentvertex;
1244 index[4] = 2 + currentvertex;
1245 index[5] = 3 + currentvertex;
1246 mesh->firstvert = currentvertex;
1247 currenttriangle += 2;
1249 mesh->lastvert = currentvertex - 1;
1252 // vertex array code is shared for transparent and opaque meshs
1256 // buf_vertex_t must match the size of the decal vertex array (or vice versa)
1257 memcpy(vert, m->vertex, 4 * sizeof(buf_vertex_t));
1261 cr = m->cr * scaler;
1262 cg = m->cg * scaler;
1263 cb = m->cb * scaler;
1265 fcolor[0].c[0] = cr;
1266 fcolor[0].c[1] = cg;
1267 fcolor[0].c[2] = cb;
1268 fcolor[0].c[3] = ca;
1269 fcolor[1].c[0] = cr;
1270 fcolor[1].c[1] = cg;
1271 fcolor[1].c[2] = cb;
1272 fcolor[1].c[3] = ca;
1273 fcolor[2].c[0] = cr;
1274 fcolor[2].c[1] = cg;
1275 fcolor[2].c[2] = cb;
1276 fcolor[2].c[3] = ca;
1277 fcolor[3].c[0] = cr;
1278 fcolor[3].c[1] = cg;
1279 fcolor[3].c[2] = cb;
1280 fcolor[3].c[3] = ca;
1284 c = in[0] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;br = (byte) j;
1285 c = in[1] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bg = (byte) j;
1286 c = in[2] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bb = (byte) j;
1287 c = in[3] + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;ba = (byte) j;
1288 bcolor[0].c[0] = br;
1289 bcolor[0].c[1] = bg;
1290 bcolor[0].c[2] = bb;
1291 bcolor[0].c[3] = ba;
1292 bcolor[1].c[0] = br;
1293 bcolor[1].c[1] = bg;
1294 bcolor[1].c[2] = bb;
1295 bcolor[1].c[3] = ba;
1296 bcolor[2].c[0] = br;
1297 bcolor[2].c[1] = bg;
1298 bcolor[2].c[2] = bb;
1299 bcolor[2].c[3] = ba;
1300 bcolor[3].c[0] = br;
1301 bcolor[3].c[1] = bg;
1302 bcolor[3].c[2] = bb;
1303 bcolor[3].c[3] = ba;
1306 // buf_texcoord_t must be the same size as the decal texcoord array (or vice versa)
1307 memcpy(&texcoord[0].t[0], m->texcoords[0], 4 * sizeof(buf_texcoord_t));