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"};
14 typedef struct buf_mesh_s
16 struct buf_mesh_s *next;
19 int blendfunc1, blendfunc2;
20 int textures[MAX_TEXTUREUNITS];
21 float texturergbscale[MAX_TEXTUREUNITS];
29 typedef struct buf_transtri_s
31 struct buf_transtri_s *next;
37 typedef struct buf_tri_s
67 static float meshfarclip;
68 static int currentmesh, currenttriangle, currentvertex, backendunits, backendactive, meshmerge, floatcolors, transranout;
69 static buf_mesh_t *buf_mesh;
70 static buf_tri_t *buf_tri;
71 static buf_vertex_t *buf_vertex;
72 static buf_fcolor_t *buf_fcolor;
73 static buf_bcolor_t *buf_bcolor;
74 static buf_texcoord_t *buf_texcoord[MAX_TEXTUREUNITS];
76 static int currenttransmesh, currenttransvertex, currenttranstriangle;
77 static buf_mesh_t *buf_transmesh;
78 static buf_transtri_t *buf_transtri;
79 static buf_transtri_t **buf_transtri_list;
80 static buf_vertex_t *buf_transvertex;
81 static buf_fcolor_t *buf_transfcolor;
82 static buf_bcolor_t *buf_transbcolor;
83 static buf_texcoord_t *buf_transtexcoord[MAX_TEXTUREUNITS];
85 static mempool_t *gl_backend_mempool;
87 static void gl_backend_start(void)
91 max_verts = max_meshs * 3;
93 gl_backend_mempool = Mem_AllocPool("GL_Backend");
95 #define BACKENDALLOC(var, count, sizeofstruct)\
97 var = Mem_Alloc(gl_backend_mempool, count * sizeof(sizeofstruct));\
99 Sys_Error("gl_backend_start: unable to allocate memory\n");\
100 memset(var, 0, count * sizeof(sizeofstruct));\
103 BACKENDALLOC(buf_mesh, max_meshs, buf_mesh_t)
104 BACKENDALLOC(buf_tri, max_meshs, buf_tri_t)
105 BACKENDALLOC(buf_vertex, max_verts, buf_vertex_t)
106 BACKENDALLOC(buf_fcolor, max_verts, buf_fcolor_t)
107 BACKENDALLOC(buf_bcolor, max_verts, buf_bcolor_t)
109 BACKENDALLOC(buf_transmesh, max_meshs, buf_mesh_t)
110 BACKENDALLOC(buf_transtri, max_meshs, buf_transtri_t)
111 BACKENDALLOC(buf_transtri_list, TRANSDEPTHRES, buf_transtri_t *)
112 BACKENDALLOC(buf_transvertex, max_verts, buf_vertex_t)
113 BACKENDALLOC(buf_transfcolor, max_verts, buf_fcolor_t)
114 BACKENDALLOC(buf_transbcolor, max_verts, buf_bcolor_t)
116 for (i = 0;i < MAX_TEXTUREUNITS;i++)
118 // only allocate as many texcoord arrays as we need
119 if (i < gl_textureunits)
121 BACKENDALLOC(buf_texcoord[i], max_verts, buf_texcoord_t)
122 BACKENDALLOC(buf_transtexcoord[i], max_verts, buf_texcoord_t)
126 buf_texcoord[i] = NULL;
127 buf_transtexcoord[i] = NULL;
130 backendunits = min(MAX_TEXTUREUNITS, gl_textureunits);
131 backendactive = true;
134 static void gl_backend_shutdown(void)
138 #define BACKENDFREE(var)\
145 #define BACKENDFREE(var) var = NULL;
147 BACKENDFREE(buf_mesh)
149 BACKENDFREE(buf_vertex)
150 BACKENDFREE(buf_fcolor)
151 BACKENDFREE(buf_bcolor)
153 BACKENDFREE(buf_transmesh)
154 BACKENDFREE(buf_transtri)
155 BACKENDFREE(buf_transtri_list)
156 BACKENDFREE(buf_transvertex)
157 BACKENDFREE(buf_transfcolor)
158 BACKENDFREE(buf_transbcolor)
160 for (i = 0;i < MAX_TEXTUREUNITS;i++)
162 BACKENDFREE(buf_texcoord[i])
163 BACKENDFREE(buf_transtexcoord[i])
166 Mem_FreePool(&gl_backend_mempool);
169 backendactive = false;
172 static void gl_backend_bufferchanges(int init)
174 // 21760 is (65536 / 3) rounded off to a multiple of 128
175 if (gl_mesh_maxtriangles.integer < 256)
176 Cvar_SetValue("gl_mesh_maxtriangles", 256);
177 if (gl_mesh_maxtriangles.integer > 21760)
178 Cvar_SetValue("gl_mesh_maxtriangles", 21760);
180 if (gl_mesh_batchtriangles.integer < 0)
181 Cvar_SetValue("gl_mesh_batchtriangles", 0);
182 if (gl_mesh_batchtriangles.integer > gl_mesh_maxtriangles.integer)
183 Cvar_SetValue("gl_mesh_batchtriangles", gl_mesh_maxtriangles.integer);
185 max_batch = gl_mesh_batchtriangles.integer;
187 if (max_meshs != gl_mesh_maxtriangles.integer)
189 max_meshs = gl_mesh_maxtriangles.integer;
193 gl_backend_shutdown();
199 float r_farclip, r_newfarclip;
201 static void gl_backend_newmap(void)
203 r_farclip = r_newfarclip = 2048.0f;
206 int polyindexarray[768];
208 void gl_backend_init(void)
211 Cvar_RegisterVariable(&gl_mesh_maxtriangles);
212 Cvar_RegisterVariable(&gl_mesh_batchtriangles);
213 Cvar_RegisterVariable(&gl_mesh_merge);
214 Cvar_RegisterVariable(&gl_mesh_floatcolors);
215 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
216 gl_backend_bufferchanges(true);
217 for (i = 0;i < 256;i++)
219 polyindexarray[i*3+0] = 0;
220 polyindexarray[i*3+1] = i + 1;
221 polyindexarray[i*3+2] = i + 2;
225 static float viewdist;
229 // called at beginning of frame
230 void R_Mesh_Clear(void)
233 Sys_Error("R_Mesh_Clear: called when backend is not active\n");
235 gl_backend_bufferchanges(false);
240 currenttransmesh = 0;
241 currenttranstriangle = 0;
242 currenttransvertex = 0;
244 meshmerge = gl_mesh_merge.integer;
245 floatcolors = gl_mesh_floatcolors.integer;
247 viewdist = DotProduct(r_origin, vpn);
253 void GL_PrintError(int errornumber, char *filename, int linenumber)
257 case GL_INVALID_ENUM:
258 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
260 case GL_INVALID_VALUE:
261 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
263 case GL_INVALID_OPERATION:
264 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
266 case GL_STACK_OVERFLOW:
267 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
269 case GL_STACK_UNDERFLOW:
270 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
272 case GL_OUT_OF_MEMORY:
273 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
275 #ifdef GL_TABLE_TOO_LARGE
276 case GL_TABLE_TOO_LARGE:
277 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
281 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
289 // renders mesh buffers, called to flush buffers when full
290 void R_Mesh_Render(void)
292 int i, k, blendfunc1, blendfunc2, blend, depthmask, depthtest, unit = 0, clientunit = 0, firsttriangle, triangles, firstvert, lastvert, texture[MAX_TEXTUREUNITS];
293 float farclip, texturergbscale[MAX_TEXTUREUNITS];
296 Sys_Error("R_Mesh_Render: called when backend is not active\n");
302 farclip = meshfarclip + 256.0f - viewdist; // + 256 just to be safe
304 // push out farclip for next frame
305 if (farclip > r_newfarclip)
306 r_newfarclip = ceil((farclip + 255) / 256) * 256 + 256;
308 for (i = 0;i < backendunits;i++)
309 texturergbscale[i] = 1;
311 glEnable(GL_CULL_FACE);
313 glCullFace(GL_FRONT);
316 glEnable(GL_DEPTH_TEST);
319 blendfunc2 = GL_ZERO;
320 glBlendFunc(blendfunc1, blendfunc2);
326 glDepthMask((GLboolean) depthmask);
330 glVertexPointer(3, GL_FLOAT, sizeof(buf_vertex_t), buf_vertex);
332 glEnableClientState(GL_VERTEX_ARRAY);
336 glColorPointer(4, GL_FLOAT, sizeof(buf_fcolor_t), buf_fcolor);
341 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(buf_bcolor_t), buf_bcolor);
344 glEnableClientState(GL_COLOR_ARRAY);
347 if (backendunits > 1)
349 for (i = 0;i < backendunits;i++)
351 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
353 glBindTexture(GL_TEXTURE_2D, (texture[i] = 0));
355 glDisable(GL_TEXTURE_2D);
357 if (gl_combine.integer)
359 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
361 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
363 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
365 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
367 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB);
369 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
371 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
373 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
375 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
377 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
379 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
381 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);
383 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
385 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
387 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
389 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
391 glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0f);
396 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
400 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
402 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[i]);
404 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
410 glBindTexture(GL_TEXTURE_2D, (texture[0] = 0));
412 glDisable(GL_TEXTURE_2D);
414 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
417 glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[0]);
419 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
423 // lock as early as possible
424 GL_LockArray(0, currentvertex);
427 for (k = 0;k < currentmesh;)
431 if (backendunits > 1)
434 for (i = 0;i < backendunits;i++)
436 if (texture[i] != mesh->textures[i])
440 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
445 glEnable(GL_TEXTURE_2D);
447 // have to disable texcoord array on disabled texture
448 // units due to NVIDIA driver bug with
449 // compiled_vertex_array
452 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
455 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
458 glBindTexture(GL_TEXTURE_2D, (texture[i] = mesh->textures[i]));
462 glDisable(GL_TEXTURE_2D);
464 // have to disable texcoord array on disabled texture
465 // units due to NVIDIA driver bug with
466 // compiled_vertex_array
469 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
472 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
476 if (texturergbscale[i] != mesh->texturergbscale[i])
480 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
483 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (texturergbscale[i] = mesh->texturergbscale[i]));
489 // if (unit != topunit)
491 // qglActiveTexture(GL_TEXTURE0_ARB + (unit = topunit));
497 if (texture[0] != mesh->textures[0])
501 glEnable(GL_TEXTURE_2D);
503 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
506 glBindTexture(GL_TEXTURE_2D, (texture[0] = mesh->textures[0]));
510 glDisable(GL_TEXTURE_2D);
512 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
517 if (blendfunc1 != mesh->blendfunc1 || blendfunc2 != mesh->blendfunc2)
519 blendfunc1 = mesh->blendfunc1;
520 blendfunc2 = mesh->blendfunc2;
521 glBlendFunc(blendfunc1, blendfunc2);
523 if (blendfunc2 == GL_ZERO)
525 if (blendfunc1 == GL_ONE)
554 if (depthtest != mesh->depthtest)
556 depthtest = mesh->depthtest;
558 glEnable(GL_DEPTH_TEST);
560 glDisable(GL_DEPTH_TEST);
562 if (depthmask != mesh->depthmask)
564 depthmask = mesh->depthmask;
565 glDepthMask((GLboolean) depthmask);
569 firsttriangle = mesh->firsttriangle;
570 triangles = mesh->triangles;
571 firstvert = mesh->firstvert;
572 lastvert = mesh->lastvert;
573 mesh = &buf_mesh[++k];
577 #if MAX_TEXTUREUNITS != 4
578 #error update this code
580 while (k < currentmesh
581 && mesh->blendfunc1 == blendfunc1
582 && mesh->blendfunc2 == blendfunc2
583 && mesh->depthtest == depthtest
584 && mesh->depthmask == depthmask
585 && mesh->textures[0] == texture[0]
586 && mesh->textures[1] == texture[1]
587 && mesh->textures[2] == texture[2]
588 && mesh->textures[3] == texture[3]
589 && mesh->texturergbscale[0] == texturergbscale[0]
590 && mesh->texturergbscale[1] == texturergbscale[1]
591 && mesh->texturergbscale[2] == texturergbscale[2]
592 && mesh->texturergbscale[3] == texturergbscale[3])
594 triangles += mesh->triangles;
595 if (firstvert > mesh->firstvert)
596 firstvert = mesh->firstvert;
597 if (lastvert < mesh->lastvert)
598 lastvert = mesh->lastvert;
599 mesh = &buf_mesh[++k];
604 // FIXME: dynamic link to GL so we can get DrawRangeElements on WIN32
605 glDrawElements(GL_TRIANGLES, triangles * 3, GL_UNSIGNED_INT, (unsigned int *)&buf_tri[firsttriangle]);
607 glDrawRangeElements(GL_TRIANGLES, firstvert, lastvert + 1, triangles * 3, GL_UNSIGNED_INT, (unsigned int *)&buf_tri[firsttriangle]);
619 if (backendunits > 1)
621 for (i = backendunits - 1;i >= 0;i--)
623 qglActiveTexture(GL_TEXTURE0_ARB + (unit = i));
625 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
627 if (gl_combine.integer)
629 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
634 glDisable(GL_TEXTURE_2D);
639 glEnable(GL_TEXTURE_2D);
642 glBindTexture(GL_TEXTURE_2D, 0);
645 qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i));
647 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
653 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
655 glEnable(GL_TEXTURE_2D);
657 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
660 glDisableClientState(GL_COLOR_ARRAY);
662 glDisableClientState(GL_VERTEX_ARRAY);
667 glEnable(GL_DEPTH_TEST);
671 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
675 void R_Mesh_AddTransparent(void)
678 float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
679 buf_vertex_t *vert1, *vert2, *vert3;
683 // process and add transparent mesh triangles
684 if (!currenttranstriangle)
687 // map farclip to 0-4095 list range
688 centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
689 viewdistcompare = viewdist + 4.0f;
691 memset(buf_transtri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
693 // process in reverse because transtri_list adding code is in reverse as well
695 for (j = currenttranstriangle - 1;j >= 0;j--)
697 tri = &buf_transtri[j];
699 vert1 = &buf_transvertex[tri->index[0]];
700 vert2 = &buf_transvertex[tri->index[1]];
701 vert3 = &buf_transvertex[tri->index[2]];
703 dist1 = DotProduct(vert1->v, vpn);
704 dist2 = DotProduct(vert2->v, vpn);
705 dist3 = DotProduct(vert3->v, vpn);
707 maxdist = max(dist1, max(dist2, dist3));
708 if (maxdist < viewdistcompare)
711 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
714 i = bound(0, i, (TRANSDEPTHRES - 1));
718 center += 8388608.0f;
719 i = *((long *)¢er) & 0x7FFFFF;
720 i = min(i, (TRANSDEPTHRES - 1));
722 tri->next = buf_transtri_list[i];
723 buf_transtri_list[i] = tri;
727 if (currentmesh + k > max_meshs || currenttriangle + k > max_batch || currentvertex + currenttransvertex > max_verts)
730 // note: can't batch these because they can be rendered in any order
731 // there can never be more transparent triangles than fit in main buffers
732 memcpy(&buf_vertex[currentvertex], &buf_transvertex[0], currenttransvertex * sizeof(buf_vertex_t));
734 memcpy(&buf_fcolor[currentvertex], &buf_transfcolor[0], currenttransvertex * sizeof(buf_fcolor_t));
736 memcpy(&buf_fcolor[currentvertex], &buf_transbcolor[0], currenttransvertex * sizeof(buf_bcolor_t));
737 for (i = 0;i < backendunits;i++)
738 memcpy(&buf_texcoord[i][currentvertex], &buf_transtexcoord[i][0], currenttransvertex * sizeof(buf_texcoord_t));
740 for (j = TRANSDEPTHRES - 1;j >= 0;j--)
742 if ((tri = buf_transtri_list[j]))
746 mesh = &buf_mesh[currentmesh++];
747 *mesh = *tri->mesh; // copy mesh properties
748 buf_tri[currenttriangle].index[0] = tri->index[0] + currentvertex;
749 buf_tri[currenttriangle].index[1] = tri->index[1] + currentvertex;
750 buf_tri[currenttriangle].index[2] = tri->index[2] + currentvertex;
751 mesh->firstvert = min(buf_tri[currenttriangle].index[0], min(buf_tri[currenttriangle].index[1], buf_tri[currenttriangle].index[2]));
752 mesh->lastvert = max(buf_tri[currenttriangle].index[0], max(buf_tri[currenttriangle].index[1], buf_tri[currenttriangle].index[2]));
753 mesh->firsttriangle = currenttriangle++;
759 currentvertex += currenttransvertex;
760 currenttransmesh = 0;
761 currenttranstriangle = 0;
762 currenttransvertex = 0;
765 void R_Mesh_Draw(const rmeshinfo_t *m)
767 // these are static because gcc runs out of virtual registers otherwise
768 static int i, j, *index, overbright;
769 static float c, *in, scaler, cr, cg, cb, ca;
770 static buf_mesh_t *mesh;
771 static buf_vertex_t *vert;
772 static buf_fcolor_t *fcolor;
773 static buf_bcolor_t *bcolor;
774 static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
775 static buf_transtri_t *tri;
776 static byte br, bg, bb, ba;
783 // ignore meaningless alpha meshs
784 if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
788 for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
791 if (i == m->numverts)
794 else if (m->ca < 0.01f)
799 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
802 if (m->blendfunc2 == GL_SRC_COLOR)
804 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
811 overbright = gl_combine.integer;
821 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
825 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
831 vert = &buf_transvertex[currenttransvertex];
832 fcolor = &buf_transfcolor[currenttransvertex];
833 bcolor = &buf_transbcolor[currenttransvertex];
834 for (i = 0;i < backendunits;i++)
835 texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
837 // transmesh is only for storage of transparent meshs until they
838 // are inserted into the main mesh array
839 mesh = &buf_transmesh[currenttransmesh++];
840 mesh->blendfunc1 = m->blendfunc1;
841 mesh->blendfunc2 = m->blendfunc2;
842 mesh->depthmask = false;
843 mesh->depthtest = !m->depthdisable;
845 for (i = 0;i < backendunits;i++)
847 if ((mesh->textures[i] = m->tex[i]))
849 mesh->texturergbscale[i] = m->texrgbscale[i];
850 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
851 mesh->texturergbscale[i] = 1;
853 if (overbright && j >= 0)
854 mesh->texturergbscale[j] = 4;
856 // transparent meshs are broken up into individual triangles which can
857 // be sorted by depth
859 for (i = 0;i < m->numtriangles;i++)
861 tri = &buf_transtri[currenttranstriangle++];
863 tri->index[0] = *index++ + currenttransvertex;
864 tri->index[1] = *index++ + currenttransvertex;
865 tri->index[2] = *index++ + currenttransvertex;
868 currenttransvertex += m->numverts;
872 if (m->numtriangles > max_meshs || m->numverts > max_verts)
874 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
878 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
881 vert = &buf_vertex[currentvertex];
882 fcolor = &buf_fcolor[currentvertex];
883 bcolor = &buf_bcolor[currentvertex];
884 for (i = 0;i < backendunits;i++)
885 texcoord[i] = &buf_texcoord[i][currentvertex];
887 mesh = &buf_mesh[currentmesh++];
888 mesh->blendfunc1 = m->blendfunc1;
889 mesh->blendfunc2 = m->blendfunc2;
890 mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
891 mesh->depthtest = !m->depthdisable;
892 mesh->firsttriangle = currenttriangle;
893 mesh->triangles = m->numtriangles;
895 for (i = 0;i < backendunits;i++)
897 if ((mesh->textures[i] = m->tex[i]))
899 mesh->texturergbscale[i] = m->texrgbscale[i];
900 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
901 mesh->texturergbscale[i] = 1;
903 if (overbright && j >= 0)
904 mesh->texturergbscale[j] = 4;
906 // opaque meshs are rendered directly
907 index = (int *)&buf_tri[currenttriangle];
908 for (i = 0;i < m->numtriangles * 3;i++)
909 index[i] = m->index[i] + currentvertex;
910 mesh->firstvert = currentvertex;
911 currenttriangle += m->numtriangles;
912 currentvertex += m->numverts;
913 mesh->lastvert = currentvertex - 1;
916 // vertex array code is shared for transparent and opaque meshs
918 c_meshtris += m->numtriangles;
920 if (m->vertexstep != sizeof(buf_vertex_t))
922 for (i = 0, in = m->vertex;i < m->numverts;i++, (int)in += m->vertexstep)
924 vert[i].v[0] = in[0];
925 vert[i].v[1] = in[1];
926 vert[i].v[2] = in[2];
927 // push out farclip based on vertices encountered
928 c = DotProduct(vert[i].v, vpn);
935 memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
936 // push out farclip based on vertices encountered
937 for (i = 0;i < m->numverts;i++)
939 c = DotProduct(vert[i].v, vpn);
949 for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep)
951 fcolor[i].c[0] = in[0] * scaler;
952 fcolor[i].c[1] = in[1] * scaler;
953 fcolor[i].c[2] = in[2] * scaler;
954 fcolor[i].c[3] = in[3];
963 for (i = 0;i < m->numverts;i++)
976 for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep)
978 // shift float to have 8bit fraction at base of number,
979 // then read as integer and kill float bits...
980 c = in[0] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[0] = (byte) j;
981 c = in[1] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[1] = (byte) j;
982 c = in[2] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[2] = (byte) j;
983 c = in[3] + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bcolor[i].c[3] = (byte) j;
988 c = in[0] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;br = (byte) j;
989 c = in[1] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bg = (byte) j;
990 c = in[2] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bb = (byte) j;
991 c = in[3] + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;ba = (byte) j;
992 for (i = 0;i < m->numverts;i++)
1002 for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1004 if (j >= backendunits)
1005 Sys_Error("R_Mesh_Draw: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1006 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1008 for (i = 0, in = m->texcoords[j];i < m->numverts;i++, (int)in += m->texcoordstep[j])
1010 texcoord[j][i].t[0] = in[0];
1011 texcoord[j][i].t[1] = in[1];
1015 memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1018 for (;j < backendunits;j++)
1019 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1023 void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts)
1025 m->index = polyindexarray;
1026 m->numverts = numverts;
1027 m->numtriangles = numverts - 2;
1028 if (m->numtriangles < 1)
1030 Con_Printf("R_Mesh_DrawPolygon: invalid vertex count\n");
1033 if (m->numtriangles >= 256)
1035 Con_Printf("R_Mesh_DrawPolygon: only up to 256 triangles (258 verts) supported\n");
1041 // LordHavoc: this thing is evil, but necessary because decals account for so much overhead
1042 void R_Mesh_DrawDecal(const rmeshinfo_t *m)
1044 // these are static because gcc runs out of virtual registers otherwise
1045 static int i, j, *index, overbright;
1046 static float c, *in, scaler, cr, cg, cb, ca;
1047 static buf_mesh_t *mesh;
1048 static buf_vertex_t *vert;
1049 static buf_fcolor_t *fcolor;
1050 static buf_bcolor_t *bcolor;
1051 static buf_texcoord_t *texcoord;
1052 static buf_transtri_t *tri;
1053 static byte br, bg, bb, ba;
1056 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1061 overbright = gl_combine.integer;
1070 if (currenttransmesh >= max_meshs || (currenttranstriangle + 2) > max_meshs || (currenttransvertex + 4) > max_verts)
1074 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1080 vert = &buf_transvertex[currenttransvertex];
1081 fcolor = &buf_transfcolor[currenttransvertex];
1082 bcolor = &buf_transbcolor[currenttransvertex];
1083 texcoord = &buf_transtexcoord[0][currenttransvertex];
1085 // transmesh is only for storage of transparent meshs until they
1086 // are inserted into the main mesh array
1087 mesh = &buf_transmesh[currenttransmesh++];
1088 mesh->blendfunc1 = m->blendfunc1;
1089 mesh->blendfunc2 = m->blendfunc2;
1090 mesh->depthmask = false;
1091 mesh->depthtest = true;
1092 mesh->textures[0] = m->tex[0];
1093 mesh->texturergbscale[0] = overbright ? 4 : 1;
1094 for (i = 1;i < backendunits;i++)
1096 mesh->textures[i] = 0;
1097 mesh->texturergbscale[i] = 1;
1100 // transparent meshs are broken up into individual triangles which can
1101 // be sorted by depth
1103 tri = &buf_transtri[currenttranstriangle++];
1105 tri->index[0] = 0 + currenttransvertex;
1106 tri->index[1] = 1 + currenttransvertex;
1107 tri->index[2] = 2 + currenttransvertex;
1108 tri = &buf_transtri[currenttranstriangle++];
1110 tri->index[0] = 0 + currenttransvertex;
1111 tri->index[1] = 2 + currenttransvertex;
1112 tri->index[2] = 3 + currenttransvertex;
1114 currenttransvertex += 4;
1118 if (2 > max_meshs || 4 > max_verts)
1120 Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
1124 if (currentmesh >= max_meshs || (currenttriangle + 2) > max_batch || (currentvertex + 4) > max_verts)
1127 vert = &buf_vertex[currentvertex];
1128 fcolor = &buf_fcolor[currentvertex];
1129 bcolor = &buf_bcolor[currentvertex];
1130 texcoord = &buf_texcoord[0][currentvertex];
1132 mesh = &buf_mesh[currentmesh++];
1133 mesh->blendfunc1 = m->blendfunc1;
1134 mesh->blendfunc2 = m->blendfunc2;
1135 mesh->depthmask = false;
1136 mesh->depthtest = !m->depthdisable;
1137 mesh->firsttriangle = currenttriangle;
1138 mesh->triangles = 2;
1139 mesh->textures[0] = m->tex[0];
1140 mesh->texturergbscale[0] = overbright ? 4 : 1;
1141 for (i = 1;i < backendunits;i++)
1143 mesh->textures[i] = 0;
1144 mesh->texturergbscale[i] = 1;
1147 // opaque meshs are rendered directly
1148 index = (int *)&buf_tri[currenttriangle];
1149 index[0] = 0 + currentvertex;
1150 index[1] = 1 + currentvertex;
1151 index[2] = 2 + currentvertex;
1152 index[3] = 0 + currentvertex;
1153 index[4] = 2 + currentvertex;
1154 index[5] = 3 + currentvertex;
1155 mesh->firstvert = currentvertex;
1156 currenttriangle += 2;
1158 mesh->lastvert = currentvertex - 1;
1161 // vertex array code is shared for transparent and opaque meshs
1165 // buf_vertex_t must match the size of the decal vertex array (or vice versa)
1166 memcpy(vert, m->vertex, 4 * sizeof(buf_vertex_t));
1167 // push out farclip based on vertices encountered
1168 c = DotProduct(vert[0].v, vpn);if (meshfarclip < c) meshfarclip = c;
1169 c = DotProduct(vert[1].v, vpn);if (meshfarclip < c) meshfarclip = c;
1170 c = DotProduct(vert[2].v, vpn);if (meshfarclip < c) meshfarclip = c;
1171 c = DotProduct(vert[3].v, vpn);if (meshfarclip < c) meshfarclip = c;
1175 cr = m->cr * scaler;
1176 cg = m->cg * scaler;
1177 cb = m->cb * scaler;
1179 fcolor[0].c[0] = cr;
1180 fcolor[0].c[1] = cg;
1181 fcolor[0].c[2] = cb;
1182 fcolor[0].c[3] = ca;
1183 fcolor[1].c[0] = cr;
1184 fcolor[1].c[1] = cg;
1185 fcolor[1].c[2] = cb;
1186 fcolor[1].c[3] = ca;
1187 fcolor[2].c[0] = cr;
1188 fcolor[2].c[1] = cg;
1189 fcolor[2].c[2] = cb;
1190 fcolor[2].c[3] = ca;
1191 fcolor[3].c[0] = cr;
1192 fcolor[3].c[1] = cg;
1193 fcolor[3].c[2] = cb;
1194 fcolor[3].c[3] = ca;
1198 c = in[0] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;br = (byte) j;
1199 c = in[1] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bg = (byte) j;
1200 c = in[2] * scaler + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;bb = (byte) j;
1201 c = in[3] + 32768.0f;j = (*((long *)&c) & 0x7FFFFF);if (j > 255) j = 255;ba = (byte) j;
1202 bcolor[0].c[0] = br;
1203 bcolor[0].c[1] = bg;
1204 bcolor[0].c[2] = bb;
1205 bcolor[0].c[3] = ba;
1206 bcolor[1].c[0] = br;
1207 bcolor[1].c[1] = bg;
1208 bcolor[1].c[2] = bb;
1209 bcolor[1].c[3] = ba;
1210 bcolor[2].c[0] = br;
1211 bcolor[2].c[1] = bg;
1212 bcolor[2].c[2] = bb;
1213 bcolor[2].c[3] = ba;
1214 bcolor[3].c[0] = br;
1215 bcolor[3].c[1] = bg;
1216 bcolor[3].c[2] = bb;
1217 bcolor[3].c[3] = ba;
1220 // buf_texcoord_t must be the same size as the decal texcoord array (or vice versa)
1221 memcpy(&texcoord[0].t[0], m->texcoords[0], 4 * sizeof(buf_texcoord_t));