#include "cl_collision.h"
cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
-cvar_t gl_mesh_testarrayelement = {0, "gl_mesh_testarrayelement", "0", "use glBegin(GL_TRIANGLES);glArrayElement();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0", "use glBegin(GL_TRIANGLES);glTexCoord2f();glVertex3f();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
-cvar_t gl_mesh_prefer_short_elements = {0, "gl_mesh_prefer_short_elements", "1", "use GL_UNSIGNED_SHORT element arrays instead of GL_UNSIGNED_INT"};
+cvar_t gl_mesh_prefer_short_elements = {CVAR_SAVE, "gl_mesh_prefer_short_elements", "1", "use GL_UNSIGNED_SHORT element arrays instead of GL_UNSIGNED_INT"};
+cvar_t gl_mesh_separatearrays = {0, "gl_mesh_separatearrays", "1", "use several separate vertex arrays rather than one combined stream"};
cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
cvar_t gl_vbo = {CVAR_SAVE, "gl_vbo", "3", "make use of GL_ARB_vertex_buffer_object extension to store static geometry in video memory for faster rendering, 0 disables VBO allocation or use, 1 enables VBOs for vertex and triangle data, 2 only for vertex data, 3 for vertex data and triangle data of simple meshes (ones with only one surface)"};
+cvar_t gl_vbo_dynamicvertex = {CVAR_SAVE, "gl_vbo_dynamicvertex", "0", "make use of GL_ARB_vertex_buffer_object extension when rendering dynamic (animated/procedural) geometry such as text and particles"};
+cvar_t gl_vbo_dynamicindex = {CVAR_SAVE, "gl_vbo_dynamicindex", "0", "make use of GL_ARB_vertex_buffer_object extension when rendering dynamic (animated/procedural) geometry such as text and particles"};
cvar_t gl_fbo = {CVAR_SAVE, "gl_fbo", "1", "make use of GL_ARB_framebuffer_object extension to enable shadowmaps and other features using pixel formats different from the framebuffer"};
cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
void SCR_ScreenShot_f (void);
-typedef struct gl_bufferobjectinfo_s
-{
- int target;
- int object;
- size_t size;
- char name[MAX_QPATH];
-}
-gl_bufferobjectinfo_t;
-
typedef struct gltextureunit_s
{
- const void *pointer_texcoord;
+ int pointer_texcoord_components;
+ int pointer_texcoord_gltype;
+ size_t pointer_texcoord_stride;
+ const void *pointer_texcoord_pointer;
+ const r_meshbuffer_t *pointer_texcoord_vertexbuffer;
size_t pointer_texcoord_offset;
- int pointer_texcoord_buffer;
+
int t2d, t3d, tcubemap, trectangle;
int arrayenabled;
- unsigned int arraycomponents;
int rgbscale, alphascale;
int combine;
int combinergb, combinealpha;
int vertexbufferobject;
int elementbufferobject;
qboolean pointer_color_enabled;
- const void *pointer_vertex;
- const void *pointer_color;
+
+ int pointer_vertex_components;
+ int pointer_vertex_gltype;
+ size_t pointer_vertex_stride;
+ const void *pointer_vertex_pointer;
+ const r_meshbuffer_t *pointer_vertex_vertexbuffer;
size_t pointer_vertex_offset;
+
+ int pointer_color_components;
+ int pointer_color_gltype;
+ size_t pointer_color_stride;
+ const void *pointer_color_pointer;
+ const r_meshbuffer_t *pointer_color_vertexbuffer;
size_t pointer_color_offset;
- int pointer_vertex_buffer;
- int pointer_color_buffer;
- memexpandablearray_t bufferobjectinfoarray;
+ void *preparevertices_tempdata;
+ size_t preparevertices_tempdatamaxsize;
+ r_meshbuffer_t *preparevertices_dynamicvertexbuffer;
+ r_vertexposition_t *preparevertices_vertexposition;
+ r_vertexgeneric_t *preparevertices_vertexgeneric;
+ r_vertexmesh_t *preparevertices_vertexmesh;
+ int preparevertices_numvertices;
+
+ r_meshbuffer_t *draw_dynamicindexbuffer;
+
+ qboolean usevbo_staticvertex;
+ qboolean usevbo_staticindex;
+ qboolean usevbo_dynamicvertex;
+ qboolean usevbo_dynamicindex;
+
+ memexpandablearray_t meshbufferarray;
qboolean active;
}
{
memset(&gl_state, 0, sizeof(gl_state));
- Mem_ExpandableArray_NewArray(&gl_state.bufferobjectinfoarray, r_main_mempool, sizeof(gl_bufferobjectinfo_t), 128);
+ gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
+ gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo;
+ gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
+ gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer) || vid.forcevbo;
+ Mem_ExpandableArray_NewArray(&gl_state.meshbufferarray, r_main_mempool, sizeof(r_meshbuffer_t), 128);
Con_DPrintf("OpenGL backend started.\n");
{
Con_DPrint("OpenGL Backend shutting down\n");
- Mem_ExpandableArray_FreeArray(&gl_state.bufferobjectinfoarray);
+ if (gl_state.preparevertices_tempdata)
+ Mem_Free(gl_state.preparevertices_tempdata);
+ if (gl_state.preparevertices_dynamicvertexbuffer)
+ R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer);
+
+ Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
memset(&gl_state, 0, sizeof(gl_state));
}
Cvar_RegisterVariable(&v_flipped);
Cvar_RegisterVariable(&gl_dither);
Cvar_RegisterVariable(&gl_vbo);
+ Cvar_RegisterVariable(&gl_vbo_dynamicvertex);
+ Cvar_RegisterVariable(&gl_vbo_dynamicindex);
Cvar_RegisterVariable(&gl_paranoid);
Cvar_RegisterVariable(&gl_printcheckerror);
Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
- Cvar_RegisterVariable(&gl_mesh_testarrayelement);
Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
+ Cvar_RegisterVariable(&gl_mesh_separatearrays);
Cmd_AddCommand("gl_vbostats", GL_VBOStats_f, "prints a list of all buffer objects (vertex data and triangle elements) and total video memory used by them");
{
BACKENDACTIVECHECK
CHECKGLERROR
+ gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
+ gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo;
+ gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
+ gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer) || vid.forcevbo;
if (gl_printcheckerror.integer && !gl_paranoid.integer)
{
Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
// renders triangles using vertices from the active arrays
int paranoidblah = 0;
-void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int bufferobject3i, int bufferobject3s)
+void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, size_t element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, size_t element3s_bufferoffset)
{
unsigned int numelements = numtriangles * 3;
+ int bufferobject3i;
+ size_t bufferoffset3i;
+ int bufferobject3s;
+ size_t bufferoffset3s;
if (numvertices < 3 || numtriangles < 1)
{
if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
- Con_DPrintf("R_Mesh_Draw(%d, %d, %d, %d, %8p, %8p, %i, %i);\n", firstvertex, numvertices, firsttriangle, numtriangles, (void *)element3i, (void *)element3s, bufferobject3i, bufferobject3s);
+ Con_DPrintf("R_Mesh_Draw(%d, %d, %d, %d, %8p, %8p, %8x, %8p, %8p, %8x);\n", firstvertex, numvertices, firsttriangle, numtriangles, (void *)element3i, (void *)element3i_indexbuffer, (int)element3i_bufferoffset, (void *)element3s, (void *)element3s_indexbuffer, (int)element3s_bufferoffset);
+ return;
+ }
+ if (gl_state.pointer_vertex_pointer == NULL)
+ {
+ Con_DPrintf("R_Mesh_Draw with no vertex pointer!\n");
return;
}
if (!gl_mesh_prefer_short_elements.integer)
{
if (element3i)
element3s = NULL;
- if (bufferobject3i)
- bufferobject3s = 0;
+ if (element3i_indexbuffer)
+ element3i_indexbuffer = NULL;
}
+ // adjust the pointers for firsttriangle
if (element3i)
element3i += firsttriangle * 3;
+ if (element3i_indexbuffer)
+ element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
if (element3s)
element3s += firsttriangle * 3;
- switch (gl_vbo.integer)
+ if (element3s_indexbuffer)
+ element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
+ // check if the user specified to ignore static index buffers
+ if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
{
- default:
- case 0:
- case 2:
- bufferobject3i = bufferobject3s = 0;
- break;
- case 1:
- break;
- case 3:
- if (firsttriangle)
- bufferobject3i = bufferobject3s = 0;
- break;
+ element3i_indexbuffer = NULL;
+ element3s_indexbuffer = NULL;
}
+ // upload a dynamic index buffer if needed
+ if (element3s)
+ {
+ if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
+ {
+ if (gl_state.draw_dynamicindexbuffer)
+ R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
+ else
+ gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true);
+ element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
+ element3s_bufferoffset = 0;
+ }
+ }
+ else if (element3i)
+ {
+ if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
+ {
+ if (gl_state.draw_dynamicindexbuffer)
+ R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
+ else
+ gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true);
+ element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
+ element3i_bufferoffset = 0;
+ }
+ }
+ bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
+ bufferoffset3i = element3i_bufferoffset;
+ bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
+ bufferoffset3s = element3s_bufferoffset;
CHECKGLERROR
r_refdef.stats.meshes++;
r_refdef.stats.meshes_elements += numelements;
if (gl_paranoid.integer)
{
- unsigned int i, j, size;
+ unsigned int i;
+ // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
+#if 0
+ unsigned int j, size;
const int *p;
// note: there's no validation done here on buffer objects because it
// is somewhat difficult to get at the data, and gl_paranoid can be
if (!qglIsEnabled(GL_VERTEX_ARRAY))
Con_Print("R_Mesh_Draw: vertex array not enabled\n");
CHECKGLERROR
- if (gl_state.pointer_vertex)
+ if (gl_state.pointer_vertex_pointer)
for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
paranoidblah += *p;
if (gl_state.pointer_color_enabled)
paranoidblah += *p;
}
}
+#endif
if (element3i)
{
for (i = 0;i < (unsigned int) numtriangles * 3;i++)
qglBegin(GL_TRIANGLES);
for (i = 0;i < (unsigned int) numtriangles * 3;i++)
{
- element = element3i ? element3i[i] : element3s[i];
+ if (element3i)
+ element = element3i[i];
+ else if (element3s)
+ element = element3s[i];
+ else
+ element = firstvertex + i;
for (j = 0;j < vid.texarrayunits;j++)
{
- if (gl_state.units[j].pointer_texcoord && gl_state.units[j].arrayenabled)
+ if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
{
- if (vid.texarrayunits > 1)
+ if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
{
- if (gl_state.units[j].arraycomponents == 4)
+ p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
+ if (vid.texarrayunits > 1)
{
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 4;
- qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
- }
- else if (gl_state.units[j].arraycomponents == 3)
- {
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 3;
- qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
- }
- else if (gl_state.units[j].arraycomponents == 2)
- {
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 2;
- qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
+ if (gl_state.units[j].pointer_texcoord_components == 4)
+ qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
+ else if (gl_state.units[j].pointer_texcoord_components == 3)
+ qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
+ else if (gl_state.units[j].pointer_texcoord_components == 2)
+ qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
+ else
+ qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
}
else
{
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 1;
- qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
+ if (gl_state.units[j].pointer_texcoord_components == 4)
+ qglTexCoord4f(p[0], p[1], p[2], p[3]);
+ else if (gl_state.units[j].pointer_texcoord_components == 3)
+ qglTexCoord3f(p[0], p[1], p[2]);
+ else if (gl_state.units[j].pointer_texcoord_components == 2)
+ qglTexCoord2f(p[0], p[1]);
+ else
+ qglTexCoord1f(p[0]);
}
}
- else
+ else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
{
- if (gl_state.units[j].arraycomponents == 4)
+ const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
+ if (vid.texarrayunits > 1)
{
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 4;
- qglTexCoord4f(p[0], p[1], p[2], p[3]);
+ if (gl_state.units[j].pointer_texcoord_components == 4)
+ qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
+ else if (gl_state.units[j].pointer_texcoord_components == 3)
+ qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
+ else if (gl_state.units[j].pointer_texcoord_components == 2)
+ qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
+ else if (gl_state.units[j].pointer_texcoord_components == 1)
+ qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
}
- else if (gl_state.units[j].arraycomponents == 3)
+ else
{
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 3;
- qglTexCoord3f(p[0], p[1], p[2]);
+ if (gl_state.units[j].pointer_texcoord_components == 4)
+ qglTexCoord4f(s[0], s[1], s[2], s[3]);
+ else if (gl_state.units[j].pointer_texcoord_components == 3)
+ qglTexCoord3f(s[0], s[1], s[2]);
+ else if (gl_state.units[j].pointer_texcoord_components == 2)
+ qglTexCoord2f(s[0], s[1]);
+ else if (gl_state.units[j].pointer_texcoord_components == 1)
+ qglTexCoord1f(s[0]);
}
- else if (gl_state.units[j].arraycomponents == 2)
+ }
+ else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
+ {
+ const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
+ if (vid.texarrayunits > 1)
{
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 2;
- qglTexCoord2f(p[0], p[1]);
+ if (gl_state.units[j].pointer_texcoord_components == 4)
+ qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
+ else if (gl_state.units[j].pointer_texcoord_components == 3)
+ qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
+ else if (gl_state.units[j].pointer_texcoord_components == 2)
+ qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
+ else if (gl_state.units[j].pointer_texcoord_components == 1)
+ qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
}
else
{
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 1;
- qglTexCoord1f(p[0]);
+ if (gl_state.units[j].pointer_texcoord_components == 4)
+ qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
+ else if (gl_state.units[j].pointer_texcoord_components == 3)
+ qglTexCoord3f(sb[0], sb[1], sb[2]);
+ else if (gl_state.units[j].pointer_texcoord_components == 2)
+ qglTexCoord2f(sb[0], sb[1]);
+ else if (gl_state.units[j].pointer_texcoord_components == 1)
+ qglTexCoord1f(sb[0]);
}
}
}
}
- if (gl_state.pointer_color && gl_state.pointer_color_enabled)
+ if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
{
- p = ((const GLfloat *)(gl_state.pointer_color)) + element * 4;
- qglColor4f(p[0], p[1], p[2], p[3]);
+ if (gl_state.pointer_color_gltype == GL_FLOAT)
+ {
+ p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
+ qglColor4f(p[0], p[1], p[2], p[3]);
+ }
+ else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
+ {
+ const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
+ qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
+ }
+ }
+ if (gl_state.pointer_vertex_gltype == GL_FLOAT)
+ {
+ p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
+ if (gl_state.pointer_vertex_components == 4)
+ qglVertex4f(p[0], p[1], p[2], p[3]);
+ else if (gl_state.pointer_vertex_components == 3)
+ qglVertex3f(p[0], p[1], p[2]);
+ else
+ qglVertex2f(p[0], p[1]);
}
- p = ((const GLfloat *)(gl_state.pointer_vertex)) + element * 3;
- qglVertex3f(p[0], p[1], p[2]);
- }
- qglEnd();
- CHECKGLERROR
- }
- else if (gl_mesh_testarrayelement.integer)
- {
- int i;
- qglBegin(GL_TRIANGLES);
- if (element3i)
- {
- for (i = 0;i < numtriangles * 3;i++)
- qglArrayElement(element3i[i]);
- }
- else if (element3s)
- {
- for (i = 0;i < numtriangles * 3;i++)
- qglArrayElement(element3s[i]);
}
qglEnd();
CHECKGLERROR
GL_BindEBO(bufferobject3s);
if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
{
- qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
+ qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
CHECKGLERROR
}
else
GL_BindEBO(bufferobject3i);
if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
{
- qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
+ qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
CHECKGLERROR
}
else
CHECKGLERROR
}
}
+ else
+ {
+ qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
+ CHECKGLERROR
+ }
}
}
{
}
-int R_Mesh_CreateStaticBufferObject(unsigned int target, void *data, size_t size, const char *name)
+r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic)
{
- gl_bufferobjectinfo_t *info;
- GLuint bufferobject;
-
- if (!gl_vbo.integer)
- return 0;
-
- qglGenBuffersARB(1, &bufferobject);
- switch(target)
+ int bufferobject = 0;
+ void *devicebuffer = NULL;
+ r_meshbuffer_t *buffer;
+ if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
+ return NULL;
+ if (isindexbuffer)
{
- case GL_ELEMENT_ARRAY_BUFFER_ARB: GL_BindEBO(bufferobject);break;
- case GL_ARRAY_BUFFER_ARB: GL_BindVBO(bufferobject);break;
- default: Sys_Error("R_Mesh_CreateStaticBufferObject: unknown target type %i\n", target);return 0;
+ r_refdef.stats.indexbufferuploadcount++;
+ r_refdef.stats.indexbufferuploadsize += size;
}
- qglBufferDataARB(target, size, data, GL_STATIC_DRAW_ARB);
-
- info = (gl_bufferobjectinfo_t *) Mem_ExpandableArray_AllocRecord(&gl_state.bufferobjectinfoarray);
- memset(info, 0, sizeof(*info));
- info->target = target;
- info->object = bufferobject;
- info->size = size;
- strlcpy(info->name, name, sizeof(info->name));
-
- return (int)bufferobject;
+ else
+ {
+ r_refdef.stats.vertexbufferuploadcount++;
+ r_refdef.stats.vertexbufferuploadsize += size;
+ }
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ qglGenBuffersARB(1, (GLuint *)&bufferobject);
+ if (isindexbuffer)
+ GL_BindEBO(bufferobject);
+ else
+ GL_BindVBO(bufferobject);
+ qglBufferDataARB(isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
+ break;
+ }
+ buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
+ memset(buffer, 0, sizeof(*buffer));
+ buffer->bufferobject = bufferobject;
+ buffer->devicebuffer = devicebuffer;
+ buffer->size = size;
+ buffer->isindexbuffer = isindexbuffer;
+ buffer->isdynamic = isdynamic;
+ strlcpy(buffer->name, name, sizeof(buffer->name));
+ return buffer;
}
-void R_Mesh_DestroyBufferObject(int bufferobject)
+void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
{
- int i, endindex;
- gl_bufferobjectinfo_t *info;
-
- qglDeleteBuffersARB(1, (GLuint *)&bufferobject);
+ if (!buffer || (!buffer->bufferobject && !buffer->devicebuffer))
+ return;
+ if (buffer->isindexbuffer)
+ {
+ r_refdef.stats.indexbufferuploadcount++;
+ r_refdef.stats.indexbufferuploadsize += size;
+ }
+ else
+ {
+ r_refdef.stats.vertexbufferuploadcount++;
+ r_refdef.stats.vertexbufferuploadsize += size;
+ }
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ if (buffer->isindexbuffer)
+ GL_BindEBO(buffer->bufferobject);
+ else
+ GL_BindVBO(buffer->bufferobject);
+ qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
+ break;
+ }
+}
- endindex = Mem_ExpandableArray_IndexRange(&gl_state.bufferobjectinfoarray);
- for (i = 0;i < endindex;i++)
+void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
+{
+ if (!buffer)
+ return;
+ switch(vid.renderpath)
{
- info = (gl_bufferobjectinfo_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.bufferobjectinfoarray, i);
- if (!info)
- continue;
- if (info->object == bufferobject)
- {
- Mem_ExpandableArray_FreeRecord(&gl_state.bufferobjectinfoarray, (void *)info);
- break;
- }
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
+ break;
}
+ Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
}
void GL_Mesh_ListVBOs(qboolean printeach)
int i, endindex;
size_t ebocount = 0, ebomemory = 0;
size_t vbocount = 0, vbomemory = 0;
- gl_bufferobjectinfo_t *info;
- endindex = Mem_ExpandableArray_IndexRange(&gl_state.bufferobjectinfoarray);
+ r_meshbuffer_t *buffer;
+ endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
for (i = 0;i < endindex;i++)
{
- info = (gl_bufferobjectinfo_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.bufferobjectinfoarray, i);
- if (!info)
+ buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
+ if (!buffer)
continue;
- switch(info->target)
- {
- case GL_ELEMENT_ARRAY_BUFFER_ARB: ebocount++;ebomemory += info->size;if (printeach) Con_Printf("EBO #%i %s = %i bytes\n", info->object, info->name, (int)info->size);break;
- case GL_ARRAY_BUFFER_ARB: vbocount++;vbomemory += info->size;if (printeach) Con_Printf("VBO #%i %s = %i bytes\n", info->object, info->name, (int)info->size);break;
- default: Con_Printf("gl_vbostats: unknown target type %i\n", info->target);break;
- }
+ if (buffer->isindexbuffer) {ebocount++;ebomemory += buffer->size;if (printeach) Con_Printf("indexbuffer #%i %s = %i bytes%s\n", i, buffer->name, (int)buffer->size, buffer->isdynamic ? " (dynamic)" : " (static)");}
+ else {vbocount++;vbomemory += buffer->size;if (printeach) Con_Printf("vertexbuffer #%i %s = %i bytes%s\n", i, buffer->name, (int)buffer->size, buffer->isdynamic ? " (dynamic)" : " (static)");}
}
- Con_Printf("vertex buffers: %i element buffers totalling %i bytes (%.3f MB), %i vertex buffers totalling %i bytes (%.3f MB), combined %i bytes (%.3fMB)\n", (int)ebocount, (int)ebomemory, ebomemory / 1048576.0, (int)vbocount, (int)vbomemory, vbomemory / 1048576.0, (int)(ebomemory + vbomemory), (ebomemory + vbomemory) / 1048576.0);
+ Con_Printf("vertex buffers: %i indexbuffers totalling %i bytes (%.3f MB), %i vertexbuffers totalling %i bytes (%.3f MB), combined %i bytes (%.3fMB)\n", (int)ebocount, (int)ebomemory, ebomemory / 1048576.0, (int)vbocount, (int)vbomemory, vbomemory / 1048576.0, (int)(ebomemory + vbomemory), (ebomemory + vbomemory) / 1048576.0);
}
-void R_Mesh_VertexPointer(const float *vertex3f, int bufferobject, size_t bufferoffset)
+
+
+void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
{
- if (!gl_vbo.integer || gl_mesh_testarrayelement.integer)
- bufferobject = 0;
- if (gl_state.pointer_vertex != vertex3f || gl_state.pointer_vertex_buffer != bufferobject || gl_state.pointer_vertex_offset != bufferoffset)
+ int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
+ if (gl_state.pointer_vertex_components != components || gl_state.pointer_vertex_gltype != gltype || gl_state.pointer_vertex_stride != stride || gl_state.pointer_vertex_pointer != pointer || gl_state.pointer_vertex_vertexbuffer != vertexbuffer || gl_state.pointer_vertex_offset != bufferoffset)
{
- gl_state.pointer_vertex = vertex3f;
- gl_state.pointer_vertex_buffer = bufferobject;
+ gl_state.pointer_vertex_components = components;
+ gl_state.pointer_vertex_gltype = gltype;
+ gl_state.pointer_vertex_stride = stride;
+ gl_state.pointer_vertex_pointer = pointer;
+ gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
gl_state.pointer_vertex_offset = bufferoffset;
CHECKGLERROR
GL_BindVBO(bufferobject);
- qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), bufferobject ? (void *)bufferoffset : vertex3f);CHECKGLERROR
+ qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
}
}
-void R_Mesh_ColorPointer(const float *color4f, int bufferobject, size_t bufferoffset)
+void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
{
- // note: this can not rely on bufferobject to decide whether a color array
- // is supplied, because surfmesh_t shares one vbo for all arrays, which
- // means that a valid vbo may be supplied even if there is no color array.
- if (color4f)
+ // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
+ // the pointer only.
+ if (pointer)
{
- if (!gl_vbo.integer || gl_mesh_testarrayelement.integer)
- bufferobject = 0;
+ int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
// caller wants color array enabled
if (!gl_state.pointer_color_enabled)
{
CHECKGLERROR
qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
}
- if (gl_state.pointer_color != color4f || gl_state.pointer_color_buffer != bufferobject || gl_state.pointer_color_offset != bufferoffset)
+ if (gl_state.pointer_color_components != components || gl_state.pointer_color_gltype != gltype || gl_state.pointer_color_stride != stride || gl_state.pointer_color_pointer != pointer || gl_state.pointer_color_vertexbuffer != vertexbuffer || gl_state.pointer_color_offset != bufferoffset)
{
- gl_state.pointer_color = color4f;
- gl_state.pointer_color_buffer = bufferobject;
+ gl_state.pointer_color_components = components;
+ gl_state.pointer_color_gltype = gltype;
+ gl_state.pointer_color_stride = stride;
+ gl_state.pointer_color_pointer = pointer;
+ gl_state.pointer_color_vertexbuffer = vertexbuffer;
gl_state.pointer_color_offset = bufferoffset;
CHECKGLERROR
GL_BindVBO(bufferobject);
- qglColorPointer(4, GL_FLOAT, sizeof(float[4]), bufferobject ? (void *)bufferoffset : color4f);CHECKGLERROR
+ qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
}
}
else
}
}
-void R_Mesh_TexCoordPointer(unsigned int unitnum, unsigned int numcomponents, const float *texcoord, int bufferobject, size_t bufferoffset)
+void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
{
gltextureunit_t *unit = gl_state.units + unitnum;
// update array settings
CHECKGLERROR
// note: there is no need to check bufferobject here because all cases
// that involve a valid bufferobject also supply a texcoord array
- if (texcoord)
+ if (pointer)
{
- if (!gl_vbo.integer || gl_mesh_testarrayelement.integer)
- bufferobject = 0;
+ int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
// texture array unit is enabled, enable the array
if (!unit->arrayenabled)
{
qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
}
// texcoord array
- if (unit->pointer_texcoord != texcoord || unit->pointer_texcoord_buffer != bufferobject || unit->pointer_texcoord_offset != bufferoffset || unit->arraycomponents != numcomponents)
+ if (unit->pointer_texcoord_components != components || unit->pointer_texcoord_gltype != gltype || unit->pointer_texcoord_stride != stride || unit->pointer_texcoord_pointer != pointer || unit->pointer_texcoord_vertexbuffer != vertexbuffer || unit->pointer_texcoord_offset != bufferoffset)
{
- unit->pointer_texcoord = texcoord;
- unit->pointer_texcoord_buffer = bufferobject;
+ unit->pointer_texcoord_components = components;
+ unit->pointer_texcoord_gltype = gltype;
+ unit->pointer_texcoord_stride = stride;
+ unit->pointer_texcoord_pointer = pointer;
+ unit->pointer_texcoord_vertexbuffer = vertexbuffer;
unit->pointer_texcoord_offset = bufferoffset;
- unit->arraycomponents = numcomponents;
GL_ClientActiveTexture(unitnum);
GL_BindVBO(bufferobject);
- qglTexCoordPointer(unit->arraycomponents, GL_FLOAT, sizeof(float) * unit->arraycomponents, bufferobject ? (void *)bufferoffset : texcoord);CHECKGLERROR
+ qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
}
}
else
break;
}
}
+
+
+
+r_vertexposition_t *R_Mesh_PrepareVertices_Position_Lock(int numvertices)
+{
+ size_t size;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ size = sizeof(r_vertexposition_t) * numvertices;
+ if (gl_state.preparevertices_tempdatamaxsize < size)
+ {
+ gl_state.preparevertices_tempdatamaxsize = size;
+ gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
+ }
+ gl_state.preparevertices_vertexposition = (r_vertexposition_t *)gl_state.preparevertices_tempdata;
+ gl_state.preparevertices_numvertices = numvertices;
+ return gl_state.preparevertices_vertexposition;
+ default:
+ Sys_Error("R_Mesh_PrepareVertices_Position_Lock: unrecognized vid.renderpath\n");
+ return NULL;
+ }
+}
+
+qboolean R_Mesh_PrepareVertices_Position_Unlock(void)
+{
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ R_Mesh_PrepareVertices_Position(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexposition, NULL);
+ gl_state.preparevertices_vertexposition = NULL;
+ gl_state.preparevertices_numvertices = 0;
+ return true;
+ default:
+ Sys_Error("R_Mesh_PrepareVertices_Position_Lock: unrecognized vid.renderpath\n");
+ return false;
+ }
+}
+
+void R_Mesh_PrepareVertices_Position_Arrays(int numvertices, const float *vertex3f)
+{
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ if (vid.texunits >= 2)
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ if (vid.texunits >= 3)
+ R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ break;
+ default:
+ Sys_Error("R_Mesh_PrepareVertices_Position_Lock: unrecognized vid.renderpath\n");
+ return;
+ }
+}
+
+void R_Mesh_PrepareVertices_Position(int numvertices, const r_vertexposition_t *vertex, const r_meshbuffer_t *vertexbuffer)
+{
+ // upload temporary vertexbuffer for this rendering
+ if (!gl_state.usevbo_staticvertex)
+ vertexbuffer = NULL;
+ if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
+ {
+ if (gl_state.preparevertices_dynamicvertexbuffer)
+ R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
+ else
+ gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true);
+ vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
+ }
+ if (vertexbuffer)
+ {
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ case RENDERPATH_GL13:
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ case RENDERPATH_GL11:
+ R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ break;
+ }
+ return;
+ }
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ case RENDERPATH_GL13:
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ case RENDERPATH_GL11:
+ R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ break;
+ }
+}
+
+
+
+r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
+{
+ size_t size;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ size = sizeof(r_vertexgeneric_t) * numvertices;
+ if (gl_state.preparevertices_tempdatamaxsize < size)
+ {
+ gl_state.preparevertices_tempdatamaxsize = size;
+ gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
+ }
+ gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
+ gl_state.preparevertices_numvertices = numvertices;
+ return gl_state.preparevertices_vertexgeneric;
+ default:
+ Sys_Error("R_Mesh_PrepareVertices_Generic_Lock: unrecognized vid.renderpath\n");
+ return NULL;
+ }
+}
+
+qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
+{
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
+ gl_state.preparevertices_vertexgeneric = NULL;
+ gl_state.preparevertices_numvertices = 0;
+ return true;
+ default:
+ Sys_Error("R_Mesh_PrepareVertices_Generic_Lock: unrecognized vid.renderpath\n");
+ return false;
+ }
+}
+
+void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
+{
+ int i;
+ r_vertexgeneric_t *vertex;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ if (gl_mesh_separatearrays.integer)
+ {
+ R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ return;
+ }
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ if (gl_mesh_separatearrays.integer)
+ {
+ R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
+ if (vid.texunits >= 2)
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ if (vid.texunits >= 3)
+ R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ return;
+ }
+ break;
+ default:
+ Sys_Error("R_Mesh_PrepareVertices_Position_Lock: unrecognized vid.renderpath\n");
+ return;
+ }
+
+ // no quick path for this case, convert to vertex structs
+ vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
+ if (color4f)
+ {
+ for (i = 0;i < numvertices;i++)
+ Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
+ }
+ else
+ {
+ float tempcolor4f[4];
+ unsigned char tempcolor4ub[4];
+ Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
+ tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
+ tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
+ tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
+ tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
+ for (i = 0;i < numvertices;i++)
+ Vector4Copy(tempcolor4ub, vertex[i].color4ub);
+ }
+ if (texcoord2f)
+ for (i = 0;i < numvertices;i++)
+ Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
+ R_Mesh_PrepareVertices_Generic_Unlock();
+ R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
+}
+
+void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
+{
+ // upload temporary vertexbuffer for this rendering
+ if (!gl_state.usevbo_staticvertex)
+ vertexbuffer = NULL;
+ if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
+ {
+ if (gl_state.preparevertices_dynamicvertexbuffer)
+ R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
+ else
+ gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true);
+ vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
+ }
+ if (vertexbuffer)
+ {
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ case RENDERPATH_GL13:
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ case RENDERPATH_GL11:
+ R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
+ R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
+ break;
+ }
+ return;
+ }
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ case RENDERPATH_GL13:
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ case RENDERPATH_GL11:
+ R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
+ R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
+ break;
+ }
+}
+
+
+
+r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
+{
+ size_t size;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ size = sizeof(r_vertexmesh_t) * numvertices;
+ if (gl_state.preparevertices_tempdatamaxsize < size)
+ {
+ gl_state.preparevertices_tempdatamaxsize = size;
+ gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
+ }
+ gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
+ gl_state.preparevertices_numvertices = numvertices;
+ return gl_state.preparevertices_vertexmesh;
+ default:
+ Sys_Error("R_Mesh_PrepareVertices_Mesh_Lock: unrecognized vid.renderpath\n");
+ return NULL;
+ }
+}
+
+qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
+{
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
+ gl_state.preparevertices_vertexmesh = NULL;
+ gl_state.preparevertices_numvertices = 0;
+ return true;
+ default:
+ Sys_Error("R_Mesh_PrepareVertices_Mesh_Lock: unrecognized vid.renderpath\n");
+ return false;
+ }
+}
+
+void R_Mesh_PrepareVertices_Mesh_Arrays(int numvertices, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const float *color4f, const float *texcoordtexture2f, const float *texcoordlightmap2f)
+{
+ int i;
+ r_vertexmesh_t *vertex;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ if (gl_mesh_separatearrays.integer)
+ {
+ R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
+ R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
+ R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
+ R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
+ R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
+ return;
+ }
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ if (gl_mesh_separatearrays.integer)
+ {
+ R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
+ if (vid.texunits >= 2)
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
+ if (vid.texunits >= 3)
+ R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ return;
+ }
+ break;
+ default:
+ Sys_Error("R_Mesh_PrepareVertices_Position_Lock: unrecognized vid.renderpath\n");
+ return;
+ }
+
+ vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
+ if (svector3f)
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(svector3f + 3*i, vertex[i].svector3f);
+ if (tvector3f)
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
+ if (normal3f)
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(normal3f + 3*i, vertex[i].normal3f);
+ if (color4f)
+ {
+ for (i = 0;i < numvertices;i++)
+ Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
+ }
+ else
+ {
+ float tempcolor4f[4];
+ unsigned char tempcolor4ub[4];
+ Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
+ tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
+ tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
+ tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
+ tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
+ for (i = 0;i < numvertices;i++)
+ Vector4Copy(tempcolor4ub, vertex[i].color4ub);
+ }
+ if (texcoordtexture2f)
+ for (i = 0;i < numvertices;i++)
+ Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
+ if (texcoordlightmap2f)
+ for (i = 0;i < numvertices;i++)
+ Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
+ R_Mesh_PrepareVertices_Mesh_Unlock();
+ R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
+}
+
+void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
+{
+ // upload temporary vertexbuffer for this rendering
+ if (!gl_state.usevbo_staticvertex)
+ vertexbuffer = NULL;
+ if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
+ {
+ if (gl_state.preparevertices_dynamicvertexbuffer)
+ R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
+ else
+ gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true);
+ vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
+ }
+ if (vertexbuffer)
+ {
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
+ R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
+ R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
+ R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
+ R_Mesh_TexCoordPointer(3, 4, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
+ R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
+ break;
+ case RENDERPATH_GL13:
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
+ case RENDERPATH_GL11:
+ R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
+ R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
+ break;
+ }
+ return;
+ }
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
+ R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
+ R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
+ R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
+ R_Mesh_TexCoordPointer(3, 4, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
+ R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
+ break;
+ case RENDERPATH_GL13:
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
+ case RENDERPATH_GL11:
+ R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
+ R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
+ break;
+ }
+}
cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
-cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
" gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
" TexCoord1 = gl_MultiTexCoord0.xy;\n"
"#ifdef USEBLOOM\n"
-" TexCoord2 = gl_MultiTexCoord1.xy;\n"
+" TexCoord2 = gl_MultiTexCoord4.xy;\n"
"#endif\n"
"}\n"
"#endif\n"
"float4 gl_Vertex : POSITION,\n"
"uniform float4x4 ModelViewProjectionMatrix,\n"
"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
-"float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
+"float4 gl_MultiTexCoord1 : TEXCOORD4,\n"
"out float4 gl_Position : POSITION,\n"
"out float2 TexCoord1 : TEXCOORD0,\n"
"out float2 TexCoord2 : TEXCOORD1\n"
extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
extern rtexture_t *r_shadow_prepasslightingspeculartexture;
-void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
+extern cvar_t gl_mesh_separatearrays;
+void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist)
{
// select a permutation of the lighting shader appropriate to this
// combination of texture, entity, light source, and fogging, only use the
mode = SHADERMODE_GENERIC;
permutation |= SHADERPERMUTATION_DIFFUSE;
}
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
- R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest(false);
GL_BlendFunc(GL_ONE, GL_ZERO);
}
mode = SHADERMODE_DEFERREDGEOMETRY;
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
- R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
- if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- else
- R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest(false);
GL_BlendFunc(GL_ONE, GL_ZERO);
}
}
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
- {
- R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
- R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- }
- else
- {
- R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
- }
- //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
- if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- else
- R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
}
permutation |= SHADERPERMUTATION_REFLECTION;
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
- {
- R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
- R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- }
- else
- {
- R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
- }
- R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
- if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- else
- R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
- {
- R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
- R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- }
- else
- {
- R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
- }
- R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
- {
- R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
- R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- }
- else
- {
- R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
- }
- R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
if (r_shadow_glossexact.integer)
permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
}
- R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
- if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- else
- R_Mesh_ColorPointer(NULL, 0, 0);
}
else if (r_glsl_deluxemapping.integer >= 2)
{
if (r_shadow_glossexact.integer)
permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
}
- R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
- if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- else
- R_Mesh_ColorPointer(NULL, 0, 0);
}
else if (rsurface.uselightmaptexture)
{
// ordinary lightmapping (q1bsp, q3bsp)
mode = SHADERMODE_LIGHTMAP;
- R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
- if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- else
- R_Mesh_ColorPointer(NULL, 0, 0);
}
else
{
// ordinary vertex coloring (q3bsp)
mode = SHADERMODE_VERTEXCOLOR;
- R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- }
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
- {
- R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
- R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- }
- else
- {
- R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
}
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
switch(vid.renderpath)
{
case RENDERPATH_GL20:
+ if (gl_mesh_separatearrays.integer)
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
+ R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
+ R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
+ R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
+ R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
+ R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
+ R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
+ }
+ else
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
+ R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
+ }
R_SetupShader_SetPermutationGLSL(mode, permutation);
if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
if (mode == SHADERMODE_LIGHTSOURCE)
break;
case RENDERPATH_CGGL:
#ifdef SUPPORTCG
+ if (gl_mesh_separatearrays.integer)
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
+ R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
+ R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
+ R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
+ R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
+ R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
+ R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
+ }
+ else
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
+ R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
+ }
R_SetupShader_SetPermutationCG(mode, permutation);
if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
if (mode == SHADERMODE_LIGHTSOURCE)
Cvar_RegisterVariable(&developer_texturelogging);
Cvar_RegisterVariable(&gl_lightmaps);
Cvar_RegisterVariable(&r_test);
- Cvar_RegisterVariable(&r_batchmode);
Cvar_RegisterVariable(&r_glsl_saturation);
Cvar_RegisterVariable(&r_framedatasize);
if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
ent->animcache_normal3f = NULL;
ent->animcache_svector3f = NULL;
ent->animcache_tvector3f = NULL;
+ ent->animcache_vertexposition = NULL;
+ ent->animcache_vertexmesh = NULL;
+ ent->animcache_vertexpositionbuffer = NULL;
+ ent->animcache_vertexmeshbuffer = NULL;
+ }
+}
+
+void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
+{
+ int i;
+ if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
+ ent->animcache_vertexmesh = R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
+ if (!ent->animcache_vertexposition)
+ ent->animcache_vertexposition = R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
+ if (ent->animcache_vertexposition)
+ {
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexposition[i].vertex3f);
+ // TODO: upload vertex buffer?
+ }
+ if (ent->animcache_vertexmesh)
+ {
+ memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexmesh[i].vertex3f);
+ if (ent->animcache_svector3f)
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(ent->animcache_svector3f + 3*i, ent->animcache_vertexmesh[i].svector3f);
+ if (ent->animcache_tvector3f)
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(ent->animcache_tvector3f + 3*i, ent->animcache_vertexmesh[i].tvector3f);
+ if (ent->animcache_normal3f)
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(ent->animcache_normal3f + 3*i, ent->animcache_vertexmesh[i].normal3f);
+ // TODO: upload vertex buffer?
}
}
// see if it's already cached this frame
if (ent->animcache_vertex3f)
{
- // add normals/tangents if needed
+ // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
if (wantnormals || wanttangents)
{
if (ent->animcache_normal3f)
ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
}
if (!r_framedata_failed)
+ {
model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
+ R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
+ }
}
}
}
ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
}
if (!r_framedata_failed)
+ {
model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
+ R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
+ }
}
return !r_framedata_failed;
}
void R_AnimCache_CacheVisibleEntities(void)
{
int i;
- qboolean wantnormals = !r_showsurfaces.integer;
+ qboolean wantnormals = true;
qboolean wanttangents = !r_showsurfaces.integer;
switch(vid.renderpath)
break;
}
+ if (r_shownormals.integer)
+ wanttangents = wantnormals = true;
+
// TODO: thread this
// NOTE: R_PrepareRTLights() also caches entities
R_SetViewport(&r_bloomstate.viewport);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_Color(colorscale, colorscale, colorscale, 1);
- // TODO: optimize with multitexture or GLSL
- R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
+ // TODO: do boxfilter scale-down in shader?
R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
// we now have a bloom image in the framebuffer
r_refdef.stats.bloom++;
R_ResetViewRendering2D();
- R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
// we have a bloom image in the framebuffer
CHECKGLERROR
x *= 2;
r = bound(0, r_bloom_colorexponent.value / x, 1);
GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
- GL_Color(r, r, r, 1);
+ GL_Color(r,r,r,1);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
- R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
// copy the vertically blurred bloom view to a texture
if(range >= 1)
brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
- R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
for (dir = 0;dir < 2;dir++)
{
if(range >= 1)
r *= (1 - x*x/(float)(range*range));
GL_Color(r, r, r, 1);
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
GL_BlendFunc(GL_ONE, GL_ONE);
}
if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
{
GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_Color(1,1,1,1);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
- R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
- GL_Color(1, 1, 1, 1);
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
GL_BlendFunc(GL_ONE, GL_ONE);
qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
- R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
qglBlendEquationEXT(GL_FUNC_ADD_EXT);
if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
R_ResetViewRendering2D();
- R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
{
{
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_Color(1, 1, 1, cl.motionbluralpha);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
- R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
}
}
{
// apply a color tint to the whole view
R_ResetViewRendering2D();
- R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
+ GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
}
break; // no screen processing, no bloom, skip it
}
sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
R_ResetViewRendering2D();
- R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
GL_Color(1, 1, 1, 1);
+ R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
GL_BlendFunc(GL_ONE, GL_ZERO);
- R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
- R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
switch(vid.renderpath)
{
default:
break;
}
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
break;
case RENDERPATH_GL13:
{
// apply a color tint to the whole view
R_ResetViewRendering2D();
- R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
+ GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
}
break;
}
c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
}
}
- R_Mesh_VertexPointer(vertex3f, 0, 0);
- R_Mesh_ColorPointer(color4f, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
R_Mesh_ResetTextureState();
R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
- R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
+ R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
}
static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
- R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
- R_Mesh_ColorPointer(color4f, 0, 0);
for (i = 0, c = color4f;i < 6;i++, c += 4)
{
c[0] *= rsurface.colormod[0];
{
for (i = 0, c = color4f;i < 6;i++, c += 4)
{
- f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
+ f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
f2 = 1 - f1;
c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
}
}
R_Mesh_ResetTextureState();
- R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
+ R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
}
void R_DrawNoModel(entity_render_t *ent)
}
else
{
- t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
+ t->backgroundbasetexture = r_texture_white;
t->backgroundnmaptexture = r_texture_blanknormalmap;
t->backgroundglosstexture = r_texture_black;
t->backgroundglowtexture = NULL;
void R_Mesh_ResizeArrays(int newvertices)
{
- float *base;
+ unsigned char *base;
+ size_t size;
if (rsurface.array_size >= newvertices)
return;
- if (rsurface.array_modelvertex3f)
- Mem_Free(rsurface.array_modelvertex3f);
+ if (rsurface.array_base)
+ Mem_Free(rsurface.array_base);
rsurface.array_size = (newvertices + 1023) & ~1023;
- base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
- rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
- rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
- rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
- rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
- rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
- rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
- rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
- rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
- rsurface.array_texcoord3f = base + rsurface.array_size * 24;
- rsurface.array_color4f = base + rsurface.array_size * 27;
- rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
+ size = 0;
+ size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
+ size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
+ size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
+ size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[4]);
+ size += rsurface.array_size * sizeof(float[2]);
+ size += rsurface.array_size * sizeof(float[2]);
+ size += rsurface.array_size * sizeof(float[4]);
+ size += rsurface.array_size * sizeof(int[3]);
+ size += rsurface.array_size * sizeof(unsigned short[3]);
+ rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
+ rsurface.array_modelvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
+ rsurface.array_batchvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
+ rsurface.array_modelvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
+ rsurface.array_batchvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
+ rsurface.array_modelvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_modelsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_modeltvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_modelnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_batchvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_batchsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_batchtvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_batchnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_batchlightmapcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
+ rsurface.array_batchtexcoordtexture2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
+ rsurface.array_batchtexcoordlightmap2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
+ rsurface.array_passcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
+ rsurface.array_batchelement3i = (int *)base;base += rsurface.array_size * sizeof(int[3]);
+ rsurface.array_batchelement3s = (unsigned short *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
}
void RSurf_ActiveWorldEntity(void)
rsurface.basepolygonfactor = r_refdef.polygonfactor;
rsurface.basepolygonoffset = r_refdef.polygonoffset;
rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
- rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
rsurface.modelsvector3f = model->surfmesh.data_svector3f;
- rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
- rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
rsurface.modelnormal3f = model->surfmesh.data_normal3f;
- rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
- rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
+ rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
- rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
- rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
rsurface.modelelement3i = model->surfmesh.data_element3i;
+ rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
+ rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
rsurface.modelelement3s = model->surfmesh.data_element3s;
- rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
- rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
+ rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
+ rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
- rsurface.modelnum_vertices = model->surfmesh.num_vertices;
- rsurface.modelnum_triangles = model->surfmesh.num_triangles;
+ rsurface.modelnumvertices = model->surfmesh.num_vertices;
+ rsurface.modelnumtriangles = model->surfmesh.num_triangles;
rsurface.modelsurfaces = model->data_surfaces;
- rsurface.generatedvertex = false;
- rsurface.vertex3f = rsurface.modelvertex3f;
- rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
- rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
- rsurface.svector3f = rsurface.modelsvector3f;
- rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
- rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
- rsurface.tvector3f = rsurface.modeltvector3f;
- rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
- rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
- rsurface.normal3f = rsurface.modelnormal3f;
- rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
- rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
- rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
+ rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
+ rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
+ rsurface.modelvertexposition = model->surfmesh.vertexposition;
+ rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
+ rsurface.modelgeneratedvertex = false;
+ rsurface.batchgeneratedvertex = false;
+ rsurface.batchfirstvertex = 0;
+ rsurface.batchnumvertices = 0;
+ rsurface.batchfirsttriangle = 0;
+ rsurface.batchnumtriangles = 0;
+ rsurface.batchvertex3f = NULL;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = NULL;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = NULL;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = NULL;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
+ rsurface.batchlightmapcolor4f = NULL;
+ rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
+ rsurface.batchlightmapcolor4f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = NULL;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordlightmap2f = NULL;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchvertexmesh = NULL;
+ rsurface.batchvertexmeshbuffer = NULL;
+ rsurface.batchvertexposition = NULL;
+ rsurface.batchvertexpositionbuffer = NULL;
+ rsurface.batchelement3i = NULL;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = NULL;
+ rsurface.passcolor4f_bufferoffset = 0;
}
void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
+ rsurface.modelvertexmesh = ent->animcache_vertexmesh;
+ rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
+ rsurface.modelvertexposition = ent->animcache_vertexposition;
+ rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
}
else if (wanttangents)
{
rsurface.modeltvector3f = rsurface.array_modeltvector3f;
rsurface.modelnormal3f = rsurface.array_modelnormal3f;
model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
+ rsurface.modelvertexmesh = NULL;
+ rsurface.modelvertexmeshbuffer = NULL;
+ rsurface.modelvertexposition = NULL;
+ rsurface.modelvertexpositionbuffer = NULL;
}
else if (wantnormals)
{
rsurface.modeltvector3f = NULL;
rsurface.modelnormal3f = rsurface.array_modelnormal3f;
model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
+ rsurface.modelvertexmesh = NULL;
+ rsurface.modelvertexmeshbuffer = NULL;
+ rsurface.modelvertexposition = NULL;
+ rsurface.modelvertexpositionbuffer = NULL;
}
else
{
rsurface.modeltvector3f = NULL;
rsurface.modelnormal3f = NULL;
model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
+ rsurface.modelvertexmesh = NULL;
+ rsurface.modelvertexmeshbuffer = NULL;
+ rsurface.modelvertexposition = NULL;
+ rsurface.modelvertexpositionbuffer = NULL;
}
- rsurface.modelvertex3f_bufferobject = 0;
+ rsurface.modelvertex3f_vertexbuffer = 0;
rsurface.modelvertex3f_bufferoffset = 0;
- rsurface.modelsvector3f_bufferobject = 0;
+ rsurface.modelsvector3f_vertexbuffer = 0;
rsurface.modelsvector3f_bufferoffset = 0;
- rsurface.modeltvector3f_bufferobject = 0;
+ rsurface.modeltvector3f_vertexbuffer = 0;
rsurface.modeltvector3f_bufferoffset = 0;
- rsurface.modelnormal3f_bufferobject = 0;
+ rsurface.modelnormal3f_vertexbuffer = 0;
rsurface.modelnormal3f_bufferoffset = 0;
- rsurface.generatedvertex = true;
+ rsurface.modelgeneratedvertex = true;
}
else
{
rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
- rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
rsurface.modelsvector3f = model->surfmesh.data_svector3f;
- rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
- rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
rsurface.modelnormal3f = model->surfmesh.data_normal3f;
- rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
- rsurface.generatedvertex = false;
+ rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
+ rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
+ rsurface.modelvertexposition = model->surfmesh.vertexposition;
+ rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
+ rsurface.modelgeneratedvertex = false;
}
rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
- rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
+ rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
- rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
- rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
rsurface.modelelement3i = model->surfmesh.data_element3i;
+ rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
+ rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
rsurface.modelelement3s = model->surfmesh.data_element3s;
- rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
- rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
+ rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
+ rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
- rsurface.modelnum_vertices = model->surfmesh.num_vertices;
- rsurface.modelnum_triangles = model->surfmesh.num_triangles;
+ rsurface.modelnumvertices = model->surfmesh.num_vertices;
+ rsurface.modelnumtriangles = model->surfmesh.num_triangles;
rsurface.modelsurfaces = model->data_surfaces;
- rsurface.vertex3f = rsurface.modelvertex3f;
- rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
- rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
- rsurface.svector3f = rsurface.modelsvector3f;
- rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
- rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
- rsurface.tvector3f = rsurface.modeltvector3f;
- rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
- rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
- rsurface.normal3f = rsurface.modelnormal3f;
- rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
- rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
- rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
+ rsurface.batchgeneratedvertex = false;
+ rsurface.batchfirstvertex = 0;
+ rsurface.batchnumvertices = 0;
+ rsurface.batchfirsttriangle = 0;
+ rsurface.batchnumtriangles = 0;
+ rsurface.batchvertex3f = NULL;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = NULL;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = NULL;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = NULL;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
+ rsurface.batchlightmapcolor4f = NULL;
+ rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
+ rsurface.batchlightmapcolor4f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = NULL;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordlightmap2f = NULL;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchvertexmesh = NULL;
+ rsurface.batchvertexmeshbuffer = NULL;
+ rsurface.batchvertexposition = NULL;
+ rsurface.batchvertexpositionbuffer = NULL;
+ rsurface.batchelement3i = NULL;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = NULL;
+ rsurface.passcolor4f_bufferoffset = 0;
}
void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
{
+ int i;
+
rsurface.entity = r_refdef.scene.worldentity;
rsurface.skeleton = NULL;
rsurface.ent_skinnum = 0;
rsurface.ent_qwskin = -1;
rsurface.ent_shadertime = shadertime;
rsurface.ent_flags = entflags;
- rsurface.modelnum_vertices = numvertices;
- rsurface.modelnum_triangles = numtriangles;
- if (rsurface.array_size < rsurface.modelnum_vertices)
- R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
+ rsurface.modelnumvertices = numvertices;
+ rsurface.modelnumtriangles = numtriangles;
+ if (rsurface.array_size < rsurface.modelnumvertices)
+ R_Mesh_ResizeArrays(rsurface.modelnumvertices);
rsurface.matrix = *matrix;
rsurface.inversematrix = *inversematrix;
rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
rsurface.modeltvector3f = NULL;
rsurface.modelnormal3f = NULL;
}
- rsurface.modelvertex3f_bufferobject = 0;
+ rsurface.modelvertexmesh = NULL;
+ rsurface.modelvertexmeshbuffer = NULL;
+ rsurface.modelvertexposition = NULL;
+ rsurface.modelvertexpositionbuffer = NULL;
+ rsurface.modelvertex3f_vertexbuffer = 0;
rsurface.modelvertex3f_bufferoffset = 0;
- rsurface.modelsvector3f_bufferobject = 0;
+ rsurface.modelsvector3f_vertexbuffer = 0;
rsurface.modelsvector3f_bufferoffset = 0;
- rsurface.modeltvector3f_bufferobject = 0;
+ rsurface.modeltvector3f_vertexbuffer = 0;
rsurface.modeltvector3f_bufferoffset = 0;
- rsurface.modelnormal3f_bufferobject = 0;
+ rsurface.modelnormal3f_vertexbuffer = 0;
rsurface.modelnormal3f_bufferoffset = 0;
- rsurface.generatedvertex = true;
+ rsurface.modelgeneratedvertex = true;
rsurface.modellightmapcolor4f = color4f;
- rsurface.modellightmapcolor4f_bufferobject = 0;
+ rsurface.modellightmapcolor4f_vertexbuffer = 0;
rsurface.modellightmapcolor4f_bufferoffset = 0;
rsurface.modeltexcoordtexture2f = texcoord2f;
- rsurface.modeltexcoordtexture2f_bufferobject = 0;
+ rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
rsurface.modeltexcoordtexture2f_bufferoffset = 0;
rsurface.modeltexcoordlightmap2f = NULL;
- rsurface.modeltexcoordlightmap2f_bufferobject = 0;
+ rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
rsurface.modelelement3i = element3i;
+ rsurface.modelelement3i_indexbuffer = NULL;
+ rsurface.modelelement3i_bufferoffset = 0;
rsurface.modelelement3s = element3s;
- rsurface.modelelement3i_bufferobject = 0;
- rsurface.modelelement3s_bufferobject = 0;
+ rsurface.modelelement3s_indexbuffer = NULL;
+ rsurface.modelelement3s_bufferoffset = 0;
rsurface.modellightmapoffsets = NULL;
rsurface.modelsurfaces = NULL;
- rsurface.vertex3f = rsurface.modelvertex3f;
- rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
- rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
- rsurface.svector3f = rsurface.modelsvector3f;
- rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
- rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
- rsurface.tvector3f = rsurface.modeltvector3f;
- rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
- rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
- rsurface.normal3f = rsurface.modelnormal3f;
- rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
- rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
- rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
-
- if (rsurface.modelnum_vertices && rsurface.modelelement3i)
+ rsurface.batchgeneratedvertex = false;
+ rsurface.batchfirstvertex = 0;
+ rsurface.batchnumvertices = 0;
+ rsurface.batchfirsttriangle = 0;
+ rsurface.batchnumtriangles = 0;
+ rsurface.batchvertex3f = NULL;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = NULL;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = NULL;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = NULL;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
+ rsurface.batchlightmapcolor4f = NULL;
+ rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
+ rsurface.batchlightmapcolor4f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = NULL;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordlightmap2f = NULL;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchvertexmesh = NULL;
+ rsurface.batchvertexmeshbuffer = NULL;
+ rsurface.batchvertexposition = NULL;
+ rsurface.batchvertexpositionbuffer = NULL;
+ rsurface.batchelement3i = NULL;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = NULL;
+ rsurface.passcolor4f_bufferoffset = 0;
+
+ if (rsurface.modelnumvertices && rsurface.modelelement3i)
{
if ((wantnormals || wanttangents) && !normal3f)
- Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
+ {
+ Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
+ rsurface.modelnormal3f = rsurface.array_modelnormal3f;
+ }
if (wanttangents && !svector3f)
- Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
+ {
+ Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
+ rsurface.modelsvector3f = rsurface.array_modelsvector3f;
+ rsurface.modeltvector3f = rsurface.array_modeltvector3f;
+ }
+ }
+
+ // now convert arrays into vertexmesh structs
+ for (i = 0;i < numvertices;i++)
+ {
+ VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
+ VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
+ if (rsurface.modelsvector3f)
+ VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
+ if (rsurface.modeltvector3f)
+ VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
+ if (rsurface.modelnormal3f)
+ VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
+ if (rsurface.modellightmapcolor4f)
+ Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
+ if (rsurface.modeltexcoordtexture2f)
+ Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
+ if (rsurface.modeltexcoordlightmap2f)
+ Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
}
}
return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
}
+void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
+{
+ int i;
+ for (i = 0;i < numelements;i++)
+ outelement3i[i] = inelement3i[i] + adjust;
+}
+
static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
-void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
+extern cvar_t gl_vbo;
+void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
{
int deformindex;
- int texturesurfaceindex;
+ int firsttriangle;
+ int numtriangles;
+ int firstvertex;
+ int endvertex;
+ int numvertices;
+ int surfacefirsttriangle;
+ int surfacenumtriangles;
+ int surfacefirstvertex;
+ int surfaceendvertex;
+ int surfacenumvertices;
+ int surfaceadjustvertex;
+ int needsupdate;
int i, j;
+ qboolean gaps;
+ qboolean dynamicvertex;
float amplitude;
float animpos;
float scale;
- const float *v1, *in_tc;
- float *out_tc;
float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
float waveparms[4];
q3shaderinfo_deform_t *deform;
- // if vertices are dynamic (animated models), generate them into the temporary rsurface.array_model* arrays and point rsurface.model* at them instead of the static data from the model itself
- if (rsurface.generatedvertex)
+ const msurface_t *surface, *firstsurface;
+ r_vertexposition_t *vertexposition;
+ r_vertexmesh_t *vertexmesh;
+ if (!texturenumsurfaces)
+ return;
+ // find vertex range of this surface batch
+ gaps = false;
+ firstsurface = texturesurfacelist[0];
+ firsttriangle = firstsurface->num_firsttriangle;
+ numtriangles = 0;
+ firstvertex = endvertex = firstsurface->num_firstvertex;
+ for (i = 0;i < texturenumsurfaces;i++)
+ {
+ surface = texturesurfacelist[i];
+ if (surface != firstsurface + i)
+ gaps = true;
+ surfacefirstvertex = surface->num_firstvertex;
+ surfaceendvertex = surfacefirstvertex + surface->num_vertices;
+ surfacenumtriangles = surface->num_triangles;
+ if (firstvertex > surfacefirstvertex)
+ firstvertex = surfacefirstvertex;
+ if (endvertex < surfaceendvertex)
+ endvertex = surfaceendvertex;
+ numtriangles += surfacenumtriangles;
+ }
+ if (!numtriangles)
+ return;
+
+ // we now know the vertex range used, and if there are any gaps in it
+ rsurface.batchfirstvertex = firstvertex;
+ rsurface.batchnumvertices = endvertex - firstvertex;
+ rsurface.batchfirsttriangle = firsttriangle;
+ rsurface.batchnumtriangles = numtriangles;
+
+ // this variable holds flags for which properties have been updated that
+ // may require regenerating vertexmesh or vertexposition arrays...
+ needsupdate = 0;
+
+ if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
+ needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
+ for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
{
- if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
- generatenormals = true;
- for (i = 0;i < Q3MAXDEFORMS;i++)
+ switch (deform->deform)
{
- if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
+ default:
+ case Q3DEFORM_PROJECTIONSHADOW:
+ case Q3DEFORM_TEXT0:
+ case Q3DEFORM_TEXT1:
+ case Q3DEFORM_TEXT2:
+ case Q3DEFORM_TEXT3:
+ case Q3DEFORM_TEXT4:
+ case Q3DEFORM_TEXT5:
+ case Q3DEFORM_TEXT6:
+ case Q3DEFORM_TEXT7:
+ case Q3DEFORM_NONE:
+ break;
+ case Q3DEFORM_AUTOSPRITE:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
+ break;
+ case Q3DEFORM_AUTOSPRITE2:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
+ break;
+ case Q3DEFORM_NORMAL:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
+ break;
+ case Q3DEFORM_WAVE:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
+ break;
+ case Q3DEFORM_BULGE:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
+ break;
+ case Q3DEFORM_MOVE:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
+ break;
+ }
+ }
+ switch(rsurface.texture->tcgen.tcgen)
+ {
+ default:
+ case Q3TCGEN_TEXTURE:
+ break;
+ case Q3TCGEN_LIGHTMAP:
+ batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
+ break;
+ case Q3TCGEN_VECTOR:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
+ break;
+ case Q3TCGEN_ENVIRONMENT:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
+ break;
+ }
+ if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
+ {
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
+ }
+
+ // check if any dynamic vertex processing must occur
+ dynamicvertex = false;
+
+ if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
+ {
+ dynamicvertex = true;
+ batchneed |= BATCHNEED_NOGAPS;
+ needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
+ }
+
+ if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
+ {
+ dynamicvertex = true;
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
+ needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
+ }
+
+ if (dynamicvertex || gaps || rsurface.batchfirstvertex)
+ {
+ // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
+ if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
+ if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
+ if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
+ if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
+ if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
+ if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
+ }
+
+ // when the model data has no vertex buffer (dynamic mesh), we need to
+ // eliminate gaps
+ if (!rsurface.modelvertexmeshbuffer || (!gl_vbo.integer && !vid.forcevbo))
+ batchneed |= BATCHNEED_NOGAPS;
+
+ // if needsupdate, we have to do a dynamic vertex batch for sure
+ if (needsupdate & batchneed)
+ dynamicvertex = true;
+
+ // see if we need to build vertexmesh from arrays
+ if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
+ dynamicvertex = true;
+
+ // see if we need to build vertexposition from arrays
+ if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
+ dynamicvertex = true;
+
+ // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
+ if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
+ dynamicvertex = true;
+
+ // if there is a chance of animated vertex colors, it's a dynamic batch
+ if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
+ dynamicvertex = true;
+
+ rsurface.batchvertex3f = rsurface.modelvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
+ rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
+ rsurface.batchsvector3f = rsurface.modelsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
+ rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
+ rsurface.batchtvector3f = rsurface.modeltvector3f;
+ rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
+ rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
+ rsurface.batchnormal3f = rsurface.modelnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
+ rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
+ rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
+ rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
+ rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
+ rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
+ rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
+ rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
+ rsurface.batchvertexposition = rsurface.modelvertexposition;
+ rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
+ rsurface.batchvertexmesh = rsurface.modelvertexmesh;
+ rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
+ rsurface.batchelement3i = rsurface.modelelement3i;
+ rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
+ rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
+ rsurface.batchelement3s = rsurface.modelelement3s;
+ rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
+ rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
+
+ // if any dynamic vertex processing has to occur in software, we copy the
+ // entire surface list together before processing to rebase the vertices
+ // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
+ //
+ // if any gaps exist and we do not have a static vertex buffer, we have to
+ // copy the surface list together to avoid wasting upload bandwidth on the
+ // vertices in the gaps.
+ //
+ // if gaps exist and we have a static vertex buffer, we still have to
+ // combine the index buffer ranges into one dynamic index buffer.
+ //
+ // in all cases we end up with data that can be drawn in one call.
+
+ if (!dynamicvertex)
+ {
+ // static vertex data, just set pointers...
+ rsurface.batchgeneratedvertex = false;
+ // if there are gaps, we want to build a combined index buffer,
+ // otherwise use the original static buffer with an appropriate offset
+ if (gaps)
+ {
+ firsttriangle = 0;
+ numtriangles = 0;
+ for (i = 0;i < texturenumsurfaces;i++)
+ {
+ surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
+ surfacenumtriangles = texturesurfacelist[i]->num_triangles;
+ memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
+ numtriangles += surfacenumtriangles;
+ }
+ rsurface.batchelement3i = rsurface.array_batchelement3i;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ if (endvertex <= 65536)
+ {
+ rsurface.batchelement3s = rsurface.array_batchelement3s;
+ for (i = 0;i < numtriangles*3;i++)
+ rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
+ }
+ rsurface.batchfirsttriangle = firsttriangle;
+ rsurface.batchnumtriangles = numtriangles;
+ }
+ return;
+ }
+
+ // something needs software processing, do it for real...
+ // we only directly handle interleaved array data in this case...
+ rsurface.batchgeneratedvertex = true;
+
+ // now copy the vertex data into a combined array and make an index array
+ // (this is what Quake3 does all the time)
+ //if (gaps || rsurface.batchfirstvertex)
+ {
+ rsurface.batchvertexposition = NULL;
+ rsurface.batchvertexpositionbuffer = NULL;
+ rsurface.batchvertexmesh = NULL;
+ rsurface.batchvertexmeshbuffer = NULL;
+ rsurface.batchvertex3f = NULL;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = NULL;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = NULL;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = NULL;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
+ rsurface.batchlightmapcolor4f = NULL;
+ rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
+ rsurface.batchlightmapcolor4f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = NULL;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordlightmap2f = NULL;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchelement3i = rsurface.array_batchelement3i;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ // we'll only be setting up certain arrays as needed
+ if (batchneed & BATCHNEED_VERTEXPOSITION)
+ rsurface.batchvertexposition = rsurface.array_batchvertexposition;
+ if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
+ rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
+ if (batchneed & BATCHNEED_ARRAY_VERTEX)
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ if (batchneed & BATCHNEED_ARRAY_NORMAL)
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ if (batchneed & BATCHNEED_ARRAY_VECTOR)
+ {
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ }
+ if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
+ rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
+ if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
+ rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
+ numvertices = 0;
+ numtriangles = 0;
+ for (i = 0;i < texturenumsurfaces;i++)
+ {
+ surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
+ surfacenumvertices = texturesurfacelist[i]->num_vertices;
+ surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
+ surfaceadjustvertex = numvertices - surfacefirstvertex;
+ surfacenumtriangles = texturesurfacelist[i]->num_triangles;
+ // copy only the data requested
+ if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
+ memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
+ if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
+ memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
+ if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
+ {
+ if (batchneed & BATCHNEED_ARRAY_VERTEX)
+ memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+ if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
+ memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+ if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
+ {
+ memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+ memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+ }
+ if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
+ memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
+ if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
+ memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
+ if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
+ memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
+ }
+ RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
+ numvertices += surfacenumvertices;
+ numtriangles += surfacenumtriangles;
+ }
+
+ // generate a 16bit index array as well if possible
+ // (in general, dynamic batches fit)
+ if (numvertices <= 65536)
+ {
+ rsurface.batchelement3s = rsurface.array_batchelement3s;
+ for (i = 0;i < numtriangles*3;i++)
+ rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
+ }
+
+ // since we've copied everything, the batch now starts at 0
+ rsurface.batchfirstvertex = 0;
+ rsurface.batchnumvertices = numvertices;
+ rsurface.batchfirsttriangle = 0;
+ rsurface.batchnumtriangles = numtriangles;
+ }
+
+ // q1bsp surfaces rendered in vertex color mode have to have colors
+ // calculated based on lightstyles
+ if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
+ {
+ // generate color arrays for the surfaces in this list
+ int c[4];
+ int scale;
+ int size3;
+ const int *offsets;
+ const unsigned char *lm;
+ numvertices = 0;
+ rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
+ rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
+ rsurface.batchlightmapcolor4f_bufferoffset = 0;
+ for (i = 0;i < texturenumsurfaces;i++)
+ {
+ surface = texturesurfacelist[i];
+ offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
+ surfacenumvertices = surface->num_vertices;
+ if (surface->lightmapinfo->samples)
+ {
+ for (j = 0;j < surfacenumvertices;j++)
+ {
+ lm = surface->lightmapinfo->samples + offsets[j];
+ scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
+ VectorScale(lm, scale, c);
+ if (surface->lightmapinfo->styles[1] != 255)
+ {
+ size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
+ lm += size3;
+ scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
+ VectorMA(c, scale, lm, c);
+ if (surface->lightmapinfo->styles[2] != 255)
+ {
+ lm += size3;
+ scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
+ VectorMA(c, scale, lm, c);
+ if (surface->lightmapinfo->styles[3] != 255)
+ {
+ lm += size3;
+ scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
+ VectorMA(c, scale, lm, c);
+ }
+ }
+ }
+ c[0] >>= 15;
+ c[1] >>= 15;
+ c[2] >>= 15;
+ Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
+ numvertices++;
+ }
+ }
+ else
{
- generatetangents = true;
- generatenormals = true;
+ for (j = 0;j < surfacenumvertices;j++)
+ {
+ Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
+ numvertices++;
+ }
}
- if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
- generatenormals = true;
- }
- if (generatenormals && !rsurface.modelnormal3f)
- {
- rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
- rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
- rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
- Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
- }
- if (generatetangents && !rsurface.modelsvector3f)
- {
- rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
- rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
- rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
- rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
- rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
- rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
- Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
- }
- }
- rsurface.vertex3f = rsurface.modelvertex3f;
- rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
- rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
- rsurface.svector3f = rsurface.modelsvector3f;
- rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
- rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
- rsurface.tvector3f = rsurface.modeltvector3f;
- rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
- rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
- rsurface.normal3f = rsurface.modelnormal3f;
- rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
- rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
+ }
+ }
+
// if vertices are deformed (sprite flares and things in maps, possibly
- // water waves, bulges and other deformations), generate them into
- // rsurface.deform* arrays from whatever the rsurface.* arrays point to
- // (may be static model data or generated data for an animated model, or
- // the previous deform pass)
+ // water waves, bulges and other deformations), modify the copied vertices
+ // in place
for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
{
switch (deform->deform)
VectorNormalize(newforward);
VectorNormalize(newright);
VectorNormalize(newup);
- // make deformed versions of only the model vertices used by the specified surfaces
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ // a single autosprite surface can contain multiple sprites...
+ for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- // a single autosprite surface can contain multiple sprites...
- for (j = 0;j < surface->num_vertices - 3;j += 4)
+ VectorClear(center);
+ for (i = 0;i < 4;i++)
+ VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
+ VectorScale(center, 0.25f, center);
+ VectorCopy(rsurface.batchnormal3f + 3*j, forward);
+ VectorCopy(rsurface.batchsvector3f + 3*j, right);
+ VectorCopy(rsurface.batchtvector3f + 3*j, up);
+ for (i = 0;i < 4;i++)
{
- VectorClear(center);
- for (i = 0;i < 4;i++)
- VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
- VectorScale(center, 0.25f, center);
- VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
- VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
- VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
- for (i = 0;i < 4;i++)
- {
- VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
- VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
- }
+ VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
+ VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
}
- Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer != 0);
- Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
}
- rsurface.vertex3f = rsurface.array_deformedvertex3f;
- rsurface.vertex3f_bufferobject = 0;
- rsurface.vertex3f_bufferoffset = 0;
- rsurface.svector3f = rsurface.array_deformedsvector3f;
- rsurface.svector3f_bufferobject = 0;
- rsurface.svector3f_bufferoffset = 0;
- rsurface.tvector3f = rsurface.array_deformedtvector3f;
- rsurface.tvector3f_bufferobject = 0;
- rsurface.tvector3f_bufferoffset = 0;
- rsurface.normal3f = rsurface.array_deformednormal3f;
- rsurface.normal3f_bufferobject = 0;
- rsurface.normal3f_bufferoffset = 0;
+ Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
+ Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
break;
case Q3DEFORM_AUTOSPRITE2:
Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
VectorNormalize(newforward);
VectorNormalize(newright);
VectorNormalize(newup);
- // make deformed versions of only the model vertices used by the specified surfaces
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
const float *v1, *v2;
vec3_t start, end;
float f, l;
shortest[2];
memset(shortest, 0, sizeof(shortest));
// a single autosprite surface can contain multiple sprites...
- for (j = 0;j < surface->num_vertices - 3;j += 4)
+ for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
{
VectorClear(center);
for (i = 0;i < 4;i++)
- VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
+ VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
VectorScale(center, 0.25f, center);
// find the two shortest edges, then use them to define the
// axis vectors for rotating around the central axis
for (i = 0;i < 6;i++)
{
- v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
- v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
-#if 0
- Debug_PolygonBegin(NULL, 0);
- Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
- Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
- Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
- Debug_PolygonEnd();
-#endif
+ v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
+ v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
l = VectorDistance2(v1, v2);
// this length bias tries to make sense of square polygons, assuming they are meant to be upright
if (v1[2] != v2[2])
}
VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
-#if 0
- Debug_PolygonBegin(NULL, 0);
- Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
- Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
- Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
- Debug_PolygonEnd();
-#endif
// this calculates the right vector from the shortest edge
// and the up vector from the edge midpoints
VectorSubtract(shortest[0].v1, shortest[0].v2, right);
VectorNormalize(forward);
CrossProduct(up, forward, newright);
VectorNormalize(newright);
-#if 0
- Debug_PolygonBegin(NULL, 0);
- Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
- Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
- Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
- Debug_PolygonEnd();
-#endif
-#if 0
- Debug_PolygonBegin(NULL, 0);
- Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
- Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
- Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
- Debug_PolygonEnd();
-#endif
// rotate the quad around the up axis vector, this is made
// especially easy by the fact we know the quad is flat,
// so we only have to subtract the center position and
l = DotProduct(right, center);
for (i = 0;i < 4;i++)
{
- v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
+ v1 = rsurface.batchvertex3f + 3*(j+i);
f = DotProduct(right, v1) - l;
- VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
+ VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
}
}
- Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer != 0);
- Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
}
- rsurface.vertex3f = rsurface.array_deformedvertex3f;
- rsurface.vertex3f_bufferobject = 0;
- rsurface.vertex3f_bufferoffset = 0;
- rsurface.svector3f = rsurface.array_deformedsvector3f;
- rsurface.svector3f_bufferobject = 0;
- rsurface.svector3f_bufferoffset = 0;
- rsurface.tvector3f = rsurface.array_deformedtvector3f;
- rsurface.tvector3f_bufferobject = 0;
- rsurface.tvector3f_bufferoffset = 0;
- rsurface.normal3f = rsurface.array_deformednormal3f;
- rsurface.normal3f_bufferobject = 0;
- rsurface.normal3f_bufferoffset = 0;
+ Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
+ Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
break;
case Q3DEFORM_NORMAL:
// deform the normals to make reflections wavey
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0;j < surface->num_vertices;j++)
- {
- float vertex[3];
- float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
- VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
- VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
- normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
- normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
- normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
- VectorNormalize(normal);
- }
- Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
+ float vertex[3];
+ float *normal = rsurface.array_batchnormal3f + 3*j;
+ VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
+ normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
+ normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
+ normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
+ VectorNormalize(normal);
}
- rsurface.svector3f = rsurface.array_deformedsvector3f;
- rsurface.svector3f_bufferobject = 0;
- rsurface.svector3f_bufferoffset = 0;
- rsurface.tvector3f = rsurface.array_deformedtvector3f;
- rsurface.tvector3f_bufferobject = 0;
- rsurface.tvector3f_bufferoffset = 0;
- rsurface.normal3f = rsurface.array_deformednormal3f;
- rsurface.normal3f_bufferobject = 0;
- rsurface.normal3f_bufferoffset = 0;
+ Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
break;
case Q3DEFORM_WAVE:
// deform vertex array to make wavey water and flags and such
// this is how a divisor of vertex influence on deformation
animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0;j < surface->num_vertices;j++)
+ // if the wavefunc depends on time, evaluate it per-vertex
+ if (waveparms[3])
{
- float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
- VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
- // if the wavefunc depends on time, evaluate it per-vertex
- if (waveparms[3])
- {
- waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
- scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
- }
- VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
+ waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
+ scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
}
+ VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
}
- rsurface.vertex3f = rsurface.array_deformedvertex3f;
- rsurface.vertex3f_bufferobject = 0;
- rsurface.vertex3f_bufferoffset = 0;
+ Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
+ Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
break;
case Q3DEFORM_BULGE:
// deform vertex array to make the surface have moving bulges
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0;j < surface->num_vertices;j++)
- {
- scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
- VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
- }
+ scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
+ VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
}
- rsurface.vertex3f = rsurface.array_deformedvertex3f;
- rsurface.vertex3f_bufferobject = 0;
- rsurface.vertex3f_bufferoffset = 0;
+ Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
+ Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
break;
case Q3DEFORM_MOVE:
// deform vertex array
scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
VectorScale(deform->parms, scale, waveparms);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0;j < surface->num_vertices;j++)
- VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
- }
- rsurface.vertex3f = rsurface.array_deformedvertex3f;
- rsurface.vertex3f_bufferobject = 0;
- rsurface.vertex3f_bufferoffset = 0;
+ for (j = 0;j < rsurface.batchnumvertices;j++)
+ VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
break;
}
}
+
// generate texcoords based on the chosen texcoord source
switch(rsurface.texture->tcgen.tcgen)
{
default:
case Q3TCGEN_TEXTURE:
- rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
- rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
- rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
break;
case Q3TCGEN_LIGHTMAP:
- rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
- rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
- rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
+ if (rsurface.batchtexcoordlightmap2f)
+ memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
break;
case Q3TCGEN_VECTOR:
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, out_tc += 2)
- {
- out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
- out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
- }
+ rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
+ rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
}
- rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
- rsurface.texcoordtexture2f_bufferobject = 0;
- rsurface.texcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
break;
case Q3TCGEN_ENVIRONMENT:
// make environment reflections using a spheremap
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
- const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
- float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
- for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
- {
- // identical to Q3A's method, but executed in worldspace so
- // carried models can be shiny too
+ // identical to Q3A's method, but executed in worldspace so
+ // carried models can be shiny too
- float viewer[3], d, reflected[3], worldreflected[3];
+ float viewer[3], d, reflected[3], worldreflected[3];
- VectorSubtract(rsurface.localvieworigin, vertex, viewer);
- // VectorNormalize(viewer);
+ VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
+ // VectorNormalize(viewer);
- d = DotProduct(normal, viewer);
+ d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
- reflected[0] = normal[0]*2*d - viewer[0];
- reflected[1] = normal[1]*2*d - viewer[1];
- reflected[2] = normal[2]*2*d - viewer[2];
- // note: this is proportinal to viewer, so we can normalize later
+ reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
+ reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
+ reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
+ // note: this is proportinal to viewer, so we can normalize later
- Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
- VectorNormalize(worldreflected);
+ Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
+ VectorNormalize(worldreflected);
- // note: this sphere map only uses world x and z!
- // so positive and negative y will LOOK THE SAME.
- out_tc[0] = 0.5 + 0.5 * worldreflected[1];
- out_tc[1] = 0.5 - 0.5 * worldreflected[2];
- }
+ // note: this sphere map only uses world x and z!
+ // so positive and negative y will LOOK THE SAME.
+ rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
+ rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
}
- rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
- rsurface.texcoordtexture2f_bufferobject = 0;
- rsurface.texcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
break;
}
// the only tcmod that needs software vertex processing is turbulent, so
{
amplitude = rsurface.texture->tcmods[0].parms[1];
animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, in_tc = rsurface.texcoordtexture2f + 2 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, in_tc += 2, out_tc += 2)
- {
- out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
- out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
- }
+ rsurface.array_batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
+ rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
}
- rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
- rsurface.texcoordtexture2f_bufferobject = 0;
- rsurface.texcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
}
- rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
- rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
- rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
- R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
-}
-void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
-{
- int i, j;
- const msurface_t *surface = texturesurfacelist[0];
- const msurface_t *surface2;
- int firstvertex;
- int endvertex;
- int numvertices;
- int numtriangles;
- // TODO: lock all array ranges before render, rather than on each surface
- if (texturenumsurfaces == 1)
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
- else if (r_batchmode.integer == 2)
+ if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
{
- #define MAXBATCHTRIANGLES 65536
- int batchtriangles = 0;
- static int batchelements[MAXBATCHTRIANGLES*3];
- for (i = 0;i < texturenumsurfaces;i = j)
+ // convert the modified arrays to vertex structs
+ rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
+ rsurface.batchvertexmeshbuffer = NULL;
+ if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
+ for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
+ VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
+ if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
+ for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
+ VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
+ if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
{
- surface = texturesurfacelist[i];
- j = i + 1;
- if (surface->num_triangles > MAXBATCHTRIANGLES)
+ for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
{
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
- continue;
- }
- memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
- batchtriangles = surface->num_triangles;
- firstvertex = surface->num_firstvertex;
- endvertex = surface->num_firstvertex + surface->num_vertices;
- for (;j < texturenumsurfaces;j++)
- {
- surface2 = texturesurfacelist[j];
- if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
- break;
- memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
- batchtriangles += surface2->num_triangles;
- firstvertex = min(firstvertex, surface2->num_firstvertex);
- endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
+ VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
+ VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
}
- surface2 = texturesurfacelist[j-1];
- numvertices = endvertex - firstvertex;
- R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
}
+ if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
+ for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
+ Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
+ if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
+ for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
+ Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
+ if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
+ for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
+ Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
}
- else if (r_batchmode.integer == 1)
- {
- for (i = 0;i < texturenumsurfaces;i = j)
- {
- surface = texturesurfacelist[i];
- for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
- if (texturesurfacelist[j] != surface2)
- break;
- surface2 = texturesurfacelist[j-1];
- numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
- numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
- R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
- }
- }
- else
+
+ if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
{
- for (i = 0;i < texturenumsurfaces;i++)
- {
- surface = texturesurfacelist[i];
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
- }
+ // convert the modified arrays to vertex structs
+ rsurface.batchvertexposition = rsurface.array_batchvertexposition;
+ rsurface.batchvertexpositionbuffer = NULL;
+ if (sizeof(r_vertexposition_t) == sizeof(float[3]))
+ memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
+ else
+ for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
+ VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
}
}
-static void RSurf_BindLightmapForSurface(const msurface_t *surface)
+void RSurf_DrawBatch(void)
+{
+ R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
+}
+
+static void RSurf_BindLightmapForBatch(void)
{
switch(vid.renderpath)
{
case RENDERPATH_CGGL:
#ifdef SUPPORTCG
- if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
- if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, rsurface.deluxemaptexture);CHECKCGERROR
#endif
break;
case RENDERPATH_GL20:
- if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
- if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
+ if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture );
+ if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, rsurface.deluxemaptexture);
break;
case RENDERPATH_GL13:
case RENDERPATH_GL11:
- R_Mesh_TexBind(0, surface->lightmaptexture);
+ R_Mesh_TexBind(0, rsurface.lightmaptexture);
break;
}
}
-static void RSurf_BindReflectionForSurface(const msurface_t *surface)
+static void RSurf_BindReflectionForBatch(void)
{
// pick the closest matching water plane and bind textures
int planeindex, vertexindex;
if(p->camera_entity != rsurface.texture->camera_entity)
continue;
d = 0;
- for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
+ for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
{
Matrix4x4_Transform(&rsurface.matrix, v, vert);
d += fabs(PlaneDiff(vert, &p->plane));
}
}
-static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
+static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
{
int i;
- const msurface_t *surface;
- if (r_waterstate.renderingscene)
- return;
- for (i = 0;i < texturenumsurfaces;i++)
- {
- surface = texturesurfacelist[i];
- RSurf_BindLightmapForSurface(surface);
- RSurf_BindReflectionForSurface(surface);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
- }
+ for (i = 0;i < rsurface.batchnumvertices;i++)
+ Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
+ rsurface.passcolor4f = rsurface.array_passcolor4f;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
}
-static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
+static void RSurf_DrawBatch_GL11_ApplyFog(void)
{
- int i;
- int j;
- const msurface_t *surface = texturesurfacelist[0];
- const msurface_t *surface2;
- int firstvertex;
- int endvertex;
- int numvertices;
- int numtriangles;
- if (texturenumsurfaces == 1)
- {
- RSurf_BindLightmapForSurface(surface);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
- }
- else if (r_batchmode.integer == 2)
- {
- int batchtriangles = 0;
- static int batchelements[MAXBATCHTRIANGLES*3];
- for (i = 0;i < texturenumsurfaces;i = j)
- {
- surface = texturesurfacelist[i];
- RSurf_BindLightmapForSurface(surface);
- j = i + 1;
- if (surface->num_triangles > MAXBATCHTRIANGLES)
- {
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
- continue;
- }
- memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
- batchtriangles = surface->num_triangles;
- firstvertex = surface->num_firstvertex;
- endvertex = surface->num_firstvertex + surface->num_vertices;
- for (;j < texturenumsurfaces;j++)
- {
- surface2 = texturesurfacelist[j];
- if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
- break;
- memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
- batchtriangles += surface2->num_triangles;
- firstvertex = min(firstvertex, surface2->num_firstvertex);
- endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
- }
- surface2 = texturesurfacelist[j-1];
- numvertices = endvertex - firstvertex;
- R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
- }
- }
- else if (r_batchmode.integer == 1)
- {
-#if 0
- Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
- for (i = 0;i < texturenumsurfaces;i = j)
- {
- surface = texturesurfacelist[i];
- for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
- if (texturesurfacelist[j] != surface2)
- break;
- Con_Printf(" %i", j - i);
- }
- Con_Printf("\n");
- Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
-#endif
- for (i = 0;i < texturenumsurfaces;i = j)
- {
- surface = texturesurfacelist[i];
- RSurf_BindLightmapForSurface(surface);
- for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
- if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
- break;
-#if 0
- Con_Printf(" %i", j - i);
-#endif
- surface2 = texturesurfacelist[j-1];
- numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
- numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
- R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
- }
-#if 0
- Con_Printf("\n");
-#endif
- }
- else
- {
- for (i = 0;i < texturenumsurfaces;i++)
- {
- surface = texturesurfacelist[i];
- RSurf_BindLightmapForSurface(surface);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
- }
- }
-}
-
-static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
-{
- int j;
- int texturesurfaceindex;
- if (r_showsurfaces.integer == 2)
- {
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0;j < surface->num_triangles;j++)
- {
- float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
- GL_Color(f, f, f, 1);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
- }
- }
- }
- else
- {
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- int k = (int)(((size_t)surface) / sizeof(msurface_t));
- GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
- }
- }
-}
-
-static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
-{
- int texturesurfaceindex;
- int i;
- const float *v;
- float *c2;
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
- {
- c2[0] = 0.5;
- c2[1] = 0.5;
- c2[2] = 0.5;
- c2[3] = 1;
- }
- }
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
-}
-
-static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
-{
- int texturesurfaceindex;
int i;
float f;
const float *v;
const float *c;
float *c2;
- if (rsurface.lightmapcolor4f)
+ if (rsurface.passcolor4f)
{
- // generate color arrays for the surfaces in this list
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ // generate color arrays
+ for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
- {
- f = RSurf_FogVertex(v);
- c2[0] = c[0] * f;
- c2[1] = c[1] * f;
- c2[2] = c[2] * f;
- c2[3] = c[3];
- }
+ f = RSurf_FogVertex(v);
+ c2[0] = c[0] * f;
+ c2[1] = c[1] * f;
+ c2[2] = c[2] * f;
+ c2[3] = c[3];
}
}
else
{
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
- {
- f = RSurf_FogVertex(v);
- c2[0] = f;
- c2[1] = f;
- c2[2] = f;
- c2[3] = 1;
- }
+ f = RSurf_FogVertex(v);
+ c2[0] = f;
+ c2[1] = f;
+ c2[2] = f;
+ c2[3] = 1;
}
}
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
+ rsurface.passcolor4f = rsurface.array_passcolor4f;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
}
-static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
+static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
{
- int texturesurfaceindex;
int i;
float f;
const float *v;
const float *c;
float *c2;
- if (!rsurface.lightmapcolor4f)
+ if (!rsurface.passcolor4f)
return;
- // generate color arrays for the surfaces in this list
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
- {
- f = RSurf_FogVertex(v);
- c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
- c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
- c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
- c2[3] = c[3];
- }
+ f = RSurf_FogVertex(v);
+ c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
+ c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
+ c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
+ c2[3] = c[3];
}
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
+ rsurface.passcolor4f = rsurface.array_passcolor4f;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
}
-static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
+static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
{
- int texturesurfaceindex;
int i;
const float *c;
float *c2;
- if (!rsurface.lightmapcolor4f)
+ if (!rsurface.passcolor4f)
return;
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
- {
- c2[0] = c[0] * r;
- c2[1] = c[1] * g;
- c2[2] = c[2] * b;
- c2[3] = c[3] * a;
- }
+ c2[0] = c[0] * r;
+ c2[1] = c[1] * g;
+ c2[2] = c[2] * b;
+ c2[3] = c[3] * a;
}
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
+ rsurface.passcolor4f = rsurface.array_passcolor4f;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
}
-static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
+static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
{
- int texturesurfaceindex;
int i;
const float *c;
float *c2;
- if (!rsurface.lightmapcolor4f)
+ if (!rsurface.passcolor4f)
return;
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
- {
- c2[0] = c[0] + r_refdef.scene.ambient;
- c2[1] = c[1] + r_refdef.scene.ambient;
- c2[2] = c[2] + r_refdef.scene.ambient;
- c2[3] = c[3];
- }
+ c2[0] = c[0] + r_refdef.scene.ambient;
+ c2[1] = c[1] + r_refdef.scene.ambient;
+ c2[2] = c[2] + r_refdef.scene.ambient;
+ c2[3] = c[3];
}
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
+ rsurface.passcolor4f = rsurface.array_passcolor4f;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
}
-static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
+static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
{
// TODO: optimize
- rsurface.lightmapcolor4f = NULL;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
- if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
- if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
- R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
+ if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
+ if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
GL_Color(r, g, b, a);
- RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
+ RSurf_BindLightmapForBatch();
+ RSurf_DrawBatch();
}
-static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
+static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
{
// TODO: optimize applyfog && applycolor case
// just apply fog if necessary, and tint the fog color array if necessary
- rsurface.lightmapcolor4f = NULL;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
- if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
- if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
- R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
+ if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
+ if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
GL_Color(r, g, b, a);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ RSurf_DrawBatch();
}
-static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
+static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
{
- int texturesurfaceindex;
- int i;
- float *c;
// TODO: optimize
- if (texturesurfacelist[0]->lightmapinfo)
- {
- // generate color arrays for the surfaces in this list
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
- {
- if (surface->lightmapinfo->samples)
- {
- const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
- float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
- VectorScale(lm, scale, c);
- if (surface->lightmapinfo->styles[1] != 255)
- {
- int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
- lm += size3;
- scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
- VectorMA(c, scale, lm, c);
- if (surface->lightmapinfo->styles[2] != 255)
- {
- lm += size3;
- scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
- VectorMA(c, scale, lm, c);
- if (surface->lightmapinfo->styles[3] != 255)
- {
- lm += size3;
- scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
- VectorMA(c, scale, lm, c);
- }
- }
- }
- }
- else
- VectorClear(c);
- c[3] = 1;
- }
- }
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
- }
- else
+ rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
+ rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
+ rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
+ if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
+ if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
+ GL_Color(r, g, b, a);
+ RSurf_DrawBatch();
+}
+
+static void RSurf_DrawBatch_GL11_ClampColor(void)
+{
+ int i;
+ const float *c1;
+ float *c2;
+ if (!rsurface.passcolor4f)
+ return;
+ for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
{
- rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
- rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
- rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
+ c2[0] = bound(0.0f, c1[0], 1.0f);
+ c2[1] = bound(0.0f, c1[1], 1.0f);
+ c2[2] = bound(0.0f, c1[2], 1.0f);
+ c2[3] = bound(0.0f, c1[3], 1.0f);
}
- if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
- if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
- R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
- GL_Color(r, g, b, a);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
}
-static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
+static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
{
- int texturesurfaceindex;
int i;
float f;
float alpha;
diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
alpha = *a;
- if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
+ if (VectorLength2(diffusecolor) > 0)
{
- // generate color arrays for the surfaces in this list
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ // q3-style directional shading
+ for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- int numverts = surface->num_vertices;
- v = rsurface.vertex3f + 3 * surface->num_firstvertex;
- n = rsurface.normal3f + 3 * surface->num_firstvertex;
- c = rsurface.array_color4f + 4 * surface->num_firstvertex;
- // q3-style directional shading
- for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
- {
- if ((f = DotProduct(n, lightdir)) > 0)
- VectorMA(ambientcolor, f, diffusecolor, c);
- else
- VectorCopy(ambientcolor, c);
- c[3] = alpha;
- }
+ if ((f = DotProduct(n, lightdir)) > 0)
+ VectorMA(ambientcolor, f, diffusecolor, c);
+ else
+ VectorCopy(ambientcolor, c);
+ c[3] = alpha;
}
*r = 1;
*g = 1;
*b = 1;
*a = 1;
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
+ rsurface.passcolor4f = rsurface.array_passcolor4f;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
*applycolor = false;
}
else
*r = ambientcolor[0];
*g = ambientcolor[1];
*b = ambientcolor[2];
- rsurface.lightmapcolor4f = NULL;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
}
}
-static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
+static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
{
- RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
- if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
- if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
- R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
+ RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
+ if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
+ if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
GL_Color(r, g, b, a);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ RSurf_DrawBatch();
+}
+
+static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
+{
+ int i;
+ float f;
+ const float *v;
+ float *c;
+ for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
+ {
+ f = 1 - RSurf_FogVertex(v);
+ c[0] = r;
+ c[1] = g;
+ c[2] = b;
+ c[3] = f * a;
+ }
}
void RSurf_SetupDepthAndCulling(void)
// level, so don't use it then either.
if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
{
- GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
- R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
if (skyrendermasked)
{
// just to make sure that braindead drivers don't draw
// anything despite that colormask...
GL_BlendFunc(GL_ZERO, GL_ONE);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
+ R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
}
else
{
R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
// fog sky
GL_BlendFunc(GL_ONE, GL_ZERO);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
+ GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
+ R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
}
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ RSurf_DrawBatch();
if (skyrendermasked)
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
}
{
if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
return;
- RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
if (prepass)
{
// render screenspace normalmap to texture
GL_DepthMask(true);
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist);
+ RSurf_DrawBatch();
}
else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
{
// render water or distortion background, then blend surface on top
GL_DepthMask(true);
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
- RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, texturenumsurfaces, texturesurfacelist);
+ RSurf_BindReflectionForBatch();
+ if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
+ RSurf_BindLightmapForBatch();
+ RSurf_DrawBatch();
GL_DepthMask(false);
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist);
if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
- RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
- else
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ RSurf_BindLightmapForBatch();
+ RSurf_DrawBatch();
}
else
{
// render surface normally
GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
- RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
- else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
- RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
- else
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ RSurf_BindReflectionForBatch();
+ if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
+ RSurf_BindLightmapForBatch();
+ RSurf_DrawBatch();
}
}
static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
{
// OpenGL 1.3 path - anything not completely ancient
- int texturesurfaceindex;
qboolean applycolor;
qboolean applyfog;
int layerindex;
const texturelayer_t *layer;
- RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+ R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
{
}
layercolor[3] = layer->color[3];
applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
- R_Mesh_ColorPointer(NULL, 0, 0);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
switch (layer->type)
{
R_Mesh_TexBind(0, r_texture_white);
R_Mesh_TexMatrix(0, NULL);
R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
- R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
R_Mesh_TexBind(1, layer->texture);
R_Mesh_TexMatrix(1, &layer->texmatrix);
R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
- R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
- RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
+ RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
else if (rsurface.uselightmaptexture)
- RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
+ RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
else
- RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
+ RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
break;
case TEXTURELAYERTYPE_TEXTURE:
// singletexture unlit texture with transparency support
R_Mesh_TexBind(0, layer->texture);
R_Mesh_TexMatrix(0, &layer->texmatrix);
R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
R_Mesh_TexBind(1, 0);
- R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
- RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
+ RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
break;
case TEXTURELAYERTYPE_FOG:
// singletexture fogging
R_Mesh_TexBind(0, layer->texture);
R_Mesh_TexMatrix(0, &layer->texmatrix);
R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
}
else
{
R_Mesh_TexBind(0, 0);
- R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
}
R_Mesh_TexBind(1, 0);
- R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
// generate a color array for the fog pass
- R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- int i;
- float f;
- const float *v;
- float *c;
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
- {
- f = 1 - RSurf_FogVertex(v);
- c[0] = layercolor[0];
- c[1] = layercolor[1];
- c[2] = layercolor[2];
- c[3] = f * layercolor[3];
- }
- }
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
+ RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
+ RSurf_DrawBatch();
break;
default:
Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
{
// OpenGL 1.1 - crusty old voodoo path
- int texturesurfaceindex;
qboolean applyfog;
int layerindex;
const texturelayer_t *layer;
- RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+ R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
{
}
GL_DepthMask(layer->depthmask && writedepth);
GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
- R_Mesh_ColorPointer(NULL, 0, 0);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
switch (layer->type)
{
R_Mesh_TexBind(0, r_texture_white);
R_Mesh_TexMatrix(0, NULL);
R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
- R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
- RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
+ RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
else if (rsurface.uselightmaptexture)
- RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
+ RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
else
- RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
+ RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
// then apply the texture to it
GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
R_Mesh_TexBind(0, layer->texture);
R_Mesh_TexMatrix(0, &layer->texmatrix);
R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
+ RSurf_DrawBatch_GL11_Unlit(layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
}
else
{
R_Mesh_TexBind(0, layer->texture);
R_Mesh_TexMatrix(0, &layer->texmatrix);
R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
- RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
+ RSurf_DrawBatch_GL11_VertexShade(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
else
- RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
+ RSurf_DrawBatch_GL11_VertexColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
}
break;
case TEXTURELAYERTYPE_TEXTURE:
R_Mesh_TexBind(0, layer->texture);
R_Mesh_TexMatrix(0, &layer->texmatrix);
R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
+ RSurf_DrawBatch_GL11_Unlit(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
break;
case TEXTURELAYERTYPE_FOG:
// singletexture fogging
R_Mesh_TexBind(0, layer->texture);
R_Mesh_TexMatrix(0, &layer->texmatrix);
R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
}
else
{
R_Mesh_TexBind(0, 0);
- R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
}
// generate a color array for the fog pass
- R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- int i;
- float f;
- const float *v;
- float *c;
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
- {
- f = 1 - RSurf_FogVertex(v);
- c[0] = layer->color[0];
- c[1] = layer->color[1];
- c[2] = layer->color[2];
- c[3] = f * layer->color[3];
- }
- }
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
+ RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
+ RSurf_DrawBatch();
break;
default:
Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
}
}
-static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
+static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
{
+ int vi;
+ int j;
+ r_vertexgeneric_t *batchvertex;
float c[4];
GL_AlphaTest(false);
- R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
GL_DepthMask(writedepth);
}
- rsurface.lightmapcolor4f = NULL;
-
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
+ if (r_showsurfaces.integer == 3)
{
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
+ rsurface.passcolor4f = NULL;
- rsurface.lightmapcolor4f = NULL;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
- }
- else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
- {
- qboolean applycolor = true;
- float one = 1.0;
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
- RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
+ }
+ else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
+ {
+ qboolean applycolor = true;
+ float one = 1.0;
- r_refdef.lightmapintensity = 1;
- RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
- r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
- }
- else
- {
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
- rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
- rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
- rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
- }
+ r_refdef.lightmapintensity = 1;
+ RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
+ r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
+ }
+ else
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
- if(!rsurface.lightmapcolor4f)
- RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
+ rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
+ rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
+ rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
+ }
+
+ if(!rsurface.passcolor4f)
+ RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
- RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
- RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
- if(r_refdef.fogenabled)
- RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
+ RSurf_DrawBatch_GL11_ApplyAmbient();
+ RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
+ if(r_refdef.fogenabled)
+ RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
+ RSurf_DrawBatch_GL11_ClampColor();
- R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+ RSurf_DrawBatch();
+ }
+ else if (!r_refdef.view.showdebug)
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+ batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
+ for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
+ {
+ VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
+ Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
+ }
+ R_Mesh_PrepareVertices_Generic_Unlock();
+ RSurf_DrawBatch();
+ }
+ else if (r_showsurfaces.integer == 4)
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+ batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
+ for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
+ {
+ unsigned char c = vi << 3;
+ VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
+ Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
+ }
+ R_Mesh_PrepareVertices_Generic_Unlock();
+ RSurf_DrawBatch();
+ }
+ else if (r_showsurfaces.integer == 2)
+ {
+ const int *e;
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+ batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
+ for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
+ {
+ unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
+ VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
+ VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
+ VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
+ Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
+ Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
+ Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
+ }
+ R_Mesh_PrepareVertices_Generic_Unlock();
+ R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
+ }
+ else
+ {
+ int texturesurfaceindex;
+ int k;
+ const msurface_t *surface;
+ unsigned char surfacecolor4ub[4];
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+ batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
+ vi = 0;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ k = (int)(((size_t)surface) / sizeof(msurface_t));
+ Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
+ for (j = 0;j < surface->num_vertices;j++)
+ {
+ VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
+ Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
+ vi++;
+ }
+ }
+ R_Mesh_PrepareVertices_Generic_Unlock();
+ RSurf_DrawBatch();
+ }
}
static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
{
CHECKGLERROR
RSurf_SetupDepthAndCulling();
- if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
+ if (r_showsurfaces.integer)
{
- R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
+ R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
return;
}
switch (vid.renderpath)
{
CHECKGLERROR
RSurf_SetupDepthAndCulling();
- if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
+ if (r_showsurfaces.integer)
{
- R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
+ R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
return;
}
switch (vid.renderpath)
surface = rsurface.modelsurfaces + surfacelist[i];
texture = surface->texture;
rsurface.texture = R_GetCurrentTexture(texture);
- rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
+ rsurface.lightmaptexture = NULL;
+ rsurface.deluxemaptexture = NULL;
+ rsurface.uselightmaptexture = false;
// scan ahead until we find a different texture
endsurface = min(i + 1024, numsurfaces);
texturenumsurfaces = 0;
for (;j < endsurface;j++)
{
surface = rsurface.modelsurfaces + surfacelist[j];
- if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
+ if (texture != surface->texture)
break;
texturesurfacelist[texturenumsurfaces++] = surface;
}
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthMask(true);
GL_AlphaTest(false);
- R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
R_SetupShader_DepthOrShadow();
}
RSurf_SetupDepthAndCulling();
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
+ R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
+ RSurf_DrawBatch();
}
if (setup)
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
surface = rsurface.modelsurfaces + surfacelist[i];
texture = surface->texture;
rsurface.texture = R_GetCurrentTexture(texture);
+ rsurface.lightmaptexture = surface->lightmaptexture;
+ rsurface.deluxemaptexture = surface->deluxemaptexture;
rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
// scan ahead until we find a different texture
endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
for (;j < endsurface;j++)
{
surface = rsurface.modelsurfaces + surfacelist[j];
- if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
+ if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
break;
texturesurfacelist[texturenumsurfaces++] = surface;
}
}
}
+static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
+{
+ if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
+ return;
+ if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
+ return;
+ RSurf_SetupDepthAndCulling();
+ RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
+ R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
+ RSurf_DrawBatch();
+}
+
static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
{
const entity_render_t *queueentity = r_refdef.scene.worldentity;
CHECKGLERROR
if (depthonly)
- {
- if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
- return;
- if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
- return;
- RSurf_SetupDepthAndCulling();
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
- }
+ R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
else if (prepass)
{
if (!rsurface.texture->currentnumlayers)
else
R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
}
- else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
- {
- RSurf_SetupDepthAndCulling();
- GL_AlphaTest(false);
- R_Mesh_ColorPointer(NULL, 0, 0);
- R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
- GL_DepthMask(true);
- GL_BlendFunc(GL_ONE, GL_ZERO);
- GL_Color(0, 0, 0, 1);
- GL_DepthTest(writedepth);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
- }
- else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
- {
- RSurf_SetupDepthAndCulling();
- GL_AlphaTest(false);
- R_Mesh_ColorPointer(NULL, 0, 0);
- R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
- GL_DepthMask(true);
- GL_BlendFunc(GL_ONE, GL_ZERO);
- GL_DepthTest(true);
- RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
- }
- else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
+ else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
else if (!rsurface.texture->currentnumlayers)
return;
// use skin 1 instead)
texture = surfacelist[i]->texture;
rsurface.texture = R_GetCurrentTexture(texture);
+ rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
+ rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
{
continue;
}
// simply scan ahead until we find a different texture or lightmap state
- for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
+ for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
;
// render the range of surfaces
R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
{
CHECKGLERROR
if (depthonly)
- {
- if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
- return;
- if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
- return;
- RSurf_SetupDepthAndCulling();
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
- }
+ R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
else if (prepass)
{
if (!rsurface.texture->currentnumlayers)
else
R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
}
- else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
- {
- RSurf_SetupDepthAndCulling();
- GL_AlphaTest(false);
- R_Mesh_ColorPointer(NULL, 0, 0);
- R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
- GL_DepthMask(true);
- GL_BlendFunc(GL_ONE, GL_ZERO);
- GL_Color(0, 0, 0, 1);
- GL_DepthTest(writedepth);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
- }
- else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
- {
- RSurf_SetupDepthAndCulling();
- GL_AlphaTest(false);
- R_Mesh_ColorPointer(NULL, 0, 0);
- R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
- GL_DepthMask(true);
- GL_BlendFunc(GL_ONE, GL_ZERO);
- GL_DepthTest(true);
- RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
- }
- else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
+ else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
else if (!rsurface.texture->currentnumlayers)
return;
// use skin 1 instead)
texture = surfacelist[i]->texture;
rsurface.texture = R_GetCurrentTexture(texture);
+ rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
+ rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
{
continue;
}
// simply scan ahead until we find a different texture or lightmap state
- for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
+ for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
;
// render the range of surfaces
R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
GL_CullFace(GL_NONE);
R_EntityMatrix(&identitymatrix);
- R_Mesh_VertexPointer(vertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
i = surfacelist[0];
GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
for (j = 0;j < 3;j++, i++)
vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
- R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+ R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
}
void R_DrawLocs(void)
t2f[5] = decal->texcoord2f[2][1];
// update vertex positions for animated models
- if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
+ if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
{
e = rsurface.modelelement3i + 3*decal->triangleindex;
- VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
- VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
- VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
+ VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
+ VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
+ VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
}
else
{
// (this assumes they all use one particle font texture!)
RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
R_Mesh_ResetTextureState();
- R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
- R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
- R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
GL_DepthMask(false);
GL_DepthRange(0, 1);
GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
GL_CullFace(GL_NONE);
GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
- R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
+ R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
}
}
flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
- R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
GL_DepthRange(0, 1);
brush = model->brush.data_brushes + bihleaf->itemindex;
if (brush->colbrushf && brush->colbrushf->numtriangles)
{
- R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
- R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
+ R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
}
break;
case BIH_COLLISIONTRIANGLE:
VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
- R_Mesh_VertexPointer(vertex3f[0], 0, 0);
GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
- R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
+ R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
break;
case BIH_RENDERTRIANGLE:
triangleindex = bihleaf->itemindex;
VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
- R_Mesh_VertexPointer(vertex3f[0], 0, 0);
GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
- R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
+ R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
break;
}
}
rsurface.texture = R_GetCurrentTexture(surface->texture);
if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
{
- RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
if (r_showtris.value > 0)
{
if (!rsurface.texture->currentlayers->depthmask)
GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
else
GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
- R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
- R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
+ RSurf_DrawBatch();
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
CHECKGLERROR
}
qglBegin(GL_LINES);
for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
{
- VectorCopy(rsurface.vertex3f + l * 3, v);
+ VectorCopy(rsurface.batchvertex3f + l * 3, v);
GL_Color(r_refdef.view.colorscale, 0, 0, 1);
qglVertex3f(v[0], v[1], v[2]);
- VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
+ VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
GL_Color(r_refdef.view.colorscale, 1, 1, 1);
qglVertex3f(v[0], v[1], v[2]);
}
qglEnd();
CHECKGLERROR
}
- if (r_shownormals.value > 0)
+ if (r_shownormals.value > 0 && rsurface.batchsvector3f)
{
qglBegin(GL_LINES);
for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
{
- VectorCopy(rsurface.vertex3f + l * 3, v);
+ VectorCopy(rsurface.batchvertex3f + l * 3, v);
GL_Color(r_refdef.view.colorscale, 0, 0, 1);
qglVertex3f(v[0], v[1], v[2]);
- VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
+ VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
GL_Color(r_refdef.view.colorscale, 1, 1, 1);
qglVertex3f(v[0], v[1], v[2]);
}
qglBegin(GL_LINES);
for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
{
- VectorCopy(rsurface.vertex3f + l * 3, v);
+ VectorCopy(rsurface.batchvertex3f + l * 3, v);
GL_Color(0, r_refdef.view.colorscale, 0, 1);
qglVertex3f(v[0], v[1], v[2]);
- VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
+ VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
GL_Color(r_refdef.view.colorscale, 1, 1, 1);
qglVertex3f(v[0], v[1], v[2]);
}
qglBegin(GL_LINES);
for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
{
- VectorCopy(rsurface.vertex3f + l * 3, v);
+ VectorCopy(rsurface.batchvertex3f + l * 3, v);
GL_Color(0, 0, r_refdef.view.colorscale, 1);
qglVertex3f(v[0], v[1], v[2]);
- VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
+ VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
GL_Color(r_refdef.view.colorscale, 1, 1, 1);
qglVertex3f(v[0], v[1], v[2]);
}
return;
}
+ rsurface.lightmaptexture = NULL;
+ rsurface.deluxemaptexture = NULL;
rsurface.uselightmaptexture = false;
rsurface.texture = NULL;
rsurface.rtlight = NULL;
return;
}
+ rsurface.lightmaptexture = NULL;
+ rsurface.deluxemaptexture = NULL;
rsurface.uselightmaptexture = false;
rsurface.texture = NULL;
rsurface.rtlight = NULL;
// now render it
rsurface.texture = R_GetCurrentTexture(surface.texture);
+ rsurface.lightmaptexture = NULL;
+ rsurface.deluxemaptexture = NULL;
rsurface.uselightmaptexture = false;
R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
}
// now render it
rsurface.texture = R_GetCurrentTexture(surface.texture);
+ rsurface.lightmaptexture = NULL;
+ rsurface.deluxemaptexture = NULL;
rsurface.uselightmaptexture = false;
R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
}