From: havoc havoc@d7cf8633-e32d-0410-b094-e92efae38249 <> Date: Sat, 1 May 2010 16:48:33 +0000 (+0000) Subject: UNMERGE X-Git-Tag: xonotic-v0.1.0preview~166 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=e1779b0d4726405972ee9fcc4f342ece8b64dac7;p=xonotic%2Fdarkplaces.git UNMERGE overhauled vertex formats, now supports 100% interleaved arrays rendering mode, reworked vertexbuffer management to be a more robust system, added fully vertex buffered rendering options (gl_vbo_dynamicvertex, gl_vbo_dynamicindex) which are off by default (they seem to hurt fps in tests here) centralized handling of "generic" mesh rendering (fixed function stuff) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@10109 d7cf8633-e32d-0410-b094-e92efae38249 ::stable-branch::unmerge=38185bc1aea210514d6970e3c36a25ad97615e5f --- diff --git a/cl_particles.c b/cl_particles.c index 05f7b246..34489597 100644 --- a/cl_particles.c +++ b/cl_particles.c @@ -2309,11 +2309,15 @@ void R_DrawDecal_TransparentCallback(const entity_render_t *ent, const rtlight_t particletexture_t *tex; float right[3], up[3], size, ca; float alphascale = (1.0f / 65536.0f) * cl_particles_alpha.value; + float particle_vertex3f[BATCHSIZE*12], particle_texcoord2f[BATCHSIZE*8], particle_color4f[BATCHSIZE*16]; RSurf_ActiveWorldEntity(); r_refdef.stats.drawndecals += numsurfaces; R_Mesh_ResetTextureState(); + R_Mesh_VertexPointer(particle_vertex3f, 0, 0); + R_Mesh_TexCoordPointer(0, 2, particle_texcoord2f, 0, 0); + R_Mesh_ColorPointer(particle_color4f, 0, 0); GL_DepthMask(false); GL_DepthRange(0, 1); GL_PolygonOffset(0, 0); @@ -2370,8 +2374,7 @@ void R_DrawDecal_TransparentCallback(const entity_render_t *ent, const rtlight_t // (this assumes they all use one particle font texture!) GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); R_SetupShader_Generic(particletexture[63].texture, NULL, GL_MODULATE, 1); - R_Mesh_PrepareVertices_Generic_Arrays(numsurfaces * 4, particle_vertex3f, particle_color4f, particle_texcoord2f); - R_Mesh_Draw(0, numsurfaces * 4, 0, numsurfaces * 2, NULL, NULL, 0, particle_elements, NULL, 0); + R_Mesh_Draw(0, numsurfaces * 4, 0, numsurfaces * 2, NULL, particle_elements, 0, 0); } void R_DrawDecals (void) @@ -2474,6 +2477,9 @@ void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtligh r_refdef.stats.particles += numsurfaces; R_Mesh_ResetTextureState(); + R_Mesh_VertexPointer(particle_vertex3f, 0, 0); + R_Mesh_TexCoordPointer(0, 2, particle_texcoord2f, 0, 0); + R_Mesh_ColorPointer(particle_color4f, 0, 0); GL_DepthMask(false); GL_DepthRange(0, 1); GL_PolygonOffset(0, 0); @@ -2679,7 +2685,6 @@ void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtligh texture = NULL; batchstart = 0; batchcount = 0; - R_Mesh_PrepareVertices_Generic_Arrays(numsurfaces * 4, particle_vertex3f, particle_color4f, particle_texcoord2f); for (surfacelistindex = 0;surfacelistindex < numsurfaces;) { p = cl.particles + surfacelist[surfacelistindex]; @@ -2717,7 +2722,7 @@ void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtligh } batchcount = surfacelistindex - batchstart; - R_Mesh_Draw(batchstart * 4, batchcount * 4, batchstart * 2, batchcount * 2, NULL, NULL, 0, particle_elements, NULL, 0); + R_Mesh_Draw(batchstart * 4, batchcount * 4, batchstart * 2, batchcount * 2, NULL, particle_elements, 0, 0); } } diff --git a/cl_screen.c b/cl_screen.c index 73a4a44b..c09ad9ce 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -775,7 +775,6 @@ void R_TimeReport_EndFrame(void) "%7i lightmap updates (%7i pixels)\n" "%4i lights%4i clears%4i scissored%7i light%7i shadow%7i dynamic\n" "rendered%6i meshes%8i triangles bloompixels%8i copied%8i drawn\n" -"updated%5i indexbuffers%8i bytes%5i vertexbuffers%8i bytes\n" "%s" , loc ? "Location: " : "", loc ? loc->name : "" , r_refdef.stats.renders, r_refdef.view.origin[0], r_refdef.view.origin[1], r_refdef.view.origin[2], r_refdef.view.forward[0], r_refdef.view.forward[1], r_refdef.view.forward[2] @@ -785,7 +784,6 @@ void R_TimeReport_EndFrame(void) , r_refdef.stats.lightmapupdates, r_refdef.stats.lightmapupdatepixels , r_refdef.stats.lights, r_refdef.stats.lights_clears, r_refdef.stats.lights_scissored, r_refdef.stats.lights_lighttriangles, r_refdef.stats.lights_shadowtriangles, r_refdef.stats.lights_dynamicshadowtriangles , r_refdef.stats.meshes, r_refdef.stats.meshes_elements / 3, r_refdef.stats.bloom_copypixels, r_refdef.stats.bloom_drawpixels -, r_refdef.stats.indexbufferuploadcount, r_refdef.stats.indexbufferuploadsize, r_refdef.stats.vertexbufferuploadcount, r_refdef.stats.vertexbufferuploadsize , r_speeds_timestring); memset(&r_refdef.stats, 0, sizeof(r_refdef.stats)); @@ -1913,7 +1911,10 @@ static void SCR_DrawLoadingStack(void) GL_DepthRange(0, 1); GL_PolygonOffset(0, 0); GL_DepthTest(false); + R_Mesh_VertexPointer(verts, 0, 0); + R_Mesh_ColorPointer(colors, 0, 0); R_Mesh_ResetTextureState(); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); verts[2] = verts[5] = verts[8] = verts[11] = 0; verts[0] = verts[9] = 0; verts[1] = verts[4] = vid_conheight.integer - scr_loadingscreen_barheight.value; @@ -1931,9 +1932,7 @@ static void SCR_DrawLoadingStack(void) sscanf(scr_loadingscreen_barcolor.string, "%f %f %f", &colors[8], &colors[9], &colors[10]); colors[11] = 1; sscanf(scr_loadingscreen_barcolor.string, "%f %f %f", &colors[12], &colors[13], &colors[14]); colors[15] = 1; - R_Mesh_PrepareVertices_Generic_Arrays(4, verts, colors, NULL); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); // make sure everything is cleared, including the progress indicator if(loadingscreenheight < 8) @@ -1983,20 +1982,25 @@ static void SCR_DrawLoadingScreen_SharedSetup (qboolean clear) static void SCR_DrawLoadingScreen (qboolean clear) { // we only need to draw the image if it isn't already there + GL_Color(1,1,1,1); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_DepthRange(0, 1); GL_PolygonOffset(0, 0); GL_DepthTest(false); - R_Mesh_ResetTextureState(); - GL_Color(1,1,1,1); - R_Mesh_PrepareVertices_Generic_Arrays(4, loadingscreentexture_vertex3f, NULL, loadingscreentexture_texcoord2f); + R_Mesh_ColorPointer(NULL, 0, 0); if(loadingscreentexture) { + R_Mesh_VertexPointer(loadingscreentexture_vertex3f, 0, 0); + R_Mesh_ResetTextureState(); R_SetupShader_Generic(loadingscreentexture, NULL, GL_MODULATE, 1); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_TexCoordPointer(0, 2, loadingscreentexture_texcoord2f, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); } + R_Mesh_VertexPointer(loadingscreenpic_vertex3f, 0, 0); + R_Mesh_ResetTextureState(); R_SetupShader_Generic(loadingscreenpic->tex, NULL, GL_MODULATE, 1); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_TexCoordPointer(0, 2, loadingscreenpic_texcoord2f, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); SCR_DrawLoadingStack(); } diff --git a/client.h b/client.h index b90ca35b..848e4427 100644 --- a/client.h +++ b/client.h @@ -368,11 +368,6 @@ typedef struct entity_render_s float *animcache_normal3f; float *animcache_svector3f; float *animcache_tvector3f; - // interleaved arrays for rendering and dynamic vertex buffers for them - r_vertexposition_t *animcache_vertexposition; - r_meshbuffer_t *animcache_vertexpositionbuffer; - r_vertexmesh_t *animcache_vertexmesh; - r_meshbuffer_t *animcache_vertexmeshbuffer; // current lighting from map (updated ONLY by client code, not renderer) vec3_t modellight_ambient; @@ -1556,10 +1551,6 @@ typedef struct r_refdef_stats_s int bloom; int bloom_copypixels; int bloom_drawpixels; - int indexbufferuploadcount; - int indexbufferuploadsize; - int vertexbufferuploadcount; - int vertexbufferuploadsize; } r_refdef_stats_t; diff --git a/clvm_cmds.c b/clvm_cmds.c index cae5257c..3c3a984b 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -3075,7 +3075,9 @@ static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t R_Mesh_ResetTextureState(); R_EntityMatrix(&identitymatrix); GL_CullFace(GL_NONE); - R_Mesh_PrepareVertices_Generic_Arrays(polys->num_vertices, polys->data_vertex3f, polys->data_color4f, polys->data_texcoord2f); + R_Mesh_VertexPointer(polys->data_vertex3f, 0, 0); + R_Mesh_ColorPointer(polys->data_color4f, 0, 0); + R_Mesh_TexCoordPointer(0, 2, polys->data_texcoord2f, 0, 0); for (surfacelistindex = 0;surfacelistindex < numsurfaces;) { @@ -3092,7 +3094,7 @@ static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t VectorCopy(polys->data_triangles[surfacelist[surfacelistindex]].elements, polys->data_sortedelement3s + 3*numtriangles); numtriangles++; } - R_Mesh_Draw(0, polys->num_vertices, 0, numtriangles, NULL, NULL, 0, polys->data_sortedelement3s, NULL, 0); + R_Mesh_Draw(0, polys->num_vertices, 0, numtriangles, NULL, polys->data_sortedelement3s, 0, 0); } } diff --git a/gl_backend.c b/gl_backend.c index df64d630..bd2d4220 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -3,9 +3,9 @@ #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 = {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_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_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"}; @@ -15,8 +15,6 @@ cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater 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)"}; @@ -93,17 +91,23 @@ void GL_PrintError(int errornumber, char *filename, int linenumber) 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 { - 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; + const void *pointer_texcoord; 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; @@ -136,37 +140,14 @@ typedef struct gl_state_s int vertexbufferobject; int elementbufferobject; qboolean pointer_color_enabled; - - 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; + const void *pointer_vertex; + const void *pointer_color; 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; - 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; + memexpandablearray_t bufferobjectinfoarray; qboolean active; } @@ -245,11 +226,7 @@ static void gl_backend_start(void) { memset(&gl_state, 0, sizeof(gl_state)); - 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); + Mem_ExpandableArray_NewArray(&gl_state.bufferobjectinfoarray, r_main_mempool, sizeof(gl_bufferobjectinfo_t), 128); Con_DPrintf("OpenGL backend started.\n"); @@ -262,12 +239,7 @@ static void gl_backend_shutdown(void) { Con_DPrint("OpenGL Backend shutting down\n"); - 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); + Mem_ExpandableArray_FreeArray(&gl_state.bufferobjectinfoarray); memset(&gl_state, 0, sizeof(gl_state)); } @@ -309,15 +281,13 @@ void gl_backend_init(void) 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"); @@ -1064,10 +1034,6 @@ void R_Mesh_Start(void) { 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"); @@ -1173,84 +1139,46 @@ void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset) // 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 r_meshbuffer_t *element3i_indexbuffer, size_t element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, size_t element3s_bufferoffset) +void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int bufferobject3i, int bufferobject3s) { 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, %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"); + Con_DPrintf("R_Mesh_Draw(%d, %d, %d, %d, %8p, %8p, %i, %i);\n", firstvertex, numvertices, firsttriangle, numtriangles, (void *)element3i, (void *)element3s, bufferobject3i, bufferobject3s); return; } if (!gl_mesh_prefer_short_elements.integer) { if (element3i) element3s = NULL; - if (element3i_indexbuffer) - element3i_indexbuffer = NULL; + if (bufferobject3i) + bufferobject3s = 0; } - // adjust the pointers for firsttriangle if (element3i) element3i += firsttriangle * 3; - if (element3i_indexbuffer) - element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i); if (element3s) element3s += firsttriangle * 3; - 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))) - { - element3i_indexbuffer = NULL; - element3s_indexbuffer = NULL; - } - // upload a dynamic index buffer if needed - if (element3s) + switch (gl_vbo.integer) { - 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; - } + default: + case 0: + case 2: + bufferobject3i = bufferobject3s = 0; + break; + case 1: + break; + case 3: + if (firsttriangle) + bufferobject3i = bufferobject3s = 0; + break; } - 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; - // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array -#if 0 - unsigned int j, size; + unsigned int i, 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 @@ -1260,7 +1188,7 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri if (!qglIsEnabled(GL_VERTEX_ARRAY)) Con_Print("R_Mesh_Draw: vertex array not enabled\n"); CHECKGLERROR - if (gl_state.pointer_vertex_pointer) + if (gl_state.pointer_vertex) 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) @@ -1285,7 +1213,6 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri paranoidblah += *p; } } -#endif if (element3i) { for (i = 0;i < (unsigned int) numtriangles * 3;i++) @@ -1320,119 +1247,83 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri qglBegin(GL_TRIANGLES); for (i = 0;i < (unsigned int) numtriangles * 3;i++) { - if (element3i) - element = element3i[i]; - else if (element3s) - element = element3s[i]; - else - element = firstvertex + i; + element = element3i ? element3i[i] : element3s[i]; for (j = 0;j < vid.texarrayunits;j++) { - if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled) + if (gl_state.units[j].pointer_texcoord && gl_state.units[j].arrayenabled) { - if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT) + if (vid.texarrayunits > 1) { - 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) + if (gl_state.units[j].arraycomponents == 4) { - 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]); + 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 + else if (gl_state.units[j].arraycomponents == 3) { - 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]); + 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].pointer_texcoord_gltype == GL_SHORT) - { - 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) + else if (gl_state.units[j].arraycomponents == 2) { - 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]); + p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 2; + qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]); } else { - 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]); + p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 1; + qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]); } } - else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE) + else { - 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) + if (gl_state.units[j].arraycomponents == 4) + { + p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 4; + qglTexCoord4f(p[0], p[1], p[2], p[3]); + } + else if (gl_state.units[j].arraycomponents == 3) { - 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]); + p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 3; + qglTexCoord3f(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; + qglTexCoord2f(p[0], p[1]); } else { - 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]); + p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 1; + qglTexCoord1f(p[0]); } } } } - if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4) + if (gl_state.pointer_color && gl_state.pointer_color_enabled) { - 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_color)) + element * 4; + qglColor4f(p[0], p[1], p[2], p[3]); } + 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 @@ -1442,7 +1333,7 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri GL_BindEBO(bufferobject3s); if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) { - qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s); + qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3]))); CHECKGLERROR } else @@ -1456,7 +1347,7 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri GL_BindEBO(bufferobject3i); if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) { - qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i); + qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3]))); CHECKGLERROR } else @@ -1493,11 +1384,6 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri CHECKGLERROR } } - else - { - qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices); - CHECKGLERROR - } } } @@ -1506,91 +1392,52 @@ void R_Mesh_Finish(void) { } -r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic) +int R_Mesh_CreateStaticBufferObject(unsigned int target, void *data, size_t size, const char *name) { - 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) - { - 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: - 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; -} + gl_bufferobjectinfo_t *info; + GLuint bufferobject; -void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size) -{ - 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) + if (!gl_vbo.integer) + return 0; + + qglGenBuffersARB(1, &bufferobject); + switch(target) { - 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; + 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; } + 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; } -void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer) +void R_Mesh_DestroyBufferObject(int bufferobject) { - if (!buffer) - return; - switch(vid.renderpath) + int i, endindex; + gl_bufferobjectinfo_t *info; + + qglDeleteBuffersARB(1, (GLuint *)&bufferobject); + + endindex = Mem_ExpandableArray_IndexRange(&gl_state.bufferobjectinfoarray); + for (i = 0;i < endindex;i++) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: - qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject); - break; + 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; + } } - Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer); } void GL_Mesh_ListVBOs(qboolean printeach) @@ -1598,45 +1445,47 @@ void GL_Mesh_ListVBOs(qboolean printeach) int i, endindex; size_t ebocount = 0, ebomemory = 0; size_t vbocount = 0, vbomemory = 0; - r_meshbuffer_t *buffer; - endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray); + gl_bufferobjectinfo_t *info; + endindex = Mem_ExpandableArray_IndexRange(&gl_state.bufferobjectinfoarray); for (i = 0;i < endindex;i++) { - buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i); - if (!buffer) + info = (gl_bufferobjectinfo_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.bufferobjectinfoarray, i); + if (!info) continue; - 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)");} + 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; + } } - 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); + 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); } - - -void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset) +void R_Mesh_VertexPointer(const float *vertex3f, int bufferobject, size_t 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) + 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) { - 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 = vertex3f; + gl_state.pointer_vertex_buffer = bufferobject; gl_state.pointer_vertex_offset = bufferoffset; CHECKGLERROR GL_BindVBO(bufferobject); - qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR + qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), bufferobject ? (void *)bufferoffset : vertex3f);CHECKGLERROR } } -void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset) +void R_Mesh_ColorPointer(const float *color4f, int bufferobject, size_t bufferoffset) { - // note: vertexbuffer may be non-NULL even if pointer is NULL, so check - // the pointer only. - if (pointer) + // 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) { - int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0; + if (!gl_vbo.integer || gl_mesh_testarrayelement.integer) + bufferobject = 0; // caller wants color array enabled if (!gl_state.pointer_color_enabled) { @@ -1644,17 +1493,14 @@ void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void * CHECKGLERROR qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR } - 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) + if (gl_state.pointer_color != color4f || gl_state.pointer_color_buffer != bufferobject || gl_state.pointer_color_offset != bufferoffset) { - 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 = color4f; + gl_state.pointer_color_buffer = bufferobject; gl_state.pointer_color_offset = bufferoffset; CHECKGLERROR GL_BindVBO(bufferobject); - qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR + qglColorPointer(4, GL_FLOAT, sizeof(float[4]), bufferobject ? (void *)bufferoffset : color4f);CHECKGLERROR } } else @@ -1671,16 +1517,17 @@ void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void * } } -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) +void R_Mesh_TexCoordPointer(unsigned int unitnum, unsigned int numcomponents, const float *texcoord, int bufferobject, 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 (pointer) + if (texcoord) { - int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0; + if (!gl_vbo.integer || gl_mesh_testarrayelement.integer) + bufferobject = 0; // texture array unit is enabled, enable the array if (!unit->arrayenabled) { @@ -1689,17 +1536,15 @@ void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, si qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR } // texcoord array - 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) + if (unit->pointer_texcoord != texcoord || unit->pointer_texcoord_buffer != bufferobject || unit->pointer_texcoord_offset != bufferoffset || unit->arraycomponents != numcomponents) { - 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 = texcoord; + unit->pointer_texcoord_buffer = bufferobject; unit->pointer_texcoord_offset = bufferoffset; + unit->arraycomponents = numcomponents; GL_ClientActiveTexture(unitnum); GL_BindVBO(bufferobject); - qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR + qglTexCoordPointer(unit->arraycomponents, GL_FLOAT, sizeof(float) * unit->arraycomponents, bufferobject ? (void *)bufferoffset : texcoord);CHECKGLERROR } } else @@ -2084,467 +1929,3 @@ void R_Mesh_ResetTextureState(void) 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; - } -} diff --git a/gl_backend.h b/gl_backend.h index 952cecd7..6643c29f 100644 --- a/gl_backend.h +++ b/gl_backend.h @@ -59,36 +59,28 @@ void R_Mesh_Start(void); // (only valid after R_Mesh_Start) void R_Mesh_Finish(void); - -// vertex buffer and index buffer creation/updating/freeing -r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic); -void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size); -void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer); +// allocates a static element array buffer object +// (storing triangle data in video memory) +int R_Mesh_CreateStaticEBO(void *data, size_t size); +// frees an element array buffer object +void R_Mesh_DestroyEBO(int bufferobject); +// allocates a static vertex/element array buffer object +// (storing vertex or element data in video memory) +// target is GL_ELEMENT_ARRAY_BUFFER_ARB (triangle elements) +// or GL_ARRAY_BUFFER_ARB (vertex data) +int R_Mesh_CreateStaticBufferObject(unsigned int target, void *data, size_t size, const char *name); +// frees a vertex/element array buffer object +void R_Mesh_DestroyBufferObject(int bufferobject); void GL_Mesh_ListVBOs(qboolean printeach); -r_vertexposition_t *R_Mesh_PrepareVertices_Position_Lock(int numvertices); -qboolean R_Mesh_PrepareVertices_Position_Unlock(void); // if this returns false, you need to prepare the mesh again! -void R_Mesh_PrepareVertices_Position_Arrays(int numvertices, const float *vertex3f); -void R_Mesh_PrepareVertices_Position(int numvertices, const r_vertexposition_t *vertex, const r_meshbuffer_t *buffer); - -r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices); -qboolean R_Mesh_PrepareVertices_Generic_Unlock(void); -void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f); -void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer); - -r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices); -qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void); // if this returns false, you need to prepare the mesh again! -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); -void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *buffer); - // sets up the requested vertex transform matrix void R_EntityMatrix(const matrix4x4_t *matrix); // sets the vertex array pointer -void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset); +void R_Mesh_VertexPointer(const float *vertex3f, int bufferobject, size_t bufferoffset); // sets the color array pointer (GL_Color only works when this is NULL) -void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset); +void R_Mesh_ColorPointer(const float *color4f, int bufferobject, size_t bufferoffset); // sets the texcoord array pointer for an array unit -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); +void R_Mesh_TexCoordPointer(unsigned int unitnum, unsigned int numcomponents, const float *texcoord, int bufferobject, size_t bufferoffset); // returns current texture bound to this identifier int R_Mesh_TexBound(unsigned int unitnum, int id); // copies a section of the framebuffer to a 2D texture @@ -103,7 +95,7 @@ void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, i void R_Mesh_ResetTextureState(void); // renders a mesh -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); +void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int bufferobject3i, int bufferobject3s); // saves a section of the rendered frame to a .tga or .jpg file qboolean SCR_ScreenShot(char *filename, unsigned char *buffer1, unsigned char *buffer2, int x, int y, int width, int height, qboolean flipx, qboolean flipy, qboolean flipdiagonal, qboolean jpeg, qboolean png, qboolean gammacorrect, qboolean keep_alpha); diff --git a/gl_draw.c b/gl_draw.c index 7a05e3a3..6821819c 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -1046,21 +1046,16 @@ void DrawQ_ProcessDrawFlag(int flags, qboolean alpha) void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, float red, float green, float blue, float alpha, int flags) { - float floats[36]; + float floats[20]; _DrawQ_SetupAndProcessDrawFlag(flags, pic, alpha); if(!r_draw2d.integer && !r_draw2d_force) return; + GL_Color(red, green, blue, alpha); + R_Mesh_VertexPointer(floats, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); - floats[12] = 0.0f;floats[13] = 0.0f; - floats[14] = 1.0f;floats[15] = 0.0f; - floats[16] = 1.0f;floats[17] = 1.0f; - floats[18] = 0.0f;floats[19] = 1.0f; - floats[20] = floats[24] = floats[28] = floats[32] = red; - floats[21] = floats[25] = floats[29] = floats[33] = green; - floats[22] = floats[26] = floats[30] = floats[34] = blue; - floats[23] = floats[27] = floats[31] = floats[35] = alpha; if (pic) { if (width == 0) @@ -1068,8 +1063,14 @@ void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, flo if (height == 0) height = pic->height; R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1); - -#if 0 + R_Mesh_TexCoordPointer(0, 2, floats + 12, 0, 0); + +#if 1 + floats[12] = 0.0f;floats[13] = 0.0f; + floats[14] = 1.0f;floats[15] = 0.0f; + floats[16] = 1.0f;floats[17] = 1.0f; + floats[18] = 0.0f;floats[19] = 1.0f; +#else // AK07: lets be texel correct on the corners { float horz_offset = 0.5f / pic->width; @@ -1091,13 +1092,12 @@ void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, flo floats[3] = floats[6] = x + width; floats[7] = floats[10] = y + height; - R_Mesh_PrepareVertices_Generic_Arrays(4, floats, floats + 20, floats + 12); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); } void DrawQ_RotPic(float x, float y, cachepic_t *pic, float width, float height, float org_x, float org_y, float angle, float red, float green, float blue, float alpha, int flags) { - float floats[36]; + float floats[20]; float af = DEG2RAD(-angle); // forward float ar = DEG2RAD(-angle + 90); // right float sinaf = sin(af); @@ -1108,7 +1108,10 @@ void DrawQ_RotPic(float x, float y, cachepic_t *pic, float width, float height, _DrawQ_SetupAndProcessDrawFlag(flags, pic, alpha); if(!r_draw2d.integer && !r_draw2d_force) return; + GL_Color(red, green, blue, alpha); + R_Mesh_VertexPointer(floats, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); if (pic) { @@ -1117,6 +1120,12 @@ void DrawQ_RotPic(float x, float y, cachepic_t *pic, float width, float height, if (height == 0) height = pic->height; R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1); + R_Mesh_TexCoordPointer(0, 2, floats + 12, 0, 0); + + floats[12] = 0.0f;floats[13] = 0.0f; + floats[14] = 1.0f;floats[15] = 0.0f; + floats[16] = 1.0f;floats[17] = 1.0f; + floats[18] = 0.0f;floats[19] = 1.0f; } else R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); @@ -1139,27 +1148,20 @@ void DrawQ_RotPic(float x, float y, cachepic_t *pic, float width, float height, floats[9] = x - cosaf*org_x + cosar*(height-org_y); floats[10] = y - sinaf*org_x + sinar*(height-org_y); - floats[12] = 0.0f;floats[13] = 0.0f; - floats[14] = 1.0f;floats[15] = 0.0f; - floats[16] = 1.0f;floats[17] = 1.0f; - floats[18] = 0.0f;floats[19] = 1.0f; - floats[20] = floats[24] = floats[28] = floats[32] = red; - floats[21] = floats[25] = floats[29] = floats[33] = green; - floats[22] = floats[26] = floats[30] = floats[34] = blue; - floats[23] = floats[27] = floats[31] = floats[35] = alpha; - - R_Mesh_PrepareVertices_Generic_Arrays(4, floats, floats + 20, floats + 12); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); } void DrawQ_Fill(float x, float y, float width, float height, float red, float green, float blue, float alpha, int flags) { - float floats[36]; + float floats[12]; _DrawQ_SetupAndProcessDrawFlag(flags, NULL, alpha); if(!r_draw2d.integer && !r_draw2d_force) return; + GL_Color(red, green, blue, alpha); + R_Mesh_VertexPointer(floats, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); @@ -1168,17 +1170,8 @@ void DrawQ_Fill(float x, float y, float width, float height, float red, float gr floats[1] = floats[4] = y; floats[3] = floats[6] = x + width; floats[7] = floats[10] = y + height; - floats[12] = 0.0f;floats[13] = 0.0f; - floats[14] = 1.0f;floats[15] = 0.0f; - floats[16] = 1.0f;floats[17] = 1.0f; - floats[18] = 0.0f;floats[19] = 1.0f; - floats[20] = floats[24] = floats[28] = floats[32] = red; - floats[21] = floats[25] = floats[29] = floats[33] = green; - floats[22] = floats[26] = floats[30] = floats[34] = blue; - floats[23] = floats[27] = floats[31] = floats[35] = alpha; - - R_Mesh_PrepareVertices_Generic_Arrays(4, floats, floats + 20, floats + 12); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); } /// color tag printing @@ -1485,9 +1478,12 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma if(!r_draw2d.integer && !r_draw2d_force) return startx + DrawQ_TextWidth_UntilWidth_TrackColors_Scale(text, &maxlen, w, h, sw, sh, NULL, ignorecolorcodes, fnt, 1000000000); + R_Mesh_ColorPointer(color4f, 0, 0); R_Mesh_ResetTextureState(); if (!fontmap) R_Mesh_TexBind(0, fnt->tex); + R_Mesh_TexCoordPointer(0, 2, texcoord2f, 0, 0); + R_Mesh_VertexPointer(vertex3f, 0, 0); R_SetupShader_Generic(fnt->tex, NULL, GL_MODULATE, 1); ac = color4f; @@ -1617,8 +1613,7 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma if (batchcount) { // switching from freetype to non-freetype rendering - R_Mesh_PrepareVertices_Generic_Arrays(batchcount * 4, vertex3f, color4f, texcoord2f); - R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, NULL, 0, quadelement3s, NULL, 0); + R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, quadelement3s, 0, 0); batchcount = 0; ac = color4f; at = texcoord2f; @@ -1655,8 +1650,7 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma batchcount++; if (batchcount >= QUADELEMENTS_MAXQUADS) { - R_Mesh_PrepareVertices_Generic_Arrays(batchcount * 4, vertex3f, color4f, texcoord2f); - R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, NULL, 0, quadelement3s, NULL, 0); + R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, quadelement3s, 0, 0); batchcount = 0; ac = color4f; at = texcoord2f; @@ -1670,8 +1664,7 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma if (batchcount) { // we need a different character map, render what we currently have: - R_Mesh_PrepareVertices_Generic_Arrays(batchcount * 4, vertex3f, color4f, texcoord2f); - R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, NULL, 0, quadelement3s, NULL, 0); + R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, quadelement3s, 0, 0); batchcount = 0; ac = color4f; at = texcoord2f; @@ -1730,8 +1723,7 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma batchcount++; if (batchcount >= QUADELEMENTS_MAXQUADS) { - R_Mesh_PrepareVertices_Generic_Arrays(batchcount * 4, vertex3f, color4f, texcoord2f); - R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, NULL, 0, quadelement3s, NULL, 0); + R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, quadelement3s, 0, 0); batchcount = 0; ac = color4f; at = texcoord2f; @@ -1749,10 +1741,7 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma } } if (batchcount > 0) - { - R_Mesh_PrepareVertices_Generic_Arrays(batchcount * 4, vertex3f, color4f, texcoord2f); - R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, NULL, 0, quadelement3s, NULL, 0); - } + R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, quadelement3s, 0, 0); if (outcolor) *outcolor = colorindex; @@ -1829,6 +1818,8 @@ void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height if(!r_draw2d.integer && !r_draw2d_force) return; + R_Mesh_VertexPointer(floats, 0, 0); + R_Mesh_ColorPointer(floats + 20, 0, 0); R_Mesh_ResetTextureState(); if (pic) { @@ -1837,6 +1828,11 @@ void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height if (height == 0) height = pic->height; R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1); + R_Mesh_TexCoordPointer(0, 2, floats + 12, 0, 0); + floats[12] = s1;floats[13] = t1; + floats[14] = s2;floats[15] = t2; + floats[16] = s4;floats[17] = t4; + floats[18] = s3;floats[19] = t3; } else R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); @@ -1846,17 +1842,12 @@ void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height floats[1] = floats[4] = y; floats[3] = floats[6] = x + width; floats[7] = floats[10] = y + height; - floats[12] = s1;floats[13] = t1; - floats[14] = s2;floats[15] = t2; - floats[16] = s4;floats[17] = t4; - floats[18] = s3;floats[19] = t3; floats[20] = r1;floats[21] = g1;floats[22] = b1;floats[23] = a1; floats[24] = r2;floats[25] = g2;floats[26] = b2;floats[27] = a2; floats[28] = r4;floats[29] = g4;floats[30] = b4;floats[31] = a4; floats[32] = r3;floats[33] = g3;floats[34] = b3;floats[35] = a3; - R_Mesh_PrepareVertices_Generic_Arrays(4, floats, floats + 20, floats + 12); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); } void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags, qboolean hasalpha) @@ -1867,11 +1858,13 @@ void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags, qboolean hasalpha) return; DrawQ_ProcessDrawFlag(flags, hasalpha); + R_Mesh_VertexPointer(mesh->data_vertex3f, 0, 0); + R_Mesh_ColorPointer(mesh->data_color4f, 0, 0); R_Mesh_ResetTextureState(); + R_Mesh_TexCoordPointer(0, 2, mesh->data_texcoord2f, 0, 0); R_SetupShader_Generic(mesh->texture, NULL, GL_MODULATE, 1); - R_Mesh_PrepareVertices_Generic_Arrays(mesh->num_vertices, mesh->data_vertex3f, mesh->data_color4f, mesh->data_texcoord2f); - R_Mesh_Draw(0, mesh->num_vertices, 0, mesh->num_triangles, mesh->data_element3i, NULL, 0, mesh->data_element3s, NULL, 0); + R_Mesh_Draw(0, mesh->num_vertices, 0, mesh->num_triangles, mesh->data_element3i, mesh->data_element3s, 0, 0); } void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags) @@ -1967,6 +1960,8 @@ void R_DrawGamma(void) break; } // all the blends ignore depth + R_Mesh_VertexPointer(blendvertex3f, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); GL_DepthMask(true); @@ -1986,9 +1981,8 @@ void R_DrawGamma(void) GL_BlendFunc(GL_DST_COLOR, GL_ONE); while (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f) { - GL_Color(c[0] - 1, c[1] - 1, c[2] - 1, 1); - R_Mesh_PrepareVertices_Generic_Arrays(3, blendvertex3f, NULL, NULL); - R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + GL_Color(bound(0, c[0] - 1, 1), bound(0, c[1] - 1, 1), bound(0, c[2] - 1, 1), 1); + R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0); VectorScale(c, 0.5, c); } } @@ -2003,9 +1997,8 @@ void R_DrawGamma(void) if (c[0] >= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f) { GL_BlendFunc(GL_ONE, GL_ONE); - GL_Color(c[0] - 1, c[1] - 1, c[2] - 1, 1); - R_Mesh_PrepareVertices_Generic_Arrays(3, blendvertex3f, NULL, NULL); - R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + GL_Color(c[0], c[1], c[2], 1); + R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0); } } diff --git a/gl_rmain.c b/gl_rmain.c index a9c9a06b..7cae34d3 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -170,6 +170,7 @@ cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces 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"}; @@ -656,7 +657,7 @@ static const char *builtinshaderstring = " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n" " TexCoord1 = gl_MultiTexCoord0.xy;\n" "#ifdef USEBLOOM\n" -" TexCoord2 = gl_MultiTexCoord4.xy;\n" +" TexCoord2 = gl_MultiTexCoord1.xy;\n" "#endif\n" "}\n" "#endif\n" @@ -1939,7 +1940,7 @@ const char *builtincgshaderstring = "float4 gl_Vertex : POSITION,\n" "uniform float4x4 ModelViewProjectionMatrix,\n" "float4 gl_MultiTexCoord0 : TEXCOORD0,\n" -"float4 gl_MultiTexCoord1 : TEXCOORD4,\n" +"float4 gl_MultiTexCoord1 : TEXCOORD1,\n" "out float4 gl_Position : POSITION,\n" "out float2 TexCoord1 : TEXCOORD0,\n" "out float2 TexCoord2 : TEXCOORD1\n" @@ -4578,7 +4579,6 @@ extern rtexture_t *r_shadow_prepassgeometrydepthtexture; extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture; extern rtexture_t *r_shadow_prepasslightingdiffusetexture; extern rtexture_t *r_shadow_prepasslightingspeculartexture; -extern cvar_t gl_mesh_separatearrays; static qboolean R_BlendFuncAllowsColormod(int src, int dst) { // a blendfunc allows colormod if: @@ -4674,7 +4674,7 @@ static qboolean R_BlendFuncAllowsColormod(int src, int dst) return false; } } -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) +void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass) { // select a permutation of the lighting shader appropriate to this // combination of texture, entity, light source, and fogging, only use the @@ -4698,6 +4698,12 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, 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); allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO); @@ -4725,6 +4731,15 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, 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); allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO); @@ -4784,6 +4799,24 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } 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); allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE); @@ -4833,6 +4866,24 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, 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); allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); @@ -4890,6 +4941,21 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, 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); allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); @@ -4940,6 +5006,21 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, 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); allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); @@ -5003,6 +5084,11 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, 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) { @@ -5015,16 +5101,41 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, 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); @@ -5035,22 +5146,6 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, 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) @@ -5181,22 +5276,6 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, 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) @@ -6560,6 +6639,7 @@ void GL_Main_Init(void) 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) @@ -6827,41 +6907,6 @@ void R_AnimCache_ClearCache(void) 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? } } @@ -6872,7 +6917,7 @@ qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qbool // see if it's already cached this frame if (ent->animcache_vertex3f) { - // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc) + // add normals/tangents if needed if (wantnormals || wanttangents) { if (ent->animcache_normal3f) @@ -6890,10 +6935,7 @@ qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qbool 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); - } } } } @@ -6913,10 +6955,7 @@ qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qbool 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; } @@ -6924,7 +6963,7 @@ qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qbool void R_AnimCache_CacheVisibleEntities(void) { int i; - qboolean wantnormals = true; + qboolean wantnormals = !r_showsurfaces.integer; qboolean wanttangents = !r_showsurfaces.integer; switch(vid.renderpath) @@ -6938,9 +6977,6 @@ void R_AnimCache_CacheVisibleEntities(void) break; } - if (r_shownormals.integer) - wanttangents = wantnormals = true; - // TODO: thread this // NOTE: R_PrepareRTLights() also caches entities @@ -7972,10 +8008,10 @@ void R_Bloom_CopyBloomTexture(float colorscale) R_SetViewport(&r_bloomstate.viewport); GL_BlendFunc(GL_ONE, GL_ZERO); GL_Color(colorscale, colorscale, colorscale, 1); - R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f); - // TODO: do boxfilter scale-down in shader? + // TODO: optimize with multitexture or GLSL + R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0); R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; // we now have a bloom image in the framebuffer @@ -7998,6 +8034,8 @@ void R_Bloom_MakeTexture(void) 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 @@ -8008,10 +8046,10 @@ void R_Bloom_MakeTexture(void) 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); - R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f); + GL_Color(r, r, r, 1); R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; // copy the vertically blurred bloom view to a texture @@ -8027,6 +8065,7 @@ void R_Bloom_MakeTexture(void) 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++) { @@ -8058,8 +8097,7 @@ void R_Bloom_MakeTexture(void) if(range >= 1) r *= (1 - x*x/(float)(range*range)); GL_Color(r, r, r, 1); - 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_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; GL_BlendFunc(GL_ONE, GL_ONE); } @@ -8074,18 +8112,18 @@ void R_Bloom_MakeTexture(void) 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_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + 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_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_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; qglBlendEquationEXT(GL_FUNC_ADD_EXT); @@ -8171,6 +8209,8 @@ static void R_BlendView(void) 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)) { @@ -8205,9 +8245,9 @@ static void R_BlendView(void) { 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_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; } } @@ -8223,11 +8263,12 @@ static void R_BlendView(void) { // apply a color tint to the whole view R_ResetViewRendering2D(); - 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_Mesh_VertexPointer(r_screenvertex3f, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + 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); } break; // no screen processing, no bloom, skip it } @@ -8251,9 +8292,12 @@ static void R_BlendView(void) 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) { @@ -8290,7 +8334,7 @@ static void R_BlendView(void) default: break; } - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; break; case RENDERPATH_GL13: @@ -8299,11 +8343,12 @@ static void R_BlendView(void) { // apply a color tint to the whole view R_ResetViewRendering2D(); - 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_Mesh_VertexPointer(r_screenvertex3f, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + 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); } break; } @@ -8895,10 +8940,11 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2; } } - R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL); + R_Mesh_VertexPointer(vertex3f, 0, 0); + R_Mesh_ColorPointer(color4f, 0, 0); R_Mesh_ResetTextureState(); R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); - R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0); + R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0); } static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) @@ -9044,7 +9090,9 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight 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]; @@ -9056,7 +9104,7 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight { for (i = 0, c = color4f;i < 6;i++, c += 4) { - f1 = RSurf_FogVertex(nomodelvertex3f + 3*i); + f1 = RSurf_FogVertex(rsurface.vertex3f + 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); @@ -9064,8 +9112,7 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight } } R_Mesh_ResetTextureState(); - R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL); - R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0); + R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0); } void R_DrawNoModel(entity_render_t *ent) @@ -9517,7 +9564,7 @@ texture_t *R_GetCurrentTexture(texture_t *t) } else { - t->backgroundbasetexture = r_texture_white; + t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white; t->backgroundnmaptexture = r_texture_blanknormalmap; t->backgroundglosstexture = r_texture_black; t->backgroundglowtexture = NULL; @@ -9667,51 +9714,24 @@ rsurfacestate_t rsurface; void R_Mesh_ResizeArrays(int newvertices) { - unsigned char *base; - size_t size; + float *base; if (rsurface.array_size >= newvertices) return; - if (rsurface.array_base) - Mem_Free(rsurface.array_base); + if (rsurface.array_modelvertex3f) + Mem_Free(rsurface.array_modelvertex3f); rsurface.array_size = (newvertices + 1023) & ~1023; - 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]); + 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; } void RSurf_ActiveWorldEntity(void) @@ -9753,80 +9773,48 @@ void RSurf_ActiveWorldEntity(void) rsurface.basepolygonfactor = r_refdef.polygonfactor; rsurface.basepolygonoffset = r_refdef.polygonoffset; rsurface.modelvertex3f = model->surfmesh.data_vertex3f; - rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo; rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f; rsurface.modelsvector3f = model->surfmesh.data_svector3f; - rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo; rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f; rsurface.modeltvector3f = model->surfmesh.data_tvector3f; - rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo; rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f; rsurface.modelnormal3f = model->surfmesh.data_normal3f; - rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo; rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f; rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f; - rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo; rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f; rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f; - rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo; rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f; rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f; - rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo; 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.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer; - rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset; + rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i; + rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s; rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets; - rsurface.modelnumvertices = model->surfmesh.num_vertices; - rsurface.modelnumtriangles = model->surfmesh.num_triangles; + rsurface.modelnum_vertices = model->surfmesh.num_vertices; + rsurface.modelnum_triangles = model->surfmesh.num_triangles; rsurface.modelsurfaces = model->data_surfaces; - 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; + 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; } void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass) @@ -9879,10 +9867,6 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q 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) { @@ -9891,10 +9875,6 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q 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) { @@ -9903,10 +9883,6 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q 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 { @@ -9915,115 +9891,77 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q 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_vertexbuffer = 0; + rsurface.modelvertex3f_bufferobject = 0; rsurface.modelvertex3f_bufferoffset = 0; - rsurface.modelsvector3f_vertexbuffer = 0; + rsurface.modelsvector3f_bufferobject = 0; rsurface.modelsvector3f_bufferoffset = 0; - rsurface.modeltvector3f_vertexbuffer = 0; + rsurface.modeltvector3f_bufferobject = 0; rsurface.modeltvector3f_bufferoffset = 0; - rsurface.modelnormal3f_vertexbuffer = 0; + rsurface.modelnormal3f_bufferobject = 0; rsurface.modelnormal3f_bufferoffset = 0; - rsurface.modelgeneratedvertex = true; + rsurface.generatedvertex = true; } else { rsurface.modelvertex3f = model->surfmesh.data_vertex3f; - rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo; rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f; rsurface.modelsvector3f = model->surfmesh.data_svector3f; - rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo; rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f; rsurface.modeltvector3f = model->surfmesh.data_tvector3f; - rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo; rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f; rsurface.modelnormal3f = model->surfmesh.data_normal3f; - rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo; rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f; - rsurface.modelvertexmesh = model->surfmesh.vertexmesh; - rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer; - rsurface.modelvertexposition = model->surfmesh.vertexposition; - rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer; - rsurface.modelgeneratedvertex = false; + rsurface.generatedvertex = false; } rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f; - rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo; rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f; rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f; - rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo; rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f; rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f; - rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo; 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.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer; - rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset; + rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i; + rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s; rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets; - rsurface.modelnumvertices = model->surfmesh.num_vertices; - rsurface.modelnumtriangles = model->surfmesh.num_triangles; + rsurface.modelnum_vertices = model->surfmesh.num_vertices; + rsurface.modelnum_triangles = model->surfmesh.num_triangles; rsurface.modelsurfaces = model->data_surfaces; - 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; + 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; } 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.modelnumvertices = numvertices; - rsurface.modelnumtriangles = numtriangles; - if (rsurface.array_size < rsurface.modelnumvertices) - R_Mesh_ResizeArrays(rsurface.modelnumvertices); + rsurface.modelnum_vertices = numvertices; + rsurface.modelnum_triangles = numtriangles; + if (rsurface.array_size < rsurface.modelnum_vertices) + R_Mesh_ResizeArrays(rsurface.modelnum_vertices); rsurface.matrix = *matrix; rsurface.inversematrix = *inversematrix; rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix); @@ -10068,108 +10006,50 @@ void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inve rsurface.modeltvector3f = NULL; rsurface.modelnormal3f = NULL; } - rsurface.modelvertexmesh = NULL; - rsurface.modelvertexmeshbuffer = NULL; - rsurface.modelvertexposition = NULL; - rsurface.modelvertexpositionbuffer = NULL; - rsurface.modelvertex3f_vertexbuffer = 0; + rsurface.modelvertex3f_bufferobject = 0; rsurface.modelvertex3f_bufferoffset = 0; - rsurface.modelsvector3f_vertexbuffer = 0; + rsurface.modelsvector3f_bufferobject = 0; rsurface.modelsvector3f_bufferoffset = 0; - rsurface.modeltvector3f_vertexbuffer = 0; + rsurface.modeltvector3f_bufferobject = 0; rsurface.modeltvector3f_bufferoffset = 0; - rsurface.modelnormal3f_vertexbuffer = 0; + rsurface.modelnormal3f_bufferobject = 0; rsurface.modelnormal3f_bufferoffset = 0; - rsurface.modelgeneratedvertex = true; + rsurface.generatedvertex = true; rsurface.modellightmapcolor4f = color4f; - rsurface.modellightmapcolor4f_vertexbuffer = 0; + rsurface.modellightmapcolor4f_bufferobject = 0; rsurface.modellightmapcolor4f_bufferoffset = 0; rsurface.modeltexcoordtexture2f = texcoord2f; - rsurface.modeltexcoordtexture2f_vertexbuffer = 0; + rsurface.modeltexcoordtexture2f_bufferobject = 0; rsurface.modeltexcoordtexture2f_bufferoffset = 0; rsurface.modeltexcoordlightmap2f = NULL; - rsurface.modeltexcoordlightmap2f_vertexbuffer = 0; + rsurface.modeltexcoordlightmap2f_bufferobject = 0; rsurface.modeltexcoordlightmap2f_bufferoffset = 0; rsurface.modelelement3i = element3i; - rsurface.modelelement3i_indexbuffer = NULL; - rsurface.modelelement3i_bufferoffset = 0; rsurface.modelelement3s = element3s; - rsurface.modelelement3s_indexbuffer = NULL; - rsurface.modelelement3s_bufferoffset = 0; + rsurface.modelelement3i_bufferobject = 0; + rsurface.modelelement3s_bufferobject = 0; rsurface.modellightmapoffsets = NULL; rsurface.modelsurfaces = NULL; - 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) + 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) { if ((wantnormals || wanttangents) && !normal3f) - { - Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0); - rsurface.modelnormal3f = rsurface.array_modelnormal3f; - } + Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0); if (wanttangents && !svector3f) - { - 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); + 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); } } @@ -10205,456 +10085,70 @@ float RSurf_FogVertex(const float *v) 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}}; -extern cvar_t gl_vbo; -void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist) +void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist) { int deformindex; - 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 texturesurfaceindex; 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; - 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 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) { - switch (deform->deform) + if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT) + generatenormals = true; + for (i = 0;i < Q3MAXDEFORMS;i++) { - 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 + if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE) { - for (j = 0;j < surfacenumvertices;j++) - { - Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1); - numvertices++; - } + generatetangents = true; + generatenormals = true; } - } - } - + 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), modify the copied vertices - // in place + // 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) for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++) { switch (deform->deform) @@ -10678,36 +10172,41 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const VectorNormalize(newforward); VectorNormalize(newright); VectorNormalize(newup); - // a single autosprite surface can contain multiple sprites... - for (j = 0;j < rsurface.batchnumvertices - 3;j += 4) + // make deformed versions of only the model vertices used by the specified surfaces + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - 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++) + const msurface_t *surface = texturesurfacelist[texturesurfaceindex]; + // a single autosprite surface can contain multiple sprites... + for (j = 0;j < surface->num_vertices - 3;j += 4) { - 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)); + 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); + } } + 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); } - 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; + 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; break; case Q3DEFORM_AUTOSPRITE2: Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward); @@ -10716,7 +10215,10 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const 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; @@ -10729,18 +10231,25 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const shortest[2]; memset(shortest, 0, sizeof(shortest)); // a single autosprite surface can contain multiple sprites... - for (j = 0;j < rsurface.batchnumvertices - 3;j += 4) + 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); + VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, 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.batchvertex3f + 3*(j+quadedges[i][0]); - v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]); + 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 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]) @@ -10761,6 +10270,13 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const } 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); @@ -10775,6 +10291,20 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const 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 @@ -10788,49 +10318,54 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const l = DotProduct(right, center); for (i = 0;i < 4;i++) { - v1 = rsurface.batchvertex3f + 3*(j+i); + v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i); f = DotProduct(right, v1) - l; - VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i)); + VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3); } } + 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); } - 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; + 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; break; case Q3DEFORM_NORMAL: // deform the normals to make reflections wavey - for (j = 0;j < rsurface.batchnumvertices;j++) + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - 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); + 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); } - 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; + 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; break; case Q3DEFORM_WAVE: // deform vertex array to make wavey water and flags and such @@ -10843,52 +10378,40 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const // 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 (j = 0;j < rsurface.batchnumvertices;j++) + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - // if the wavefunc depends on time, evaluate it per-vertex - if (waveparms[3]) + const msurface_t *surface = texturesurfacelist[texturesurfaceindex]; + for (j = 0;j < surface->num_vertices;j++) { - 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); + 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); } - VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j); } - 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; + rsurface.vertex3f = rsurface.array_deformedvertex3f; + rsurface.vertex3f_bufferobject = 0; + rsurface.vertex3f_bufferoffset = 0; break; case Q3DEFORM_BULGE: // deform vertex array to make the surface have moving bulges - for (j = 0;j < rsurface.batchnumvertices;j++) + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - 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); + 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)); + } } - 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; + rsurface.vertex3f = rsurface.array_deformedvertex3f; + rsurface.vertex3f_bufferobject = 0; + rsurface.vertex3f_bufferoffset = 0; break; case Q3DEFORM_MOVE: // deform vertex array @@ -10896,68 +10419,83 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const break; // if wavefunc is a nop, don't make a dynamic vertex array scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms); VectorScale(deform->parms, scale, waveparms); - 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; + 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; 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: - 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; + rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f; + rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject; + rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset; break; case Q3TCGEN_VECTOR: - for (j = 0;j < rsurface.batchnumvertices;j++) + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - 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); + 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.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f; - rsurface.batchtexcoordtexture2f_vertexbuffer = NULL; - rsurface.batchtexcoordtexture2f_bufferoffset = 0; + rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f; + rsurface.texcoordtexture2f_bufferobject = 0; + rsurface.texcoordtexture2f_bufferoffset = 0; break; case Q3TCGEN_ENVIRONMENT: // make environment reflections using a spheremap - for (j = 0;j < rsurface.batchnumvertices;j++) + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - // identical to Q3A's method, but executed in worldspace so - // carried models can be shiny too + 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 - float viewer[3], d, reflected[3], worldreflected[3]; + float viewer[3], d, reflected[3], worldreflected[3]; - VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer); - // VectorNormalize(viewer); + VectorSubtract(rsurface.localvieworigin, vertex, viewer); + // VectorNormalize(viewer); - d = DotProduct(rsurface.batchnormal3f + 3*j, viewer); + d = DotProduct(normal, viewer); - 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 + 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 - 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. - rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1]; - rsurface.array_batchtexcoordtexture2f[j*2+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. + out_tc[0] = 0.5 + 0.5 * worldreflected[1]; + out_tc[1] = 0.5 - 0.5 * worldreflected[2]; + } } - rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f; - rsurface.batchtexcoordtexture2f_vertexbuffer = NULL; - rsurface.batchtexcoordtexture2f_bufferoffset = 0; + rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f; + rsurface.texcoordtexture2f_bufferobject = 0; + rsurface.texcoordtexture2f_bufferoffset = 0; break; } // the only tcmod that needs software vertex processing is turbulent, so @@ -10969,86 +10507,116 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const { 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 (j = 0;j < rsurface.batchnumvertices;j++) + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - 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); + 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.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f; - rsurface.batchtexcoordtexture2f_vertexbuffer = NULL; - rsurface.batchtexcoordtexture2f_bufferoffset = 0; + rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f; + rsurface.texcoordtexture2f_bufferobject = 0; + rsurface.texcoordtexture2f_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); +} - if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) +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) { - // 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) + #define MAXBATCHTRIANGLES 65536 + int batchtriangles = 0; + static int batchelements[MAXBATCHTRIANGLES*3]; + for (i = 0;i < texturenumsurfaces;i = j) { - for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++) + surface = texturesurfacelist[i]; + j = i + 1; + if (surface->num_triangles > MAXBATCHTRIANGLES) { - VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f); - VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f); + 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); } + 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); } - - if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION) + else if (r_batchmode.integer == 1) { - // 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); + 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 + { + 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); + } } } -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) +static void RSurf_BindLightmapForSurface(const msurface_t *surface) { switch(vid.renderpath) { case RENDERPATH_CGGL: #ifdef SUPPORTCG - 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 + 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 #endif break; case RENDERPATH_GL20: - 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); + 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); break; case RENDERPATH_GL13: case RENDERPATH_GL11: - R_Mesh_TexBind(0, rsurface.lightmaptexture); + R_Mesh_TexBind(0, surface->lightmaptexture); break; } } -static void RSurf_BindReflectionForBatch(void) +static void RSurf_BindReflectionForSurface(const msurface_t *surface) { // pick the closest matching water plane and bind textures int planeindex, vertexindex; @@ -11063,7 +10631,7 @@ static void RSurf_BindReflectionForBatch(void) if(p->camera_entity != rsurface.texture->camera_entity) continue; d = 0; - for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3) + for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3) { Matrix4x4_Transform(&rsurface.matrix, v, vert); d += fabs(PlaneDiff(vert, &p->plane)); @@ -11094,170 +10662,376 @@ static void RSurf_BindReflectionForBatch(void) } } -static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void) +static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist) { int i; - 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; + 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); + } } -static void RSurf_DrawBatch_GL11_ApplyFog(void) +static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist) { + 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.passcolor4f) + if (rsurface.lightmapcolor4f) { - // 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) + // generate color arrays for the surfaces in this list + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - f = RSurf_FogVertex(v); - c2[0] = c[0] * f; - c2[1] = c[1] * f; - c2[2] = c[2] * f; - c2[3] = c[3]; + 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]; + } } } else { - for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4) + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - f = RSurf_FogVertex(v); - c2[0] = f; - c2[1] = f; - c2[2] = f; - c2[3] = 1; + 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; + } } } - rsurface.passcolor4f = rsurface.array_passcolor4f; - rsurface.passcolor4f_vertexbuffer = 0; - rsurface.passcolor4f_bufferoffset = 0; + rsurface.lightmapcolor4f = rsurface.array_color4f; + rsurface.lightmapcolor4f_bufferobject = 0; + rsurface.lightmapcolor4f_bufferoffset = 0; } -static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void) +static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist) { + int texturesurfaceindex; int i; float f; const float *v; const float *c; float *c2; - if (!rsurface.passcolor4f) + if (!rsurface.lightmapcolor4f) return; - 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) + // generate color arrays for the surfaces in this list + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - 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]; + 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]; + } } - rsurface.passcolor4f = rsurface.array_passcolor4f; - rsurface.passcolor4f_vertexbuffer = 0; - rsurface.passcolor4f_bufferoffset = 0; + rsurface.lightmapcolor4f = rsurface.array_color4f; + rsurface.lightmapcolor4f_bufferobject = 0; + rsurface.lightmapcolor4f_bufferoffset = 0; } -static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a) +static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a) { + int texturesurfaceindex; int i; const float *c; float *c2; - if (!rsurface.passcolor4f) + if (!rsurface.lightmapcolor4f) return; - for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4) + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - c2[0] = c[0] * r; - c2[1] = c[1] * g; - c2[2] = c[2] * b; - c2[3] = c[3] * a; + 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; + } } - rsurface.passcolor4f = rsurface.array_passcolor4f; - rsurface.passcolor4f_vertexbuffer = 0; - rsurface.passcolor4f_bufferoffset = 0; + rsurface.lightmapcolor4f = rsurface.array_color4f; + rsurface.lightmapcolor4f_bufferobject = 0; + rsurface.lightmapcolor4f_bufferoffset = 0; } -static void RSurf_DrawBatch_GL11_ApplyAmbient(void) +static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist) { + int texturesurfaceindex; int i; const float *c; float *c2; - if (!rsurface.passcolor4f) + if (!rsurface.lightmapcolor4f) return; - for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4) + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - 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]; + 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]; + } } - rsurface.passcolor4f = rsurface.array_passcolor4f; - rsurface.passcolor4f_vertexbuffer = 0; - rsurface.passcolor4f_bufferoffset = 0; + rsurface.lightmapcolor4f = rsurface.array_color4f; + rsurface.lightmapcolor4f_bufferobject = 0; + rsurface.lightmapcolor4f_bufferoffset = 0; } -static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog) +static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog) { // TODO: optimize - 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); + 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); GL_Color(r, g, b, a); - RSurf_BindLightmapForBatch(); - RSurf_DrawBatch(); + RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist); } -static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog) +static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, 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.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); + 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); GL_Color(r, g, b, a); - RSurf_DrawBatch(); + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); } -static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog) -{ - // TODO: optimize - 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) +static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog) { + int texturesurfaceindex; 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) + 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 { - 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); + rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f; + rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject; + rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset; } + 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(float *r, float *g, float *b, float *a, qboolean *applycolor) +static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor) { + int texturesurfaceindex; int i; float f; float alpha; @@ -11278,24 +11052,33 @@ static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f; diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f; alpha = *a; - if (VectorLength2(diffusecolor) > 0) + if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f) { - // 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) + // generate color arrays for the surfaces in this list + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - if ((f = DotProduct(n, lightdir)) > 0) - VectorMA(ambientcolor, f, diffusecolor, c); - else - VectorCopy(ambientcolor, c); - c[3] = alpha; + 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; + } } *r = 1; *g = 1; *b = 1; *a = 1; - rsurface.passcolor4f = rsurface.array_passcolor4f; - rsurface.passcolor4f_vertexbuffer = 0; - rsurface.passcolor4f_bufferoffset = 0; + rsurface.lightmapcolor4f = rsurface.array_color4f; + rsurface.lightmapcolor4f_bufferobject = 0; + rsurface.lightmapcolor4f_bufferoffset = 0; *applycolor = false; } else @@ -11303,36 +11086,20 @@ static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, *r = ambientcolor[0]; *g = ambientcolor[1]; *b = ambientcolor[2]; - rsurface.passcolor4f = NULL; - rsurface.passcolor4f_vertexbuffer = 0; - rsurface.passcolor4f_bufferoffset = 0; + rsurface.lightmapcolor4f = NULL; + rsurface.lightmapcolor4f_bufferobject = 0; + rsurface.lightmapcolor4f_bufferoffset = 0; } } -static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog) +static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog) { - 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); + 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); GL_Color(r, g, b, a); - 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; - } + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); } void RSurf_SetupDepthAndCulling(void) @@ -11363,6 +11130,8 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_ // 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) { @@ -11372,19 +11141,15 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_ // 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_DrawBatch(); + RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); if (skyrendermasked) GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1); } @@ -11398,50 +11163,50 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface { 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, texturenumsurfaces, texturesurfacelist); - RSurf_DrawBatch(); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY); + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); } 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, texturenumsurfaces, texturesurfacelist); - RSurf_BindReflectionForBatch(); - if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) - RSurf_BindLightmapForBatch(); - RSurf_DrawBatch(); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND); + RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist); GL_DepthMask(false); - R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE); if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) - RSurf_BindLightmapForBatch(); - RSurf_DrawBatch(); + RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist); + else + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); } 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, texturenumsurfaces, texturesurfacelist); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE); if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) - RSurf_BindReflectionForBatch(); - if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) - RSurf_BindLightmapForBatch(); - RSurf_DrawBatch(); + 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); } } 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(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); + RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist); for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++) { @@ -11476,7 +11241,7 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface } layercolor[3] = layer->color[3]; applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1; - R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED); switch (layer->type) { @@ -11485,27 +11250,27 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface 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, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset); + R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_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, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset); + R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset); if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) - RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog); + RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog); else if (rsurface.uselightmaptexture) - RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog); + RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog); else - RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog); + RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 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, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset); + R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset); R_Mesh_TexBind(1, 0); - 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); + R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0); + RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog); break; case TEXTURELAYERTYPE_FOG: // singletexture fogging @@ -11514,19 +11279,34 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface 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, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset); + R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset); } else { R_Mesh_TexBind(0, 0); - R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0); + R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0); } R_Mesh_TexBind(1, 0); - R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0); + R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0); // generate a color array for the fog pass - 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(); + 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); break; default: Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type); @@ -11543,11 +11323,11 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface 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(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); + RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist); for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++) { @@ -11563,7 +11343,7 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface } GL_DepthMask(layer->depthmask && writedepth); GL_BlendFunc(layer->blendfunc1, layer->blendfunc2); - R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED); switch (layer->type) { @@ -11575,20 +11355,20 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface 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, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset); + R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset); if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) - RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false); + RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false); else if (rsurface.uselightmaptexture) - RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false); + RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false); else - RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false); + RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 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, 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); + 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); } else { @@ -11596,11 +11376,11 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface 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, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset); + R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset); if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) - 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); + 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); else - 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); + 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); } break; case TEXTURELAYERTYPE_TEXTURE: @@ -11608,8 +11388,8 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface 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, 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); + 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); break; case TEXTURELAYERTYPE_FOG: // singletexture fogging @@ -11618,17 +11398,32 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface 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, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset); + R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset); } else { R_Mesh_TexBind(0, 0); - R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0); + R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0); } // generate a color array for the fog pass - 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(); + 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); break; default: Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type); @@ -11642,14 +11437,12 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface } } -static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth) +static void R_DrawTextureSurfaceList_ShowSurfaces3(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); @@ -11707,127 +11500,55 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const GL_DepthMask(writedepth); } - if (r_showsurfaces.integer == 3) - { - rsurface.passcolor4f = NULL; - - if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) - { - RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 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; + rsurface.lightmapcolor4f = NULL; - RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); - - 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); - - 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(); - 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_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) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) { - 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(); + RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); + + rsurface.lightmapcolor4f = NULL; + rsurface.lightmapcolor4f_bufferobject = 0; + rsurface.lightmapcolor4f_bufferoffset = 0; } - else if (r_showsurfaces.integer == 2) + else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) { - 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); + qboolean applycolor = true; + float one = 1.0; + + RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist); + + 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 { - 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(); + RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); + + rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f; + rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject; + rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset; } + + if(!rsurface.lightmapcolor4f) + RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist); + + 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); + + R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset); + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); } static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass) { CHECKGLERROR RSurf_SetupDepthAndCulling(); - if (r_showsurfaces.integer) + if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)) { - R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth); + R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth); return; } switch (vid.renderpath) @@ -11850,9 +11571,9 @@ static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface { CHECKGLERROR RSurf_SetupDepthAndCulling(); - if (r_showsurfaces.integer) + if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)) { - R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth); + R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth); return; } switch (vid.renderpath) @@ -11911,9 +11632,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const surface = rsurface.modelsurfaces + surfacelist[i]; texture = surface->texture; rsurface.texture = R_GetCurrentTexture(texture); - rsurface.lightmaptexture = NULL; - rsurface.deluxemaptexture = NULL; - rsurface.uselightmaptexture = false; + rsurface.uselightmaptexture = surface->lightmaptexture != NULL; // scan ahead until we find a different texture endsurface = min(i + 1024, numsurfaces); texturenumsurfaces = 0; @@ -11921,7 +11640,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const for (;j < endsurface;j++) { surface = rsurface.modelsurfaces + surfacelist[j]; - if (texture != surface->texture) + if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL)) break; texturesurfacelist[texturenumsurfaces++] = surface; } @@ -11937,13 +11656,13 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const 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(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist); - R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer); - RSurf_DrawBatch(); + RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); } if (setup) GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1); @@ -11955,8 +11674,6 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const 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); @@ -11965,7 +11682,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const for (;j < endsurface;j++) { surface = rsurface.modelsurfaces + surfacelist[j]; - if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture) + if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL)) break; texturesurfacelist[texturenumsurfaces++] = surface; } @@ -12002,24 +11719,20 @@ static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const } } -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) - R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, 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(false, false, texturenumsurfaces, texturesurfacelist); + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); + } else if (prepass) { if (!rsurface.texture->currentnumlayers) @@ -12029,7 +11742,34 @@ static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurf else R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass); } - else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer) + 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) R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist); else if (!rsurface.texture->currentnumlayers) return; @@ -12061,8 +11801,6 @@ void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, in // 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)) { @@ -12072,7 +11810,7 @@ void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, in continue; } // simply scan ahead until we find a different texture or lightmap state - for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++) + for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++) ; // render the range of surfaces R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass); @@ -12083,7 +11821,15 @@ static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurf { CHECKGLERROR if (depthonly) - R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, 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(false, false, texturenumsurfaces, texturesurfacelist); + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); + } else if (prepass) { if (!rsurface.texture->currentnumlayers) @@ -12093,7 +11839,34 @@ static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurf else R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass); } - else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer) + 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) R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist); else if (!rsurface.texture->currentnumlayers) return; @@ -12125,8 +11898,6 @@ void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurfa // 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)) { @@ -12136,7 +11907,7 @@ void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurfa continue; } // simply scan ahead until we find a different texture or lightmap state - for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++) + for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++) ; // render the range of surfaces R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass); @@ -12178,7 +11949,10 @@ void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, in 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, @@ -12201,9 +11975,7 @@ void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, in for (j = 0;j < 3;j++, i++) vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i]; - 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); + R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0); } void R_DrawLocs(void) @@ -12766,12 +12538,12 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent) t2f[5] = decal->texcoord2f[2][1]; // update vertex positions for animated models - if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles) + if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles) { e = rsurface.modelelement3i + 3*decal->triangleindex; - VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f); - VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3); - VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6); + VectorCopy(rsurface.vertex3f + 3*e[0], v3f); + VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3); + VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6); } else { @@ -12804,7 +12576,9 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent) // (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_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f); + R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0); + R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0); + R_Mesh_ColorPointer(decalsystem->color4f, 0, 0); GL_DepthMask(false); GL_DepthRange(0, 1); GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value); @@ -12812,7 +12586,7 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent) 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, NULL, 0, decalsystem->element3s, NULL, 0); + R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0); } } @@ -12863,6 +12637,7 @@ void R_DrawDebugModel(void) 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); @@ -12891,9 +12666,9 @@ void R_DrawDebugModel(void) 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_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); + R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0); } break; case BIH_COLLISIONTRIANGLE: @@ -12901,18 +12676,18 @@ void R_DrawDebugModel(void) 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_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL); - R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 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_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL); - R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0); break; } } @@ -12939,7 +12714,7 @@ void R_DrawDebugModel(void) rsurface.texture = R_GetCurrentTexture(surface->texture); if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles) { - RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface); + RSurf_PrepareVerticesForBatch(true, true, 1, &surface); if (r_showtris.value > 0) { if (!rsurface.texture->currentlayers->depthmask) @@ -12948,9 +12723,12 @@ void R_DrawDebugModel(void) 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_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL); + R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); + R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0); qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - RSurf_DrawBatch(); + //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); qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL); CHECKGLERROR } @@ -12959,25 +12737,25 @@ void R_DrawDebugModel(void) qglBegin(GL_LINES); for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++) { - VectorCopy(rsurface.batchvertex3f + l * 3, v); + VectorCopy(rsurface.vertex3f + 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.batchsvector3f + l * 3, v); + VectorMA(v, -r_shownormals.value, rsurface.svector3f + 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 && rsurface.batchsvector3f) + if (r_shownormals.value > 0) { qglBegin(GL_LINES); for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++) { - VectorCopy(rsurface.batchvertex3f + l * 3, v); + VectorCopy(rsurface.vertex3f + 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.batchsvector3f + l * 3, v); + VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v); GL_Color(r_refdef.view.colorscale, 1, 1, 1); qglVertex3f(v[0], v[1], v[2]); } @@ -12986,10 +12764,10 @@ void R_DrawDebugModel(void) qglBegin(GL_LINES); for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++) { - VectorCopy(rsurface.batchvertex3f + l * 3, v); + VectorCopy(rsurface.vertex3f + 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.batchtvector3f + l * 3, v); + VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v); GL_Color(r_refdef.view.colorscale, 1, 1, 1); qglVertex3f(v[0], v[1], v[2]); } @@ -12998,10 +12776,10 @@ void R_DrawDebugModel(void) qglBegin(GL_LINES); for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++) { - VectorCopy(rsurface.batchvertex3f + l * 3, v); + VectorCopy(rsurface.vertex3f + 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.batchnormal3f + l * 3, v); + VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v); GL_Color(r_refdef.view.colorscale, 1, 1, 1); qglVertex3f(v[0], v[1], v[2]); } @@ -13065,8 +12843,6 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep return; } - rsurface.lightmaptexture = NULL; - rsurface.deluxemaptexture = NULL; rsurface.uselightmaptexture = false; rsurface.texture = NULL; rsurface.rtlight = NULL; @@ -13197,8 +12973,6 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr return; } - rsurface.lightmaptexture = NULL; - rsurface.deluxemaptexture = NULL; rsurface.uselightmaptexture = false; rsurface.texture = NULL; rsurface.rtlight = NULL; @@ -13268,8 +13042,6 @@ void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, i // now render it rsurface.texture = R_GetCurrentTexture(surface.texture); - rsurface.lightmaptexture = NULL; - rsurface.deluxemaptexture = NULL; rsurface.uselightmaptexture = false; R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass); } @@ -13289,8 +13061,6 @@ void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatri // now render it rsurface.texture = R_GetCurrentTexture(surface.texture); - rsurface.lightmaptexture = NULL; - rsurface.deluxemaptexture = NULL; rsurface.uselightmaptexture = false; R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass); } diff --git a/gl_rsurf.c b/gl_rsurf.c index 615119ba..d3b941aa 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -349,7 +349,10 @@ static void R_DrawPortal_Callback(const entity_render_t *ent, const rtlight_t *r numpoints = min(portal->numpoints, POLYGONELEMENTS_MAXPOINTS); + R_Mesh_VertexPointer(vertex3f, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); isvis = (portal->here->clusterindex >= 0 && portal->past->clusterindex >= 0 && portal->here->clusterindex != portal->past->clusterindex); @@ -360,9 +363,7 @@ static void R_DrawPortal_Callback(const entity_render_t *ent, const rtlight_t *r isvis ? 0.125f : 0.03125f); for (i = 0, v = vertex3f;i < numpoints;i++, v += 3) VectorCopy(portal->points[i].position, v); - R_Mesh_PrepareVertices_Generic_Arrays(numpoints, vertex3f, NULL, NULL); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); - R_Mesh_Draw(0, numpoints, 0, numpoints - 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_Draw(0, numpoints, 0, numpoints - 2, polygonelement3i, polygonelement3s, 0, 0); } // LordHavoc: this is just a nice debugging tool, very slow @@ -610,6 +611,7 @@ void R_Q1BSP_DrawDepth(entity_render_t *ent) GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); GL_AlphaTest(false); + R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); R_SetupShader_DepthOrShadow(); if (ent == r_refdef.scene.worldentity) @@ -1084,10 +1086,10 @@ void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, const vec3_t relativelightor rsurface.texture = R_GetCurrentTexture(surface->texture); if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NOSHADOW) continue; - RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface); - R_Shadow_MarkVolumeFromBox(surface->num_firsttriangle, surface->num_triangles, rsurface.batchvertex3f, rsurface.modelelement3i, relativelightorigin, relativelightdirection, lightmins, lightmaxs, surface->mins, surface->maxs); + RSurf_PrepareVerticesForBatch(false, false, 1, &surface); + R_Shadow_MarkVolumeFromBox(surface->num_firsttriangle, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i, relativelightorigin, relativelightdirection, lightmins, lightmaxs, surface->mins, surface->maxs); } - R_Shadow_VolumeFromList(model->surfmesh.num_vertices, model->surfmesh.num_triangles, rsurface.batchvertex3f, model->surfmesh.data_element3i, model->surfmesh.data_neighbor3i, relativelightorigin, relativelightdirection, projectdistance, numshadowmark, shadowmarklist, ent->mins, ent->maxs); + R_Shadow_VolumeFromList(model->surfmesh.num_vertices, model->surfmesh.num_triangles, rsurface.vertex3f, model->surfmesh.data_element3i, model->surfmesh.data_neighbor3i, relativelightorigin, relativelightdirection, projectdistance, numshadowmark, shadowmarklist, ent->mins, ent->maxs); } if (ent->model->brush.submodel) GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset); @@ -1157,9 +1159,8 @@ void R_Q1BSP_DrawShadowMap(int side, entity_render_t *ent, const vec3_t relative } --modelsurfacelistindex; GL_CullFace(rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE ? GL_NONE : r_refdef.view.cullface_back); - RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, batchnumsurfaces, batchsurfacelist); - R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer); - RSurf_DrawBatch(); + RSurf_PrepareVerticesForBatch(false, false, batchnumsurfaces, batchsurfacelist); + RSurf_DrawBatch_Simple(batchnumsurfaces, batchsurfacelist); } } @@ -1170,7 +1171,7 @@ static void R_Q1BSP_DrawLight_TransparentCallback(const entity_render_t *ent, co int i, j, endsurface; texture_t *t; const msurface_t *surface; - // note: in practice this never actually receives batches + // note: in practice this never actually receives batches), oh well R_Shadow_RenderMode_Begin(); R_Shadow_RenderMode_ActiveLight(rtlight); R_Shadow_RenderMode_Lighting(false, true, false); @@ -1187,7 +1188,8 @@ static void R_Q1BSP_DrawLight_TransparentCallback(const entity_render_t *ent, co surface = rsurface.modelsurfaces + surfacelist[j]; if (t != surface->texture) break; - R_Shadow_RenderLighting(1, &surface); + RSurf_PrepareVerticesForBatch(true, true, 1, &surface); + R_Shadow_RenderLighting(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, ent->model->surfmesh.data_element3s, ent->model->surfmesh.ebo3i, ent->model->surfmesh.ebo3s); } } R_Shadow_RenderMode_End(); @@ -1198,9 +1200,9 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, int numsurfaces, const int *surface { dp_model_t *model = ent->model; const msurface_t *surface; - int i, k, kend, l, endsurface, batchnumsurfaces, texturenumsurfaces; - const msurface_t **texturesurfacelist; + int i, k, kend, l, m, mend, endsurface, batchnumsurfaces, batchnumtriangles, batchfirstvertex, batchlastvertex, batchfirsttriangle; const int *element3i; + static int batchelements[BATCHSIZE*3]; texture_t *tex; CHECKGLERROR element3i = rsurface.modelelement3i; @@ -1254,9 +1256,45 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, int numsurfaces, const int *surface } if (r_shadow_usingdeferredprepass) continue; - texturenumsurfaces = kend - k; - texturesurfacelist = batchsurfacelist + k; - R_Shadow_RenderLighting(texturenumsurfaces, texturesurfacelist); + batchnumtriangles = 0; + batchfirsttriangle = surface->num_firsttriangle; + m = 0; // hush warning + for (l = k;l < kend;l++) + { + surface = batchsurfacelist[l]; + RSurf_PrepareVerticesForBatch(true, true, 1, &surface); + for (m = surface->num_firsttriangle, mend = m + surface->num_triangles;m < mend;m++) + { + if (lighttrispvs && r_test.integer && !CHECKPVSBIT(lighttrispvs, m)) + continue; + if (batchnumtriangles >= BATCHSIZE) + { + r_refdef.stats.lights_lighttriangles += batchnumtriangles; + Mod_VertexRangeFromElements(batchnumtriangles*3, batchelements, &batchfirstvertex, &batchlastvertex); + // use the element buffer if all triangles are consecutive + if (m == batchfirsttriangle + batchnumtriangles) + R_Shadow_RenderLighting(batchfirstvertex, batchlastvertex + 1 - batchfirstvertex, batchfirsttriangle, batchnumtriangles, ent->model->surfmesh.data_element3i, ent->model->surfmesh.data_element3s, ent->model->surfmesh.ebo3i, ent->model->surfmesh.ebo3s); + else + R_Shadow_RenderLighting(batchfirstvertex, batchlastvertex + 1 - batchfirstvertex, 0, batchnumtriangles, batchelements, NULL, 0, 0); + batchnumtriangles = 0; + batchfirsttriangle = m; + } + batchelements[batchnumtriangles*3+0] = element3i[m*3+0]; + batchelements[batchnumtriangles*3+1] = element3i[m*3+1]; + batchelements[batchnumtriangles*3+2] = element3i[m*3+2]; + batchnumtriangles++; + } + } + if (batchnumtriangles > 0) + { + r_refdef.stats.lights_lighttriangles += batchnumtriangles; + Mod_VertexRangeFromElements(batchnumtriangles*3, batchelements, &batchfirstvertex, &batchlastvertex); + // use the element buffer if all triangles are consecutive + if (m == batchfirsttriangle + batchnumtriangles) + R_Shadow_RenderLighting(batchfirstvertex, batchlastvertex + 1 - batchfirstvertex, batchfirsttriangle, batchnumtriangles, ent->model->surfmesh.data_element3i, ent->model->surfmesh.data_element3s, ent->model->surfmesh.ebo3i, ent->model->surfmesh.ebo3s); + else + R_Shadow_RenderLighting(batchfirstvertex, batchlastvertex + 1 - batchfirstvertex, 0, batchnumtriangles, batchelements, NULL, 0, 0); + } } } } diff --git a/glquake.h b/glquake.h index 4e7ceb8a..bd3e133c 100644 --- a/glquake.h +++ b/glquake.h @@ -636,14 +636,12 @@ extern void (GLAPIENTRY *qglColorMask)(GLboolean red, GLboolean green, GLboolean extern void (GLAPIENTRY *qglDrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); extern void (GLAPIENTRY *qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); -extern void (GLAPIENTRY *qglDrawArrays)(GLenum mode, GLint first, GLsizei count); extern void (GLAPIENTRY *qglVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); extern void (GLAPIENTRY *qglNormalPointer)(GLenum type, GLsizei stride, const GLvoid *ptr); extern void (GLAPIENTRY *qglColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); extern void (GLAPIENTRY *qglTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); extern void (GLAPIENTRY *qglArrayElement)(GLint i); -extern void (GLAPIENTRY *qglColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); extern void (GLAPIENTRY *qglColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); extern void (GLAPIENTRY *qglTexCoord1f)(GLfloat s); extern void (GLAPIENTRY *qglTexCoord2f)(GLfloat s, GLfloat t); @@ -651,7 +649,6 @@ extern void (GLAPIENTRY *qglTexCoord3f)(GLfloat s, GLfloat t, GLfloat r); extern void (GLAPIENTRY *qglTexCoord4f)(GLfloat s, GLfloat t, GLfloat r, GLfloat q); extern void (GLAPIENTRY *qglVertex2f)(GLfloat x, GLfloat y); extern void (GLAPIENTRY *qglVertex3f)(GLfloat x, GLfloat y, GLfloat z); -extern void (GLAPIENTRY *qglVertex4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); extern void (GLAPIENTRY *qglBegin)(GLenum mode); extern void (GLAPIENTRY *qglEnd)(void); diff --git a/mathlib.h b/mathlib.h index d8a902d4..8832e062 100644 --- a/mathlib.h +++ b/mathlib.h @@ -83,7 +83,6 @@ unsigned int CeilPowerOf2(unsigned int value); #define Vector2Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1]) #define Vector2Negate(a,b) ((b)[0]=-((a)[0]),(b)[1]=-((a)[1])) #define Vector2Set(a,b,c,d,e) ((a)[0]=(b),(a)[1]=(c)) -#define Vector2Scale(in, scale, out) ((out)[0] = (in)[0] * (scale),(out)[1] = (in)[1] * (scale)) #define Vector2Normalize2(v,dest) {float ilength = (float) sqrt(DotProduct2((v),(v)));if (ilength) ilength = 1.0f / ilength;dest[0] = (v)[0] * ilength;dest[1] = (v)[1] * ilength;} #define DotProduct4(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2]+(a)[3]*(b)[3]) @@ -95,7 +94,6 @@ unsigned int CeilPowerOf2(unsigned int value); #define Vector4Normalize2(v,dest) {float ilength = (float) sqrt(DotProduct4((v),(v)));if (ilength) ilength = 1.0f / ilength;dest[0] = (v)[0] * ilength;dest[1] = (v)[1] * ilength;dest[2] = (v)[2] * ilength;dest[3] = (v)[3] * ilength;} #define Vector4Subtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3]) #define Vector4Add(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3]) -#define Vector4Scale(in, scale, out) ((out)[0] = (in)[0] * (scale),(out)[1] = (in)[1] * (scale),(out)[2] = (in)[2] * (scale),(out)[3] = (in)[3] * (scale)) #define Vector4Multiply(a,b,c) ((c)[0]=(a)[0]*(b)[0],(c)[1]=(a)[1]*(b)[1],(c)[2]=(a)[2]*(b)[2],(c)[3]=(a)[3]*(b)[3]) #define Vector4MA(a, scale, b, c) ((c)[0] = (a)[0] + (scale) * (b)[0],(c)[1] = (a)[1] + (scale) * (b)[1],(c)[2] = (a)[2] + (scale) * (b)[2],(c)[3] = (a)[3] + (scale) * (b)[3]) #define Vector4Lerp(v1,lerp,v2,c) ((c)[0] = (v1)[0] + (lerp) * ((v2)[0] - (v1)[0]), (c)[1] = (v1)[1] + (lerp) * ((v2)[1] - (v1)[1]), (c)[2] = (v1)[2] + (lerp) * ((v2)[2] - (v1)[2]), (c)[3] = (v1)[3] + (lerp) * ((v2)[3] - (v1)[3])) diff --git a/model_shared.c b/model_shared.c index 5cd6890d..9374b669 100644 --- a/model_shared.c +++ b/model_shared.c @@ -196,24 +196,12 @@ void Mod_UnloadModel (dp_model_t *mod) strlcpy(name, mod->name, sizeof(name)); parentmodel = mod->brush.parentmodel; used = mod->used; - if (mod->mempool) - { - if (mod->surfmesh.vertexpositionbuffer) - R_Mesh_DestroyMeshBuffer(mod->surfmesh.vertexpositionbuffer); - mod->surfmesh.vertexpositionbuffer = NULL; - if (mod->surfmesh.vertexmeshbuffer) - R_Mesh_DestroyMeshBuffer(mod->surfmesh.vertexmeshbuffer); - mod->surfmesh.vertexmeshbuffer = NULL; - if (mod->surfmesh.data_element3i_indexbuffer) - R_Mesh_DestroyMeshBuffer(mod->surfmesh.data_element3i_indexbuffer); - mod->surfmesh.data_element3i_indexbuffer = NULL; - if (mod->surfmesh.data_element3s_indexbuffer) - R_Mesh_DestroyMeshBuffer(mod->surfmesh.data_element3s_indexbuffer); - mod->surfmesh.data_element3s_indexbuffer = NULL; - if (mod->surfmesh.vbo_vertexbuffer) - R_Mesh_DestroyMeshBuffer(mod->surfmesh.vbo_vertexbuffer); - mod->surfmesh.vbo_vertexbuffer = NULL; - } + if (mod->surfmesh.ebo3i) + R_Mesh_DestroyBufferObject(mod->surfmesh.ebo3i); + if (mod->surfmesh.ebo3s) + R_Mesh_DestroyBufferObject(mod->surfmesh.ebo3s); + if (mod->surfmesh.vbo) + R_Mesh_DestroyBufferObject(mod->surfmesh.vbo); // free textures/memory attached to the model R_FreeTexturePool(&mod->texturepool); Mem_FreePool(&mod->mempool); @@ -1189,60 +1177,26 @@ shadowmesh_t *Mod_ShadowMesh_Begin(mempool_t *mempool, int maxverts, int maxtria static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh) { - if (!mesh->numverts) + if (!vid.support.arb_vertex_buffer_object) + return; + if (mesh->vbo) return; - // build r_vertexmesh_t array - // (compressed interleaved array for faster rendering) - if (!mesh->vertexmesh && mesh->texcoord2f) - { - int vertexindex; - int numvertices = mesh->numverts; - r_vertexmesh_t *vertexmesh; - mesh->vertexmesh = vertexmesh = (r_vertexmesh_t*)Mem_Alloc(loadmodel->mempool, numvertices * sizeof(*mesh->vertexmesh)); - for (vertexindex = 0;vertexindex < numvertices;vertexindex++, vertexmesh++) - { - VectorCopy(mesh->vertex3f + 3*vertexindex, vertexmesh->vertex3f); - VectorScale(mesh->svector3f + 3*vertexindex, 1.0f, vertexmesh->svector3f); - VectorScale(mesh->tvector3f + 3*vertexindex, 1.0f, vertexmesh->tvector3f); - VectorScale(mesh->normal3f + 3*vertexindex, 1.0f, vertexmesh->normal3f); - Vector2Copy(mesh->texcoord2f + 2*vertexindex, vertexmesh->texcoordtexture2f); - } - } - - // build r_vertexposition_t array - if (!mesh->vertexposition) + // element buffer is easy because it's just one array + if (mesh->numtriangles) { - int vertexindex; - int numvertices = mesh->numverts; - r_vertexposition_t *vertexposition; - mesh->vertexposition = vertexposition = (r_vertexposition_t*)Mem_Alloc(loadmodel->mempool, numvertices * sizeof(*mesh->vertexposition)); - for (vertexindex = 0;vertexindex < numvertices;vertexindex++, vertexposition++) - VectorCopy(mesh->vertex3f + 3*vertexindex, vertexposition->vertex3f); + if (mesh->element3s) + mesh->ebo3s = R_Mesh_CreateStaticBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB, mesh->element3s, mesh->numtriangles * sizeof(unsigned short[3]), "shadowmesh"); + else + mesh->ebo3i = R_Mesh_CreateStaticBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB, mesh->element3i, mesh->numtriangles * sizeof(unsigned int[3]), "shadowmesh"); } - // upload r_vertexmesh_t array as a buffer - if (mesh->vertexmesh && !mesh->vertexmeshbuffer) - mesh->vertexmeshbuffer = R_Mesh_CreateMeshBuffer(mesh->vertexmesh, mesh->numverts * sizeof(*mesh->vertexmesh), loadmodel->name, false, false); - - // upload r_vertexposition_t array as a buffer - if (mesh->vertexposition && !mesh->vertexpositionbuffer) - mesh->vertexpositionbuffer = R_Mesh_CreateMeshBuffer(mesh->vertexposition, mesh->numverts * sizeof(*mesh->vertexposition), loadmodel->name, false, false); - - // upload short indices as a buffer - if (mesh->element3s && !mesh->element3s_indexbuffer) - mesh->element3s_indexbuffer = R_Mesh_CreateMeshBuffer(mesh->element3s, mesh->numtriangles * sizeof(short[3]), loadmodel->name, true, false); - - // upload int indices as a buffer - if (mesh->element3i && !mesh->element3i_indexbuffer && !mesh->element3s) - mesh->element3i_indexbuffer = R_Mesh_CreateMeshBuffer(mesh->element3i, mesh->numtriangles * sizeof(int[3]), loadmodel->name, true, false); - // vertex buffer is several arrays and we put them in the same buffer // // is this wise? the texcoordtexture2f array is used with dynamic // vertex/svector/tvector/normal when rendering animated models, on the // other hand animated models don't use a lot of vertices anyway... - if (!mesh->vbo_vertexbuffer) + if (mesh->numverts) { size_t size; unsigned char *mem; @@ -1258,7 +1212,7 @@ static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh) if (mesh->tvector3f ) memcpy(mem + mesh->vbooffset_tvector3f , mesh->tvector3f , mesh->numverts * sizeof(float[3])); if (mesh->normal3f ) memcpy(mem + mesh->vbooffset_normal3f , mesh->normal3f , mesh->numverts * sizeof(float[3])); if (mesh->texcoord2f ) memcpy(mem + mesh->vbooffset_texcoord2f , mesh->texcoord2f , mesh->numverts * sizeof(float[2])); - mesh->vbo_vertexbuffer = R_Mesh_CreateMeshBuffer(mem, size, "shadowmesh", false, false); + mesh->vbo = R_Mesh_CreateStaticBufferObject(GL_ARRAY_BUFFER_ARB, mem, size, "shadowmesh"); Mem_Free(mem); } } @@ -1347,16 +1301,12 @@ void Mod_ShadowMesh_Free(shadowmesh_t *mesh) shadowmesh_t *nextmesh; for (;mesh;mesh = nextmesh) { - if (mesh->vertexpositionbuffer) - R_Mesh_DestroyMeshBuffer(mesh->vertexpositionbuffer); - if (mesh->vertexmeshbuffer) - R_Mesh_DestroyMeshBuffer(mesh->vertexmeshbuffer); - if (mesh->element3i_indexbuffer) - R_Mesh_DestroyMeshBuffer(mesh->element3i_indexbuffer); - if (mesh->element3s_indexbuffer) - R_Mesh_DestroyMeshBuffer(mesh->element3s_indexbuffer); - if (mesh->vbo_vertexbuffer) - R_Mesh_DestroyMeshBuffer(mesh->vbo_vertexbuffer); + if (mesh->ebo3i) + R_Mesh_DestroyBufferObject(mesh->ebo3i); + if (mesh->ebo3s) + R_Mesh_DestroyBufferObject(mesh->ebo3s); + if (mesh->vbo) + R_Mesh_DestroyBufferObject(mesh->vbo); nextmesh = mesh->next; Mem_Free(mesh); } @@ -2738,9 +2688,6 @@ void Mod_MakeSortedSurfaces(dp_model_t *mod) void Mod_BuildVBOs(void) { - if (!loadmodel->surfmesh.num_vertices) - return; - if (gl_paranoid.integer && loadmodel->surfmesh.data_element3s && loadmodel->surfmesh.data_element3i) { int i; @@ -2754,62 +2701,27 @@ void Mod_BuildVBOs(void) } } - // build r_vertexmesh_t array - // (compressed interleaved array for faster rendering) - if (!loadmodel->surfmesh.vertexmesh) - { - int vertexindex; - int numvertices = loadmodel->surfmesh.num_vertices; - r_vertexmesh_t *vertexmesh; - loadmodel->surfmesh.vertexmesh = vertexmesh = (r_vertexmesh_t*)Mem_Alloc(loadmodel->mempool, numvertices * sizeof(*loadmodel->surfmesh.vertexmesh)); - for (vertexindex = 0;vertexindex < numvertices;vertexindex++, vertexmesh++) - { - VectorCopy(loadmodel->surfmesh.data_vertex3f + 3*vertexindex, vertexmesh->vertex3f); - VectorScale(loadmodel->surfmesh.data_svector3f + 3*vertexindex, 1.0f, vertexmesh->svector3f); - VectorScale(loadmodel->surfmesh.data_tvector3f + 3*vertexindex, 1.0f, vertexmesh->tvector3f); - VectorScale(loadmodel->surfmesh.data_normal3f + 3*vertexindex, 1.0f, vertexmesh->normal3f); - if (loadmodel->surfmesh.data_lightmapcolor4f) - Vector4Scale(loadmodel->surfmesh.data_lightmapcolor4f + 4*vertexindex, 255.0f, vertexmesh->color4ub); - Vector2Copy(loadmodel->surfmesh.data_texcoordtexture2f + 2*vertexindex, vertexmesh->texcoordtexture2f); - if (loadmodel->surfmesh.data_texcoordlightmap2f) - Vector2Scale(loadmodel->surfmesh.data_texcoordlightmap2f + 2*vertexindex, 1.0f, vertexmesh->texcoordlightmap2f); - } - } + if (!vid.support.arb_vertex_buffer_object) + return; + // only build a vbo if one has not already been created (this is important for brush models which load specially) + if (loadmodel->surfmesh.vbo) + return; - // build r_vertexposition_t array - if (!loadmodel->surfmesh.vertexposition) + // element buffer is easy because it's just one array + if (loadmodel->surfmesh.num_triangles) { - int vertexindex; - int numvertices = loadmodel->surfmesh.num_vertices; - r_vertexposition_t *vertexposition; - loadmodel->surfmesh.vertexposition = vertexposition = (r_vertexposition_t*)Mem_Alloc(loadmodel->mempool, numvertices * sizeof(*loadmodel->surfmesh.vertexposition)); - for (vertexindex = 0;vertexindex < numvertices;vertexindex++, vertexposition++) - VectorCopy(loadmodel->surfmesh.data_vertex3f + 3*vertexindex, vertexposition->vertex3f); + if (loadmodel->surfmesh.data_element3s) + loadmodel->surfmesh.ebo3s = R_Mesh_CreateStaticBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB, loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]), loadmodel->name); + else + loadmodel->surfmesh.ebo3i = R_Mesh_CreateStaticBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles * sizeof(unsigned int[3]), loadmodel->name); } - // upload r_vertexmesh_t array as a buffer - if (loadmodel->surfmesh.vertexmesh && !loadmodel->surfmesh.vertexmeshbuffer) - loadmodel->surfmesh.vertexmeshbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.vertexmesh, loadmodel->surfmesh.num_vertices * sizeof(*loadmodel->surfmesh.vertexmesh), loadmodel->name, false, false); - - // upload r_vertexposition_t array as a buffer - if (loadmodel->surfmesh.vertexposition && !loadmodel->surfmesh.vertexpositionbuffer) - loadmodel->surfmesh.vertexpositionbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.vertexposition, loadmodel->surfmesh.num_vertices * sizeof(*loadmodel->surfmesh.vertexposition), loadmodel->name, false, false); - - // upload short indices as a buffer - if (loadmodel->surfmesh.data_element3s && !loadmodel->surfmesh.data_element3s_indexbuffer) - loadmodel->surfmesh.data_element3s_indexbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.num_triangles * sizeof(short[3]), loadmodel->name, true, false); - - // upload int indices as a buffer - if (loadmodel->surfmesh.data_element3i && !loadmodel->surfmesh.data_element3i_indexbuffer && !loadmodel->surfmesh.data_element3s) - loadmodel->surfmesh.data_element3i_indexbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles * sizeof(int[3]), loadmodel->name, true, false); - - // only build a vbo if one has not already been created (this is important for brush models which load specially) // vertex buffer is several arrays and we put them in the same buffer // // is this wise? the texcoordtexture2f array is used with dynamic // vertex/svector/tvector/normal when rendering animated models, on the // other hand animated models don't use a lot of vertices anyway... - if (!loadmodel->surfmesh.vbo_vertexbuffer) + if (loadmodel->surfmesh.num_vertices) { size_t size; unsigned char *mem; @@ -2829,7 +2741,7 @@ void Mod_BuildVBOs(void) if (loadmodel->surfmesh.data_texcoordtexture2f ) memcpy(mem + loadmodel->surfmesh.vbooffset_texcoordtexture2f , loadmodel->surfmesh.data_texcoordtexture2f , loadmodel->surfmesh.num_vertices * sizeof(float[2])); if (loadmodel->surfmesh.data_texcoordlightmap2f) memcpy(mem + loadmodel->surfmesh.vbooffset_texcoordlightmap2f, loadmodel->surfmesh.data_texcoordlightmap2f, loadmodel->surfmesh.num_vertices * sizeof(float[2])); if (loadmodel->surfmesh.data_lightmapcolor4f ) memcpy(mem + loadmodel->surfmesh.vbooffset_lightmapcolor4f , loadmodel->surfmesh.data_lightmapcolor4f , loadmodel->surfmesh.num_vertices * sizeof(float[4])); - loadmodel->surfmesh.vbo_vertexbuffer = R_Mesh_CreateMeshBuffer(mem, size, loadmodel->name, false, false); + loadmodel->surfmesh.vbo = R_Mesh_CreateStaticBufferObject(GL_ARRAY_BUFFER_ARB, mem, size, loadmodel->name); Mem_Free(mem); } } @@ -3796,27 +3708,15 @@ static void Mod_GenerateLightmaps_UnweldTriangles(dp_model_t *model) if (model->surfmesh.num_vertices > 65536) model->surfmesh.data_element3s = NULL; - if (model->surfmesh.vertexposition) - Mem_Free(model->surfmesh.vertexposition); - model->surfmesh.vertexposition = NULL; - if (model->surfmesh.vertexmesh) - Mem_Free(model->surfmesh.vertexmesh); - model->surfmesh.vertexmesh = NULL; - if (model->surfmesh.vertexpositionbuffer) - R_Mesh_DestroyMeshBuffer(model->surfmesh.vertexpositionbuffer); - model->surfmesh.vertexpositionbuffer = NULL; - if (model->surfmesh.vertexmeshbuffer) - R_Mesh_DestroyMeshBuffer(model->surfmesh.vertexmeshbuffer); - model->surfmesh.vertexmeshbuffer = NULL; - if (model->surfmesh.data_element3i_indexbuffer) - R_Mesh_DestroyMeshBuffer(model->surfmesh.data_element3i_indexbuffer); - model->surfmesh.data_element3i_indexbuffer = NULL; - if (model->surfmesh.data_element3s_indexbuffer) - R_Mesh_DestroyMeshBuffer(model->surfmesh.data_element3s_indexbuffer); - model->surfmesh.data_element3s_indexbuffer = NULL; - if (model->surfmesh.vbo_vertexbuffer) - R_Mesh_DestroyMeshBuffer(model->surfmesh.vbo_vertexbuffer); - model->surfmesh.vbo_vertexbuffer = 0; + if (model->surfmesh.vbo) + R_Mesh_DestroyBufferObject(model->surfmesh.vbo); + model->surfmesh.vbo = 0; + if (model->surfmesh.ebo3i) + R_Mesh_DestroyBufferObject(model->surfmesh.ebo3i); + model->surfmesh.ebo3i = 0; + if (model->surfmesh.ebo3s) + R_Mesh_DestroyBufferObject(model->surfmesh.ebo3s); + model->surfmesh.ebo3s = 0; // convert all triangles to unique vertex data outvertexindex = 0; diff --git a/model_shared.h b/model_shared.h index e6f0ed53..56e20ce6 100644 --- a/model_shared.h +++ b/model_shared.h @@ -101,46 +101,6 @@ typedef struct blendweights_s } blendweights_t; -typedef struct r_vertexposition_s -{ - // 12 bytes - float vertex3f[3]; -} -r_vertexposition_t; - -typedef struct r_vertexgeneric_s -{ - // 24 bytes - float vertex3f[3]; - unsigned char color4ub[4]; - float texcoord2f[2]; -} -r_vertexgeneric_t; - -typedef struct r_vertexmesh_s -{ - // 68 bytes - float vertex3f[3]; - unsigned char color4ub[4]; - float texcoordtexture2f[2]; - float texcoordlightmap2f[2]; - float svector3f[3]; - float tvector3f[3]; - float normal3f[3]; -} -r_vertexmesh_t; - -typedef struct r_meshbuffer_s -{ - int bufferobject; // OpenGL - void *devicebuffer; // Direct3D - size_t size; - qboolean isindexbuffer; - qboolean isdynamic; - char name[MAX_QPATH]; -} -r_meshbuffer_t; - // used for mesh lists in q1bsp/q3bsp map models // (the surfaces reference portions of these meshes) typedef struct surfmesh_s @@ -148,12 +108,11 @@ typedef struct surfmesh_s // triangle data in system memory int num_triangles; // number of triangles in the mesh int *data_element3i; // int[tris*3] triangles of the mesh, 3 indices into vertex arrays for each - r_meshbuffer_t *data_element3i_indexbuffer; - size_t data_element3i_bufferoffset; unsigned short *data_element3s; // unsigned short[tris*3] triangles of the mesh in unsigned short format (NULL if num_vertices > 65536) - r_meshbuffer_t *data_element3s_indexbuffer; - size_t data_element3s_bufferoffset; int *data_neighbor3i; // int[tris*3] neighboring triangle on each edge (-1 if none) + // element buffer object (stores triangles in video memory) + int ebo3i; // unsigned int format (only allocated if num_vertices > 65536) + int ebo3s; // unsigned short format (only allocated if num_vertices <= 65536) // vertex data in system memory int num_vertices; // number of vertices in the mesh float *data_vertex3f; // float[verts*3] vertex locations @@ -165,7 +124,7 @@ typedef struct surfmesh_s float *data_lightmapcolor4f; int *data_lightmapoffsets; // index into surface's lightmap samples for vertex lighting // vertex buffer object (stores geometry in video memory) - r_meshbuffer_t *vbo_vertexbuffer; + int vbo; size_t vbooffset_vertex3f; size_t vbooffset_svector3f; size_t vbooffset_tvector3f; @@ -187,12 +146,6 @@ typedef struct surfmesh_s unsigned short *blends; // set if there is some kind of animation on this model qboolean isanimated; - - // vertex and index buffers for rendering - r_vertexposition_t *vertexposition; - r_vertexmesh_t *vertexmesh; - r_meshbuffer_t *vertexpositionbuffer; - r_meshbuffer_t *vertexmeshbuffer; } surfmesh_t; @@ -223,11 +176,7 @@ typedef struct shadowmesh_s float *texcoord2f; // used always int *element3i; - r_meshbuffer_t *element3i_indexbuffer; - size_t element3i_bufferoffset; unsigned short *element3s; - r_meshbuffer_t *element3s_indexbuffer; - size_t element3s_bufferoffset; // used for shadow mapping cubemap side partitioning int sideoffsets[6], sidetotals[6]; // used for shadow mesh (NULL on light mesh) @@ -235,18 +184,18 @@ typedef struct shadowmesh_s // these are NULL after Mod_ShadowMesh_Finish is performed, only used // while building meshes shadowmeshvertexhash_t **vertexhashtable, *vertexhashentries; - r_meshbuffer_t *vbo_vertexbuffer; + // element buffer object (stores triangles in video memory) + // (created by Mod_ShadowMesh_Finish if possible) + int ebo3i; + int ebo3s; + // vertex buffer object (stores vertices in video memory) + // (created by Mod_ShadowMesh_Finish if possible) + int vbo; size_t vbooffset_vertex3f; size_t vbooffset_svector3f; size_t vbooffset_tvector3f; size_t vbooffset_normal3f; size_t vbooffset_texcoord2f; - // vertex/index buffers for rendering - // (created by Mod_ShadowMesh_Finish if possible) - r_vertexposition_t *vertexposition; - r_vertexmesh_t *vertexmesh; // usually NULL - r_meshbuffer_t *vertexpositionbuffer; - r_meshbuffer_t *vertexmeshbuffer; // usually NULL } shadowmesh_t; diff --git a/r_explosion.c b/r_explosion.c index 3519fd94..1c12a07b 100644 --- a/r_explosion.c +++ b/r_explosion.c @@ -212,15 +212,17 @@ static void R_DrawExplosion_TransparentCallback(const entity_render_t *ent, cons GL_CullFace(r_refdef.view.cullface_back); R_EntityMatrix(&identitymatrix); + R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); R_SetupShader_Generic(explosiontexture, NULL, GL_MODULATE, 1); + R_Mesh_TexCoordPointer(0, 2, explosiontexcoord2f[0], 0, 0); for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) { const explosion_t *e = explosion + surfacelist[surfacelistindex]; - // FIXME: this can't properly handle r_refdef.view.colorscale > 1 + R_Mesh_VertexPointer(e->vert[0], 0, 0); + // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1 GL_Color(e->alpha * r_refdef.view.colorscale, e->alpha * r_refdef.view.colorscale, e->alpha * r_refdef.view.colorscale, 1); - R_Mesh_PrepareVertices_Generic_Arrays(numverts, e->vert[0], NULL, explosiontexcoord2f[0]); - R_Mesh_Draw(0, numverts, 0, numtriangles, NULL, NULL, 0, explosiontris[0], NULL, 0); + R_Mesh_Draw(0, numverts, 0, numtriangles, NULL, explosiontris[0], 0, 0); } } diff --git a/r_shadow.c b/r_shadow.c index 9f0ee258..2aed02fc 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -1324,8 +1324,8 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_VISIBLEVOLUMES) { tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris); - R_Mesh_PrepareVertices_Position_Arrays(outverts, shadowvertex3f); - R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0); + R_Mesh_VertexPointer(shadowvertex3f, 0, 0); + R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0); } else { @@ -1339,12 +1339,13 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, r_refdef.stats.lights_dynamicshadowtriangles += tris; r_refdef.stats.lights_shadowtriangles += tris; CHECKGLERROR + R_Mesh_VertexPointer(shadowvertex3f, 0, 0); if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL) { // increment stencil if frontface is infront of depthbuffer GL_CullFace(r_refdef.view.cullface_front); qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR - R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0); + R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0); // decrement stencil if backface is infront of depthbuffer GL_CullFace(r_refdef.view.cullface_back); qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR @@ -1354,13 +1355,12 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, // decrement stencil if backface is behind depthbuffer GL_CullFace(r_refdef.view.cullface_front); qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR - R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0); + R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0); // increment stencil if frontface is behind depthbuffer GL_CullFace(r_refdef.view.cullface_back); qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR } - R_Mesh_PrepareVertices_Position_Arrays(outverts, shadowvertex3f); - R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0); + R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0); CHECKGLERROR } } @@ -1896,8 +1896,6 @@ void R_Shadow_ValidateCvars(void) Cvar_SetValueQuick(&gl_ext_stenciltwoside, 0); } -static const r_vertexposition_t resetvertexposition[3]; - void R_Shadow_RenderMode_Begin(void) { #if 0 @@ -1913,8 +1911,8 @@ void R_Shadow_RenderMode_Begin(void) R_Shadow_MakeTextures(); CHECKGLERROR + R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); - R_Mesh_PrepareVertices_Position(0, resetvertexposition, NULL); GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthRange(0, 1); GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset); @@ -1993,8 +1991,8 @@ void R_Shadow_RenderMode_Reset(void) #endif R_SetViewport(&r_refdef.view.viewport); GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]); + R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); - R_Mesh_PrepareVertices_Position(0, resetvertexposition, NULL); GL_DepthRange(0, 1); GL_DepthTest(true); GL_DepthMask(false); @@ -2304,7 +2302,7 @@ void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qb break; } } - //R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0); + R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0); CHECKGLERROR } @@ -2373,6 +2371,8 @@ void R_Shadow_RenderMode_DrawDeferredLight(qboolean stenciltest, qboolean shadow for (i = 0;i < 8;i++) Matrix4x4_Transform(matrix, bboxpoints[i], vertex3f + i*3); CHECKGLERROR + R_Mesh_VertexPointer(vertex3f, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); GL_ColorMask(1,1,1,1); GL_DepthMask(false); GL_DepthRange(0, 1); @@ -2380,8 +2380,7 @@ void R_Shadow_RenderMode_DrawDeferredLight(qboolean stenciltest, qboolean shadow GL_DepthTest(true); qglDepthFunc(GL_GREATER);CHECKGLERROR GL_CullFace(r_refdef.view.cullface_back); - R_Mesh_PrepareVertices_Position_Arrays(8, vertex3f); - R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0); + R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0); } } @@ -2562,12 +2561,11 @@ qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs) return false; } -static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, const float *diffusecolor, const float *ambientcolor) +static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, int numtriangles, const int *element3i, const float *diffusecolor, const float *ambientcolor) { - int i; - const float *vertex3f; - const float *normal3f; - float *color4f; + const float *vertex3f = rsurface.vertex3f + 3 * firstvertex; + const float *normal3f = rsurface.normal3f + 3 * firstvertex; + float *color4f = rsurface.array_color4f + 4 * firstvertex; float dist, dot, distintensity, shadeintensity, v[3], n[3]; switch (r_shadow_rendermode) { @@ -2575,7 +2573,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN: if (VectorLength2(diffusecolor) > 0) { - for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4) + for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4) { Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v); Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n); @@ -2597,7 +2595,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu } else { - for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4) + for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4) { VectorCopy(ambientcolor, color4f); if (r_refdef.fogenabled) @@ -2605,7 +2603,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu float f; Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v); f = RSurf_FogVertex(vertex3f); - VectorScale(color4f + 4*i, f, color4f); + VectorScale(color4f, f, color4f); } color4f[3] = 1; } @@ -2614,7 +2612,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN: if (VectorLength2(diffusecolor) > 0) { - for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4) + for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4) { Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v); if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)])) @@ -2647,7 +2645,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu } else { - for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4) + for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4) { Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v); if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)])) @@ -2671,7 +2669,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu case R_SHADOW_RENDERMODE_LIGHT_VERTEX: if (VectorLength2(diffusecolor) > 0) { - for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4) + for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4) { Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v); if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)])) @@ -2705,7 +2703,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu } else { - for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4) + for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4) { Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v); if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)])) @@ -2732,23 +2730,21 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu } } -static void R_Shadow_RenderLighting_VisibleLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist) +static void R_Shadow_RenderLighting_VisibleLighting(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject) { // used to display how many times a surface is lit for level design purposes - RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); - R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL); - RSurf_DrawBatch(); + R_Mesh_Draw(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject); } -static void R_Shadow_RenderLighting_Light_GLSL(int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t lightcolor, float ambientscale, float diffusescale, float specularscale) +static void R_Shadow_RenderLighting_Light_GLSL(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject, const vec3_t lightcolor, float ambientscale, float diffusescale, float specularscale) { // ARB2 GLSL shader path (GFFX5200, Radeon 9500) - R_SetupShader_Surface(lightcolor, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist); + R_SetupShader_Surface(lightcolor, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT); if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) { qglDepthFunc(GL_EQUAL);CHECKGLERROR } - RSurf_DrawBatch(); + R_Mesh_Draw(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject); if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) { qglDepthFunc(GL_LEQUAL);CHECKGLERROR @@ -2768,7 +2764,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve float *c; int maxtriangles = 4096; static int newelements[4096*3]; - R_Shadow_RenderLighting_Light_Vertex_Shading(firstvertex, numvertices, diffusecolor2, ambientcolor2); + R_Shadow_RenderLighting_Light_Vertex_Shading(firstvertex, numvertices, numtriangles, element3i, diffusecolor2, ambientcolor2); for (renders = 0;renders < 4;renders++) { stop = true; @@ -2783,7 +2779,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve // renders them at once for (i = 0, e = element3i;i < numtriangles;i++, e += 3) { - if (VectorLength2(rsurface.array_passcolor4f + e[0] * 4) + VectorLength2(rsurface.array_passcolor4f + e[1] * 4) + VectorLength2(rsurface.array_passcolor4f + e[2] * 4) >= 0.01) + if (VectorLength2(rsurface.array_color4f + e[0] * 4) + VectorLength2(rsurface.array_color4f + e[1] * 4) + VectorLength2(rsurface.array_color4f + e[2] * 4) >= 0.01) { if (newnumtriangles) { @@ -2806,7 +2802,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve newe += 3; if (newnumtriangles >= maxtriangles) { - R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, NULL, NULL, 0); + R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, 0); newnumtriangles = 0; newe = newelements; stop = false; @@ -2815,7 +2811,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve } if (newnumtriangles >= 1) { - R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, NULL, NULL, 0); + R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, 0); stop = false; } // if we couldn't find any lit triangles, exit early @@ -2826,7 +2822,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve // handling of negative colors // (some old drivers even have improper handling of >1 color) stop = true; - for (i = 0, c = rsurface.array_passcolor4f + 4 * firstvertex;i < numvertices;i++, c += 4) + for (i = 0, c = rsurface.array_color4f + 4 * firstvertex;i < numvertices;i++, c += 4) { if (c[0] > 1 || c[1] > 1 || c[2] > 1) { @@ -2844,7 +2840,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve } } -static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t lightcolor, float ambientscale, float diffusescale) +static void R_Shadow_RenderLighting_Light_Vertex(int firstvertex, int numvertices, int numtriangles, const int *element3i, const vec3_t lightcolor, float ambientscale, float diffusescale) { // OpenGL 1.1 path (anything) float ambientcolorbase[3], diffusecolorbase[3]; @@ -2866,32 +2862,29 @@ static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const m diffusecolorpants[0] = diffusecolorbase[0] * surfacepants[0];diffusecolorpants[1] = diffusecolorbase[1] * surfacepants[1];diffusecolorpants[2] = diffusecolorbase[2] * surfacepants[2]; ambientcolorshirt[0] = ambientcolorbase[0] * surfaceshirt[0];ambientcolorshirt[1] = ambientcolorbase[1] * surfaceshirt[1];ambientcolorshirt[2] = ambientcolorbase[2] * surfaceshirt[2]; diffusecolorshirt[0] = diffusecolorbase[0] * surfaceshirt[0];diffusecolorshirt[1] = diffusecolorbase[1] * surfaceshirt[1];diffusecolorshirt[2] = diffusecolorbase[2] * surfaceshirt[2]; - RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | (diffusescale > 0 ? BATCHNEED_ARRAY_NORMAL : 0) | BATCHNEED_ARRAY_TEXCOORD, 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.array_passcolor4f, 0, 0); - R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset); R_Mesh_TexBind(0, basetexture); R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix); R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1); + R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset); switch(r_shadow_rendermode) { case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN: R_Mesh_TexBind(1, r_shadow_attenuation3dtexture); R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz); R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1); - R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset); + R_Mesh_TexCoordPointer(1, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset); break; case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN: R_Mesh_TexBind(2, r_shadow_attenuation2dtexture); R_Mesh_TexMatrix(2, &rsurface.entitytoattenuationz); R_Mesh_TexCombine(2, GL_MODULATE, GL_MODULATE, 1, 1); - R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset); + R_Mesh_TexCoordPointer(2, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset); // fall through case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN: R_Mesh_TexBind(1, r_shadow_attenuation2dtexture); R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz); R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1); - R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset); + R_Mesh_TexCoordPointer(1, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset); break; case R_SHADOW_RENDERMODE_LIGHT_VERTEX: break; @@ -2899,21 +2892,21 @@ static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const m break; } //R_Mesh_TexBind(0, basetexture); - R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorbase, ambientcolorbase); + R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorbase, ambientcolorbase); if (dopants) { R_Mesh_TexBind(0, pantstexture); - R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorpants, ambientcolorpants); + R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorpants, ambientcolorpants); } if (doshirt) { R_Mesh_TexBind(0, shirttexture); - R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorshirt, ambientcolorshirt); + R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorshirt, ambientcolorshirt); } } extern cvar_t gl_lightmaps; -void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist) +void R_Shadow_RenderLighting(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject) { float ambientscale, diffusescale, specularscale; qboolean negated; @@ -2941,16 +2934,16 @@ void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **textures { case R_SHADOW_RENDERMODE_VISIBLELIGHTING: GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer); - R_Shadow_RenderLighting_VisibleLighting(texturenumsurfaces, texturesurfacelist); + R_Shadow_RenderLighting_VisibleLighting(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject); break; case R_SHADOW_RENDERMODE_LIGHT_GLSL: - R_Shadow_RenderLighting_Light_GLSL(texturenumsurfaces, texturesurfacelist, lightcolor, ambientscale, diffusescale, specularscale); + R_Shadow_RenderLighting_Light_GLSL(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject, lightcolor, ambientscale, diffusescale, specularscale); break; case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN: case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN: case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN: case R_SHADOW_RENDERMODE_LIGHT_VERTEX: - R_Shadow_RenderLighting_Light_Vertex(texturenumsurfaces, texturesurfacelist, lightcolor, ambientscale, diffusescale); + R_Shadow_RenderLighting_Light_Vertex(firstvertex, numvertices, numtriangles, element3i + firsttriangle * 3, lightcolor, ambientscale, diffusescale); break; default: Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode); @@ -3334,8 +3327,8 @@ void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const if (!mesh->sidetotals[r_shadow_shadowmapside]) continue; r_refdef.stats.lights_shadowtriangles += mesh->sidetotals[r_shadow_shadowmapside]; - R_Mesh_PrepareVertices_Position(mesh->numverts, mesh->vertexposition, mesh->vertexpositionbuffer); - R_Mesh_Draw(0, mesh->numverts, mesh->sideoffsets[r_shadow_shadowmapside], mesh->sidetotals[r_shadow_shadowmapside], mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset); + R_Mesh_VertexPointer(mesh->vertex3f, mesh->vbo, mesh->vbooffset_vertex3f); + R_Mesh_Draw(0, mesh->numverts, mesh->sideoffsets[r_shadow_shadowmapside], mesh->sidetotals[r_shadow_shadowmapside], mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s); } CHECKGLERROR } @@ -3367,13 +3360,13 @@ void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, co for (;mesh;mesh = mesh->next) { r_refdef.stats.lights_shadowtriangles += mesh->numtriangles; - R_Mesh_PrepareVertices_Position(mesh->numverts, mesh->vertexposition, mesh->vertexpositionbuffer); + R_Mesh_VertexPointer(mesh->vertex3f, mesh->vbo, mesh->vbooffset_vertex3f); if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL) { // increment stencil if frontface is infront of depthbuffer GL_CullFace(r_refdef.view.cullface_back); qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR - R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset); + R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s); // decrement stencil if backface is infront of depthbuffer GL_CullFace(r_refdef.view.cullface_front); qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR @@ -3383,12 +3376,12 @@ void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, co // decrement stencil if backface is behind depthbuffer GL_CullFace(r_refdef.view.cullface_front); qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR - R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset); + R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s); // increment stencil if frontface is behind depthbuffer GL_CullFace(r_refdef.view.cullface_back); qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR } - R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset); + R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s); } CHECKGLERROR } @@ -3998,6 +3991,7 @@ void R_Shadow_DrawPrepass(void) entity_render_t *ent; GL_AlphaTest(false); + R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); GL_DepthMask(true); GL_ColorMask(1,1,1,1); @@ -4585,6 +4579,9 @@ void R_DrawModelShadows(void) //R_EntityMatrix(&identitymatrix); //R_Mesh_ResetTextureState(); R_ResetViewRendering2D(); + R_Mesh_VertexPointer(r_screenvertex3f, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); // set up a darkening blend on shadowed areas GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -4601,9 +4598,7 @@ void R_DrawModelShadows(void) qglStencilFunc(GL_NOTEQUAL, 128, 255);CHECKGLERROR // apply the blend to the shadowed areas - R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); // restore the viewport R_SetViewport(&r_refdef.view.viewport); @@ -4635,14 +4630,14 @@ void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery) qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels); qglDepthFunc(GL_ALWAYS); R_CalcSprite_Vertex3f(vertex3f, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale); - R_Mesh_PrepareVertices_Position_Arrays(4, vertex3f); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_VertexPointer(vertex3f, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); qglEndQueryARB(GL_SAMPLES_PASSED_ARB); qglDepthFunc(GL_LEQUAL); qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_visiblepixels); R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale); - R_Mesh_PrepareVertices_Position_Arrays(4, vertex3f); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + R_Mesh_VertexPointer(vertex3f, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); qglEndQueryARB(GL_SAMPLES_PASSED_ARB); CHECKGLERROR } @@ -4734,6 +4729,7 @@ void R_Shadow_DrawCoronas(void) GL_DepthRange(0, 1); GL_PolygonOffset(0, 0); GL_DepthTest(true); + R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); } diff --git a/r_shadow.h b/r_shadow.h index cf74e268..5997605e 100644 --- a/r_shadow.h +++ b/r_shadow.h @@ -45,7 +45,7 @@ void R_Shadow_MarkVolumeFromBox(int firsttriangle, int numtris, const float *inv int R_Shadow_CalcTriangleSideMask(const vec3_t p1, const vec3_t p2, const vec3_t p3, float bias); int R_Shadow_CalcSphereSideMask(const vec3_t p1, float radius, float bias); int R_Shadow_ChooseSidesFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const matrix4x4_t *worldtolight, const vec3_t projectorigin, const vec3_t projectdirection, const vec3_t lightmins, const vec3_t lightmaxs, const vec3_t surfacemins, const vec3_t surfacemaxs, int *totals); -void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist); +void R_Shadow_RenderLighting(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject); void R_Shadow_RenderMode_Begin(void); void R_Shadow_RenderMode_ActiveLight(const rtlight_t *rtlight); void R_Shadow_RenderMode_Reset(void); diff --git a/render.h b/render.h index d81cc565..ea72d282 100644 --- a/render.h +++ b/render.h @@ -232,27 +232,19 @@ extern mempool_t *r_main_mempool; typedef struct rsurfacestate_s { - // software processing buffers - int array_size; - unsigned char *array_base; - r_vertexmesh_t *array_modelvertexmesh; - r_vertexmesh_t *array_batchvertexmesh; - r_vertexposition_t *array_modelvertexposition; - r_vertexposition_t *array_batchvertexposition; - float *array_modelvertex3f; - float *array_modelsvector3f; - float *array_modeltvector3f; - float *array_modelnormal3f; - float *array_batchvertex3f; - float *array_batchsvector3f; - float *array_batchtvector3f; - float *array_batchnormal3f; - float *array_batchlightmapcolor4f; - float *array_batchtexcoordtexture2f; - float *array_batchtexcoordlightmap2f; - float *array_passcolor4f; - int *array_batchelement3i; - unsigned short *array_batchelement3s; + // processing buffers + int array_size; + float *array_modelvertex3f; + float *array_modelsvector3f; + float *array_modeltvector3f; + float *array_modelnormal3f; + float *array_deformedvertex3f; + float *array_deformedsvector3f; + float *array_deformedtvector3f; + float *array_deformednormal3f; + float *array_generatedtexcoordtexture2f; + float *array_color4f; + float *array_texcoord3f; // current model array pointers // these may point to processing buffers if model is animated, @@ -268,89 +260,67 @@ typedef struct rsurfacestate_s // // this indicates the model* arrays are pointed at array_model* buffers // (in other words, the model has been animated in software) - qboolean modelgeneratedvertex; - const float *modelvertex3f; - const r_meshbuffer_t *modelvertex3f_vertexbuffer; - size_t modelvertex3f_bufferoffset; - const float *modelsvector3f; - const r_meshbuffer_t *modelsvector3f_vertexbuffer; - size_t modelsvector3f_bufferoffset; - const float *modeltvector3f; - const r_meshbuffer_t *modeltvector3f_vertexbuffer; - size_t modeltvector3f_bufferoffset; - const float *modelnormal3f; - const r_meshbuffer_t *modelnormal3f_vertexbuffer; - size_t modelnormal3f_bufferoffset; - const float *modellightmapcolor4f; - const r_meshbuffer_t *modellightmapcolor4f_vertexbuffer; - size_t modellightmapcolor4f_bufferoffset; - const float *modeltexcoordtexture2f; - const r_meshbuffer_t *modeltexcoordtexture2f_vertexbuffer; - size_t modeltexcoordtexture2f_bufferoffset; - const float *modeltexcoordlightmap2f; - const r_meshbuffer_t *modeltexcoordlightmap2f_vertexbuffer; - size_t modeltexcoordlightmap2f_bufferoffset; - const r_vertexmesh_t *modelvertexmesh; - const r_meshbuffer_t *modelvertexmeshbuffer; - const r_vertexposition_t *modelvertexposition; - const r_meshbuffer_t *modelvertexpositionbuffer; - const int *modelelement3i; - const r_meshbuffer_t *modelelement3i_indexbuffer; - size_t modelelement3i_bufferoffset; - const unsigned short *modelelement3s; - const r_meshbuffer_t *modelelement3s_indexbuffer; - size_t modelelement3s_bufferoffset; - const int *modellightmapoffsets; - int modelnumvertices; - int modelnumtriangles; - const msurface_t *modelsurfaces; + qboolean generatedvertex; + const float *modelvertex3f; + int modelvertex3f_bufferobject; + size_t modelvertex3f_bufferoffset; + const float *modelsvector3f; + int modelsvector3f_bufferobject; + size_t modelsvector3f_bufferoffset; + const float *modeltvector3f; + int modeltvector3f_bufferobject; + size_t modeltvector3f_bufferoffset; + const float *modelnormal3f; + int modelnormal3f_bufferobject; + size_t modelnormal3f_bufferoffset; + const float *modellightmapcolor4f; + int modellightmapcolor4f_bufferobject; + size_t modellightmapcolor4f_bufferoffset; + const float *modeltexcoordtexture2f; + int modeltexcoordtexture2f_bufferobject; + size_t modeltexcoordtexture2f_bufferoffset; + const float *modeltexcoordlightmap2f; + int modeltexcoordlightmap2f_bufferobject; + size_t modeltexcoordlightmap2f_bufferoffset; + const int *modelelement3i; + const unsigned short *modelelement3s; + int modelelement3i_bufferobject; + int modelelement3s_bufferobject; + const int *modellightmapoffsets; + int modelnum_vertices; + int modelnum_triangles; + const msurface_t *modelsurfaces; // current rendering array pointers // these may point to any of several different buffers depending on how // much processing was needed to prepare this model for rendering // these usually equal the model* pointers, they only differ if // deformvertexes is used in a q3 shader, and consequently these can // change on a per-surface basis (according to rsurface.texture) - qboolean batchgeneratedvertex; - int batchfirstvertex; - int batchnumvertices; - int batchfirsttriangle; - int batchnumtriangles; - const r_vertexmesh_t *batchvertexmesh; - const r_meshbuffer_t *batchvertexmeshbuffer; - const r_vertexposition_t *batchvertexposition; - const r_meshbuffer_t *batchvertexpositionbuffer; - const float *batchvertex3f; - const r_meshbuffer_t *batchvertex3f_vertexbuffer; - size_t batchvertex3f_bufferoffset; - const float *batchsvector3f; - const r_meshbuffer_t *batchsvector3f_vertexbuffer; - size_t batchsvector3f_bufferoffset; - const float *batchtvector3f; - const r_meshbuffer_t *batchtvector3f_vertexbuffer; - size_t batchtvector3f_bufferoffset; - const float *batchnormal3f; - const r_meshbuffer_t *batchnormal3f_vertexbuffer; - size_t batchnormal3f_bufferoffset; - const float *batchlightmapcolor4f; - const r_meshbuffer_t *batchlightmapcolor4f_vertexbuffer; - size_t batchlightmapcolor4f_bufferoffset; - const float *batchtexcoordtexture2f; - const r_meshbuffer_t *batchtexcoordtexture2f_vertexbuffer; - size_t batchtexcoordtexture2f_bufferoffset; - const float *batchtexcoordlightmap2f; - const r_meshbuffer_t *batchtexcoordlightmap2f_vertexbuffer; - size_t batchtexcoordlightmap2f_bufferoffset; - const int *batchelement3i; - const r_meshbuffer_t *batchelement3i_indexbuffer; - size_t batchelement3i_bufferoffset; - const unsigned short *batchelement3s; - const r_meshbuffer_t *batchelement3s_indexbuffer; - size_t batchelement3s_bufferoffset; - // rendering pass processing arrays in GL11 and GL13 paths - const float *passcolor4f; - const r_meshbuffer_t *passcolor4f_vertexbuffer; - size_t passcolor4f_bufferoffset; - + // + // the exception is the color array which is often generated based on + // colormod, alpha fading, and fogging, it may also come from q3bsp vertex + // lighting of certain surfaces + const float *vertex3f; + int vertex3f_bufferobject; + size_t vertex3f_bufferoffset; + const float *svector3f; + int svector3f_bufferobject; + size_t svector3f_bufferoffset; + const float *tvector3f; + int tvector3f_bufferobject; + size_t tvector3f_bufferoffset; + const float *normal3f; + int normal3f_bufferobject; + size_t normal3f_bufferoffset; + const float *lightmapcolor4f; + int lightmapcolor4f_bufferobject; + size_t lightmapcolor4f_bufferoffset; + const float *texcoordtexture2f; + int texcoordtexture2f_bufferobject; + size_t texcoordtexture2f_bufferoffset; + const float *texcoordlightmap2f; + int texcoordlightmap2f_bufferobject; + size_t texcoordlightmap2f_bufferoffset; // some important fields from the entity int ent_skinnum; int ent_qwskin; @@ -383,10 +353,8 @@ typedef struct rsurfacestate_s // polygon offset data for submodels float basepolygonfactor; float basepolygonoffset; - // current textures in batching code + // current texture in batching code texture_t *texture; - rtexture_t *lightmaptexture; - rtexture_t *deluxemaptexture; // whether lightmapping is active on this batch // (otherwise vertex colored) qboolean uselightmaptexture; @@ -438,22 +406,8 @@ void R_AddWaterPlanes(entity_render_t *ent); void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass); void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass); -#define BATCHNEED_VERTEXPOSITION (1<< 0) // set up rsurface.batchvertexposition -#define BATCHNEED_VERTEXMESH_VERTEX (1<< 1) // set up rsurface.batchvertexmesh -#define BATCHNEED_VERTEXMESH_NORMAL (1<< 2) // set up normals in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchnormal3f if BATCHNEED_ARRAYS -#define BATCHNEED_VERTEXMESH_VECTOR (1<< 3) // set up vectors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchsvector3f and rsurface.batchtvector3f if BATCHNEED_ARRAYS -#define BATCHNEED_VERTEXMESH_VERTEXCOLOR (1<< 4) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS -#define BATCHNEED_VERTEXMESH_TEXCOORD (1<< 5) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS -#define BATCHNEED_VERTEXMESH_LIGHTMAP (1<< 6) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS -#define BATCHNEED_ARRAY_VERTEX (1<< 7) // set up rsurface.batchvertex3f and optionally others -#define BATCHNEED_ARRAY_NORMAL (1<< 8) // set up normals in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchnormal3f if BATCHNEED_ARRAYS -#define BATCHNEED_ARRAY_VECTOR (1<< 9) // set up vectors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchsvector3f and rsurface.batchtvector3f if BATCHNEED_ARRAYS -#define BATCHNEED_ARRAY_VERTEXCOLOR (1<<10) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS -#define BATCHNEED_ARRAY_TEXCOORD (1<<11) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS -#define BATCHNEED_ARRAY_LIGHTMAP (1<<12) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS -#define BATCHNEED_NOGAPS (1<<13) // force vertex copying (no gaps) -void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist); -void RSurf_DrawBatch(void); +void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist); +void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist); void R_DecalSystem_SplatEntities(const vec3_t org, const vec3_t normal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float size); @@ -523,7 +477,7 @@ gl20_texunit; void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale); void R_SetupShader_DepthOrShadow(void); void R_SetupShader_ShowDepth(void); -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); +void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass); void R_SetupShader_DeferredLight(const rtlight_t *rtlight); typedef struct r_waterstate_waterplane_s diff --git a/vid.h b/vid.h index b5ffc050..52331ae4 100644 --- a/vid.h +++ b/vid.h @@ -100,7 +100,6 @@ typedef struct viddef_s void *cgcontext; renderpath_t renderpath; - qboolean forcevbo; // some renderpaths can not operate without it unsigned int texunits; unsigned int teximageunits; diff --git a/vid_shared.c b/vid_shared.c index eb6c56d4..4579c143 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -147,14 +147,12 @@ void (GLAPIENTRY *qglColorMask)(GLboolean red, GLboolean green, GLboolean blue, void (GLAPIENTRY *qglDrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); void (GLAPIENTRY *qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); -void (GLAPIENTRY *qglDrawArrays)(GLenum mode, GLint first, GLsizei count); void (GLAPIENTRY *qglVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); void (GLAPIENTRY *qglNormalPointer)(GLenum type, GLsizei stride, const GLvoid *ptr); void (GLAPIENTRY *qglColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); void (GLAPIENTRY *qglTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); void (GLAPIENTRY *qglArrayElement)(GLint i); -void (GLAPIENTRY *qglColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); void (GLAPIENTRY *qglColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); void (GLAPIENTRY *qglTexCoord1f)(GLfloat s); void (GLAPIENTRY *qglTexCoord2f)(GLfloat s, GLfloat t); @@ -162,7 +160,6 @@ void (GLAPIENTRY *qglTexCoord3f)(GLfloat s, GLfloat t, GLfloat r); void (GLAPIENTRY *qglTexCoord4f)(GLfloat s, GLfloat t, GLfloat r, GLfloat q); void (GLAPIENTRY *qglVertex2f)(GLfloat x, GLfloat y); void (GLAPIENTRY *qglVertex3f)(GLfloat x, GLfloat y, GLfloat z); -void (GLAPIENTRY *qglVertex4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); void (GLAPIENTRY *qglBegin)(GLenum mode); void (GLAPIENTRY *qglEnd)(void); @@ -491,14 +488,12 @@ static dllfunction_t opengl110funcs[] = {"glDepthMask", (void **) &qglDepthMask}, {"glDepthRange", (void **) &qglDepthRange}, {"glDrawElements", (void **) &qglDrawElements}, - {"glDrawArrays", (void **) &qglDrawArrays}, {"glColorMask", (void **) &qglColorMask}, {"glVertexPointer", (void **) &qglVertexPointer}, {"glNormalPointer", (void **) &qglNormalPointer}, {"glColorPointer", (void **) &qglColorPointer}, {"glTexCoordPointer", (void **) &qglTexCoordPointer}, {"glArrayElement", (void **) &qglArrayElement}, - {"glColor4ub", (void **) &qglColor4ub}, {"glColor4f", (void **) &qglColor4f}, {"glTexCoord1f", (void **) &qglTexCoord1f}, {"glTexCoord2f", (void **) &qglTexCoord2f}, @@ -506,7 +501,6 @@ static dllfunction_t opengl110funcs[] = {"glTexCoord4f", (void **) &qglTexCoord4f}, {"glVertex2f", (void **) &qglVertex2f}, {"glVertex3f", (void **) &qglVertex3f}, - {"glVertex4f", (void **) &qglVertex4f}, {"glBegin", (void **) &qglBegin}, {"glEnd", (void **) &qglEnd}, //[515]: added on 29.07.2005 @@ -804,7 +798,6 @@ void VID_CheckExtensions(void) Con_DPrint("Checking OpenGL extensions...\n"); - vid.forcevbo = false; vid.support.amd_texture_texture4 = GL_CheckExtension("GL_AMD_texture_texture4", NULL, "-notexture4", false); vid.support.arb_depth_texture = GL_CheckExtension("GL_ARB_depth_texture", NULL, "-nodepthtexture", false); vid.support.arb_draw_buffers = GL_CheckExtension("GL_ARB_draw_buffers", drawbuffersfuncs, "-nodrawbuffers", false);