From: havoc Date: Tue, 1 Jul 2003 18:43:42 +0000 (+0000) Subject: redesigned how the renderer handles much of it's state (R_Mesh_State turned into... X-Git-Tag: xonotic-v0.1.0preview~6577 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=dda9525d00cbd81ad257870fbcb60079e11e367f;p=xonotic%2Fdarkplaces.git redesigned how the renderer handles much of it's state (R_Mesh_State turned into R_Mesh_State_Textures - no longer handles blendfunc and depthmask and depthtest and vertex pointers and so on) batching is gone VAR support is gone (but may make a return someday) dynamic shadow volumes are now more optimized (removal of unused verts) added a glossary of terminology to the start of r_shadow.c added gl_mesh_testarrayelement and gl_mesh_testmanualfeeding cvars for testing/debugging purposes in the backend (incase vertex array state is a mess) added gl_paranoid cvar (enables CHECKGLERROR and verifies geometry before rendering it) added gl_printcheckerror cvar (prints location of every CHECKGLERROR statement as it executes, for tracking code flow) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3119 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/cl_main.c b/cl_main.c index d1b514ce..2fe8e736 100644 --- a/cl_main.c +++ b/cl_main.c @@ -1251,18 +1251,7 @@ void R_DrawLightningBeamCallback(const void *calldata1, int calldata2) rmeshstate_t m; vec3_t beamdir, right, up, offset; float length, t1, t2; - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; - if (r_lightningbeam_qmbtexture.integer && r_lightningbeamqmbtexture == NULL) - r_lightningbeams_setupqmbtexture(); - if (!r_lightningbeam_qmbtexture.integer && r_lightningbeamtexture == NULL) - r_lightningbeams_setuptexture(); - if (r_lightningbeam_qmbtexture.integer) - m.tex[0] = R_GetTexture(r_lightningbeamqmbtexture); - else - m.tex[0] = R_GetTexture(r_lightningbeamtexture); - R_Mesh_State(&m); + R_Mesh_Matrix(&r_identitymatrix); // calculate beam direction (beamdir) vector and beam length @@ -1304,29 +1293,42 @@ void R_DrawLightningBeamCallback(const void *calldata1, int calldata2) // (and realize that the whole polygon assembly orients itself to face // the viewer) - R_Mesh_GetSpace(12); + memset(&m, 0, sizeof(m)); + if (r_lightningbeam_qmbtexture.integer) + m.tex[0] = R_GetTexture(r_lightningbeamqmbtexture); + else + m.tex[0] = R_GetTexture(r_lightningbeamtexture); + m.pointer_texcoord[0] = varray_texcoord2f[0]; + R_Mesh_State_Texture(&m); + + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); + GL_DepthTest(true); + if (r_lightningbeam_qmbtexture.integer && r_lightningbeamqmbtexture == NULL) + r_lightningbeams_setupqmbtexture(); + if (!r_lightningbeam_qmbtexture.integer && r_lightningbeamtexture == NULL) + r_lightningbeams_setuptexture(); // polygon 1, verts 0-3 VectorScale(right, r_lightningbeam_thickness.value, offset); - R_CalcLightningBeamPolygonVertex3f(varray_vertex3f, b->start, b->end, offset); - R_CalcLightningBeamPolygonTexCoord2f(varray_texcoord2f[0], t1, t2); - + R_CalcLightningBeamPolygonVertex3f(varray_vertex3f + 0, b->start, b->end, offset); // polygon 2, verts 4-7 VectorAdd(right, up, offset); VectorScale(offset, r_lightningbeam_thickness.value * 0.70710681f, offset); R_CalcLightningBeamPolygonVertex3f(varray_vertex3f + 12, b->start, b->end, offset); - R_CalcLightningBeamPolygonTexCoord2f(varray_texcoord2f[0] + 8, t1 + 0.33, t2 + 0.33); - // polygon 3, verts 8-11 VectorSubtract(right, up, offset); VectorScale(offset, r_lightningbeam_thickness.value * 0.70710681f, offset); R_CalcLightningBeamPolygonVertex3f(varray_vertex3f + 24, b->start, b->end, offset); + R_CalcLightningBeamPolygonTexCoord2f(varray_texcoord2f[0] + 0, t1, t2); + R_CalcLightningBeamPolygonTexCoord2f(varray_texcoord2f[0] + 8, t1 + 0.33, t2 + 0.33); R_CalcLightningBeamPolygonTexCoord2f(varray_texcoord2f[0] + 16, t1 + 0.66, t2 + 0.66); + GL_VertexPointer(varray_vertex3f); if (fogenabled) { // per vertex colors if fog is used - GL_UseColorArray(); + GL_ColorPointer(varray_color4f); R_FogLightningBeam_Vertex3f_Color4f(varray_vertex3f, varray_color4f, 12, r_lightningbeam_color_red.value, r_lightningbeam_color_green.value, r_lightningbeam_color_blue.value, 1); } else diff --git a/cl_particles.c b/cl_particles.c index fae3e46b..339bdd73 100644 --- a/cl_particles.c +++ b/cl_particles.c @@ -1663,10 +1663,10 @@ void R_InitParticles(void) CL_Particles_Init(); R_Particles_Init(); } - -float varray_vertex3f[12], varray_texcoord2f[1][8]; #endif +float particle_vertex3f[12], particle_texcoord2f[8]; + #ifdef WORKINGLQUAKE void R_DrawParticle(particle_t *p) { @@ -1698,26 +1698,6 @@ void R_DrawParticleCallback(const void *calldata1, int calldata2) } #ifndef WORKINGLQUAKE - memset(&m, 0, sizeof(m)); - if (p->blendmode == 0) - { - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - } - else if (p->blendmode == 1) - { - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; - } - else - { - m.blendfunc1 = GL_ZERO; - m.blendfunc2 = GL_ONE_MINUS_SRC_COLOR; - } - m.tex[0] = R_GetTexture(tex->texture); - R_Mesh_Matrix(&r_identitymatrix); - R_Mesh_State(&m); - if (fogenabled && p->blendmode != PBLEND_MOD) { VectorSubtract(org, r_origin, fogvec); @@ -1739,7 +1719,22 @@ void R_DrawParticleCallback(const void *calldata1, int calldata2) GL_Color(cr, cg, cb, ca); - R_Mesh_GetSpace(4); + R_Mesh_Matrix(&r_identitymatrix); + + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(tex->texture); + m.pointer_texcoord[0] = particle_texcoord2f; + R_Mesh_State_Texture(&m); + + if (p->blendmode == 0) + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + else if (p->blendmode == 1) + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + else + GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); + GL_DepthMask(false); + GL_DepthTest(true); + GL_VertexPointer(particle_vertex3f); #endif if (p->orientation == PARTICLE_BILLBOARD || p->orientation == PARTICLE_ORIENTED_DOUBLESIDED) { @@ -1761,44 +1756,44 @@ void R_DrawParticleCallback(const void *calldata1, int calldata2) VectorScale(vright, p->scalex, right); VectorScale(vup, p->scaley, up); } - varray_vertex3f[ 0] = org[0] - right[0] - up[0]; - varray_vertex3f[ 1] = org[1] - right[1] - up[1]; - varray_vertex3f[ 2] = org[2] - right[2] - up[2]; - varray_vertex3f[ 3] = org[0] - right[0] + up[0]; - varray_vertex3f[ 4] = org[1] - right[1] + up[1]; - varray_vertex3f[ 5] = org[2] - right[2] + up[2]; - varray_vertex3f[ 6] = org[0] + right[0] + up[0]; - varray_vertex3f[ 7] = org[1] + right[1] + up[1]; - varray_vertex3f[ 8] = org[2] + right[2] + up[2]; - varray_vertex3f[ 9] = org[0] + right[0] - up[0]; - varray_vertex3f[10] = org[1] + right[1] - up[1]; - varray_vertex3f[11] = org[2] + right[2] - up[2]; - varray_texcoord2f[0][0] = tex->s1;varray_texcoord2f[0][1] = tex->t2; - varray_texcoord2f[0][2] = tex->s1;varray_texcoord2f[0][3] = tex->t1; - varray_texcoord2f[0][4] = tex->s2;varray_texcoord2f[0][5] = tex->t1; - varray_texcoord2f[0][6] = tex->s2;varray_texcoord2f[0][7] = tex->t2; + particle_vertex3f[ 0] = org[0] - right[0] - up[0]; + particle_vertex3f[ 1] = org[1] - right[1] - up[1]; + particle_vertex3f[ 2] = org[2] - right[2] - up[2]; + particle_vertex3f[ 3] = org[0] - right[0] + up[0]; + particle_vertex3f[ 4] = org[1] - right[1] + up[1]; + particle_vertex3f[ 5] = org[2] - right[2] + up[2]; + particle_vertex3f[ 6] = org[0] + right[0] + up[0]; + particle_vertex3f[ 7] = org[1] + right[1] + up[1]; + particle_vertex3f[ 8] = org[2] + right[2] + up[2]; + particle_vertex3f[ 9] = org[0] + right[0] - up[0]; + particle_vertex3f[10] = org[1] + right[1] - up[1]; + particle_vertex3f[11] = org[2] + right[2] - up[2]; + particle_texcoord2f[0] = tex->s1;particle_texcoord2f[1] = tex->t2; + particle_texcoord2f[2] = tex->s1;particle_texcoord2f[3] = tex->t1; + particle_texcoord2f[4] = tex->s2;particle_texcoord2f[5] = tex->t1; + particle_texcoord2f[6] = tex->s2;particle_texcoord2f[7] = tex->t2; } else if (p->orientation == PARTICLE_SPARK) { VectorMA(p->org, -p->scaley, p->vel, v); VectorMA(p->org, p->scaley, p->vel, up2); - R_CalcBeam_Vertex3f(varray_vertex3f, v, up2, p->scalex); - varray_texcoord2f[0][0] = tex->s1;varray_texcoord2f[0][1] = tex->t2; - varray_texcoord2f[0][2] = tex->s1;varray_texcoord2f[0][3] = tex->t1; - varray_texcoord2f[0][4] = tex->s2;varray_texcoord2f[0][5] = tex->t1; - varray_texcoord2f[0][6] = tex->s2;varray_texcoord2f[0][7] = tex->t2; + R_CalcBeam_Vertex3f(particle_vertex3f, v, up2, p->scalex); + particle_texcoord2f[0] = tex->s1;particle_texcoord2f[1] = tex->t2; + particle_texcoord2f[2] = tex->s1;particle_texcoord2f[3] = tex->t1; + particle_texcoord2f[4] = tex->s2;particle_texcoord2f[5] = tex->t1; + particle_texcoord2f[6] = tex->s2;particle_texcoord2f[7] = tex->t2; } else if (p->orientation == PARTICLE_BEAM) { - R_CalcBeam_Vertex3f(varray_vertex3f, p->org, p->vel2, p->scalex); + R_CalcBeam_Vertex3f(particle_vertex3f, p->org, p->vel2, p->scalex); VectorSubtract(p->vel2, p->org, up); VectorNormalizeFast(up); v[0] = DotProduct(p->org, up) * (1.0f / 64.0f) - cl.time * 0.25; v[1] = DotProduct(p->vel2, up) * (1.0f / 64.0f) - cl.time * 0.25; - varray_texcoord2f[0][0] = 1;varray_texcoord2f[0][1] = v[0]; - varray_texcoord2f[0][2] = 0;varray_texcoord2f[0][3] = v[0]; - varray_texcoord2f[0][4] = 0;varray_texcoord2f[0][5] = v[1]; - varray_texcoord2f[0][6] = 1;varray_texcoord2f[0][7] = v[1]; + particle_texcoord2f[0] = 1;particle_texcoord2f[1] = v[0]; + particle_texcoord2f[2] = 0;particle_texcoord2f[3] = v[0]; + particle_texcoord2f[4] = 0;particle_texcoord2f[5] = v[1]; + particle_texcoord2f[6] = 1;particle_texcoord2f[7] = v[1]; } else Host_Error("R_DrawParticles: unknown particle orientation %i\n", p->orientation); @@ -1812,10 +1807,10 @@ void R_DrawParticleCallback(const void *calldata1, int calldata2) glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); glColor4f(cr, cg, cb, ca); glBegin(GL_QUADS); - glTexCoord2f(varray_texcoord2f[0][0], varray_texcoord2f[0][1]);glVertex3f(varray_vertex3f[ 0], varray_vertex3f[ 1], varray_vertex3f[ 2]); - glTexCoord2f(varray_texcoord2f[0][2], varray_texcoord2f[0][3]);glVertex3f(varray_vertex3f[ 3], varray_vertex3f[ 4], varray_vertex3f[ 5]); - glTexCoord2f(varray_texcoord2f[0][4], varray_texcoord2f[0][5]);glVertex3f(varray_vertex3f[ 6], varray_vertex3f[ 7], varray_vertex3f[ 8]); - glTexCoord2f(varray_texcoord2f[0][6], varray_texcoord2f[0][7]);glVertex3f(varray_vertex3f[ 9], varray_vertex3f[10], varray_vertex3f[11]); + glTexCoord2f(particle_texcoord2f[0], particle_texcoord2f[1]);glVertex3f(particle_vertex3f[ 0], particle_vertex3f[ 1], particle_vertex3f[ 2]); + glTexCoord2f(particle_texcoord2f[2], particle_texcoord2f[3]);glVertex3f(particle_vertex3f[ 3], particle_vertex3f[ 4], particle_vertex3f[ 5]); + glTexCoord2f(particle_texcoord2f[4], particle_texcoord2f[5]);glVertex3f(particle_vertex3f[ 6], particle_vertex3f[ 7], particle_vertex3f[ 8]); + glTexCoord2f(particle_texcoord2f[6], particle_texcoord2f[7]);glVertex3f(particle_vertex3f[ 9], particle_vertex3f[10], particle_vertex3f[11]); glEnd(); #else R_Mesh_Draw(4, 2, polygonelements); diff --git a/gl_backend.c b/gl_backend.c index cc88e36d..3a15f7a5 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -3,25 +3,12 @@ #include "image.h" #include "jpeg.h" -//#define MESH_VAR -#define MESH_BATCH - -// 65536 is the max addressable on a Geforce 256 up until Geforce3 -// (excluding MX), seems a reasonable number... -cvar_t gl_mesh_maxverts = {0, "gl_mesh_maxverts", "65536"}; -cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "1"}; cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1"}; -#ifdef MESH_VAR -cvar_t gl_mesh_vertex_array_range = {0, "gl_mesh_vertex_array_range", "0"}; -cvar_t gl_mesh_vertex_array_range_readfrequency = {0, "gl_mesh_vertex_array_range_readfrequency", "0.2"}; -cvar_t gl_mesh_vertex_array_range_writefrequency = {0, "gl_mesh_vertex_array_range_writefrequency", "0.2"}; -cvar_t gl_mesh_vertex_array_range_priority = {0, "gl_mesh_vertex_array_range_priority", "0.7"}; -#endif -#ifdef MESH_BATCH -cvar_t gl_mesh_batching = {0, "gl_mesh_batching", "1"}; -#endif -cvar_t gl_mesh_copyarrays = {0, "gl_mesh_copyarrays", "1"}; +cvar_t gl_mesh_testarrayelement = {0, "gl_mesh_testarrayelement", "0"}; +cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0"}; cvar_t gl_delayfinish = {CVAR_SAVE, "gl_delayfinish", "0"}; +cvar_t gl_paranoid = {0, "gl_paranoid", "0"}; +cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0"}; cvar_t r_render = {0, "r_render", "1"}; cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1"}; // whether or not to use dithering @@ -88,26 +75,6 @@ void SCR_ScreenShot_f (void); // these are externally accessible int r_lightmapscalebit; float r_colorscale; -GLfloat *varray_vertex3f, *varray_buf_vertex3f; -GLfloat *varray_color4f, *varray_buf_color4f; -GLfloat *varray_texcoord3f[MAX_TEXTUREUNITS], *varray_buf_texcoord3f[MAX_TEXTUREUNITS]; -GLfloat *varray_texcoord2f[MAX_TEXTUREUNITS], *varray_buf_texcoord2f[MAX_TEXTUREUNITS]; -static qbyte *varray_buf_color4b; -int mesh_maxverts; -#ifdef MESH_VAR -int mesh_var; -float mesh_var_readfrequency; -float mesh_var_writefrequency; -float mesh_var_priority; -#endif -int varray_offset = 0, varray_offsetnext = 0; -GLuint *varray_buf_elements3i; -int mesh_maxelements = 32768; -#ifdef MESH_BATCH -int gl_batchvertexfirst = 0; -int gl_batchvertexcount = 0; -int gl_batchelementcount = 0; -#endif static matrix4x4_t backend_viewmatrix; static matrix4x4_t backend_modelmatrix; @@ -135,149 +102,26 @@ A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E *elements++ = i + row + 1; */ -void GL_Backend_AllocElementsArray(void) -{ - if (varray_buf_elements3i) - Mem_Free(varray_buf_elements3i); - varray_buf_elements3i = Mem_Alloc(gl_backend_mempool, mesh_maxelements * sizeof(GLuint)); -} - -void GL_Backend_FreeElementArray(void) -{ - if (varray_buf_elements3i) - Mem_Free(varray_buf_elements3i); - varray_buf_elements3i = NULL; -} - -void GL_Backend_CheckCvars(void) -{ - if (gl_mesh_maxverts.integer < 1024) - Cvar_SetValueQuick(&gl_mesh_maxverts, 1024); - if (gl_mesh_maxverts.integer > 65536) - Cvar_SetValueQuick(&gl_mesh_maxverts, 65536); -#ifdef MESH_VAR - if (gl_mesh_vertex_array_range.integer && !gl_support_var) - Cvar_SetValueQuick(&gl_mesh_vertex_array_range, 0); - if (gl_mesh_vertex_array_range_readfrequency.value < 0) - Cvar_SetValueQuick(&gl_mesh_vertex_array_range_readfrequency, 0); - if (gl_mesh_vertex_array_range_readfrequency.value > 1) - Cvar_SetValueQuick(&gl_mesh_vertex_array_range_readfrequency, 1); - if (gl_mesh_vertex_array_range_writefrequency.value < 0) - Cvar_SetValueQuick(&gl_mesh_vertex_array_range_writefrequency, 0); - if (gl_mesh_vertex_array_range_writefrequency.value > 1) - Cvar_SetValueQuick(&gl_mesh_vertex_array_range_writefrequency, 1); - if (gl_mesh_vertex_array_range_priority.value < 0) - Cvar_SetValueQuick(&gl_mesh_vertex_array_range_priority, 0); - if (gl_mesh_vertex_array_range_priority.value > 1) - Cvar_SetValueQuick(&gl_mesh_vertex_array_range_priority, 1); -#endif -} - int polygonelements[768]; static void R_Mesh_CacheArray_Startup(void); static void R_Mesh_CacheArray_Shutdown(void); void GL_Backend_AllocArrays(void) { - int i, size; - qbyte *data; - if (!gl_backend_mempool) - { gl_backend_mempool = Mem_AllocPool("GL_Backend"); - varray_buf_vertex3f = NULL; - varray_buf_color4f = NULL; - varray_buf_color4b = NULL; - varray_buf_elements3i = NULL; - for (i = 0;i < MAX_TEXTUREUNITS;i++) - varray_buf_texcoord3f[i] = varray_buf_texcoord2f[i] = NULL; - } - - if (varray_buf_vertex3f) -#ifdef MESH_VAR - VID_FreeVertexArrays(varray_buf_vertex3f); -#else - Mem_Free(varray_buf_vertex3f); -#endif - varray_buf_vertex3f = NULL; - varray_buf_color4f = NULL; - varray_buf_color4b = NULL; - for (i = 0;i < MAX_TEXTUREUNITS;i++) - varray_buf_texcoord3f[i] = varray_buf_texcoord2f[i] = NULL; - - mesh_maxverts = gl_mesh_maxverts.integer; - size = mesh_maxverts * (sizeof(float[3]) + sizeof(float[4]) + sizeof(qbyte[4]) + (sizeof(float[3]) + sizeof(float[2])) * backendunits); -#ifdef MESH_VAR - mesh_var = gl_mesh_vertex_array_range.integer && gl_support_var; - mesh_var_readfrequency = gl_mesh_vertex_array_range_readfrequency.value; - mesh_var_writefrequency = gl_mesh_vertex_array_range_writefrequency.value; - mesh_var_priority = gl_mesh_vertex_array_range_priority.value; - data = VID_AllocVertexArrays(gl_backend_mempool, size, gl_mesh_vertex_array_range.integer, gl_mesh_vertex_array_range_readfrequency.value, gl_mesh_vertex_array_range_writefrequency.value, gl_mesh_vertex_array_range_priority.value); -#else - data = Mem_Alloc(gl_backend_mempool, size); -#endif - - varray_buf_vertex3f = (void *)data;data += sizeof(float[3]) * mesh_maxverts; - varray_buf_color4f = (void *)data;data += sizeof(float[4]) * mesh_maxverts; - for (i = 0;i < backendunits;i++) - { - varray_buf_texcoord3f[i] = (void *)data;data += sizeof(float[3]) * mesh_maxverts; - varray_buf_texcoord2f[i] = (void *)data;data += sizeof(float[2]) * mesh_maxverts; - } - for (;i < MAX_TEXTUREUNITS;i++) - varray_buf_texcoord3f[i] = varray_buf_texcoord2f[i] = NULL; - varray_buf_color4b = (void *)data;data += sizeof(qbyte[4]) * mesh_maxverts; - - GL_Backend_AllocElementsArray(); - -#ifdef MESH_VAR - if (mesh_var) - { - CHECKGLERROR - qglVertexArrayRangeNV(size, varray_buf_vertex3f); - CHECKGLERROR - } -#endif - R_Mesh_CacheArray_Startup(); } void GL_Backend_FreeArrays(void) { - int i; - R_Mesh_CacheArray_Shutdown(); - -#ifdef MESH_VAR - if (mesh_var) - { - CHECKGLERROR - qglDisableClientState(GL_VERTEX_ARRAY_RANGE_NV); - CHECKGLERROR - } -#endif - - if (varray_buf_vertex3f) -#ifdef MESH_VAR - VID_FreeVertexArrays(varray_buf_vertex3f); -#else - Mem_Free(varray_buf_vertex3f); -#endif - varray_buf_vertex3f = NULL; - varray_buf_color4f = NULL; - varray_buf_color4b = NULL; - for (i = 0;i < MAX_TEXTUREUNITS;i++) - varray_buf_texcoord3f[i] = varray_buf_texcoord2f[i] = NULL; - varray_buf_elements3i = NULL; - Mem_FreePool(&gl_backend_mempool); } static void gl_backend_start(void) { - GL_Backend_CheckCvars(); - - Con_Printf("OpenGL Backend started with gl_mesh_maxverts %i\n", gl_mesh_maxverts.integer); + Con_Printf("OpenGL Backend started\n"); if (qglDrawRangeElements != NULL) { CHECKGLERROR @@ -287,31 +131,11 @@ static void gl_backend_start(void) CHECKGLERROR Con_Printf("glDrawRangeElements detected (max vertices %i, max indices %i)\n", gl_maxdrawrangeelementsvertices, gl_maxdrawrangeelementsindices); } - if (strstr(gl_renderer, "3Dfx")) - { - Con_Printf("3Dfx driver detected, forcing gl_mesh_floatcolors to 0 to prevent crashs\n"); - Cvar_SetValueQuick(&gl_mesh_floatcolors, 0); - } backendunits = min(MAX_TEXTUREUNITS, gl_textureunits); GL_Backend_AllocArrays(); -#ifdef MESH_VAR - if (mesh_var) - { - CHECKGLERROR - qglEnableClientState(GL_VERTEX_ARRAY_RANGE_NV); - CHECKGLERROR - } -#endif - varray_offset = varray_offsetnext = 0; -#ifdef MESH_BATCH - gl_batchvertexfirst = 0; - gl_batchvertexcount = 0; - gl_batchelementcount = 0; -#endif - backendactive = true; } @@ -322,26 +146,9 @@ static void gl_backend_shutdown(void) Con_Printf("OpenGL Backend shutting down\n"); -#ifdef MESH_VAR - if (mesh_var) - { - CHECKGLERROR - qglDisableClientState(GL_VERTEX_ARRAY_RANGE_NV); - CHECKGLERROR - } -#endif - GL_Backend_FreeArrays(); } -void GL_Backend_ResizeArrays(int numvertices) -{ - Cvar_SetValueQuick(&gl_mesh_maxverts, numvertices); - GL_Backend_CheckCvars(); - mesh_maxverts = gl_mesh_maxverts.integer; - GL_Backend_AllocArrays(); -} - static void gl_backend_newmap(void) { } @@ -361,23 +168,15 @@ void gl_backend_init(void) Cvar_RegisterVariable(&gl_dither); Cvar_RegisterVariable(&gl_lockarrays); Cvar_RegisterVariable(&gl_delayfinish); + Cvar_RegisterVariable(&gl_paranoid); + Cvar_RegisterVariable(&gl_printcheckerror); #ifdef NORENDER Cvar_SetValue("r_render", 0); #endif - Cvar_RegisterVariable(&gl_mesh_maxverts); - Cvar_RegisterVariable(&gl_mesh_floatcolors); Cvar_RegisterVariable(&gl_mesh_drawrangeelements); -#ifdef MESH_VAR - Cvar_RegisterVariable(&gl_mesh_vertex_array_range); - Cvar_RegisterVariable(&gl_mesh_vertex_array_range_readfrequency); - Cvar_RegisterVariable(&gl_mesh_vertex_array_range_writefrequency); - Cvar_RegisterVariable(&gl_mesh_vertex_array_range_priority); -#endif -#ifdef MESH_BATCH - Cvar_RegisterVariable(&gl_mesh_batching); -#endif - Cvar_RegisterVariable(&gl_mesh_copyarrays); + Cvar_RegisterVariable(&gl_mesh_testarrayelement); + Cvar_RegisterVariable(&gl_mesh_testmanualfeeding); R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap); } @@ -492,11 +291,13 @@ void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double typedef struct gltextureunit_s { int t1d, t2d, t3d, tcubemap; - int arrayenabled, arrayis3d; + int arrayenabled; + int arrayis3d; const void *pointer_texcoord; float rgbscale, alphascale; int combinergb, combinealpha; // FIXME: add more combine stuff + matrix4x4_t matrix; } gltextureunit_t; @@ -506,15 +307,13 @@ static struct int blendfunc2; int blend; GLboolean depthmask; - int depthdisable; + int depthtest; int unit; int clientunit; gltextureunit_t units[MAX_TEXTUREUNITS]; - int colorarray; float color4f[4]; int lockrange_first; int lockrange_count; - int pointervertexcount; const void *pointer_vertex; const void *pointer_color; } @@ -524,26 +323,26 @@ void GL_SetupTextureState(void) { int i; gltextureunit_t *unit; + gl_state.unit = -1; + gl_state.clientunit = -1; for (i = 0;i < backendunits;i++) { - if (qglActiveTexture) - qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR - if (qglClientActiveTexture) - qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR + GL_ActiveTexture(i); + GL_ClientActiveTexture(i); unit = gl_state.units + i; unit->t1d = 0; unit->t2d = 0; unit->t3d = 0; unit->tcubemap = 0; - unit->arrayenabled = false; - unit->arrayis3d = false; unit->pointer_texcoord = NULL; unit->rgbscale = 1; unit->alphascale = 1; unit->combinergb = GL_MODULATE; unit->combinealpha = GL_MODULATE; + + qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR - qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), varray_buf_texcoord2f[i]);CHECKGLERROR + qglDisable(GL_TEXTURE_1D);CHECKGLERROR qglDisable(GL_TEXTURE_2D);CHECKGLERROR if (gl_texture3d) @@ -584,22 +383,18 @@ void GL_SetupTextureState(void) void GL_Backend_ResetState(void) { memset(&gl_state, 0, sizeof(gl_state)); - gl_state.depthdisable = false; + gl_state.depthtest = true; gl_state.blendfunc1 = GL_ONE; gl_state.blendfunc2 = GL_ZERO; gl_state.blend = false; gl_state.depthmask = GL_TRUE; - gl_state.colorarray = false; gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1; gl_state.lockrange_first = 0; gl_state.lockrange_count = 0; - gl_state.pointervertexcount = 0; gl_state.pointer_vertex = NULL; gl_state.pointer_color = NULL; CHECKGLERROR - qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR - qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR qglEnable(GL_CULL_FACE);CHECKGLERROR qglCullFace(GL_FRONT);CHECKGLERROR @@ -607,65 +402,148 @@ void GL_Backend_ResetState(void) qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR qglDisable(GL_BLEND);CHECKGLERROR qglDepthMask(gl_state.depthmask);CHECKGLERROR - qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), varray_buf_vertex3f);CHECKGLERROR + + qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR - if (gl_mesh_floatcolors.integer) + + qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR + qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR + + GL_Color(0, 0, 0, 0); + GL_Color(1, 1, 1, 1); + + GL_SetupTextureState(); +} + +void GL_ActiveTexture(int num) +{ + if (gl_state.unit != num) { - qglColorPointer(4, GL_FLOAT, sizeof(float[4]), varray_buf_color4f);CHECKGLERROR + gl_state.unit = num; + if (qglActiveTexture) + { + qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit); + CHECKGLERROR + } } - else +} + +void GL_ClientActiveTexture(int num) +{ + if (gl_state.clientunit != num) { - qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(qbyte[4]), varray_buf_color4b);CHECKGLERROR + gl_state.clientunit = num; + if (qglActiveTexture) + { + qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit); + CHECKGLERROR + } } - GL_Color(0, 0, 0, 0); - GL_Color(1, 1, 1, 1); +} - GL_SetupTextureState(); +void GL_BlendFunc(int blendfunc1, int blendfunc2) +{ + if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2) + { + qglBlendFunc(gl_state.blendfunc1 = blendfunc1, gl_state.blendfunc2 = blendfunc2);CHECKGLERROR + if (gl_state.blendfunc2 == GL_ZERO) + { + if (gl_state.blendfunc1 == GL_ONE) + { + if (gl_state.blend) + { + gl_state.blend = 0; + qglDisable(GL_BLEND);CHECKGLERROR + } + } + else + { + if (!gl_state.blend) + { + gl_state.blend = 1; + qglEnable(GL_BLEND);CHECKGLERROR + } + } + } + else + { + if (!gl_state.blend) + { + gl_state.blend = 1; + qglEnable(GL_BLEND);CHECKGLERROR + } + } + } } -void GL_UseColorArray(void) +void GL_DepthMask(int state) { - if (!gl_state.colorarray) + if (gl_state.depthmask != state) { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - gl_state.colorarray = true; - qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR + qglDepthMask(gl_state.depthmask = state);CHECKGLERROR + } +} + +void GL_DepthTest(int state) +{ + if (gl_state.depthtest != state) + { + gl_state.depthtest = state; + if (gl_state.depthtest) + { + qglEnable(GL_DEPTH_TEST);CHECKGLERROR + } + else + { + qglDisable(GL_DEPTH_TEST);CHECKGLERROR + } + } +} + +void GL_VertexPointer(const float *p) +{ + if (gl_state.pointer_vertex != p) + { + gl_state.pointer_vertex = p; + CHECKGLERROR + qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), gl_state.pointer_vertex); + CHECKGLERROR + } +} + +void GL_ColorPointer(const float *p) +{ + if (gl_state.pointer_color != p) + { + CHECKGLERROR + if (!gl_state.pointer_color) + { + qglEnableClientState(GL_COLOR_ARRAY); + CHECKGLERROR + } + else if (!p) + { + qglDisableClientState(GL_COLOR_ARRAY); + CHECKGLERROR + } + gl_state.pointer_color = p; + qglColorPointer(4, GL_FLOAT, sizeof(float[4]), gl_state.pointer_color); + CHECKGLERROR } } void GL_Color(float cr, float cg, float cb, float ca) { - if (gl_state.colorarray) + if (gl_state.pointer_color || gl_state.color4f[0] != cr || gl_state.color4f[1] != cg || gl_state.color4f[2] != cb || gl_state.color4f[3] != ca) { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - gl_state.colorarray = false; - qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR + GL_ColorPointer(NULL); gl_state.color4f[0] = cr; gl_state.color4f[1] = cg; gl_state.color4f[2] = cb; gl_state.color4f[3] = ca; + CHECKGLERROR qglColor4f(cr, cg, cb, ca); - } - else - { - if (gl_state.color4f[0] != cr || gl_state.color4f[1] != cg || gl_state.color4f[2] != cb || gl_state.color4f[3] != ca) - { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - gl_state.color4f[0] = cr; - gl_state.color4f[1] = cg; - gl_state.color4f[2] = cb; - gl_state.color4f[3] = ca; - qglColor4f(cr, cg, cb, ca); - } + CHECKGLERROR } } @@ -707,168 +585,30 @@ void GL_TransformToScreen(const vec4_t in, vec4_t out) void R_Mesh_Start(void) { BACKENDACTIVECHECK - CHECKGLERROR - - GL_Backend_CheckCvars(); - if (mesh_maxverts != gl_mesh_maxverts.integer -#ifdef MESH_VAR - || mesh_var != (gl_mesh_vertex_array_range.integer && gl_support_var) - || mesh_var_readfrequency != gl_mesh_vertex_array_range_readfrequency.value - || mesh_var_writefrequency != gl_mesh_vertex_array_range_writefrequency.value - || mesh_var_priority != gl_mesh_vertex_array_range_priority.value -#endif - ) - GL_Backend_ResizeArrays(gl_mesh_maxverts.integer); - GL_Backend_ResetState(); -#ifdef MESH_VAR - if (!mesh_var) - { - gl_batchvertexfirst = gl_batchvertexcount = gl_batchelementcount = 0; - varray_offset = varray_offsetnext = 0; - } -#else - varray_offset = varray_offsetnext = 0; -#endif } int gl_backend_rebindtextures; -void GL_ConvertColorsFloatToByte(int first, int count) -{ - int i, k; - union {float f[4];int i[4];} *color4fi; - struct {GLubyte c[4];} *color4b; - - // shift float to have 8bit fraction at base of number - color4fi = (void *)(varray_buf_color4f + first * 4); - for (i = 0;i < count;i++, color4fi++) - { - color4fi->f[0] += 32768.0f; - color4fi->f[1] += 32768.0f; - color4fi->f[2] += 32768.0f; - color4fi->f[3] += 32768.0f; - } - - // then read as integer and kill float bits... - color4fi = (void *)(varray_buf_color4f + first * 4); - color4b = (void *)(varray_buf_color4b + first * 4); - for (i = 0;i < count;i++, color4fi++, color4b++) - { - k = color4fi->i[0] & 0x7FFFFF;color4b->c[0] = (GLubyte) min(k, 255); - k = color4fi->i[1] & 0x7FFFFF;color4b->c[1] = (GLubyte) min(k, 255); - k = color4fi->i[2] & 0x7FFFFF;color4b->c[2] = (GLubyte) min(k, 255); - k = color4fi->i[3] & 0x7FFFFF;color4b->c[3] = (GLubyte) min(k, 255); - } -} - -/* -// enlarges geometry buffers if they are too small -void _R_Mesh_ResizeCheck(int numverts) -{ - if (numverts > mesh_maxverts) - { - BACKENDACTIVECHECK - GL_Backend_ResizeArrays(numverts + 100); - GL_Backend_ResetState(); - } -} -*/ - -void R_Mesh_EndBatch(void) -{ -#ifdef MESH_BATCH - if (gl_batchelementcount) - { - if (gl_state.pointervertexcount) - Host_Error("R_Mesh_EndBatch: called with pointers enabled\n"); - - if (gl_state.colorarray && !gl_mesh_floatcolors.integer && gl_state.pointer_color == NULL) - GL_ConvertColorsFloatToByte(gl_batchvertexfirst, gl_batchvertexcount); - if (r_render.integer) - { - //int i;for (i = 0;i < gl_batchelementcount;i++) if (varray_buf_elements3i[i] < gl_batchvertexfirst || varray_buf_elements3i[i] >= (gl_batchvertexfirst + gl_batchvertexcount)) Host_Error("R_Mesh_EndBatch: invalid element #%i (value %i) outside range %i-%i\n", i, varray_buf_elements3i[i], gl_batchvertexfirst, gl_batchvertexfirst + gl_batchvertexcount); - CHECKGLERROR - GL_LockArrays(gl_batchvertexfirst, gl_batchvertexcount); - if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) - { - qglDrawRangeElements(GL_TRIANGLES, gl_batchvertexfirst, gl_batchvertexfirst + gl_batchvertexcount, gl_batchelementcount, GL_UNSIGNED_INT, (const GLuint *) varray_buf_elements3i);CHECKGLERROR - } - else - { - qglDrawElements(GL_TRIANGLES, gl_batchelementcount, GL_UNSIGNED_INT, (const GLuint *) varray_buf_elements3i);CHECKGLERROR - } - GL_LockArrays(0, 0); - } - gl_batchelementcount = 0; - gl_batchvertexcount = 0; - } -#endif -} - void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset) { int i; - //if (offset) + if (offset) + { for (i = 0;i < count;i++) *out++ = *in++ + offset; - //else - // memcpy(out, in, sizeof(*out) * count); -} - -// gets vertex buffer space for use with a following R_Mesh_Draw -// (can be multiple Draw calls per GetSpace) -void R_Mesh_GetSpace(int numverts) -{ - int i; - - if (gl_state.pointervertexcount) - Host_Error("R_Mesh_GetSpace: called with pointers enabled\n"); - if (gl_state.lockrange_count) - Host_Error("R_Mesh_GetSpace: called with arrays locked\n"); - - varray_offset = varray_offsetnext; - if (varray_offset + numverts > mesh_maxverts) - { - //Con_Printf("R_Mesh_GetSpace: vertex buffer wrap\n"); -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - varray_offset = 0; -#ifdef MESH_VAR - if (mesh_var) - { - CHECKGLERROR - qglFlushVertexArrayRangeNV(); - CHECKGLERROR - } -#endif - if (numverts > mesh_maxverts) - { - GL_Backend_ResizeArrays(numverts + 100); - GL_Backend_ResetState(); - } - } - - varray_vertex3f = varray_buf_vertex3f + varray_offset * 3; - varray_color4f = varray_buf_color4f + varray_offset * 4; - for (i = 0;i < backendunits;i++) - { - varray_texcoord3f[i] = varray_buf_texcoord3f[i] + varray_offset * 3; - varray_texcoord2f[i] = varray_buf_texcoord2f[i] + varray_offset * 2; } - - varray_offsetnext = varray_offset + numverts; + else + memcpy(out, in, sizeof(*out) * count); } -// renders triangles using vertices from the most recent GetSpace call -// (can be multiple Draw calls per GetSpace) +// renders triangles using vertices from the active arrays +int paranoidblah = 0; void R_Mesh_Draw(int numverts, int numtriangles, const int *elements) { int numelements = numtriangles * 3; - if (numtriangles == 0 || numverts == 0) + if (numverts == 0 || numtriangles == 0) { Con_Printf("R_Mesh_Draw(%d, %d, %08p);\n", numverts, numtriangles, elements); return; @@ -876,117 +616,120 @@ void R_Mesh_Draw(int numverts, int numtriangles, const int *elements) c_meshs++; c_meshelements += numelements; CHECKGLERROR - if (gl_state.pointervertexcount) + if (r_render.integer) { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - if (r_render.integer) + if (gl_paranoid.integer) { - GL_LockArrays(0, gl_state.pointervertexcount); - if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) + int i, j, size; + const int *p; + if (!qglIsEnabled(GL_VERTEX_ARRAY)) + Con_Printf("R_Mesh_Draw: vertex array not enabled\n"); + for (j = 0, size = numverts * (int)sizeof(float[3]), p = gl_state.pointer_vertex;j < size;j += sizeof(int), p++) + paranoidblah += *p; + if (gl_state.pointer_color) { - qglDrawRangeElements(GL_TRIANGLES, 0, gl_state.pointervertexcount, numelements, GL_UNSIGNED_INT, elements);CHECKGLERROR + if (!qglIsEnabled(GL_COLOR_ARRAY)) + Con_Printf("R_Mesh_Draw: color array set but not enabled\n"); + for (j = 0, size = numverts * (int)sizeof(float[4]), p = gl_state.pointer_color;j < size;j += sizeof(int), p++) + paranoidblah += *p; } - else - { - qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, elements);CHECKGLERROR - } - GL_LockArrays(0, 0); - } - } -#ifdef MESH_BATCH - else if (gl_mesh_batching.integer) - { - if (mesh_maxelements < gl_batchelementcount + numelements) - { - //Con_Printf("R_Mesh_Draw: enlarging elements array\n"); - if (gl_batchelementcount) - R_Mesh_EndBatch(); - // round up to a multiple of 1024 and add another 1024 just for good measure - mesh_maxelements = (gl_batchelementcount + numelements + 1024 + 1023) & ~1023; - GL_Backend_AllocElementsArray(); - } - if (varray_offset < gl_batchvertexfirst && gl_batchelementcount) - R_Mesh_EndBatch(); - if (gl_batchelementcount == 0) - { - gl_batchvertexfirst = varray_offset; - gl_batchvertexcount = 0; - } - if (gl_batchvertexcount < varray_offsetnext - gl_batchvertexfirst) - gl_batchvertexcount = varray_offsetnext - gl_batchvertexfirst; - GL_Backend_RenumberElements(varray_buf_elements3i + gl_batchelementcount, numelements, elements, varray_offset); - //Con_Printf("off %i:%i, vertex %i:%i, element %i:%i\n", varray_offset, varray_offsetnext, gl_batchvertexfirst, gl_batchvertexfirst + gl_batchvertexcount, gl_batchelementcount, gl_batchelementcount + numelements); - gl_batchelementcount += numelements; - //{int i;for (i = 0;i < gl_batchelementcount;i++) if (varray_buf_elements3i[i] < gl_batchvertexfirst || varray_buf_elements3i[i] >= (gl_batchvertexfirst + gl_batchvertexcount)) Host_Error("R_Mesh_EndBatch: invalid element #%i (value %i) outside range %i-%i, there were previously %i elements and there are now %i elements, varray_offset is %i\n", i, varray_buf_elements3i[i], gl_batchvertexfirst, gl_batchvertexfirst + gl_batchvertexcount, gl_batchelementcount - numelements, gl_batchelementcount, varray_offset);} - } -#endif - else - { - GL_Backend_RenumberElements(varray_buf_elements3i, numelements, elements, varray_offset); - if (r_render.integer) - { - GL_LockArrays(varray_offset, numverts); - if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) + for (i = 0;i < backendunits;i++) { - qglDrawRangeElements(GL_TRIANGLES, varray_offset, varray_offset + numverts, numelements, GL_UNSIGNED_INT, varray_buf_elements3i);CHECKGLERROR + if (gl_state.units[i].t1d || gl_state.units[i].t2d || gl_state.units[i].t3d || gl_state.units[i].tcubemap || gl_state.units[i].arrayenabled) + { + if (gl_state.units[i].arrayenabled && !(gl_state.units[i].t1d || gl_state.units[i].t2d || gl_state.units[i].t3d || gl_state.units[i].tcubemap)) + Con_Printf("R_Mesh_Draw: array enabled but no texture bound\n"); + GL_ActiveTexture(i); + if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY)) + Con_Printf("R_Mesh_Draw: texcoord array set but not enabled\n"); + for (j = 0, size = numverts * ((gl_state.units[i].t3d || gl_state.units[i].tcubemap) ? (int)sizeof(float[3]) : (int)sizeof(float[2])), p = gl_state.units[i].pointer_texcoord;j < size;j += sizeof(int), p++) + paranoidblah += *p; + } } - else + for (i = 0;i < numtriangles * 3;i++) { - qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, varray_buf_elements3i);CHECKGLERROR + if (elements[i] < 0 || elements[i] >= numverts) + { + Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range 0 - %i) in elements list\n", elements[i], numverts); + return; + } } - GL_LockArrays(0, 0); } - } -} - -// renders triangles using vertices from the most recent GetSpace call -// (can be multiple Draw calls per GetSpace) -void R_Mesh_Draw_NoBatching(int numverts, int numtriangles, const int *elements) -{ - int numelements = numtriangles * 3; - if (numtriangles == 0 || numverts == 0) - { - Con_Printf("R_Mesh_Draw_NoBatching(%d, %d, %08p);\n", numverts, numtriangles, elements); - return; - } - c_meshs++; - c_meshelements += numelements; - CHECKGLERROR - if (gl_state.pointervertexcount) - { - if (r_render.integer) + CHECKGLERROR + GL_LockArrays(0, numverts); + CHECKGLERROR + if (gl_mesh_testmanualfeeding.integer) { - GL_LockArrays(0, gl_state.pointervertexcount); - if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) - { - qglDrawRangeElements(GL_TRIANGLES, 0, gl_state.pointervertexcount, numelements, GL_UNSIGNED_INT, elements);CHECKGLERROR - } - else + int i, j; + const GLfloat *p; + qglBegin(GL_TRIANGLES); + for (i = 0;i < numtriangles * 3;i++) { - qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, elements);CHECKGLERROR + for (j = 0;j < backendunits;j++) + { + if (gl_state.units[j].pointer_texcoord) + { + if (backendunits > 1) + { + if (gl_state.units[j].t3d || gl_state.units[j].tcubemap) + { + p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3; + qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]); + } + else + { + p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2; + qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]); + } + } + else + { + if (gl_state.units[j].t3d || gl_state.units[j].tcubemap) + { + p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3; + qglTexCoord3f(p[0], p[1], p[2]); + } + else + { + p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2; + qglTexCoord2f(p[0], p[1]); + } + } + } + } + if (gl_state.pointer_color) + { + p = ((const GLfloat *)(gl_state.pointer_color)) + elements[i] * 4; + qglColor4f(p[0], p[1], p[2], p[3]); + } + p = ((const GLfloat *)(gl_state.pointer_vertex)) + elements[i] * 3; + qglVertex3f(p[0], p[1], p[2]); } - GL_LockArrays(0, 0); + qglEnd(); + CHECKGLERROR } - } - else - { - GL_Backend_RenumberElements(varray_buf_elements3i, numelements, elements, varray_offset); - if (r_render.integer) + else if (gl_mesh_testarrayelement.integer) { - GL_LockArrays(varray_offset, numverts); - if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) + int i; + qglBegin(GL_TRIANGLES); + for (i = 0;i < numtriangles * 3;i++) { - qglDrawRangeElements(GL_TRIANGLES, varray_offset, varray_offset + numverts, numelements, GL_UNSIGNED_INT, varray_buf_elements3i);CHECKGLERROR + qglArrayElement(elements[i]); } - else - { - qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, varray_buf_elements3i);CHECKGLERROR - } - GL_LockArrays(0, 0); + qglEnd(); + CHECKGLERROR + } + else if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) + { + qglDrawRangeElements(GL_TRIANGLES, 0, numverts, numelements, GL_UNSIGNED_INT, elements);CHECKGLERROR + } + else + { + qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, elements);CHECKGLERROR } + CHECKGLERROR + GL_LockArrays(0, 0); + CHECKGLERROR } } @@ -995,11 +738,9 @@ void R_Mesh_Finish(void) { int i; BACKENDACTIVECHECK -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif + CHECKGLERROR GL_LockArrays(0, 0); + CHECKGLERROR for (i = backendunits - 1;i >= 0;i--) { @@ -1038,10 +779,6 @@ void R_Mesh_Matrix(const matrix4x4_t *matrix) { if (memcmp(matrix, &backend_modelmatrix, sizeof(matrix4x4_t))) { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif backend_modelmatrix = *matrix; Matrix4x4_Concat(&backend_modelviewmatrix, &backend_viewmatrix, matrix); Matrix4x4_Transpose(&backend_glmodelviewmatrix, &backend_modelviewmatrix); @@ -1049,110 +786,24 @@ void R_Mesh_Matrix(const matrix4x4_t *matrix) } } -// sets up the requested state -void R_Mesh_MainState(const rmeshstate_t *m) +void R_Mesh_TextureMatrix(int unitnumber, const matrix4x4_t *matrix) { - const void *p; - BACKENDACTIVECHECK - - if (gl_state.blendfunc1 != m->blendfunc1 || gl_state.blendfunc2 != m->blendfunc2) - { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - qglBlendFunc(gl_state.blendfunc1 = m->blendfunc1, gl_state.blendfunc2 = m->blendfunc2);CHECKGLERROR - if (gl_state.blendfunc2 == GL_ZERO) - { - if (gl_state.blendfunc1 == GL_ONE) - { - if (gl_state.blend) - { - gl_state.blend = 0; - qglDisable(GL_BLEND);CHECKGLERROR - } - } - else - { - if (!gl_state.blend) - { - gl_state.blend = 1; - qglEnable(GL_BLEND);CHECKGLERROR - } - } - } - else - { - if (!gl_state.blend) - { - gl_state.blend = 1; - qglEnable(GL_BLEND);CHECKGLERROR - } - } - } - if (gl_state.depthdisable != m->depthdisable) + if (memcmp(&gl_state.units[unitnumber].matrix, matrix, sizeof(matrix4x4_t))) { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - gl_state.depthdisable = m->depthdisable; - if (gl_state.depthdisable) - qglDisable(GL_DEPTH_TEST); - else - qglEnable(GL_DEPTH_TEST); - } - if (gl_state.depthmask != (m->blendfunc2 == GL_ZERO || m->depthwrite)) - { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - qglDepthMask(gl_state.depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite));CHECKGLERROR - } - - if (gl_state.pointervertexcount != m->pointervertexcount) - { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - gl_state.pointervertexcount = m->pointervertexcount; - } - - p = gl_state.pointervertexcount ? m->pointer_vertex : NULL; - if (gl_state.pointer_vertex != p) - { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - gl_state.pointer_vertex = p; - qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), p ? p : varray_buf_vertex3f);CHECKGLERROR - } - - p = gl_state.pointervertexcount ? m->pointer_color : NULL; - if (gl_state.pointer_color != p) - { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - gl_state.pointer_color = p; - if (p || gl_mesh_floatcolors.integer) - qglColorPointer(4, GL_FLOAT, sizeof(float[4]), p ? p : varray_buf_color4f); - else - qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(GLubyte[4]), p ? p : varray_buf_color4b); - CHECKGLERROR + matrix4x4_t tempmatrix; + gl_state.units[unitnumber].matrix = *matrix; + Matrix4x4_Transpose(&tempmatrix, &gl_state.units[unitnumber].matrix); + qglMatrixMode(GL_TEXTURE); + GL_ActiveTexture(unitnumber); + qglLoadMatrixf(&tempmatrix.m[0][0]); + qglMatrixMode(GL_MODELVIEW); } } -void R_Mesh_TextureState(const rmeshstate_t *m) +void R_Mesh_State_Texture(const rmeshstate_t *m) { - int i, combinergb, combinealpha; - float scale; + int i, combinergb, combinealpha, scale, arrayis3d; gltextureunit_t *unit; - const void *p; BACKENDACTIVECHECK @@ -1162,187 +813,74 @@ void R_Mesh_TextureState(const rmeshstate_t *m) GL_SetupTextureState(); } - for (i = 0;i < backendunits;i++) + for (i = 0, unit = gl_state.units;i < backendunits;i++, unit++) { - unit = gl_state.units + i; - if (unit->t1d != m->tex1d[i] || unit->t2d != m->tex[i] || unit->t3d != m->tex3d[i] || unit->tcubemap != m->texcubemap[i]) + if (unit->t1d != m->tex1d[i]) { - if (m->tex3d[i] || m->texcubemap[i]) + GL_ActiveTexture(i); + if (m->tex1d[i]) { - if (!unit->arrayis3d) - { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - unit->arrayis3d = true; - if (gl_state.clientunit != i) - { - qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR - } - qglTexCoordPointer(3, GL_FLOAT, sizeof(float[3]), varray_buf_texcoord3f[i]); - } - if (!unit->arrayenabled) - { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - unit->arrayenabled = true; - if (gl_state.clientunit != i) - { - qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR - } - qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR - } + if (unit->t1d == 0) + qglEnable(GL_TEXTURE_1D);CHECKGLERROR } - else if (m->tex1d[i] || m->tex[i]) + else { - if (unit->arrayis3d) - { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - unit->arrayis3d = false; - if (gl_state.clientunit != i) - { - qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR - } - qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), varray_buf_texcoord2f[i]); - } - if (!unit->arrayenabled) - { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - unit->arrayenabled = true; - if (gl_state.clientunit != i) - { - qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR - } - qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR - } + if (unit->t1d) + qglDisable(GL_TEXTURE_1D);CHECKGLERROR + } + qglBindTexture(GL_TEXTURE_1D, (unit->t1d = m->tex1d[i]));CHECKGLERROR + } + if (unit->t2d != m->tex[i]) + { + GL_ActiveTexture(i); + if (m->tex[i]) + { + if (unit->t2d == 0) + qglEnable(GL_TEXTURE_2D);CHECKGLERROR } else { - if (unit->arrayenabled) - { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - unit->arrayenabled = false; - if (gl_state.clientunit != i) - { - qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR - } - qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR - } + if (unit->t2d) + qglDisable(GL_TEXTURE_2D);CHECKGLERROR } - if (unit->t1d != m->tex1d[i]) + qglBindTexture(GL_TEXTURE_2D, (unit->t2d = m->tex[i]));CHECKGLERROR + } + if (unit->t3d != m->tex3d[i]) + { + GL_ActiveTexture(i); + if (m->tex3d[i]) { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - if (gl_state.unit != i) - { - qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR - } - if (m->tex1d[i]) - { - if (unit->t1d == 0) - qglEnable(GL_TEXTURE_1D);CHECKGLERROR - } - else - { - if (unit->t1d) - qglDisable(GL_TEXTURE_1D);CHECKGLERROR - } - qglBindTexture(GL_TEXTURE_1D, (unit->t1d = m->tex1d[i]));CHECKGLERROR + if (unit->t3d == 0) + qglEnable(GL_TEXTURE_3D);CHECKGLERROR } - if (unit->t2d != m->tex[i]) + else { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - if (gl_state.unit != i) - { - qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR - } - if (m->tex[i]) - { - if (unit->t2d == 0) - qglEnable(GL_TEXTURE_2D);CHECKGLERROR - } - else - { - if (unit->t2d) - qglDisable(GL_TEXTURE_2D);CHECKGLERROR - } - qglBindTexture(GL_TEXTURE_2D, (unit->t2d = m->tex[i]));CHECKGLERROR + if (unit->t3d) + qglDisable(GL_TEXTURE_3D);CHECKGLERROR } - if (unit->t3d != m->tex3d[i]) + qglBindTexture(GL_TEXTURE_3D, (unit->t3d = m->tex3d[i]));CHECKGLERROR + } + if (unit->tcubemap != m->texcubemap[i]) + { + GL_ActiveTexture(i); + if (m->texcubemap[i]) { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - if (gl_state.unit != i) - { - qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR - } - if (m->tex3d[i]) - { - if (unit->t3d == 0) - qglEnable(GL_TEXTURE_3D);CHECKGLERROR - } - else - { - if (unit->t3d) - qglDisable(GL_TEXTURE_3D);CHECKGLERROR - } - qglBindTexture(GL_TEXTURE_3D, (unit->t3d = m->tex3d[i]));CHECKGLERROR + if (unit->tcubemap == 0) + qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR } - if (unit->tcubemap != m->texcubemap[i]) + else { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - if (gl_state.unit != i) - { - qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR - } - if (m->texcubemap[i]) - { - if (unit->tcubemap == 0) - qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR - } - else - { - if (unit->tcubemap) - qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR - } - qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, (unit->tcubemap = m->texcubemap[i]));CHECKGLERROR + if (unit->tcubemap) + qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR } + qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, (unit->tcubemap = m->texcubemap[i]));CHECKGLERROR } combinergb = m->texcombinergb[i]; if (!combinergb) combinergb = GL_MODULATE; if (unit->combinergb != combinergb) { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - if (gl_state.unit != i) - { - qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR - } + GL_ActiveTexture(i); unit->combinergb = combinergb; if (gl_combine.integer) { @@ -1358,14 +896,7 @@ void R_Mesh_TextureState(const rmeshstate_t *m) combinealpha = GL_MODULATE; if (unit->combinealpha != combinealpha) { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - if (gl_state.unit != i) - { - qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR - } + GL_ActiveTexture(i); unit->combinealpha = combinealpha; if (gl_combine.integer) { @@ -1373,61 +904,48 @@ void R_Mesh_TextureState(const rmeshstate_t *m) } } scale = max(m->texrgbscale[i], 1); - if (gl_state.units[i].rgbscale != scale) + if (unit->rgbscale != scale) { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - if (gl_state.unit != i) - { - qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR - } - qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (gl_state.units[i].rgbscale = scale));CHECKGLERROR + GL_ActiveTexture(i); + qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = scale));CHECKGLERROR } scale = max(m->texalphascale[i], 1); - if (gl_state.units[i].alphascale != scale) + if (unit->alphascale != scale) { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - if (gl_state.unit != i) - { - qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR - } - qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (gl_state.units[i].alphascale = scale));CHECKGLERROR + GL_ActiveTexture(i); + qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = scale));CHECKGLERROR } - if (unit->arrayenabled) + arrayis3d = unit->t3d || unit->tcubemap; + if (unit->pointer_texcoord != m->pointer_texcoord[i] || unit->arrayis3d != arrayis3d) { - p = gl_state.pointervertexcount ? m->pointer_texcoord[i] : NULL; - if (unit->pointer_texcoord != p) + GL_ClientActiveTexture(i); + if (m->pointer_texcoord[i]) { -#ifdef MESH_BATCH - if (gl_batchelementcount) - R_Mesh_EndBatch(); -#endif - unit->pointer_texcoord = p; - if (gl_state.clientunit != i) + if (!unit->arrayenabled) { - qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR + unit->arrayenabled = true; + qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR } - if (unit->arrayis3d) - qglTexCoordPointer(3, GL_FLOAT, sizeof(float[3]), p ? p : varray_buf_texcoord3f[i]); - else - qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), p ? p : varray_buf_texcoord2f[i]); - CHECKGLERROR } + else + { + if (unit->arrayenabled) + { + unit->arrayenabled = false; + qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR + } + } + unit->pointer_texcoord = m->pointer_texcoord[i]; + unit->arrayis3d = arrayis3d; + if (unit->arrayis3d) + qglTexCoordPointer(3, GL_FLOAT, sizeof(float[3]), unit->pointer_texcoord); + else + qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), unit->pointer_texcoord); + CHECKGLERROR } } } -void R_Mesh_State(const rmeshstate_t *m) -{ - R_Mesh_MainState(m); - R_Mesh_TextureState(m); -} - /* ============================================================================== @@ -1557,70 +1075,16 @@ void SCR_UpdateScreen (void) } } -// utility functions -void R_Mesh_CopyVertex3f(const float *vertex3f, int numverts) -{ -#ifdef MESH_VAR - if (mesh_var) - { - float *out = varray_vertex3f; - while (--numverts) - { - *out++ = *vertex3f++; - *out++ = *vertex3f++; - *out++ = *vertex3f++; - } - } - else -#endif - memcpy(varray_vertex3f, vertex3f, numverts * sizeof(float[3])); -} - -void R_Mesh_CopyTexCoord2f(int tmu, const float *texcoord2f, int numverts) -{ -#ifdef MESH_VAR - if (mesh_var) - { - float *out = varray_texcoord2f[tmu]; - while (numverts--) - { - *out++ = *texcoord2f++; - *out++ = *texcoord2f++; - } - } - else -#endif - memcpy(varray_texcoord2f[tmu], texcoord2f, numverts * sizeof(float[2])); -} - -void R_Mesh_CopyColor4f(const float *color4f, int numverts) -{ -#ifdef MESH_VAR - if (mesh_var) - { - float *out = varray_color4f; - while (numverts--) - { - *out++ = *color4f++; - *out++ = *color4f++; - *out++ = *color4f++; - *out++ = *color4f++; - } - } - else -#endif - memcpy(varray_color4f, color4f, numverts * sizeof(float[4])); -} +//=========================================================================== +// dynamic vertex array buffer subsystem +//=========================================================================== -void R_ScrollTexCoord2f (float *out2f, const float *in2f, int numverts, float s, float t) -{ - while (numverts--) - { - *out2f++ = *in2f++ + s; - *out2f++ = *in2f++ + t; - } -} +float varray_vertex3f[65536*3]; +float varray_color4f[65536*4]; +float varray_texcoord2f[4][65536*2]; +float varray_texcoord3f[4][65536*3]; +float varray_normal3f[65536*3]; //=========================================================================== // vertex array caching subsystem diff --git a/gl_backend.h b/gl_backend.h index 12061681..e8918dc3 100644 --- a/gl_backend.h +++ b/gl_backend.h @@ -7,41 +7,44 @@ #define POLYGONELEMENTS_MAXPOINTS 258 extern int polygonelements[768]; -void GL_SetupView_ViewPort (int x, int y, int width, int height); -void GL_SetupView_Orientation_Identity (void); -void GL_SetupView_Orientation_FromEntity (vec3_t origin, vec3_t angles); -void GL_SetupView_Mode_Perspective (double fovx, double fovy, double zNear, double zFar); -void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double fovx, double fovy, double zNear); -void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double zNear, double zFar); -void GL_UseColorArray(void); +void GL_SetupView_ViewPort(int x, int y, int width, int height); +void GL_SetupView_Orientation_Identity(void); +void GL_SetupView_Orientation_FromEntity(vec3_t origin, vec3_t angles); +void GL_SetupView_Mode_Perspective(double fovx, double fovy, double zNear, double zFar); +void GL_SetupView_Mode_PerspectiveInfiniteFarClip(double fovx, double fovy, double zNear); +void GL_SetupView_Mode_Ortho(double x1, double y1, double x2, double y2, double zNear, double zFar); +void GL_BlendFunc(int blendfunc1, int blendfunc2); +void GL_DepthMask(int state); +void GL_DepthTest(int state); +void GL_VertexPointer(const float *p); +void GL_ColorPointer(const float *p); void GL_Color(float cr, float cg, float cb, float ca); void GL_TransformToScreen(const vec4_t in, vec4_t out); void GL_LockArrays(int first, int count); +void GL_ActiveTexture(int num); +void GL_ClientActiveTexture(int num); extern cvar_t gl_lockarrays; extern cvar_t gl_mesh_copyarrays; +extern cvar_t gl_paranoid; +extern cvar_t gl_printcheckerror; extern int c_meshelements, c_meshs; //input to R_Mesh_State typedef struct { - int depthwrite; // force depth writing enabled even if polygon is not opaque - int depthdisable; // disable depth read/write entirely - int blendfunc1; - int blendfunc2; - //int wantoverbright; + // textures int tex1d[MAX_TEXTUREUNITS]; int tex[MAX_TEXTUREUNITS]; int tex3d[MAX_TEXTUREUNITS]; int texcubemap[MAX_TEXTUREUNITS]; + // texture combine settings int texrgbscale[MAX_TEXTUREUNITS]; // used only if COMBINE is present int texalphascale[MAX_TEXTUREUNITS]; // used only if COMBINE is present int texcombinergb[MAX_TEXTUREUNITS]; // works with or without combine for some operations int texcombinealpha[MAX_TEXTUREUNITS]; // does nothing without combine - int pointervertexcount; - const float *pointer_vertex; - const float *pointer_color; + // pointers const float *pointer_texcoord[MAX_TEXTUREUNITS]; } rmeshstate_t; @@ -49,11 +52,6 @@ rmeshstate_t; // overbright rendering scale for the current state extern int r_lightmapscalebit; extern float r_colorscale; -extern float *varray_vertex3f; -extern float *varray_color4f; -extern float *varray_texcoord3f[MAX_TEXTUREUNITS]; -extern float *varray_texcoord2f[MAX_TEXTUREUNITS]; -extern int mesh_maxverts; // adds console variables and registers the render module (only call from GL_Init) void gl_backend_init(void); @@ -68,39 +66,21 @@ void R_Mesh_Finish(void); // sets up the requested transform matrix void R_Mesh_Matrix(const matrix4x4_t *matrix); -// sets up the requested state -void R_Mesh_State(const rmeshstate_t *m); - -// sets up the requested main state -void R_Mesh_MainState(const rmeshstate_t *m); +// sets up the requested transform matrix +void R_Mesh_TextureMatrix(int unitnumber, const matrix4x4_t *matrix); -// sets up the requested texture state -void R_Mesh_TextureState(const rmeshstate_t *m); +// set up the requested state +void R_Mesh_State_Texture(const rmeshstate_t *m); -// forcefully ends a batch (do this before calling any gl functions directly) -void R_Mesh_EndBatch(void); -// prepares varray_* buffers for rendering a mesh -void R_Mesh_GetSpace(int numverts); -// renders a mesh (optionally with batching) +// renders a mesh void R_Mesh_Draw(int numverts, int numtriangles, const int *elements); -// renders a mesh without affecting batching -void R_Mesh_Draw_NoBatching(int numverts, int numtriangles, const int *elements); - -// copies a vertex3f array into varray_vertex3f -void R_Mesh_CopyVertex3f(const float *vertex3f, int numverts); -// copies a texcoord2f array into varray_texcoord[tmu] -void R_Mesh_CopyTexCoord2f(int tmu, const float *texcoord2f, int numverts); -// copies a color4f array into varray_color4f -void R_Mesh_CopyColor4f(const float *color4f, int numverts); -// copies a texcoord2f array into another array, with scrolling -void R_ScrollTexCoord2f (float *out2f, const float *in2f, int numverts, float s, float t); // saves a section of the rendered frame to a .tga or .jpg file qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height, qboolean jpeg); // used by R_Envmap_f and internally in backend, clears the frame void R_ClearScreen(void); // invoke refresh of frame -void SCR_UpdateScreen (void); +void SCR_UpdateScreen(void); // public structure typedef struct rcachearrayrequest_s @@ -123,5 +103,11 @@ rcachearrayrequest_t; int R_Mesh_CacheArray(rcachearrayrequest_t *r); +extern float varray_vertex3f[65536*3]; +extern float varray_color4f[65536*4]; +extern float varray_texcoord2f[4][65536*2]; +extern float varray_texcoord3f[4][65536*3]; +extern float varray_normal3f[65536*3]; + #endif diff --git a/gl_draw.c b/gl_draw.c index 8830e060..88b9f194 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -380,8 +380,6 @@ void GL_Draw_Init (void) float blendvertex3f[9] = {-5000, -5000, 10, 10000, -5000, 10, -5000, 10000, 10}; int quadelements[768]; -float textverts[128*4*3]; -float texttexcoords[128*4*2]; void R_DrawQueue(void) { int pos, num, chartexnum, overbright, texnum, additive, batch; @@ -420,7 +418,7 @@ void R_DrawQueue(void) memset(&m, 0, sizeof(m)); m.tex[0] = 0; - R_Mesh_TextureState(&m); + R_Mesh_State_Texture(&m); currentpic = ""; pic = NULL; @@ -435,12 +433,9 @@ void R_DrawQueue(void) dq = (drawqueue_t *)(r_refdef.drawqueue + pos); additive = (dq->flags & DRAWFLAG_ADDITIVE) != 0; color = dq->color; - m.blendfunc1 = GL_SRC_ALPHA; - if (additive) - m.blendfunc2 = GL_ONE; - else - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - m.depthdisable = true; + GL_BlendFunc(GL_SRC_ALPHA, additive ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(true); + GL_DepthTest(false); c[0] = (float) ((color >> 24) & 0xFF) * (1.0f / 255.0f) * r_colorscale; c[1] = (float) ((color >> 16) & 0xFF) * (1.0f / 255.0f) * r_colorscale; @@ -454,6 +449,7 @@ void R_DrawQueue(void) switch(dq->command) { case DRAWQUEUE_STRING: + GL_Color(c[0], c[1], c[2], c[3]); str = (char *)(dq + 1); if (strcmp("gfx/conchars", currentpic)) { @@ -461,9 +457,11 @@ void R_DrawQueue(void) m.tex[0] = chartexnum; } batchcount = 0; - at = texttexcoords; - av = textverts; - GL_Color(c[0], c[1], c[2], c[3]); + GL_VertexPointer(varray_vertex3f); + m.pointer_texcoord[0] = varray_texcoord2f[0]; + R_Mesh_State_Texture(&m); + at = varray_texcoord2f[0]; + av = varray_vertex3f; while ((num = *str++) && x < vid.conwidth) { if (num != ' ') @@ -485,81 +483,24 @@ void R_DrawQueue(void) batchcount++; if (batchcount >= 128) { - if (gl_mesh_copyarrays.integer) - { - m.pointervertexcount = 0; - m.pointer_vertex = NULL; - m.pointer_texcoord[0] = NULL; - m.pointer_color = NULL; - R_Mesh_State(&m); - R_Mesh_GetSpace(batchcount * 4); - R_Mesh_CopyVertex3f(textverts, batchcount * 4); - R_Mesh_CopyTexCoord2f(0, texttexcoords, batchcount * 4); - } - else - { - m.pointervertexcount = batchcount * 4; - m.pointer_vertex = textverts; - m.pointer_texcoord[0] = texttexcoords; - m.pointer_color = NULL; - R_Mesh_State(&m); - } R_Mesh_Draw(batchcount * 4, batchcount * 2, quadelements); batchcount = 0; - at = texttexcoords; - av = textverts; + at = varray_texcoord2f[0]; + av = varray_vertex3f; } } x += w; } if (batchcount > 0) - { - if (gl_mesh_copyarrays.integer) - { - m.pointervertexcount = 0; - m.pointer_vertex = NULL; - m.pointer_texcoord[0] = NULL; - m.pointer_color = NULL; - R_Mesh_State(&m); - R_Mesh_GetSpace(batchcount * 4); - R_Mesh_CopyVertex3f(textverts, batchcount * 4); - R_Mesh_CopyTexCoord2f(0, texttexcoords, batchcount * 4); - } - else - { - m.pointervertexcount = batchcount * 4; - m.pointer_vertex = textverts; - m.pointer_texcoord[0] = texttexcoords; - m.pointer_color = NULL; - R_Mesh_State(&m); - } R_Mesh_Draw(batchcount * 4, batchcount * 2, quadelements); - } break; case DRAWQUEUE_MESH: mesh = (void *)(dq + 1); + GL_VertexPointer(mesh->vertex3f); + GL_ColorPointer(mesh->color4f); m.tex[0] = R_GetTexture(mesh->texture); - GL_UseColorArray(); - if (gl_mesh_copyarrays.integer) - { - m.pointervertexcount = 0; - m.pointer_vertex = NULL; - m.pointer_texcoord[0] = NULL; - m.pointer_color = NULL; - R_Mesh_State(&m); - R_Mesh_GetSpace(mesh->numvertices); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numvertices); - R_Mesh_CopyTexCoord2f(0, mesh->texcoord2f, mesh->numvertices); - R_Mesh_CopyColor4f(mesh->color4f, mesh->numvertices); - } - else - { - m.pointervertexcount = mesh->numvertices; - m.pointer_vertex = mesh->vertex3f; - m.pointer_texcoord[0] = mesh->texcoord2f; - m.pointer_color = mesh->color4f; - R_Mesh_State(&m); - } + m.pointer_texcoord[0] = mesh->texcoord2f; + R_Mesh_State_Texture(&m); R_Mesh_Draw(mesh->numvertices, mesh->numtriangles, mesh->element3i); currentpic = "\0"; break; @@ -570,7 +511,9 @@ void R_DrawQueue(void) { // all the blends ignore depth memset(&m, 0, sizeof(m)); - m.depthdisable = true; + R_Mesh_State_Texture(&m); + GL_DepthMask(true); + GL_DepthTest(false); if (v_color_enable.integer) { c[0] = v_color_white_r.value; @@ -582,20 +525,8 @@ void R_DrawQueue(void) VectorScale(c, (float) (1 << v_overbrightbits.integer), c); if (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f) { - m.blendfunc1 = GL_DST_COLOR; - m.blendfunc2 = GL_ONE; - if (gl_mesh_copyarrays.integer) - { - R_Mesh_State(&m); - R_Mesh_GetSpace(3); - R_Mesh_CopyVertex3f(blendvertex3f, 3); - } - else - { - m.pointervertexcount = 3; - m.pointer_vertex = blendvertex3f; - R_Mesh_State(&m); - } + GL_BlendFunc(GL_DST_COLOR, GL_ONE); + GL_VertexPointer(blendvertex3f); while (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f) { GL_Color(bound(0, c[0] - 1, 1), bound(0, c[1] - 1, 1), bound(0, c[2] - 1, 1), 1); @@ -613,22 +544,8 @@ void R_DrawQueue(void) c[0] = c[1] = c[2] = v_brightness.value; if (c[0] >= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f) { - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ONE; - if (gl_mesh_copyarrays.integer) - { - m.pointervertexcount = 0; - m.pointer_vertex = NULL; - R_Mesh_State(&m); - R_Mesh_GetSpace(3); - R_Mesh_CopyVertex3f(blendvertex3f, 3); - } - else - { - m.pointervertexcount = 3; - m.pointer_vertex = blendvertex3f; - R_Mesh_State(&m); - } + GL_BlendFunc(GL_ONE, GL_ONE); + GL_VertexPointer(blendvertex3f); GL_Color(c[0], c[1], c[2], 1); R_Mesh_Draw(3, 1, polygonelements); } diff --git a/gl_models.c b/gl_models.c index 3cbd420b..ec9ed00e 100644 --- a/gl_models.c +++ b/gl_models.c @@ -86,7 +86,7 @@ void GL_Models_Init(void) #define MODELARRAY_TVECTOR 2 #define MODELARRAY_NORMAL 3 -void R_Model_Alias_GetMesh_Array3f(const entity_render_t *ent, aliasmesh_t *mesh, int whicharray, float *out3f) +void R_Model_Alias_GetMesh_Array3f(const entity_render_t *ent, const aliasmesh_t *mesh, int whicharray, float *out3f) { int i, vertcount; float lerp1, lerp2, lerp3, lerp4; @@ -161,7 +161,7 @@ aliasskin_t *R_FetchAliasSkin(const entity_render_t *ent, const aliasmesh_t *mes void R_DrawAliasModelCallback (const void *calldata1, int calldata2) { int c, fullbright, layernum, firstpass; - float tint[3], fog, ifog, colorscale, ambientcolor4f[4], *fcolor; + float tint[3], fog, ifog, colorscale, ambientcolor4f[4]; vec3_t diff; qbyte *bcolor; rmeshstate_t m; @@ -169,7 +169,6 @@ void R_DrawAliasModelCallback (const void *calldata1, int calldata2) aliasmesh_t *mesh = ent->model->aliasdata_meshes + calldata2; aliaslayer_t *layer; aliasskin_t *skin; - rcachearrayrequest_t request; R_Mesh_Matrix(&ent->matrix); @@ -204,55 +203,42 @@ void R_DrawAliasModelCallback (const void *calldata1, int calldata2) || ((layer->flags & ALIASLAYER_DIFFUSE) && (r_shadow_realtime_world.integer && r_ambient.integer <= 0 && r_fullbright.integer == 0 && !(ent->effects & EF_FULLBRIGHT)))) continue; } - memset(&m, 0, sizeof(m)); if (!firstpass || (ent->effects & EF_ADDITIVE)) { - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); } else if ((skin->flags & ALIASSKIN_TRANSPARENT) || ent->alpha != 1.0) { - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); } else { - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); } + GL_DepthTest(true); firstpass = false; expandaliasvert(mesh->num_vertices); colorscale = r_colorscale; - m.texrgbscale[0] = 1; - m.tex[0] = R_GetTexture(layer->texture); - if (gl_combine.integer && layer->flags & (ALIASLAYER_DIFFUSE | ALIASLAYER_SPECULAR)) + + memset(&m, 0, sizeof(m)); + if (layer->texture != NULL) { - colorscale *= 0.25f; - m.texrgbscale[0] = 4; + m.tex[0] = R_GetTexture(layer->texture); + m.pointer_texcoord[0] = mesh->data_texcoord2f; + if (gl_combine.integer && layer->flags & (ALIASLAYER_DIFFUSE | ALIASLAYER_SPECULAR)) + { + colorscale *= 0.25f; + m.texrgbscale[0] = 4; + } } + R_Mesh_State_Texture(&m); + c_alias_polys += mesh->num_triangles; - if (gl_mesh_copyarrays.integer) - { - R_Mesh_State(&m); - R_Mesh_GetSpace(mesh->num_vertices); - if (layer->texture != NULL) - R_Mesh_CopyTexCoord2f(0, mesh->data_texcoord2f, mesh->num_vertices); - R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f); - } - else - { - m.pointervertexcount = mesh->num_vertices; - memset(&request, 0, sizeof(request)); - request.data_size = mesh->num_vertices * sizeof(float[3]); - request.id_pointer2 = mesh->data_aliasvertex3f; - request.id_number1 = layernum; - request.id_number2 = 0; - request.id_number3 = CRC_Block((void *)ent->frameblend, sizeof(ent->frameblend)); - if (R_Mesh_CacheArray(&request)) - R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, request.data); - m.pointer_vertex = request.data; - m.pointer_texcoord[0] = layer->texture != NULL ? mesh->data_texcoord2f : NULL; - } + GL_VertexPointer(varray_vertex3f); + R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f); if (layer->flags & ALIASLAYER_FOG) { colorscale *= fog; @@ -260,6 +246,12 @@ void R_DrawAliasModelCallback (const void *calldata1, int calldata2) } else { + fullbright = !(layer->flags & ALIASLAYER_DIFFUSE) || r_fullbright.integer || (ent->effects & EF_FULLBRIGHT); + if (r_shadow_realtime_world.integer && !fullbright) + { + colorscale *= r_ambient.value * (2.0f / 128.0f); + fullbright = true; + } if (layer->flags & (ALIASLAYER_COLORMAP_PANTS | ALIASLAYER_COLORMAP_SHIRT)) { // 128-224 are backwards ranges @@ -269,63 +261,26 @@ void R_DrawAliasModelCallback (const void *calldata1, int calldata2) c = (ent->colormap & 0xF0); c += (c >= 128 && c < 224) ? 4 : 12; bcolor = (qbyte *) (&palette_complete[c]); - fullbright = c >= 224; + fullbright = fullbright || c >= 224; VectorScale(bcolor, (1.0f / 255.0f), tint); } else - { tint[0] = tint[1] = tint[2] = 1; - fullbright = false; - } colorscale *= ifog; - if (fullbright || !(layer->flags & ALIASLAYER_DIFFUSE) || r_fullbright.integer || (ent->effects & EF_FULLBRIGHT)) - GL_Color(tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha); - else if (r_shadow_realtime_world.integer) - { - colorscale *= r_ambient.value * (2.0f / 128.0f); + if (fullbright) GL_Color(tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha); - } else { if (R_LightModel(ambientcolor4f, ent, tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha, false)) { - GL_UseColorArray(); - if (gl_mesh_copyarrays.integer) - { - R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_NORMAL, aliasvert_normal3f); - R_LightModel_CalcVertexColors(ambientcolor4f, mesh->num_vertices, varray_vertex3f, aliasvert_normal3f, varray_color4f); - } - else - { - // request color4f cache - request.data_size = mesh->num_vertices * sizeof(float[4]); - request.id_pointer1 = ent; - request.id_number2 = 2; - request.id_number3 = CRC_Block((void *)ent->frameblend, sizeof(ent->frameblend)) + CRC_Block((void *)&ent->entlightstime, sizeof(ent->entlightstime)); - if (R_Mesh_CacheArray(&request)) - { - // save off the color pointer before we blow away the request - fcolor = request.data; - m.pointer_color = fcolor; - // request normal3f cache - request.data_size = mesh->num_vertices * sizeof(float[3]); - request.id_pointer1 = NULL; - request.id_number2 = 3; - request.id_number3 = CRC_Block((void *)ent->frameblend, sizeof(ent->frameblend)); - if (R_Mesh_CacheArray(&request)) - R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_NORMAL, request.data); - R_LightModel_CalcVertexColors(ambientcolor4f, mesh->num_vertices, m.pointer_vertex, request.data, fcolor); - } - else - m.pointer_color = request.data; - } + GL_ColorPointer(varray_color4f); + R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_NORMAL, varray_normal3f); + R_LightModel_CalcVertexColors(ambientcolor4f, mesh->num_vertices, varray_vertex3f, varray_normal3f, varray_color4f); } else GL_Color(ambientcolor4f[0], ambientcolor4f[1], ambientcolor4f[2], ambientcolor4f[3]); } } - if (!gl_mesh_copyarrays.integer) - R_Mesh_State(&m); R_Mesh_Draw(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i); } } @@ -355,7 +310,6 @@ void R_Model_Alias_DrawFakeShadow (entity_render_t *ent) aliasskin_t *skin; rmeshstate_t m; float *v, plane[4], dist, projection[3], floororigin[3], surfnormal[3], lightdirection[3], v2[3]; - rcachearrayrequest_t request; if ((ent->effects & EF_ADDITIVE) || ent->alpha < 1) return; @@ -372,10 +326,12 @@ void R_Model_Alias_DrawFakeShadow (entity_render_t *ent) R_Mesh_Matrix(&ent->matrix); memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - if (gl_mesh_copyarrays.integer) - R_Mesh_State(&m); + R_Mesh_State_Texture(&m); + + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); + GL_DepthTest(true); + GL_VertexPointer(varray_vertex3f); GL_Color(0, 0, 0, 0.5); // put a light direction in the entity's coordinate space @@ -392,43 +348,17 @@ void R_Model_Alias_DrawFakeShadow (entity_render_t *ent) dist = -1.0f / DotProduct(projection, plane); VectorScale(projection, dist, projection); - memset(&request, 0, sizeof(request)); for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++) { skin = R_FetchAliasSkin(ent, mesh); if (skin->flags & ALIASSKIN_TRANSPARENT) continue; - if (gl_mesh_copyarrays.integer) + R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f); + for (i = 0, v = varray_vertex3f;i < mesh->num_vertices;i++, v += 3) { - R_Mesh_GetSpace(mesh->num_vertices); - R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f); - for (i = 0, v = varray_vertex3f;i < mesh->num_vertices;i++, v += 3) - { - dist = DotProduct(v, plane) - plane[3]; - if (dist > 0) - VectorMA(v, dist, projection, v); - } - } - else - { - request.data_size = mesh->num_vertices * sizeof(float[3]); - request.id_pointer1 = mesh; - request.id_number1 = CRC_Block((void *)&ent->matrix, sizeof(ent->matrix)); - request.id_number2 = CRC_Block((void *)&plane, sizeof(plane)); - request.id_number3 = CRC_Block((void *)&ent->frameblend, sizeof(ent->frameblend)); - m.pointervertexcount = mesh->num_vertices; - if (R_Mesh_CacheArray(&request)) - { - R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, request.data); - for (i = 0, v = request.data;i < mesh->num_vertices;i++, v += 3) - { - dist = DotProduct(v, plane) - plane[3]; - if (dist > 0) - VectorMA(v, dist, projection, v); - } - } - m.pointer_vertex = request.data; - R_Mesh_State(&m); + dist = DotProduct(v, plane) - plane[3]; + if (dist > 0) + VectorMA(v, dist, projection, v); } c_alias_polys += mesh->num_triangles; R_Mesh_Draw(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i); @@ -452,9 +382,8 @@ void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightor skin = R_FetchAliasSkin(ent, mesh); if (skin->flags & ALIASSKIN_TRANSPARENT) continue; - R_Mesh_GetSpace(mesh->num_vertices * 2); R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f); - R_Shadow_Volume(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, mesh->data_neighbor3i, relativelightorigin, lightradius, projectdistance); + R_Shadow_Volume(mesh->num_vertices, mesh->num_triangles, varray_vertex3f, mesh->data_element3i, mesh->data_neighbor3i, relativelightorigin, lightradius, projectdistance); } } } @@ -852,22 +781,25 @@ void R_DrawZymoticModelMeshCallback (const void *calldata1, int calldata2) } ifog = 1 - fog; - memset(&mstate, 0, sizeof(mstate)); if (ent->effects & EF_ADDITIVE) { - mstate.blendfunc1 = GL_SRC_ALPHA; - mstate.blendfunc2 = GL_ONE; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); } else if (ent->alpha != 1.0 || R_TextureHasAlpha(texture)) { - mstate.blendfunc1 = GL_SRC_ALPHA; - mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); } else { - mstate.blendfunc1 = GL_ONE; - mstate.blendfunc2 = GL_ZERO; + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); } + GL_DepthTest(true); + GL_VertexPointer(varray_vertex3f); + + memset(&mstate, 0, sizeof(mstate)); colorscale = r_colorscale; if (gl_combine.integer) { @@ -875,16 +807,16 @@ void R_DrawZymoticModelMeshCallback (const void *calldata1, int calldata2) colorscale *= 0.25f; } mstate.tex[0] = R_GetTexture(texture); - R_Mesh_State(&mstate); + mstate.pointer_texcoord[0] = ent->model->zymdata_texcoords; + R_Mesh_State_Texture(&mstate); + ZymoticLerpBones(ent->model->zymnum_bones, (zymbonematrix *) ent->model->zymdata_poses, ent->frameblend, ent->model->zymdata_bones); - R_Mesh_GetSpace(numverts); ZymoticTransformVerts(numverts, varray_vertex3f, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts); - R_Mesh_CopyTexCoord2f(0, ent->model->zymdata_texcoords, ent->model->zymnum_verts); ZymoticCalcNormal3f(numverts, varray_vertex3f, aliasvert_normal3f, ent->model->zymnum_shaders, ent->model->zymdata_renderlist); if (R_LightModel(ambientcolor4f, ent, ifog * colorscale, ifog * colorscale, ifog * colorscale, ent->alpha, false)) { - GL_UseColorArray(); + GL_ColorPointer(varray_color4f); R_LightModel_CalcVertexColors(ambientcolor4f, numverts, varray_vertex3f, aliasvert_normal3f, varray_color4f); } else @@ -894,14 +826,18 @@ void R_DrawZymoticModelMeshCallback (const void *calldata1, int calldata2) if (fog) { + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); + GL_DepthTest(true); + GL_VertexPointer(varray_vertex3f); + memset(&mstate, 0, sizeof(mstate)); - mstate.blendfunc1 = GL_SRC_ALPHA; - mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; // FIXME: need alpha mask for fogging... //mstate.tex[0] = R_GetTexture(texture); - R_Mesh_State(&mstate); + //mstate.pointer_texcoord = ent->model->zymdata_texcoords; + R_Mesh_State_Texture(&mstate); + GL_Color(fogcolor[0] * r_colorscale, fogcolor[1] * r_colorscale, fogcolor[2] * r_colorscale, ent->alpha * fog); - R_Mesh_GetSpace(numverts); ZymoticTransformVerts(numverts, varray_vertex3f, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts); R_Mesh_Draw(numverts, numtriangles, elements); c_alias_polys += numtriangles; diff --git a/gl_rmain.c b/gl_rmain.c index f3538129..efe64d9a 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -817,11 +817,11 @@ void R_ShadowVolumeLighting (int visiblevolumes) if (visiblevolumes) { memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ONE; - if (r_shadow_visiblevolumes.integer >= 2) - m.depthdisable = true; - R_Mesh_State(&m); + R_Mesh_State_Texture(&m); + + GL_BlendFunc(GL_ONE, GL_ONE); + GL_DepthMask(false); + GL_DepthTest(r_shadow_visiblevolumes.integer < 2); qglDisable(GL_CULL_FACE); GL_Color(0.0 * r_colorscale, 0.0125 * r_colorscale, 0.1 * r_colorscale, 1); } @@ -1055,9 +1055,10 @@ void R_ShadowVolumeLighting (int visiblevolumes) } } - if (!visiblevolumes) + if (visiblevolumes) + qglEnable(GL_CULL_FACE); + else R_Shadow_Stage_End(); - qglEnable(GL_CULL_FACE); qglDisable(GL_SCISSOR_TEST); } @@ -1119,29 +1120,31 @@ static void R_BlendView(void) { rmeshstate_t m; float r; + float vertex3f[3*3]; if (r_refdef.viewblend[3] < 0.01f) return; - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - m.depthdisable = true; // magic R_Mesh_Matrix(&r_identitymatrix); - R_Mesh_State(&m); - R_Mesh_GetSpace(3); - r = 64000; - varray_vertex3f[0] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r - vup[0] * r; - varray_vertex3f[1] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r - vup[1] * r; - varray_vertex3f[2] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r - vup[2] * r; - varray_vertex3f[3] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r + vup[0] * r * 3; - varray_vertex3f[4] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r + vup[1] * r * 3; - varray_vertex3f[5] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r + vup[2] * r * 3; - varray_vertex3f[6] = r_origin[0] + vpn[0] * 1.5 + vright[0] * r * 3 - vup[0] * r; - varray_vertex3f[7] = r_origin[1] + vpn[1] * 1.5 + vright[1] * r * 3 - vup[1] * r; - varray_vertex3f[8] = r_origin[2] + vpn[2] * 1.5 + vright[2] * r * 3 - vup[2] * r; + memset(&m, 0, sizeof(m)); + R_Mesh_State_Texture(&m); + + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(true); + GL_DepthTest(false); // magic + GL_VertexPointer(vertex3f); GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]); + r = 64000; + vertex3f[0] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r - vup[0] * r; + vertex3f[1] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r - vup[1] * r; + vertex3f[2] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r - vup[2] * r; + vertex3f[3] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r + vup[0] * r * 3; + vertex3f[4] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r + vup[1] * r * 3; + vertex3f[5] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r + vup[2] * r * 3; + vertex3f[6] = r_origin[0] + vpn[0] * 1.5 + vright[0] * r * 3 - vup[0] * r; + vertex3f[7] = r_origin[1] + vpn[1] * 1.5 + vright[1] * r * 3 - vup[1] * r; + vertex3f[8] = r_origin[2] + vpn[2] * 1.5 + vright[2] * r * 3 - vup[2] * r; R_Mesh_Draw(3, 1, polygonelements); } @@ -1267,26 +1270,30 @@ void R_RenderView (void) void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca) { int i; - float *v, *c, f1, f2, diff[3]; + float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4]; rmeshstate_t m; - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); + GL_DepthTest(true); R_Mesh_Matrix(&r_identitymatrix); - R_Mesh_State(&m); + + memset(&m, 0, sizeof(m)); + R_Mesh_State_Texture(&m); R_Mesh_GetSpace(8); - varray_vertex[ 0] = mins[0];varray_vertex[ 1] = mins[1];varray_vertex[ 2] = mins[2]; - varray_vertex[ 4] = maxs[0];varray_vertex[ 5] = mins[1];varray_vertex[ 6] = mins[2]; - varray_vertex[ 8] = mins[0];varray_vertex[ 9] = maxs[1];varray_vertex[10] = mins[2]; - varray_vertex[12] = maxs[0];varray_vertex[13] = maxs[1];varray_vertex[14] = mins[2]; - varray_vertex[16] = mins[0];varray_vertex[17] = mins[1];varray_vertex[18] = maxs[2]; - varray_vertex[20] = maxs[0];varray_vertex[21] = mins[1];varray_vertex[22] = maxs[2]; - varray_vertex[24] = mins[0];varray_vertex[25] = maxs[1];varray_vertex[26] = maxs[2]; - varray_vertex[28] = maxs[0];varray_vertex[29] = maxs[1];varray_vertex[30] = maxs[2]; - R_FillColors(varray_color, 8, cr * r_colorscale, cg * r_colorscale, cb * r_colorscale, ca); + vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; + vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2]; + vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2]; + vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2]; + vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2]; + vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2]; + vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2]; + vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2]; + GL_ColorPointer(color); + R_FillColors(color, 8, cr * r_colorscale, cg * r_colorscale, cb * r_colorscale, ca); if (fogenabled) { - for (i = 0, v = varray_vertex, c = varray_color;i < 8;i++, v += 4, c += 4) + for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4) { VectorSubtract(v, r_origin, diff); f2 = exp(fogdensity/DotProduct(diff, diff)); @@ -1297,7 +1304,6 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa c[2] = c[2] * f1 + fogcolor[2] * f2; } } - GL_UseColorArray(); R_Mesh_Draw(8, 12); } */ @@ -1314,66 +1320,84 @@ int nomodelelements[24] = 1, 3, 4 }; +float nomodelvertex3f[6*3] = +{ + -16, 0, 0, + 16, 0, 0, + 0, -16, 0, + 0, 16, 0, + 0, 0, -16, + 0, 0, 16 +}; + +float nomodelcolor4f[6*4] = +{ + 0.0f, 0.0f, 0.5f, 1.0f, + 0.0f, 0.0f, 0.5f, 1.0f, + 0.0f, 0.5f, 0.0f, 1.0f, + 0.0f, 0.5f, 0.0f, 1.0f, + 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, 0.0f, 0.0f, 1.0f +}; + void R_DrawNoModelCallback(const void *calldata1, int calldata2) { const entity_render_t *ent = calldata1; int i; float f1, f2, *c, diff[3]; + float color4f[6*4]; rmeshstate_t m; + R_Mesh_Matrix(&ent->matrix); + memset(&m, 0, sizeof(m)); + R_Mesh_State_Texture(&m); + if (ent->flags & EF_ADDITIVE) { - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); } else if (ent->alpha < 1) { - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); } else { - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); } - R_Mesh_Matrix(&ent->matrix); - R_Mesh_State(&m); - - GL_UseColorArray(); - R_Mesh_GetSpace(6); - varray_vertex3f[ 0] = -16;varray_vertex3f[ 1] = 0;varray_vertex3f[ 2] = 0; - varray_vertex3f[ 3] = 16;varray_vertex3f[ 4] = 0;varray_vertex3f[ 5] = 0; - varray_vertex3f[ 6] = 0;varray_vertex3f[ 7] = -16;varray_vertex3f[ 8] = 0; - varray_vertex3f[ 9] = 0;varray_vertex3f[10] = 16;varray_vertex3f[11] = 0; - varray_vertex3f[12] = 0;varray_vertex3f[13] = 0;varray_vertex3f[14] = -16; - varray_vertex3f[15] = 0;varray_vertex3f[16] = 0;varray_vertex3f[17] = 16; - varray_color4f[ 0] = 0.00f * r_colorscale;varray_color4f[ 1] = 0.00f * r_colorscale;varray_color4f[ 2] = 0.50f * r_colorscale;varray_color4f[ 3] = ent->alpha; - varray_color4f[ 4] = 0.00f * r_colorscale;varray_color4f[ 5] = 0.00f * r_colorscale;varray_color4f[ 6] = 0.50f * r_colorscale;varray_color4f[ 7] = ent->alpha; - varray_color4f[ 8] = 0.00f * r_colorscale;varray_color4f[ 9] = 0.50f * r_colorscale;varray_color4f[10] = 0.00f * r_colorscale;varray_color4f[11] = ent->alpha; - varray_color4f[12] = 0.00f * r_colorscale;varray_color4f[13] = 0.50f * r_colorscale;varray_color4f[14] = 0.00f * r_colorscale;varray_color4f[15] = ent->alpha; - varray_color4f[16] = 0.50f * r_colorscale;varray_color4f[17] = 0.00f * r_colorscale;varray_color4f[18] = 0.00f * r_colorscale;varray_color4f[19] = ent->alpha; - varray_color4f[20] = 0.50f * r_colorscale;varray_color4f[21] = 0.00f * r_colorscale;varray_color4f[22] = 0.00f * r_colorscale;varray_color4f[23] = ent->alpha; + GL_DepthTest(true); + GL_VertexPointer(nomodelvertex3f); if (fogenabled) { + memcpy(color4f, nomodelcolor4f, sizeof(float[6*4])); + GL_ColorPointer(color4f); VectorSubtract(ent->origin, r_origin, diff); f2 = exp(fogdensity/DotProduct(diff, diff)); f1 = 1 - f2; - for (i = 0, c = varray_color4f;i < 6;i++, c += 4) + for (i = 0, c = color4f;i < 6;i++, c += 4) { c[0] = (c[0] * f1 + fogcolor[0] * f2) * r_colorscale; c[1] = (c[1] * f1 + fogcolor[1] * f2) * r_colorscale; c[2] = (c[2] * f1 + fogcolor[2] * f2) * r_colorscale; + c[3] *= ent->alpha; } } - else + else if (r_colorscale != 1 || ent->alpha != 1) { - for (i = 0, c = varray_color4f;i < 6;i++, c += 4) + memcpy(color4f, nomodelcolor4f, sizeof(float[6*4])); + GL_ColorPointer(color4f); + for (i = 0, c = color4f;i < 6;i++, c += 4) { c[0] *= r_colorscale; c[1] *= r_colorscale; c[2] *= r_colorscale; + c[3] *= ent->alpha; } } + else + GL_ColorPointer(nomodelcolor4f); R_Mesh_Draw(6, 8, nomodelelements); } @@ -1416,13 +1440,31 @@ void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, flo vert[11] = org2[2] + width * right2[2]; } -void R_DrawSpriteMesh(const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2) +float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1}; + +void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca) { - R_Mesh_GetSpace(4); - varray_texcoord2f[0][0] = 0;varray_texcoord2f[0][1] = 1; - varray_texcoord2f[0][2] = 0;varray_texcoord2f[0][3] = 0; - varray_texcoord2f[0][4] = 1;varray_texcoord2f[0][5] = 0; - varray_texcoord2f[0][6] = 1;varray_texcoord2f[0][7] = 1; + float diff[3]; + rmeshstate_t m; + + if (fogenabled) + { + VectorSubtract(origin, r_origin, diff); + ca *= 1 - exp(fogdensity/DotProduct(diff,diff)); + } + + R_Mesh_Matrix(&r_identitymatrix); + GL_Color(cr * r_colorscale, cg * r_colorscale, cb * r_colorscale, ca); + GL_VertexPointer(varray_vertex3f); + GL_BlendFunc(blendfunc1, blendfunc2); + GL_DepthMask(false); + GL_DepthTest(!depthdisable); + + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(texture); + m.pointer_texcoord[0] = spritetexcoord2f; + R_Mesh_State_Texture(&m); + varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1; varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1; varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1; diff --git a/gl_rsurf.c b/gl_rsurf.c index f35c425e..252d7e2a 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -741,33 +741,33 @@ static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture R_Mesh_Matrix(&ent->matrix); - // draw depth-only polys - memset(&m, 0, sizeof(m)); + GL_Color(fogcolor[0] * r_colorscale, fogcolor[1] * r_colorscale, fogcolor[2] * r_colorscale, 1); if (skyrendermasked) { + // depth-only (masking) qglColorMask(0,0,0,0); // just to make sure that braindead drivers don't draw anything // despite that colormask... - m.blendfunc1 = GL_ZERO; - m.blendfunc2 = GL_ONE; + GL_BlendFunc(GL_ZERO, GL_ONE); } else { // fog sky - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; + GL_BlendFunc(GL_ONE, GL_ZERO); } - m.depthwrite = true; - R_Mesh_State(&m); + GL_DepthMask(true); + GL_DepthTest(true); + + memset(&m, 0, sizeof(m)); + R_Mesh_State_Texture(&m); + while((surf = *surfchain++) != NULL) { if (surf->visframe == r_framecount) { for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - GL_Color(fogcolor[0] * r_colorscale, fogcolor[1] * r_colorscale, fogcolor[2] * r_colorscale, 1); - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); + GL_VertexPointer(mesh->vertex3f); R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); } } @@ -785,27 +785,32 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2) float alpha; float modelorg[3]; texture_t *texture; - Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg); + matrix4x4_t tempmatrix; + + // scrolling in texture matrix + Matrix4x4_CreateTranslate(&tempmatrix, sin(cl.time) * 0.125, sin(cl.time * 0.8f) * 0.125, 0); + R_Mesh_TextureMatrix(0, &tempmatrix); R_Mesh_Matrix(&ent->matrix); + Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg); memset(&m, 0, sizeof(m)); texture = surf->texinfo->texture->currentframe; alpha = texture->currentalpha; if (texture->rendertype == SURFRENDER_ADD) { - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); } else if (texture->rendertype == SURFRENDER_ALPHA) { - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); } else { - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); } m.tex[0] = R_GetTexture(texture->skin.base); colorscale = r_colorscale; @@ -814,13 +819,13 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2) m.texrgbscale[0] = 4; colorscale *= 0.25f; } - R_Mesh_State(&m); - GL_UseColorArray(); + GL_DepthTest(true); + GL_ColorPointer(varray_color4f); for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - R_ScrollTexCoord2f(varray_texcoord2f[0], mesh->texcoordtexture2f, mesh->numverts, sin(cl.time) * 0.125f, sin(cl.time * 0.8f) * 0.125f); + GL_VertexPointer(mesh->vertex3f); + m.pointer_texcoord[0] = mesh->texcoordtexture2f; + R_Mesh_State_Texture(&m); f = surf->flags & SURF_DRAWFULLBRIGHT ? 1.0f : ((surf->flags & SURF_LIGHTMAP) ? 0 : 0.5f); R_FillColors(varray_color4f, mesh->numverts, f, f, f, alpha); if (!(surf->flags & SURF_DRAWFULLBRIGHT || ent->effects & EF_FULLBRIGHT)) @@ -837,20 +842,23 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2) if (fogenabled) { memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); + GL_DepthTest(true); m.tex[0] = R_GetTexture(texture->skin.fog); - R_Mesh_State(&m); for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - if (m.tex[0]) - R_Mesh_CopyTexCoord2f(0, mesh->texcoordtexture2f, mesh->numverts); + GL_VertexPointer(mesh->vertex3f); + m.pointer_texcoord[0] = mesh->texcoordtexture2f; + GL_ColorPointer(varray_color4f); + R_Mesh_State_Texture(&m); RSurf_FogPassColors_Vertex3f_Color4f(mesh->vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], alpha, r_colorscale, mesh->numverts, modelorg); R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); } } + + Matrix4x4_CreateIdentity(&tempmatrix); + R_Mesh_TextureMatrix(0, &tempmatrix); } static void RSurfShader_Water(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain) @@ -880,25 +888,23 @@ static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const m float base, colorscale; const surfmesh_t *mesh; rmeshstate_t m; - rcachearrayrequest_t request; float modelorg[3]; Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg); - memset(&request, 0, sizeof(request)); memset(&m, 0, sizeof(m)); if (rendertype == SURFRENDER_ADD) { - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); } else if (rendertype == SURFRENDER_ALPHA) { - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); } else { - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); } m.tex[0] = R_GetTexture(texture->skin.base); colorscale = r_colorscale; @@ -908,53 +914,23 @@ static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const m colorscale *= 0.25f; } base = ent->effects & EF_FULLBRIGHT ? 2.0f : r_ambient.value * (1.0f / 64.0f); - R_Mesh_State(&m); - GL_UseColorArray(); + GL_DepthTest(true); + GL_ColorPointer(varray_color4f); for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - if (gl_mesh_copyarrays.integer) - { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - R_Mesh_CopyTexCoord2f(0, mesh->texcoordtexture2f, mesh->numverts); - R_FillColors(varray_color4f, mesh->numverts, base, base, base, currentalpha); - if (!(ent->effects & EF_FULLBRIGHT)) - { - if (surf->dlightframe == r_framecount) - RSurf_LightSeparate_Vertex3f_Color4f(&ent->inversematrix, surf->dlightbits, mesh->numverts, mesh->vertex3f, varray_color4f, 1); - if (surf->flags & SURF_LIGHTMAP) - RSurf_AddLightmapToVertexColors_Color4f(mesh->lightmapoffsets, varray_color4f, mesh->numverts, surf->samples, ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3, surf->styles); - } - RSurf_FogColors_Vertex3f_Color4f(mesh->vertex3f, varray_color4f, colorscale, mesh->numverts, modelorg); - R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); - } - else + GL_VertexPointer(mesh->vertex3f); + m.pointer_texcoord[0] = mesh->texcoordtexture2f; + R_Mesh_State_Texture(&m); + R_FillColors(varray_color4f, mesh->numverts, base, base, base, currentalpha); + if (!(ent->effects & EF_FULLBRIGHT)) { - m.pointervertexcount = mesh->numverts; - m.pointer_vertex = mesh->vertex3f; - m.pointer_texcoord[0] = mesh->texcoordtexture2f; - // LordHavoc: this is not caching at all (difficult to - // cache fogging information), it's just (ab)using the - // cache system to get some memory - request.data_size = mesh->numverts * sizeof(float[4]); - request.id_pointer1 = ent; - request.id_pointer2 = mesh; - request.id_number1 = r_framecount; - if (R_Mesh_CacheArray(&request)) - { - R_FillColors(request.data, mesh->numverts, base, base, base, currentalpha); - if (!(ent->effects & EF_FULLBRIGHT)) - { - if (surf->dlightframe == r_framecount) - RSurf_LightSeparate_Vertex3f_Color4f(&ent->inversematrix, surf->dlightbits, mesh->numverts, mesh->vertex3f, request.data, 1); - if (surf->flags & SURF_LIGHTMAP) - RSurf_AddLightmapToVertexColors_Color4f(mesh->lightmapoffsets, request.data, mesh->numverts, surf->samples, ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3, surf->styles); - } - RSurf_FogColors_Vertex3f_Color4f(mesh->vertex3f, request.data, colorscale, mesh->numverts, modelorg); - } - m.pointer_color = request.data; - R_Mesh_State(&m); + if (surf->dlightframe == r_framecount) + RSurf_LightSeparate_Vertex3f_Color4f(&ent->inversematrix, surf->dlightbits, mesh->numverts, mesh->vertex3f, varray_color4f, 1); + if (surf->flags & SURF_LIGHTMAP) + RSurf_AddLightmapToVertexColors_Color4f(mesh->lightmapoffsets, varray_color4f, mesh->numverts, surf->samples, ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3, surf->styles); } + RSurf_FogColors_Vertex3f_Color4f(mesh->vertex3f, varray_color4f, colorscale, mesh->numverts, modelorg); + R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); } } @@ -962,43 +938,21 @@ static void RSurfShader_Wall_Pass_Glow(const entity_render_t *ent, const msurfac { const surfmesh_t *mesh; rmeshstate_t m; - rcachearrayrequest_t request; float modelorg[3]; Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg); - memset(&request, 0, sizeof(request)); memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); + GL_DepthTest(true); m.tex[0] = R_GetTexture(texture->skin.glow); - R_Mesh_State(&m); - GL_UseColorArray(); + GL_ColorPointer(varray_color4f); for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - if (gl_mesh_copyarrays.integer) - { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - R_Mesh_CopyTexCoord2f(0, mesh->texcoordtexture2f, mesh->numverts); - RSurf_FoggedColors_Vertex3f_Color4f(mesh->vertex3f, varray_color4f, 1, 1, 1, currentalpha, r_colorscale, mesh->numverts, modelorg); - } - else - { - m.pointervertexcount = mesh->numverts; - m.pointer_vertex = mesh->vertex3f; - if (m.tex[0]) - m.pointer_texcoord[0] = mesh->texcoordtexture2f; - // LordHavoc: this is not caching at all (difficult to - // cache fogging information), it's just (ab)using the - // cache system to get some memory - request.data_size = mesh->numverts * sizeof(float[4]); - request.id_pointer1 = ent; - request.id_pointer2 = mesh; - request.id_number1 = r_framecount; - if (R_Mesh_CacheArray(&request)) - RSurf_FoggedColors_Vertex3f_Color4f(mesh->vertex3f, request.data, 1, 1, 1, currentalpha, r_colorscale, mesh->numverts, modelorg); - m.pointer_color = request.data; - R_Mesh_State(&m); - } + GL_VertexPointer(mesh->vertex3f); + if (m.tex[0]) + m.pointer_texcoord[0] = mesh->texcoordtexture2f; + R_Mesh_State_Texture(&m); + RSurf_FoggedColors_Vertex3f_Color4f(mesh->vertex3f, varray_color4f, 1, 1, 1, currentalpha, r_colorscale, mesh->numverts, modelorg); R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); } } @@ -1007,44 +961,21 @@ static void RSurfShader_Wall_Pass_Fog(const entity_render_t *ent, const msurface { const surfmesh_t *mesh; rmeshstate_t m; - rcachearrayrequest_t request; float modelorg[3]; Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg); - memset(&request, 0, sizeof(request)); memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); + GL_DepthTest(true); m.tex[0] = R_GetTexture(texture->skin.fog); - R_Mesh_State(&m); - GL_UseColorArray(); + GL_ColorPointer(varray_color4f); for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - if (gl_mesh_copyarrays.integer) - { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - if (m.tex[0]) - R_Mesh_CopyTexCoord2f(0, mesh->texcoordtexture2f, mesh->numverts); - RSurf_FogPassColors_Vertex3f_Color4f(mesh->vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], currentalpha, r_colorscale, mesh->numverts, modelorg); - } - else - { - m.pointervertexcount = mesh->numverts; - m.pointer_vertex = mesh->vertex3f; - if (m.tex[0]) - m.pointer_texcoord[0] = mesh->texcoordtexture2f; - // LordHavoc: this is not caching at all (difficult to - // cache fogging information), it's just (ab)using the - // cache system to get some memory - request.data_size = mesh->numverts * sizeof(float[4]); - request.id_pointer1 = ent; - request.id_pointer2 = mesh; - request.id_number1 = r_framecount; - if (R_Mesh_CacheArray(&request)) - RSurf_FogPassColors_Vertex3f_Color4f(mesh->vertex3f, request.data, fogcolor[0], fogcolor[1], fogcolor[2], currentalpha, r_colorscale, mesh->numverts, modelorg); - m.pointer_color = request.data; - R_Mesh_State(&m); - } + GL_VertexPointer(mesh->vertex3f); + if (m.tex[0]) + m.pointer_texcoord[0] = mesh->texcoordtexture2f; + R_Mesh_State_Texture(&m); + RSurf_FogPassColors_Vertex3f_Color4f(mesh->vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], currentalpha, r_colorscale, mesh->numverts, modelorg); R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); } } @@ -1057,15 +988,15 @@ static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render int lightmaptexturenum; float cl; memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); + GL_DepthTest(true); m.tex[0] = R_GetTexture(texture->skin.base); m.tex[1] = R_GetTexture((**surfchain).lightmaptexture); m.tex[2] = R_GetTexture(texture->skin.detail); m.texrgbscale[0] = 1; m.texrgbscale[1] = 4; m.texrgbscale[2] = 2; - R_Mesh_State(&m); cl = (float) (1 << r_lightmapscalebit) * r_colorscale; GL_Color(cl, cl, cl, 1); @@ -1074,31 +1005,18 @@ static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render if (surf->visframe == r_framecount) { lightmaptexturenum = R_GetTexture(surf->lightmaptexture); - if (m.tex[1] != lightmaptexturenum) - { + //if (m.tex[1] != lightmaptexturenum) + //{ m.tex[1] = lightmaptexturenum; - if (gl_mesh_copyarrays.integer) - R_Mesh_State(&m); - } + // R_Mesh_State_Texture(&m); + //} for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - if (gl_mesh_copyarrays.integer) - { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - R_Mesh_CopyTexCoord2f(0, mesh->texcoordtexture2f, mesh->numverts); - R_Mesh_CopyTexCoord2f(1, mesh->texcoordlightmap2f, mesh->numverts); - R_Mesh_CopyTexCoord2f(2, mesh->texcoorddetail2f, mesh->numverts); - } - else - { - m.pointervertexcount = mesh->numverts; - m.pointer_vertex = mesh->vertex3f; - m.pointer_texcoord[0] = mesh->texcoordtexture2f; - m.pointer_texcoord[1] = mesh->texcoordlightmap2f; - m.pointer_texcoord[2] = mesh->texcoorddetail2f; - R_Mesh_State(&m); - } + GL_VertexPointer(mesh->vertex3f); + m.pointer_texcoord[0] = mesh->texcoordtexture2f; + m.pointer_texcoord[1] = mesh->texcoordlightmap2f; + m.pointer_texcoord[2] = mesh->texcoorddetail2f; + R_Mesh_State_Texture(&m); R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); } } @@ -1112,41 +1030,30 @@ static void RSurfShader_OpaqueWall_Pass_BaseDoubleTex(const entity_render_t *ent rmeshstate_t m; int lightmaptexturenum; memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); + GL_DepthTest(true); m.tex[0] = R_GetTexture(texture->skin.base); m.tex[1] = R_GetTexture((**surfchain).lightmaptexture); if (gl_combine.integer) m.texrgbscale[1] = 4; - R_Mesh_State(&m); GL_Color(r_colorscale, r_colorscale, r_colorscale, 1); while((surf = *surfchain++) != NULL) { if (surf->visframe == r_framecount) { lightmaptexturenum = R_GetTexture(surf->lightmaptexture); - if (m.tex[1] != lightmaptexturenum) - { + //if (m.tex[1] != lightmaptexturenum) + //{ m.tex[1] = lightmaptexturenum; - R_Mesh_State(&m); - } + // R_Mesh_State_Texture(&m); + //} for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - if (gl_mesh_copyarrays.integer) - { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - R_Mesh_CopyTexCoord2f(0, mesh->texcoordtexture2f, mesh->numverts); - R_Mesh_CopyTexCoord2f(1, mesh->texcoordlightmap2f, mesh->numverts); - } - else - { - m.pointervertexcount = mesh->numverts; - m.pointer_vertex = mesh->vertex3f; - m.pointer_texcoord[0] = mesh->texcoordtexture2f; - m.pointer_texcoord[1] = mesh->texcoordlightmap2f; - R_Mesh_State(&m); - } + GL_VertexPointer(mesh->vertex3f); + m.pointer_texcoord[0] = mesh->texcoordtexture2f; + m.pointer_texcoord[1] = mesh->texcoordlightmap2f; + R_Mesh_State_Texture(&m); R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); } } @@ -1159,10 +1066,10 @@ static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent, const surfmesh_t *mesh; rmeshstate_t m; memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; + GL_DepthMask(true); + GL_DepthTest(true); + GL_BlendFunc(GL_ONE, GL_ZERO); m.tex[0] = R_GetTexture(texture->skin.base); - R_Mesh_State(&m); GL_Color(1, 1, 1, 1); while((surf = *surfchain++) != NULL) { @@ -1170,19 +1077,9 @@ static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent, { for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - if (gl_mesh_copyarrays.integer) - { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - R_Mesh_CopyTexCoord2f(0, mesh->texcoordtexture2f, mesh->numverts); - } - else - { - m.pointervertexcount = mesh->numverts; - m.pointer_vertex = mesh->vertex3f; - m.pointer_texcoord[0] = mesh->texcoordtexture2f; - R_Mesh_State(&m); - } + GL_VertexPointer(mesh->vertex3f); + m.pointer_texcoord[0] = mesh->texcoordtexture2f; + R_Mesh_State_Texture(&m); R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); } } @@ -1196,38 +1093,28 @@ static void RSurfShader_OpaqueWall_Pass_BaseLightmap(const entity_render_t *ent, rmeshstate_t m; int lightmaptexturenum; memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_ZERO; - m.blendfunc2 = GL_SRC_COLOR; + GL_BlendFunc(GL_ZERO, GL_SRC_COLOR); + GL_DepthMask(false); + GL_DepthTest(true); m.tex[0] = R_GetTexture((**surfchain).lightmaptexture); if (gl_combine.integer) m.texrgbscale[0] = 4; - R_Mesh_State(&m); GL_Color(r_colorscale, r_colorscale, r_colorscale, 1); while((surf = *surfchain++) != NULL) { if (surf->visframe == r_framecount) { lightmaptexturenum = R_GetTexture(surf->lightmaptexture); - if (m.tex[0] != lightmaptexturenum) - { + //if (m.tex[0] != lightmaptexturenum) + //{ m.tex[0] = lightmaptexturenum; - R_Mesh_State(&m); - } + // R_Mesh_State_Texture(&m); + //} for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - if (gl_mesh_copyarrays.integer) - { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - R_Mesh_CopyTexCoord2f(0, mesh->texcoordlightmap2f, mesh->numverts); - } - else - { - m.pointervertexcount = mesh->numverts; - m.pointer_vertex = mesh->vertex3f; - m.pointer_texcoord[0] = mesh->texcoordlightmap2f; - R_Mesh_State(&m); - } + GL_VertexPointer(mesh->vertex3f); + m.pointer_texcoord[0] = mesh->texcoordlightmap2f; + R_Mesh_State_Texture(&m); R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); } } @@ -1239,13 +1126,12 @@ static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const const msurface_t *surf; const surfmesh_t *mesh; float colorscale; - rcachearrayrequest_t request; rmeshstate_t m; - memset(&request, 0, sizeof(request)); memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); + GL_DepthTest(true); m.tex[0] = R_GetTexture(texture->skin.base); colorscale = r_colorscale; if (gl_combine.integer) @@ -1253,8 +1139,7 @@ static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const m.texrgbscale[0] = 4; colorscale *= 0.25f; } - R_Mesh_State(&m); - GL_UseColorArray(); + GL_ColorPointer(varray_color4f); while((surf = *surfchain++) != NULL) { if (surf->visframe == r_framecount && surf->dlightframe == r_framecount) @@ -1263,34 +1148,11 @@ static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const { if (RSurf_LightCheck(&ent->inversematrix, surf->dlightbits, mesh)) { - if (gl_mesh_copyarrays.integer) - { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - R_Mesh_CopyTexCoord2f(0, mesh->texcoordtexture2f, mesh->numverts); - R_FillColors(varray_color4f, mesh->numverts, 0, 0, 0, 1); - RSurf_LightSeparate_Vertex3f_Color4f(&ent->inversematrix, surf->dlightbits, mesh->numverts, mesh->vertex3f, varray_color4f, colorscale); - } - else - { - m.pointervertexcount = mesh->numverts; - m.pointer_vertex = mesh->vertex3f; - m.pointer_texcoord[0] = mesh->texcoordtexture2f; - // LordHavoc: this is not caching at all (difficult to - // cache lighting information), it's just (ab)using the - // cache system to get some memory - request.data_size = mesh->numverts * sizeof(float[4]); - request.id_pointer1 = ent; - request.id_pointer2 = mesh; - request.id_number1 = r_framecount; - if (R_Mesh_CacheArray(&request)) - { - R_FillColors(request.data, mesh->numverts, 0, 0, 0, 1); - RSurf_LightSeparate_Vertex3f_Color4f(&ent->inversematrix, surf->dlightbits, mesh->numverts, mesh->vertex3f, request.data, colorscale); - } - m.pointer_color = request.data; - R_Mesh_State(&m); - } + GL_VertexPointer(mesh->vertex3f); + m.pointer_texcoord[0] = mesh->texcoordtexture2f; + R_FillColors(varray_color4f, mesh->numverts, 0, 0, 0, 1); + R_Mesh_State_Texture(&m); + RSurf_LightSeparate_Vertex3f_Color4f(&ent->inversematrix, surf->dlightbits, mesh->numverts, mesh->vertex3f, varray_color4f, colorscale); R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); } } @@ -1302,48 +1164,25 @@ static void RSurfShader_OpaqueWall_Pass_Fog(const entity_render_t *ent, const te { const msurface_t *surf; const surfmesh_t *mesh; - rcachearrayrequest_t request; rmeshstate_t m; float modelorg[3]; Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg); - memset(&request, 0, sizeof(request)); memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - R_Mesh_State(&m); - GL_UseColorArray(); + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); + GL_DepthTest(true); + GL_ColorPointer(varray_color4f); while((surf = *surfchain++) != NULL) { if (surf->visframe == r_framecount) { for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - if (gl_mesh_copyarrays.integer) - { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - if (m.tex[0]) - R_Mesh_CopyTexCoord2f(0, mesh->texcoordtexture2f, mesh->numverts); - RSurf_FogPassColors_Vertex3f_Color4f(mesh->vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], 1, r_colorscale, mesh->numverts, modelorg); - } - else - { - m.pointervertexcount = mesh->numverts; - m.pointer_vertex = mesh->vertex3f; - if (m.tex[0]) - m.pointer_texcoord[0] = mesh->texcoordtexture2f; - // LordHavoc: this is not caching at all (difficult to - // cache fogging information), it's just (ab)using the - // cache system to get some memory - request.data_size = mesh->numverts * sizeof(float[4]); - request.id_pointer1 = ent; - request.id_pointer2 = mesh; - request.id_number1 = r_framecount; - if (R_Mesh_CacheArray(&request)) - RSurf_FogPassColors_Vertex3f_Color4f(mesh->vertex3f, request.data, fogcolor[0], fogcolor[1], fogcolor[2], 1, r_colorscale, mesh->numverts, modelorg); - m.pointer_color = request.data; - R_Mesh_State(&m); - } + GL_VertexPointer(mesh->vertex3f); + if (m.tex[0]) + m.pointer_texcoord[0] = mesh->texcoordtexture2f; + R_Mesh_State_Texture(&m); + RSurf_FogPassColors_Vertex3f_Color4f(mesh->vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], 1, r_colorscale, mesh->numverts, modelorg); R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); } } @@ -1356,10 +1195,10 @@ static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, c const surfmesh_t *mesh; rmeshstate_t m; memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_DST_COLOR; - m.blendfunc2 = GL_SRC_COLOR; + GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); + GL_DepthMask(false); + GL_DepthTest(true); m.tex[0] = R_GetTexture(texture->skin.detail); - R_Mesh_State(&m); GL_Color(1, 1, 1, 1); while((surf = *surfchain++) != NULL) { @@ -1367,19 +1206,9 @@ static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, c { for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - if (gl_mesh_copyarrays.integer) - { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - R_Mesh_CopyTexCoord2f(0, mesh->texcoorddetail2f, mesh->numverts); - } - else - { - m.pointervertexcount = mesh->numverts; - m.pointer_vertex = mesh->vertex3f; - m.pointer_texcoord[0] = mesh->texcoorddetail2f; - R_Mesh_State(&m); - } + GL_VertexPointer(mesh->vertex3f); + m.pointer_texcoord[0] = mesh->texcoorddetail2f; + R_Mesh_State_Texture(&m); R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); } } @@ -1392,10 +1221,10 @@ static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const t const surfmesh_t *mesh; rmeshstate_t m; memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); + GL_DepthTest(true); m.tex[0] = R_GetTexture(texture->skin.glow); - R_Mesh_State(&m); GL_Color(r_colorscale, r_colorscale, r_colorscale, 1); while((surf = *surfchain++) != NULL) { @@ -1403,19 +1232,9 @@ static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const t { for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - if (gl_mesh_copyarrays.integer) - { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - R_Mesh_CopyTexCoord2f(0, mesh->texcoordtexture2f, mesh->numverts); - } - else - { - m.pointervertexcount = mesh->numverts; - m.pointer_vertex = mesh->vertex3f; - m.pointer_texcoord[0] = mesh->texcoordtexture2f; - R_Mesh_State(&m); - } + GL_VertexPointer(mesh->vertex3f); + m.pointer_texcoord[0] = mesh->texcoordtexture2f; + R_Mesh_State_Texture(&m); R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); } } @@ -1428,10 +1247,9 @@ static void RSurfShader_OpaqueWall_Pass_OpaqueGlow(const entity_render_t *ent, c const surfmesh_t *mesh; rmeshstate_t m; memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ZERO; + GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO); + GL_DepthMask(true); m.tex[0] = R_GetTexture(texture->skin.glow); - R_Mesh_State(&m); if (m.tex[0]) GL_Color(r_colorscale, r_colorscale, r_colorscale, 1); else @@ -1442,19 +1260,9 @@ static void RSurfShader_OpaqueWall_Pass_OpaqueGlow(const entity_render_t *ent, c { for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - if (gl_mesh_copyarrays.integer) - { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - R_Mesh_CopyTexCoord2f(0, mesh->texcoordtexture2f, mesh->numverts); - } - else - { - m.pointervertexcount = mesh->numverts; - m.pointer_vertex = mesh->vertex3f; - m.pointer_texcoord[0] = mesh->texcoordtexture2f; - R_Mesh_State(&m); - } + GL_VertexPointer(mesh->vertex3f); + m.pointer_texcoord[0] = mesh->texcoordtexture2f; + R_Mesh_State_Texture(&m); R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); } } @@ -1689,12 +1497,15 @@ static void R_DrawPortal_Callback(const void *calldata1, int calldata2) rmeshstate_t m; const entity_render_t *ent = calldata1; const mportal_t *portal = ent->model->portals + calldata2; - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); + GL_DepthTest(true); R_Mesh_Matrix(&ent->matrix); - R_Mesh_State(&m); - R_Mesh_GetSpace(portal->numpoints); + GL_VertexPointer(varray_vertex3f); + + memset(&m, 0, sizeof(m)); + R_Mesh_State_Texture(&m); + i = portal - ent->model->portals; GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_colorscale, ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_colorscale, @@ -2015,14 +1826,8 @@ void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelighto temp[1] = bound(surf->poly_mins[1], relativelightorigin[1], surf->poly_maxs[1]) - relativelightorigin[1]; temp[2] = bound(surf->poly_mins[2], relativelightorigin[2], surf->poly_maxs[2]) - relativelightorigin[2]; if (DotProduct(temp, temp) < lightradius2) - { for (mesh = surf->mesh;mesh;mesh = mesh->chain) - { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - R_Shadow_Volume(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->neighbor3i, relativelightorigin, lightradius, projectdistance); - } - } + R_Shadow_Volume(mesh->numverts, mesh->numtriangles, mesh->vertex3f, mesh->element3i, mesh->neighbor3i, relativelightorigin, lightradius, projectdistance); } } } @@ -2073,57 +1878,22 @@ void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v lightmaxs[1] = relativelightorigin[1] + lightradius; lightmaxs[2] = relativelightorigin[2] + lightradius; R_UpdateTextureInfo(ent); - if (ent != &cl_entities[0].render) + for (surfnum = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;surfnum < ent->model->nummodelsurfaces;surfnum++, surf++) { - // bmodel, cull crudely to view and light - for (surfnum = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;surfnum < ent->model->nummodelsurfaces;surfnum++, surf++) + if ((ent != &cl_entities[0].render || surf->visframe == r_framecount) && BoxesOverlap(surf->poly_mins, surf->poly_maxs, lightmins, lightmaxs)) { - if (BoxesOverlap(surf->poly_mins, surf->poly_maxs, lightmins, lightmaxs)) - { - f = PlaneDiff(relativelightorigin, surf->plane); - if (surf->flags & SURF_PLANEBACK) - f = -f; - if (f >= -0.1 && f < lightradius) - { - f = PlaneDiff(relativeeyeorigin, surf->plane); - if (surf->flags & SURF_PLANEBACK) - f = -f; - if (f > 0) - { - t = surf->texinfo->texture->currentframe; - if (t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT) - { - for (mesh = surf->mesh;mesh;mesh = mesh->chain) - { - R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoordtexture2f, relativelightorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, NULL); - R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.gloss, t->skin.nmap, NULL); - } - } - } - } - } - } - } - else - { - // world, already culled to view, just cull to light - for (surfnum = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;surfnum < ent->model->nummodelsurfaces;surfnum++, surf++) - { - if (surf->visframe == r_framecount && BoxesOverlap(surf->poly_mins, surf->poly_maxs, lightmins, lightmaxs)) + f = PlaneDiff(relativelightorigin, surf->plane); + if (surf->flags & SURF_PLANEBACK) + f = -f; + if (f >= -0.1 && f < lightradius) { - f = PlaneDiff(relativelightorigin, surf->plane); - if (surf->flags & SURF_PLANEBACK) - f = -f; - if (f >= -0.1 && f < lightradius) + t = surf->texinfo->texture->currentframe; + if (t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT) { - t = surf->texinfo->texture->currentframe; - if (t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT) + for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - for (mesh = surf->mesh;mesh;mesh = mesh->chain) - { - R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoordtexture2f, relativelightorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, NULL); - R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.gloss, t->skin.nmap, NULL); - } + R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoordtexture2f, relativelightorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, NULL); + R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.gloss, t->skin.nmap, NULL); } } } diff --git a/gl_textures.c b/gl_textures.c index 8ed0cca9..e1ccf153 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -55,6 +55,7 @@ static textypeinfo_t textype_rgba_alpha = {TEXTYPE_RGBA , 4, 4, GL_RGBA, 4} #define GLTEXTURETYPE_CUBEMAP 3 static int gltexturetypeenums[4] = {GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARB}; +static int gltexturetypebindingenums[4] = {GL_TEXTURE_BINDING_1D, GL_TEXTURE_BINDING_2D, GL_TEXTURE_BINDING_3D, GL_TEXTURE_BINDING_CUBE_MAP_ARB}; static int gltexturetypedimensions[4] = {1, 2, 3, 2}; static int cubemapside[6] = { @@ -320,11 +321,10 @@ static glmode_t modes[] = {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR} }; -extern int gl_backend_rebindtextures; - static void GL_TextureMode_f (void) { int i; + GLint oldbindtexnum; gltextureimage_t *image; gltexturepool_t *pool; @@ -363,12 +363,14 @@ static void GL_TextureMode_f (void) // only update already uploaded images if (!(image->flags & GLTEXF_UPLOAD)) { - qglBindTexture(GL_TEXTURE_2D, image->texnum); + qglGetIntegerv(gltexturetypebindingenums[image->texturetype], &oldbindtexnum); + qglBindTexture(gltexturetypeenums[image->texturetype], image->texnum); if (image->flags & TEXF_MIPMAP) - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); + qglTexParameteri(gltexturetypeenums[image->texturetype], GL_TEXTURE_MIN_FILTER, gl_filter_min); else - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_mag); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_mag); + qglTexParameteri(gltexturetypeenums[image->texturetype], GL_TEXTURE_MIN_FILTER, gl_filter_mag); + qglTexParameteri(gltexturetypeenums[image->texturetype], GL_TEXTURE_MAG_FILTER, gl_filter_mag); + qglBindTexture(gltexturetypeenums[image->texturetype], oldbindtexnum); } } } @@ -603,19 +605,19 @@ static void GL_SetupTextureParameters(int flags, int texturetype) static void R_Upload(gltexture_t *glt, qbyte *data) { - int i, mip, width, height, depth, internalformat; + int i, mip, width, height, depth; + GLint oldbindtexnum; qbyte *prevbuffer; prevbuffer = data; - R_Mesh_EndBatch(); - CHECKGLERROR glt->texnum = glt->image->texnum; + // we need to restore the texture binding after finishing the upload + qglGetIntegerv(gltexturetypebindingenums[glt->image->texturetype], &oldbindtexnum); qglBindTexture(gltexturetypeenums[glt->image->texturetype], glt->image->texnum); CHECKGLERROR glt->flags &= ~GLTEXF_UPLOAD; - gl_backend_rebindtextures = true; if (glt->flags & TEXF_FRAGMENT) { @@ -679,124 +681,85 @@ static void R_Upload(gltexture_t *glt, qbyte *data) Host_Error("R_Upload: fragment texture of type other than 1D, 2D, or 3D\n"); break; } - glt->texnum = glt->image->texnum; - return; - } - - glt->image->flags &= ~GLTEXF_UPLOAD; - - // these are rounded up versions of the size to do better resampling - for (width = 1;width < glt->width ;width <<= 1); - for (height = 1;height < glt->height;height <<= 1); - for (depth = 1;depth < glt->depth ;depth <<= 1); - - R_MakeResizeBufferBigger(width * height * depth * glt->image->sides * glt->image->bytesperpixel); - - if (prevbuffer == NULL) - { - width = glt->image->width; - height = glt->image->height; - depth = glt->image->depth; - memset(resizebuffer, 255, width * height * depth * glt->image->bytesperpixel); - prevbuffer = resizebuffer; } else { - if (glt->textype->textype == TEXTYPE_PALETTE) - { - // promote paletted to RGBA, so we only have to worry about RGB and - // RGBA in the rest of this code - Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, glt->width * glt->height * glt->depth * glt->image->sides, glt->palette); - prevbuffer = colorconvertbuffer; - } - } + glt->image->flags &= ~GLTEXF_UPLOAD; - // 3 and 4 are converted by the driver to it's preferred format for the current display mode - internalformat = 3; - if (glt->flags & TEXF_ALPHA) - internalformat = 4; + // these are rounded up versions of the size to do better resampling + for (width = 1;width < glt->width ;width <<= 1); + for (height = 1;height < glt->height;height <<= 1); + for (depth = 1;depth < glt->depth ;depth <<= 1); - // cubemaps contain multiple images and thus get processed a bit differently - if (glt->image->texturetype != GLTEXTURETYPE_CUBEMAP) - { - if (glt->width != width || glt->height != height || glt->depth != depth) - { - Image_Resample(prevbuffer, glt->width, glt->height, glt->depth, resizebuffer, width, height, depth, glt->image->bytesperpixel, r_lerpimages.integer); - prevbuffer = resizebuffer; - } - // picmip/max_size - while (width > glt->image->width || height > glt->image->height || depth > glt->image->depth) + R_MakeResizeBufferBigger(width * height * depth * glt->image->sides * glt->image->bytesperpixel); + + if (prevbuffer == NULL) { - Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, glt->image->width, glt->image->height, glt->image->depth, glt->image->bytesperpixel); + width = glt->image->width; + height = glt->image->height; + depth = glt->image->depth; + memset(resizebuffer, 255, width * height * depth * glt->image->bytesperpixel); prevbuffer = resizebuffer; } - } - mip = 0; - switch(glt->image->texturetype) - { - case GLTEXTURETYPE_1D: - qglTexImage1D(GL_TEXTURE_1D, mip++, internalformat, width, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); - CHECKGLERROR - if (glt->flags & TEXF_MIPMAP) + else { - while (width > 1 || height > 1 || depth > 1) + if (glt->textype->textype == TEXTYPE_PALETTE) { - Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1, glt->image->bytesperpixel); - prevbuffer = resizebuffer; - qglTexImage1D(GL_TEXTURE_1D, mip++, internalformat, width, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); - CHECKGLERROR + // promote paletted to RGBA, so we only have to worry about RGB and + // RGBA in the rest of this code + Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, glt->width * glt->height * glt->depth * glt->image->sides, glt->palette); + prevbuffer = colorconvertbuffer; } } - break; - case GLTEXTURETYPE_2D: - qglTexImage2D(GL_TEXTURE_2D, mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); - CHECKGLERROR - if (glt->flags & TEXF_MIPMAP) + + // cubemaps contain multiple images and thus get processed a bit differently + if (glt->image->texturetype != GLTEXTURETYPE_CUBEMAP) { - while (width > 1 || height > 1 || depth > 1) + if (glt->width != width || glt->height != height || glt->depth != depth) { - Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1, glt->image->bytesperpixel); + Image_Resample(prevbuffer, glt->width, glt->height, glt->depth, resizebuffer, width, height, depth, glt->image->bytesperpixel, r_lerpimages.integer); prevbuffer = resizebuffer; - qglTexImage2D(GL_TEXTURE_2D, mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); - CHECKGLERROR } - } - break; - case GLTEXTURETYPE_3D: - qglTexImage3D(GL_TEXTURE_3D, mip++, internalformat, width, height, depth, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); - CHECKGLERROR - if (glt->flags & TEXF_MIPMAP) - { - while (width > 1 || height > 1 || depth > 1) + // picmip/max_size + while (width > glt->image->width || height > glt->image->height || depth > glt->image->depth) { - Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1, glt->image->bytesperpixel); + Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, glt->image->width, glt->image->height, glt->image->depth, glt->image->bytesperpixel); prevbuffer = resizebuffer; - qglTexImage3D(GL_TEXTURE_3D, mip++, internalformat, width, height, depth, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); - CHECKGLERROR } } - break; - case GLTEXTURETYPE_CUBEMAP: - // convert and upload each side in turn, - // from a continuous block of input texels - texturebuffer = prevbuffer; - for (i = 0;i < 6;i++) + mip = 0; + switch(glt->image->texturetype) { - prevbuffer = texturebuffer; - texturebuffer += width * height * depth * glt->textype->inputbytesperpixel; - if (glt->width != width || glt->height != height || glt->depth != depth) + case GLTEXTURETYPE_1D: + qglTexImage1D(GL_TEXTURE_1D, mip++, glt->image->glinternalformat, width, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); + CHECKGLERROR + if (glt->flags & TEXF_MIPMAP) { - Image_Resample(prevbuffer, glt->width, glt->height, glt->depth, resizebuffer, width, height, depth, glt->image->bytesperpixel, r_lerpimages.integer); - prevbuffer = resizebuffer; + while (width > 1 || height > 1 || depth > 1) + { + Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1, glt->image->bytesperpixel); + prevbuffer = resizebuffer; + qglTexImage1D(GL_TEXTURE_1D, mip++, glt->image->glinternalformat, width, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); + CHECKGLERROR + } } - // picmip/max_size - while (width > glt->image->width || height > glt->image->height || depth > glt->image->depth) + break; + case GLTEXTURETYPE_2D: + qglTexImage2D(GL_TEXTURE_2D, mip++, glt->image->glinternalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); + CHECKGLERROR + if (glt->flags & TEXF_MIPMAP) { - Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, glt->image->width, glt->image->height, glt->image->depth, glt->image->bytesperpixel); - prevbuffer = resizebuffer; + while (width > 1 || height > 1 || depth > 1) + { + Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1, glt->image->bytesperpixel); + prevbuffer = resizebuffer; + qglTexImage2D(GL_TEXTURE_2D, mip++, glt->image->glinternalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); + CHECKGLERROR + } } - mip = 0; - qglTexImage2D(cubemapside[i], mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); + break; + case GLTEXTURETYPE_3D: + qglTexImage3D(GL_TEXTURE_3D, mip++, glt->image->glinternalformat, width, height, depth, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); CHECKGLERROR if (glt->flags & TEXF_MIPMAP) { @@ -804,14 +767,49 @@ static void R_Upload(gltexture_t *glt, qbyte *data) { Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1, glt->image->bytesperpixel); prevbuffer = resizebuffer; - qglTexImage2D(cubemapside[i], mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); + qglTexImage3D(GL_TEXTURE_3D, mip++, glt->image->glinternalformat, width, height, depth, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); CHECKGLERROR } } + break; + case GLTEXTURETYPE_CUBEMAP: + // convert and upload each side in turn, + // from a continuous block of input texels + texturebuffer = prevbuffer; + for (i = 0;i < 6;i++) + { + prevbuffer = texturebuffer; + texturebuffer += width * height * depth * glt->textype->inputbytesperpixel; + if (glt->width != width || glt->height != height || glt->depth != depth) + { + Image_Resample(prevbuffer, glt->width, glt->height, glt->depth, resizebuffer, width, height, depth, glt->image->bytesperpixel, r_lerpimages.integer); + prevbuffer = resizebuffer; + } + // picmip/max_size + while (width > glt->image->width || height > glt->image->height || depth > glt->image->depth) + { + Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, glt->image->width, glt->image->height, glt->image->depth, glt->image->bytesperpixel); + prevbuffer = resizebuffer; + } + mip = 0; + qglTexImage2D(cubemapside[i], mip++, glt->image->glinternalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); + CHECKGLERROR + if (glt->flags & TEXF_MIPMAP) + { + while (width > 1 || height > 1 || depth > 1) + { + Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1, glt->image->bytesperpixel); + prevbuffer = resizebuffer; + qglTexImage2D(cubemapside[i], mip++, glt->image->glinternalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); + CHECKGLERROR + } + } + } + break; } - break; + GL_SetupTextureParameters(glt->image->flags, glt->image->texturetype); } - GL_SetupTextureParameters(glt->image->flags, glt->image->texturetype); + qglBindTexture(gltexturetypeenums[glt->image->texturetype], oldbindtexnum); } static void R_FindImageForTexture(gltexture_t *glt) diff --git a/glquake.h b/glquake.h index 4e9e3a24..69542c0e 100644 --- a/glquake.h +++ b/glquake.h @@ -111,6 +111,8 @@ typedef double GLclampd; #define GL_TEXTURE_MAG_FILTER 0x2800 #define GL_TEXTURE_MIN_FILTER 0x2801 #define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_2D 0x8069 #define GL_NEAREST 0x2600 #define GL_LINEAR 0x2601 @@ -207,6 +209,7 @@ typedef double GLclampd; // GL_ARB_multitexture extern int gl_textureunits; extern void (GLAPIENTRY *qglMultiTexCoord2f) (GLenum, GLfloat, GLfloat); +extern void (GLAPIENTRY *qglMultiTexCoord3f) (GLenum, GLfloat, GLfloat, GLfloat); extern void (GLAPIENTRY *qglActiveTexture) (GLenum); extern void (GLAPIENTRY *qglClientActiveTexture) (GLenum); #ifndef GL_ACTIVE_TEXTURE_ARB @@ -377,7 +380,7 @@ extern void (GLAPIENTRY *qglCullFace)(GLenum mode); //extern void (GLAPIENTRY *qglReadBuffer)(GLenum mode); extern void (GLAPIENTRY *qglEnable)(GLenum cap); extern void (GLAPIENTRY *qglDisable)(GLenum cap); -//extern GLboolean GLAPIENTRY *qglIsEnabled)(GLenum cap); +extern GLboolean (GLAPIENTRY *qglIsEnabled)(GLenum cap); extern void (GLAPIENTRY *qglEnableClientState)(GLenum cap); extern void (GLAPIENTRY *qglDisableClientState)(GLenum cap); @@ -395,23 +398,24 @@ extern void (GLAPIENTRY *qglFlush)(void); extern void (GLAPIENTRY *qglClearDepth)(GLclampd depth); extern void (GLAPIENTRY *qglDepthFunc)(GLenum func); extern void (GLAPIENTRY *qglDepthMask)(GLboolean flag); -//extern void (GLAPIENTRY *qglDepthRange)(GLclampd near_val, GLclampd far_val); +extern void (GLAPIENTRY *qglDepthRange)(GLclampd near_val, GLclampd far_val); extern void (GLAPIENTRY *qglColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); 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 *qglVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -//extern void (GLAPIENTRY *qglNormalPointer)(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 *qglArrayElement)(GLint i); extern void (GLAPIENTRY *qglColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -//extern void (GLAPIENTRY *qglTexCoord2f)(GLfloat s, GLfloat t); -//extern void (GLAPIENTRY *qglVertex2f)(GLfloat x, GLfloat y); -//extern void (GLAPIENTRY *qglVertex3f)(GLfloat x, GLfloat y, GLfloat z); -//extern void (GLAPIENTRY *qglBegin)(GLenum mode); -//extern void (GLAPIENTRY *qglEnd)(void); +extern void (GLAPIENTRY *qglTexCoord2f)(GLfloat s, GLfloat t); +extern void (GLAPIENTRY *qglTexCoord3f)(GLfloat s, GLfloat t, GLfloat r); +extern void (GLAPIENTRY *qglVertex2f)(GLfloat x, GLfloat y); +extern void (GLAPIENTRY *qglVertex3f)(GLfloat x, GLfloat y, GLfloat z); +extern void (GLAPIENTRY *qglBegin)(GLenum mode); +extern void (GLAPIENTRY *qglEnd)(void); extern void (GLAPIENTRY *qglMatrixMode)(GLenum mode); extern void (GLAPIENTRY *qglOrtho)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val); @@ -480,7 +484,7 @@ extern BOOL (WINAPI *qwglSwapIntervalEXT)(int interval); #define DEBUGGL #ifdef DEBUGGL -#define CHECKGLERROR if ((errornumber = qglGetError())) GL_PrintError(errornumber, __FILE__, __LINE__); +#define CHECKGLERROR {if (gl_printcheckerror.integer) Con_Printf("CHECKGLERROR at %s:%d\n", __FILE__, __LINE__);if (gl_paranoid.integer && (errornumber = qglGetError())) GL_PrintError(errornumber, __FILE__, __LINE__);} extern int errornumber; void GL_PrintError(int errornumber, char *filename, int linenumber); #else diff --git a/model_shared.c b/model_shared.c index 5703e611..d882c023 100644 --- a/model_shared.c +++ b/model_shared.c @@ -676,7 +676,7 @@ void Mod_ShadowMesh_AddPolygon(mempool_t *mempool, shadowmesh_t *mesh, int numve */ } -void Mod_ShadowMesh_AddMesh(mempool_t *mempool, shadowmesh_t *mesh, int numverts, float *verts, int numtris, int *elements) +void Mod_ShadowMesh_AddMesh(mempool_t *mempool, shadowmesh_t *mesh, float *verts, int numtris, int *elements) { int i; for (i = 0;i < numtris;i++, elements += 3) diff --git a/model_shared.h b/model_shared.h index dd09ee69..762f4a90 100644 --- a/model_shared.h +++ b/model_shared.h @@ -315,7 +315,7 @@ shadowmesh_t *Mod_ShadowMesh_ReAlloc(mempool_t *mempool, shadowmesh_t *oldmesh); int Mod_ShadowMesh_AddVertex(shadowmesh_t *mesh, float *v); void Mod_ShadowMesh_AddTriangle(mempool_t *mempool, shadowmesh_t *mesh, float *vert0, float *vert1, float *vert2); void Mod_ShadowMesh_AddPolygon(mempool_t *mempool, shadowmesh_t *mesh, int numverts, float *verts); -void Mod_ShadowMesh_AddMesh(mempool_t *mempool, shadowmesh_t *mesh, int numverts, float *verts, int numtris, int *elements); +void Mod_ShadowMesh_AddMesh(mempool_t *mempool, shadowmesh_t *mesh, float *verts, int numtris, int *elements); shadowmesh_t *Mod_ShadowMesh_Begin(mempool_t *mempool, int initialnumtriangles); shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh); void Mod_ShadowMesh_CalcBBox(shadowmesh_t *firstmesh, vec3_t mins, vec3_t maxs, vec3_t center, float *radius); diff --git a/r_crosshairs.c b/r_crosshairs.c index ba08ed9c..4ed1ca65 100644 --- a/r_crosshairs.c +++ b/r_crosshairs.c @@ -22,29 +22,6 @@ void R_Crosshairs_Init(void) Cvar_RegisterVariable(&crosshair_static); } -void R_DrawCrosshairSprite(rtexture_t *texture, vec3_t origin, vec_t scale, float cr, float cg, float cb, float ca) -{ - rmeshstate_t m; - float diff[3]; - - if (fogenabled) - { - VectorSubtract(origin, r_origin, diff); - ca *= 1 - exp(fogdensity/DotProduct(diff,diff)); - } - - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; - m.depthdisable = true; - m.tex[0] = R_GetTexture(texture); - R_Mesh_Matrix(&r_identitymatrix); - R_Mesh_State(&m); - - GL_Color(cr * r_colorscale, cg * r_colorscale, cb * r_colorscale, ca); - R_DrawSpriteMesh(origin, vright, vup, scale, -scale, -scale, scale); -} - void R_GetCrosshairColor(float *out) { int i; @@ -108,7 +85,7 @@ void R_DrawWorldCrosshair(void) spritescale = CL_TraceLine(v1, v2, spriteorigin, NULL, 0, true, NULL) * (8192.0f / 40.0f) * crosshair_size.value; // draw the sprite - R_DrawCrosshairSprite(pic->tex, spriteorigin, spritescale, color[0], color[1], color[2], color[3]); + R_DrawSprite(GL_SRC_ALPHA, GL_ONE, pic->tex, true, spriteorigin, vright, vup, spritescale, -spritescale, -spritescale, spritescale, color[0], color[1], color[2], color[3]); } void R_Draw2DCrosshair(void) diff --git a/r_explosion.c b/r_explosion.c index 80f4909f..b8eeb84f 100644 --- a/r_explosion.c +++ b/r_explosion.c @@ -181,30 +181,22 @@ void R_DrawExplosionCallback(const void *calldata1, int calldata2) const explosion_t *e; e = calldata1; - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; - m.tex[0] = R_GetTexture(explosiontexture); + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); + GL_DepthTest(true); R_Mesh_Matrix(&r_identitymatrix); numtriangles = EXPLOSIONTRIS; numverts = EXPLOSIONVERTS; alpha = e->alpha * r_colorscale; GL_Color(alpha, alpha, alpha, 1); - if (gl_mesh_copyarrays.integer) - { - R_Mesh_State(&m); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(e->vert[0], numverts); - R_Mesh_CopyTexCoord2f(0, explosiontexcoord2f[0], numverts); - } - else - { - m.pointervertexcount = numverts; - m.pointer_vertex = e->vert[0]; - m.pointer_texcoord[0] = explosiontexcoord2f[0]; - R_Mesh_State(&m); - } + GL_VertexPointer(e->vert[0]); + + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(explosiontexture); + m.pointer_texcoord[0] = explosiontexcoord2f[0]; + R_Mesh_State_Texture(&m); + R_Mesh_Draw(numverts, numtriangles, explosiontris[0]); } diff --git a/r_light.c b/r_light.c index d8708134..c032679b 100644 --- a/r_light.c +++ b/r_light.c @@ -141,18 +141,11 @@ void R_BuildLightList(void) void R_DrawCoronas(void) { int i; - rmeshstate_t m; - float scale, viewdist, diff[3], dist; + float cscale, scale, viewdist, dist; rdlight_t *rd; if (!r_coronas.integer) return; - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ONE; - m.depthdisable = true; // magic - m.tex[0] = R_GetTexture(lightcorona); R_Mesh_Matrix(&r_identitymatrix); - R_Mesh_State(&m); viewdist = DotProduct(r_origin, vpn); for (i = 0;i < r_numdlights;i++) { @@ -160,19 +153,14 @@ void R_DrawCoronas(void) dist = (DotProduct(rd->origin, vpn) - viewdist); if (dist >= 24.0f && CL_TraceLine(rd->origin, r_origin, NULL, NULL, 0, true, NULL) == 1) { - scale = r_colorscale * (1.0f / 131072.0f); - if (gl_flashblend.integer) - scale *= 4.0f; - if (fogenabled) - { - VectorSubtract(rd->origin, r_origin, diff); - scale *= 1 - exp(fogdensity/DotProduct(diff,diff)); - } - GL_Color(rd->light[0] * scale, rd->light[1] * scale, rd->light[2] * scale, 1); + cscale = (1.0f / 131072.0f); scale = rd->cullradius * 0.25f; if (gl_flashblend.integer) + { + cscale *= 4.0f; scale *= 2.0f; - R_DrawSpriteMesh(rd->origin, vright, vup, scale, -scale, -scale, scale); + } + R_DrawSprite(GL_ONE, GL_ONE, lightcorona, true, rd->origin, vright, vup, scale, -scale, -scale, scale, rd->light[0] * cscale, rd->light[1] * cscale, rd->light[2] * cscale, 1); } } } diff --git a/r_shadow.c b/r_shadow.c index 16cb6eda..dcb2b3a3 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -1,4 +1,107 @@ +/* +Terminology: Stencil Shadow Volume (sometimes called Stencil Shadows) +An extrusion of the lit faces, beginning at the original geometry and ending +further from the light source than the original geometry (presumably at least +as far as the light's radius, if the light has a radius at all), capped at +both front and back to avoid any problems (extrusion from dark faces also +works but has a different set of problems) + +This is rendered using Carmack's Reverse technique, in which backfaces behind +zbuffer (zfail) increment the stencil, and frontfaces behind zbuffer (zfail) +decrement the stencil, the result is a stencil value of zero where shadows +did not intersect the visible geometry, suitable as a stencil mask for +rendering lighting everywhere but shadow. + +In our case we use a biased stencil clear of 128 to avoid requiring the +stencil wrap extension (but probably should support it). + + + +Terminology: Stencil Light Volume (sometimes called Light Volumes) +Similar to a Stencil Shadow Volume, but inverted; rather than containing the +areas in shadow it contanis the areas in light, this can only be built +quickly for certain limited cases (such as portal visibility from a point), +but is quite useful for some effects (sunlight coming from sky polygons is +one possible example, translucent occluders is another example). + + + +Terminology: Optimized Stencil Shadow Volume +A Stencil Shadow Volume that has been processed sufficiently to ensure it has +no duplicate coverage of areas (no need to shadow an area twice), often this +greatly improves performance but is an operation too costly to use on moving +lights (however completely optimal Stencil Light Volumes can be constructed +in some ideal cases). + + + +Terminology: Per Pixel Lighting (sometimes abbreviated PPL) +Per pixel evaluation of lighting equations, at a bare minimum this involves +DOT3 shading of diffuse lighting (per pixel dotproduct of negated incidence +vector and surface normal, using a texture of the surface bumps, called a +NormalMap) if supported by hardware; in our case there is support for cards +which are incapable of DOT3, the quality is quite poor however. Additionally +it is desirable to have specular evaluation per pixel, per vertex +normalization of specular halfangle vectors causes noticable distortion but +is unavoidable on hardware without GL_ARB_fragment_program. + + + +Terminology: Normalization CubeMap +A cubemap containing normalized dot3-encoded (vectors of length 1 or less +encoded as RGB colors) for any possible direction, this technique allows per +pixel calculation of incidence vector for per pixel lighting purposes, which +would not otherwise be possible per pixel without GL_ARB_fragment_program. + + + +Terminology: 2D Attenuation Texturing +A very crude approximation of light attenuation with distance which results +in cylindrical light shapes which fade vertically as a streak (some games +such as Doom3 allow this to be rotated to be less noticable in specific +cases), the technique is simply modulating lighting by two 2D textures (which +can be the same) on different axes of projection (XY and Z, typically), this +is the best technique available without 3D Attenuation Texturing or +GL_ARB_fragment_program technology. + + + +Terminology: 3D Attenuation Texturing +A slightly crude approximation of light attenuation with distance, its flaws +are limited radius and resolution (performance tradeoffs). + + + +Terminology: 3D Attenuation-Normalization Texturing +A 3D Attenuation Texture merged with a Normalization CubeMap, by making the +vectors shorter the lighting becomes darker, a very effective optimization of +diffuse lighting if 3D Attenuation Textures are already used. + + + +Terminology: Light Cubemap Filtering +A technique for modeling non-uniform light distribution according to +direction, for example projecting a stained glass window image onto a wall, +this is done by texturing the lighting with a cubemap. + + + +Terminology: Light Projection Filtering +A technique for modeling shadowing of light passing through translucent +surfaces, allowing stained glass windows and other effects to be done more +elegantly than possible with Light Cubemap Filtering by applying an occluder +texture to the lighting combined with a stencil light volume to limit the lit +area (this allows evaluating multiple translucent occluders in a scene). + + + +Terminology: Doom3 Lighting +A combination of Stencil Shadow Volume, Per Pixel Lighting, Normalization +CubeMap, 2D Attenuation Texturing, and Light Filtering, as demonstrated by +the (currently upcoming) game Doom3. +*/ + #include "quakedef.h" #include "r_shadow.h" #include "cl_collision.h" @@ -24,6 +127,7 @@ int *trianglefacinglightlist; int maxvertexupdate; int *vertexupdate; +int *vertexremap; int vertexupdatenum; rtexturepool_t *r_shadow_texturepool; @@ -45,10 +149,11 @@ cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1"}; cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1"}; cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4"}; cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0"}; -cvar_t r_shadow_polygonoffset = {0, "r_shadow_polygonoffset", "-1"}; +cvar_t r_shadow_polygonoffset = {0, "r_shadow_polygonoffset", "0"}; cvar_t r_shadow_portallight = {0, "r_shadow_portallight", "1"}; -cvar_t r_shadow_projectdistance = {0, "r_shadow_projectdistance", "100000"}; +cvar_t r_shadow_projectdistance = {0, "r_shadow_projectdistance", "10000"}; cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1"}; +cvar_t r_shadow_singlepassvolumegeneration = {0, "r_shadow_singlepassvolumegeneration", "1"}; int c_rt_lights, c_rt_clears, c_rt_scissored; int c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris; @@ -68,6 +173,7 @@ void r_shadow_start(void) shadowelements = NULL; maxvertexupdate = 0; vertexupdate = NULL; + vertexremap = NULL; vertexupdatenum = 0; maxtrianglefacinglight = 0; trianglefacinglight = NULL; @@ -98,6 +204,7 @@ void r_shadow_shutdown(void) shadowelements = NULL; maxvertexupdate = 0; vertexupdate = NULL; + vertexremap = NULL; vertexupdatenum = 0; maxtrianglefacinglight = 0; trianglefacinglight = NULL; @@ -128,126 +235,11 @@ void R_Shadow_Init(void) Cvar_RegisterVariable(&r_shadow_portallight); Cvar_RegisterVariable(&r_shadow_projectdistance); Cvar_RegisterVariable(&r_shadow_texture3d); + Cvar_RegisterVariable(&r_shadow_singlepassvolumegeneration); R_Shadow_EditLights_Init(); R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap); } -int R_Shadow_MakeTriangleShadowFlags_Vertex3f(const int *elements, const float *vertex, int numtris, qbyte *facing, int *list, const float *relativelightorigin) -{ - int i, tris = 0; - const float *v0, *v1, *v2; - for (i = 0;i < numtris;i++, elements += 3) - { - // calculate triangle facing flag - v0 = vertex + elements[0] * 3; - v1 = vertex + elements[1] * 3; - v2 = vertex + elements[2] * 3; - if(PointInfrontOfTriangle(relativelightorigin, v0, v1, v2)) - { - facing[i] = true; - list[tris++] = i; - } - else - facing[i] = false; - } - return tris; -} - -int R_Shadow_BuildShadowVolume(const int *elements, const int *neighbors, int numverts, const qbyte *facing, const int *facinglist, int numfacing, int *out, float *vertices, const float *relativelightorigin, float projectdistance) -{ - int i, j, tris, vertexpointeradjust = numverts * 3; - const int *e, *n; - float *vin, *vout; - - if (maxvertexupdate < numverts) - { - maxvertexupdate = numverts; - if (vertexupdate) - Mem_Free(vertexupdate); - vertexupdate = Mem_Alloc(r_shadow_mempool, maxvertexupdate * sizeof(int)); - } - vertexupdatenum++; - - // check each frontface for bordering backfaces, - // and cast shadow polygons from those edges, - // also create front and back caps for shadow volume - tris = numfacing * 2; - // output front caps - for (i = 0;i < numfacing;i++) - { - e = elements + facinglist[i] * 3; - out[0] = e[0]; - out[1] = e[1]; - out[2] = e[2]; - out += 3; - } - // output back caps - for (i = 0;i < numfacing;i++) - { - e = elements + facinglist[i] * 3; - // generate vertices if needed - for (j = 0;j < 3;j++) - { - if (vertexupdate[e[j]] != vertexupdatenum) - { - vertexupdate[e[j]] = vertexupdatenum; - vin = vertices + e[j] * 3; - vout = vin + vertexpointeradjust; - vout[0] = relativelightorigin[0] + projectdistance * (vin[0] - relativelightorigin[0]); - vout[1] = relativelightorigin[1] + projectdistance * (vin[1] - relativelightorigin[1]); - vout[2] = relativelightorigin[2] + projectdistance * (vin[2] - relativelightorigin[2]); - } - } - out[0] = e[2] + numverts; - out[1] = e[1] + numverts; - out[2] = e[0] + numverts; - out += 3; - } - // output sides around frontfaces - for (i = 0;i < numfacing;i++) - { - n = neighbors + facinglist[i] * 3; - // check the edges - if (n[0] < 0 || !facing[n[0]]) - { - e = elements + facinglist[i] * 3; - out[0] = e[1]; - out[1] = e[0]; - out[2] = e[0] + numverts; - out[3] = e[1]; - out[4] = e[0] + numverts; - out[5] = e[1] + numverts; - out += 6; - tris += 2; - } - if (n[1] < 0 || !facing[n[1]]) - { - e = elements + facinglist[i] * 3; - out[0] = e[2]; - out[1] = e[1]; - out[2] = e[1] + numverts; - out[3] = e[2]; - out[4] = e[1] + numverts; - out[5] = e[2] + numverts; - out += 6; - tris += 2; - } - if (n[2] < 0 || !facing[n[2]]) - { - e = elements + facinglist[i] * 3; - out[0] = e[0]; - out[1] = e[2]; - out[2] = e[2] + numverts; - out[3] = e[0]; - out[4] = e[2] + numverts; - out[5] = e[0] + numverts; - out += 6; - tris += 2; - } - } - return tris; -} - void R_Shadow_ResizeTriangleFacingLight(int numtris) { // make sure trianglefacinglight is big enough for this volume @@ -278,9 +270,252 @@ int *R_Shadow_ResizeShadowElements(int numtris) return shadowelements; } -void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float lightradius, float projectdistance) +int R_Shadow_ConstructShadowVolume(int innumvertices, int trianglerange_start, int trianglerange_end, const int *inelement3i, const int *inneighbor3i, const float *invertex3f, int *outnumvertices, int *outelement3i, float *outvertex3f, const float *relativelightorigin, float projectdistance) +{ + int i, j, tris = 0, numfacing = 0, vr[3], t, outvertices = 0; + const float *v[3]; + const int *e, *n, *te; + float f, temp[3]; + + // make sure trianglefacinglight is big enough for this volume + if (maxtrianglefacinglight < trianglerange_end) + R_Shadow_ResizeTriangleFacingLight(trianglerange_end); + + if (maxvertexupdate < innumvertices) + { + maxvertexupdate = innumvertices; + if (vertexupdate) + Mem_Free(vertexupdate); + if (vertexremap) + Mem_Free(vertexremap); + vertexupdate = Mem_Alloc(r_shadow_mempool, maxvertexupdate * sizeof(int)); + vertexremap = Mem_Alloc(r_shadow_mempool, maxvertexupdate * sizeof(int)); + } + vertexupdatenum++; + + if (r_shadow_singlepassvolumegeneration.integer) + { + // one pass approach (identify lit/dark faces and generate sides while doing so) + for (i = trianglerange_start, e = inelement3i + i * 3, n = inneighbor3i + i * 3;i < trianglerange_end;i++, e += 3, n += 3) + { + // calculate triangle facing flag + v[0] = invertex3f + e[0] * 3; + v[1] = invertex3f + e[1] * 3; + v[2] = invertex3f + e[2] * 3; + if((trianglefacinglight[i] = PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]))) + { + // make sure the vertices are created + for (j = 0;j < 3;j++) + { + if (vertexupdate[e[j]] != vertexupdatenum) + { + vertexupdate[e[j]] = vertexupdatenum; + vertexremap[e[j]] = outvertices; + VectorCopy(v[j], outvertex3f); + VectorSubtract(v[j], relativelightorigin, temp); + f = projectdistance / VectorLength(temp); + VectorMA(relativelightorigin, f, temp, (outvertex3f + 3)); + outvertex3f += 6; + outvertices += 2; + } + } + // output the front and back triangles + vr[0] = vertexremap[e[0]]; + vr[1] = vertexremap[e[1]]; + vr[2] = vertexremap[e[2]]; + outelement3i[0] = vr[0]; + outelement3i[1] = vr[1]; + outelement3i[2] = vr[2]; + outelement3i[3] = vr[2] + 1; + outelement3i[4] = vr[1] + 1; + outelement3i[5] = vr[0] + 1; + outelement3i += 6; + tris += 2; + // output the sides (facing outward from this triangle) + t = n[0]; + if ((t >= trianglerange_start && t < trianglerange_end) ? (t < i && !trianglefacinglight[t]) : (t < 0 || (te = inelement3i + t * 3, v[0] = invertex3f + te[0] * 3, v[1] = invertex3f + te[1] * 3, v[2] = invertex3f + te[2] * 3, !PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2])))) + { + outelement3i[0] = vr[1]; + outelement3i[1] = vr[0]; + outelement3i[2] = vr[0] + 1; + outelement3i[3] = vr[1]; + outelement3i[4] = vr[0] + 1; + outelement3i[5] = vr[1] + 1; + outelement3i += 6; + tris += 2; + } + t = n[1]; + if ((t >= trianglerange_start && t < trianglerange_end) ? (t < i && !trianglefacinglight[t]) : (t < 0 || (te = inelement3i + t * 3, v[0] = invertex3f + te[0] * 3, v[1] = invertex3f + te[1] * 3, v[2] = invertex3f + te[2] * 3, !PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2])))) + { + outelement3i[0] = vr[2]; + outelement3i[1] = vr[1]; + outelement3i[2] = vr[1] + 1; + outelement3i[3] = vr[2]; + outelement3i[4] = vr[1] + 1; + outelement3i[5] = vr[2] + 1; + outelement3i += 6; + tris += 2; + } + t = n[2]; + if ((t >= trianglerange_start && t < trianglerange_end) ? (t < i && !trianglefacinglight[t]) : (t < 0 || (te = inelement3i + t * 3, v[0] = invertex3f + te[0] * 3, v[1] = invertex3f + te[1] * 3, v[2] = invertex3f + te[2] * 3, !PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2])))) + { + outelement3i[0] = vr[0]; + outelement3i[1] = vr[2]; + outelement3i[2] = vr[2] + 1; + outelement3i[3] = vr[0]; + outelement3i[4] = vr[2] + 1; + outelement3i[5] = vr[0] + 1; + outelement3i += 6; + tris += 2; + } + } + else + { + // this triangle is not facing the light + // output the sides (facing inward to this triangle) + t = n[0]; + if (t < i && t >= trianglerange_start && t < trianglerange_end && trianglefacinglight[t]) + { + vr[0] = vertexremap[e[0]]; + vr[1] = vertexremap[e[1]]; + outelement3i[0] = vr[1]; + outelement3i[1] = vr[0] + 1; + outelement3i[2] = vr[0]; + outelement3i[3] = vr[1]; + outelement3i[4] = vr[1] + 1; + outelement3i[5] = vr[0] + 1; + outelement3i += 6; + tris += 2; + } + t = n[1]; + if (t < i && t >= trianglerange_start && t < trianglerange_end && trianglefacinglight[t]) + { + vr[1] = vertexremap[e[1]]; + vr[2] = vertexremap[e[2]]; + outelement3i[0] = vr[2]; + outelement3i[1] = vr[1] + 1; + outelement3i[2] = vr[1]; + outelement3i[3] = vr[2]; + outelement3i[4] = vr[2] + 1; + outelement3i[5] = vr[1] + 1; + outelement3i += 6; + tris += 2; + } + t = n[2]; + if (t < i && t >= trianglerange_start && t < trianglerange_end && trianglefacinglight[t]) + { + vr[0] = vertexremap[e[0]]; + vr[2] = vertexremap[e[2]]; + outelement3i[0] = vr[0]; + outelement3i[1] = vr[2] + 1; + outelement3i[2] = vr[2]; + outelement3i[3] = vr[0]; + outelement3i[4] = vr[0] + 1; + outelement3i[5] = vr[2] + 1; + outelement3i += 6; + tris += 2; + } + } + } + } + else + { + // two pass approach (identify lit/dark faces and then generate sides) + for (i = trianglerange_start, e = inelement3i + i * 3, numfacing = 0;i < trianglerange_end;i++, e += 3) + { + // calculate triangle facing flag + v[0] = invertex3f + e[0] * 3; + v[1] = invertex3f + e[1] * 3; + v[2] = invertex3f + e[2] * 3; + if((trianglefacinglight[i] = PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]))) + { + trianglefacinglightlist[numfacing++] = i; + // make sure the vertices are created + for (j = 0;j < 3;j++) + { + if (vertexupdate[e[j]] != vertexupdatenum) + { + vertexupdate[e[j]] = vertexupdatenum; + vertexremap[e[j]] = outvertices; + VectorSubtract(v[j], relativelightorigin, temp); + f = projectdistance / VectorLength(temp); + VectorCopy(v[j], outvertex3f); + VectorMA(relativelightorigin, f, temp, (outvertex3f + 3)); + outvertex3f += 6; + outvertices += 2; + } + } + // output the front and back triangles + outelement3i[3] = vertexremap[e[0]]; + outelement3i[4] = vertexremap[e[1]]; + outelement3i[5] = vertexremap[e[2]]; + outelement3i[0] = vertexremap[e[2]] + 1; + outelement3i[1] = vertexremap[e[1]] + 1; + outelement3i[2] = vertexremap[e[0]] + 1; + outelement3i += 6; + tris += 2; + } + } + for (i = 0;i < numfacing;i++) + { + t = trianglefacinglightlist[i]; + e = inelement3i + t * 3; + n = inneighbor3i + t * 3; + // output the sides (facing outward from this triangle) + t = n[0]; + if ((t >= trianglerange_start && t < trianglerange_end) ? (!trianglefacinglight[t]) : (t < 0 || (te = inelement3i + t * 3, v[0] = invertex3f + te[0] * 3, v[1] = invertex3f + te[1] * 3, v[2] = invertex3f + te[2] * 3, !PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2])))) + { + vr[0] = vertexremap[e[0]]; + vr[1] = vertexremap[e[1]]; + outelement3i[0] = vr[1]; + outelement3i[1] = vr[0]; + outelement3i[2] = vr[0] + 1; + outelement3i[3] = vr[1]; + outelement3i[4] = vr[0] + 1; + outelement3i[5] = vr[1] + 1; + outelement3i += 6; + tris += 2; + } + t = n[1]; + if ((t >= trianglerange_start && t < trianglerange_end) ? (!trianglefacinglight[t]) : (t < 0 || (te = inelement3i + t * 3, v[0] = invertex3f + te[0] * 3, v[1] = invertex3f + te[1] * 3, v[2] = invertex3f + te[2] * 3, !PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2])))) + { + vr[1] = vertexremap[e[1]]; + vr[2] = vertexremap[e[2]]; + outelement3i[0] = vr[2]; + outelement3i[1] = vr[1]; + outelement3i[2] = vr[1] + 1; + outelement3i[3] = vr[2]; + outelement3i[4] = vr[1] + 1; + outelement3i[5] = vr[2] + 1; + outelement3i += 6; + tris += 2; + } + t = n[2]; + if ((t >= trianglerange_start && t < trianglerange_end) ? (!trianglefacinglight[t]) : (t < 0 || (te = inelement3i + t * 3, v[0] = invertex3f + te[0] * 3, v[1] = invertex3f + te[1] * 3, v[2] = invertex3f + te[2] * 3, !PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2])))) + { + vr[0] = vertexremap[e[0]]; + vr[2] = vertexremap[e[2]]; + outelement3i[0] = vr[0]; + outelement3i[1] = vr[2]; + outelement3i[2] = vr[2] + 1; + outelement3i[3] = vr[0]; + outelement3i[4] = vr[2] + 1; + outelement3i[5] = vr[0] + 1; + outelement3i += 6; + tris += 2; + } + } + } + if (outnumvertices) + *outnumvertices = outvertices; + return tris; +} + +float varray_vertex3f2[65536*3]; + +void R_Shadow_Volume(int numverts, int numtris, const float *invertex3f, int *elements, int *neighbors, vec3_t relativelightorigin, float lightradius, float projectdistance) { - int tris; + int tris, outverts; if (projectdistance < 0.1) { Con_Printf("R_Shadow_Volume: projectdistance %f\n"); @@ -288,93 +523,61 @@ void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, v } if (!numverts) return; -// terminology: -// -// frontface: -// a triangle facing the light source -// -// backface: -// a triangle not facing the light source -// -// shadow volume: -// an extrusion of the frontfaces, beginning at the original geometry and -// ending further from the light source than the original geometry -// (presumably at least as far as the light's radius, if the light has a -// radius at all), capped at both front and back to avoid any problems -// -// description: -// draws the shadow volumes of the model. -// requirements: -// vertex locations must already be in varray_vertex3f before use. -// varray_vertex3f must have capacity for numverts * 2. - - // make sure trianglefacinglight is big enough for this volume - if (maxtrianglefacinglight < numtris) - R_Shadow_ResizeTriangleFacingLight(numtris); // make sure shadowelements is big enough for this volume if (maxshadowelements < numtris * 24) R_Shadow_ResizeShadowElements(numtris); - // check which triangles are facing the light - tris = R_Shadow_MakeTriangleShadowFlags_Vertex3f(elements, varray_vertex3f, numtris, trianglefacinglight, trianglefacinglightlist, relativelightorigin); - if (!tris) - return; - - // by clever use of elements we can construct the whole shadow from - // the unprojected vertices and the projected vertices - - // output triangle elements and vertices - tris = R_Shadow_BuildShadowVolume(elements, neighbors, numverts, trianglefacinglight, trianglefacinglightlist, tris, shadowelements, varray_vertex3f, relativelightorigin, projectdistance); - if (!tris) - return; - - if (r_shadowstage == SHADOWSTAGE_STENCIL) + // check which triangles are facing the light, and then output + // triangle elements and vertices... by clever use of elements we + // can construct the whole shadow from the unprojected vertices and + // the projected vertices + if ((tris = R_Shadow_ConstructShadowVolume(numverts, 0, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, varray_vertex3f2, relativelightorigin, projectdistance))) { - // increment stencil if backface is behind depthbuffer - //R_Mesh_EndBatch(); - qglCullFace(GL_BACK); // quake is backwards, this culls front faces - qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP); - R_Mesh_Draw_NoBatching(numverts * 2, tris, shadowelements); + GL_VertexPointer(varray_vertex3f2); + if (r_shadowstage == SHADOWSTAGE_STENCIL) + { + // increment stencil if backface is behind depthbuffer + qglCullFace(GL_BACK); // quake is backwards, this culls front faces + qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP); + R_Mesh_Draw(outverts, tris, shadowelements); + c_rt_shadowmeshes++; + c_rt_shadowtris += numtris; + // decrement stencil if frontface is behind depthbuffer + qglCullFace(GL_FRONT); // quake is backwards, this culls back faces + qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP); + } + R_Mesh_Draw(outverts, tris, shadowelements); c_rt_shadowmeshes++; c_rt_shadowtris += numtris; - // decrement stencil if frontface is behind depthbuffer - //R_Mesh_EndBatch(); - qglCullFace(GL_FRONT); // quake is backwards, this culls back faces - qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP); } - R_Mesh_Draw_NoBatching(numverts * 2, tris, shadowelements); - c_rt_shadowmeshes++; - c_rt_shadowtris += numtris; } void R_Shadow_RenderShadowMeshVolume(shadowmesh_t *firstmesh) { shadowmesh_t *mesh; + rmeshstate_t m; + memset(&m, 0, sizeof(m)); if (r_shadowstage == SHADOWSTAGE_STENCIL) { // increment stencil if backface is behind depthbuffer - //R_Mesh_EndBatch(); qglCullFace(GL_BACK); // quake is backwards, this culls front faces qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP); for (mesh = firstmesh;mesh;mesh = mesh->next) { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - R_Mesh_Draw_NoBatching(mesh->numverts, mesh->numtriangles, mesh->element3i); + GL_VertexPointer(mesh->vertex3f); + R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); c_rtcached_shadowmeshes++; c_rtcached_shadowtris += mesh->numtriangles; } // decrement stencil if frontface is behind depthbuffer - //R_Mesh_EndBatch(); qglCullFace(GL_FRONT); // quake is backwards, this culls back faces qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP); } for (mesh = firstmesh;mesh;mesh = mesh->next) { - R_Mesh_GetSpace(mesh->numverts); - R_Mesh_CopyVertex3f(mesh->vertex3f, mesh->numverts); - R_Mesh_Draw_NoBatching(mesh->numverts, mesh->numtriangles, mesh->element3i); + GL_VertexPointer(mesh->vertex3f); + R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i); c_rtcached_shadowmeshes++; c_rtcached_shadowtris += mesh->numtriangles; } @@ -523,12 +726,14 @@ void R_Shadow_Stage_Begin(void) || r_shadow_lightattenuationscale.value != r_shadow_attenscale) R_Shadow_MakeTextures(); - R_Mesh_EndBatch(); - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; - R_Mesh_State(&m); + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(false); + GL_DepthTest(true); GL_Color(0, 0, 0, 1); + + memset(&m, 0, sizeof(m)); + R_Mesh_State_Texture(&m); + qglDisable(GL_SCISSOR_TEST); r_shadowstage = SHADOWSTAGE_NONE; @@ -556,20 +761,29 @@ void R_Shadow_LoadWorldLightsIfNeeded(void) void R_Shadow_Stage_ShadowVolumes(void) { rmeshstate_t m; - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); - R_Mesh_TextureState(&m); + R_Mesh_State_Texture(&m); + GL_Color(1, 1, 1, 1); + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(false); + GL_DepthTest(true); + + if (r_shadow_polygonoffset.value != 0) + { + qglPolygonOffset(1.0f, r_shadow_polygonoffset.value); + qglEnable(GL_POLYGON_OFFSET_FILL); + } + else + qglDisable(GL_POLYGON_OFFSET_FILL); qglColorMask(0, 0, 0, 0); - qglDisable(GL_BLEND); - qglDepthMask(0); qglDepthFunc(GL_LESS); qglEnable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglStencilFunc(GL_ALWAYS, 128, 0xFF); - qglEnable(GL_CULL_FACE); - qglEnable(GL_DEPTH_TEST); r_shadowstage = SHADOWSTAGE_STENCIL; + qglClear(GL_STENCIL_BUFFER_BIT); c_rt_clears++; // LordHavoc note: many shadow volumes reside entirely inside the world @@ -584,22 +798,24 @@ void R_Shadow_Stage_ShadowVolumes(void) void R_Shadow_Stage_LightWithoutShadows(void) { rmeshstate_t m; - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); - R_Mesh_TextureState(&m); - qglActiveTexture(GL_TEXTURE0_ARB); + R_Mesh_State_Texture(&m); - qglEnable(GL_BLEND); - qglBlendFunc(GL_ONE, GL_ONE); GL_Color(1, 1, 1, 1); + GL_BlendFunc(GL_ONE, GL_ONE); + GL_DepthMask(false); + GL_DepthTest(true); + qglDisable(GL_POLYGON_OFFSET_FILL); + + //GL_DepthTest(false); + qglColorMask(1, 1, 1, 1); - qglDepthMask(0); - qglDepthFunc(GL_EQUAL); + qglDepthFunc(GL_LEQUAL); qglDisable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglStencilFunc(GL_EQUAL, 128, 0xFF); - qglEnable(GL_CULL_FACE); - qglEnable(GL_DEPTH_TEST); + r_shadowstage = SHADOWSTAGE_LIGHT; c_rt_lights++; } @@ -607,24 +823,26 @@ void R_Shadow_Stage_LightWithoutShadows(void) void R_Shadow_Stage_LightWithShadows(void) { rmeshstate_t m; - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); - R_Mesh_TextureState(&m); - qglActiveTexture(GL_TEXTURE0_ARB); + R_Mesh_State_Texture(&m); - qglEnable(GL_BLEND); - qglBlendFunc(GL_ONE, GL_ONE); GL_Color(1, 1, 1, 1); + GL_BlendFunc(GL_ONE, GL_ONE); + GL_DepthMask(false); + GL_DepthTest(true); + qglDisable(GL_POLYGON_OFFSET_FILL); + + //GL_DepthTest(false); + qglColorMask(1, 1, 1, 1); - qglDepthMask(0); - qglDepthFunc(GL_EQUAL); + qglDepthFunc(GL_LEQUAL); qglEnable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // only draw light where this geometry was already rendered AND the // stencil is 128 (values other than this mean shadow) qglStencilFunc(GL_EQUAL, 128, 0xFF); - qglEnable(GL_CULL_FACE); - qglEnable(GL_DEPTH_TEST); + r_shadowstage = SHADOWSTAGE_LIGHT; c_rt_lights++; } @@ -632,29 +850,23 @@ void R_Shadow_Stage_LightWithShadows(void) void R_Shadow_Stage_End(void) { rmeshstate_t m; - //R_Mesh_EndBatch(); - // attempt to restore state to what Mesh_State thinks it is - qglDisable(GL_BLEND); - qglBlendFunc(GL_ONE, GL_ZERO); - qglDepthMask(1); - // now restore the rest of the state to normal + + memset(&m, 0, sizeof(m)); + R_Mesh_State_Texture(&m); + GL_Color(1, 1, 1, 1); + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); + GL_DepthTest(true); + qglDisable(GL_POLYGON_OFFSET_FILL); + qglColorMask(1, 1, 1, 1); qglDisable(GL_SCISSOR_TEST); qglDepthFunc(GL_LEQUAL); qglDisable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglStencilFunc(GL_ALWAYS, 128, 0xFF); - qglEnable(GL_CULL_FACE); - qglEnable(GL_DEPTH_TEST); - // force mesh state to reset by using various combinations of features - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - R_Mesh_State(&m); - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; - R_Mesh_State(&m); + r_shadowstage = SHADOWSTAGE_NONE; } @@ -672,14 +884,12 @@ int R_Shadow_ScissorForBBoxAndSphere(const float *mins, const float *maxs, const && r_origin[1] >= mins[1] && r_origin[1] <= maxs[1] && r_origin[2] >= mins[2] && r_origin[2] <= maxs[2]) { - //R_Mesh_EndBatch(); qglDisable(GL_SCISSOR_TEST); return false; } VectorSubtract(r_origin, origin, v); if (DotProduct(v, v) < radius * radius) { - //R_Mesh_EndBatch(); qglDisable(GL_SCISSOR_TEST); return false; } @@ -794,7 +1004,6 @@ int R_Shadow_ScissorForBBoxAndSphere(const float *mins, const float *maxs, const if (ix2 <= ix1 || iy2 <= iy1) return true; // set up the scissor rectangle - //R_Mesh_EndBatch(); qglScissor(ix1, iy1, ix2 - ix1, iy2 - iy1); qglEnable(GL_SCISSOR_TEST); c_rt_scissored++; @@ -815,7 +1024,6 @@ int R_Shadow_ScissorForBBox(const float *mins, const float *maxs) // (?!? seems like a driver bug) so abort if gl_stencil is false if (!gl_stencil || BoxesOverlap(r_origin, r_origin, mins, maxs)) { - //R_Mesh_EndBatch(); qglDisable(GL_SCISSOR_TEST); return false; } @@ -969,7 +1177,6 @@ int R_Shadow_ScissorForBBox(const float *mins, const float *maxs) if (ix2 <= ix1 || iy2 <= iy1) return true; // set up the scissor rectangle - //R_Mesh_EndBatch(); qglScissor(ix1, iy1, ix2 - ix1, iy2 - iy1); qglEnable(GL_SCISSOR_TEST); c_rt_scissored++; @@ -1101,11 +1308,12 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element int renders; float color[3], color2[3]; rmeshstate_t m; - memset(&m, 0, sizeof(m)); + GL_VertexPointer(vertex3f); if (gl_dot3arb && gl_texturecubemap && gl_combine.integer && gl_stencil) { if (!bumptexture) bumptexture = r_shadow_blankbumptexture; + GL_Color(1,1,1,1); // colorscale accounts for how much we multiply the brightness during combine // mult is how many times the final pass of the lighting will be // performed to get more brightness than otherwise possible @@ -1113,39 +1321,32 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element if (r_shadow_texture3d.integer && r_textureunits.integer >= 4) { // 3/2 3D combine path (Geforce3, Radeon 8500) - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(bumptexture); m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); m.tex3d[2] = R_GetTexture(r_shadow_attenuation3dtexture); m.texcombinergb[0] = GL_REPLACE; m.texcombinergb[1] = GL_DOT3_RGBA_ARB; - R_Mesh_TextureState(&m); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = varray_texcoord3f[1]; + m.pointer_texcoord[2] = varray_texcoord3f[2]; + R_Mesh_State_Texture(&m); qglColorMask(0,0,0,1); - qglDisable(GL_BLEND); - GL_Color(1,1,1,1); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + GL_BlendFunc(GL_ONE, GL_ZERO); R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[2], numverts, vertex3f, matrix_modeltoattenuationxyz); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(basetexture); - m.tex[1] = 0; m.texcubemap[1] = R_GetTexture(lightcubemap); - m.tex3d[2] = 0; - m.texcombinergb[0] = GL_MODULATE; - m.texcombinergb[1] = GL_MODULATE; - R_Mesh_TextureState(&m); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = lightcubemap ? varray_texcoord3f[1] : NULL; + R_Mesh_State_Texture(&m); qglColorMask(1,1,1,0); - qglBlendFunc(GL_DST_ALPHA, GL_ONE); - qglEnable(GL_BLEND); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + GL_BlendFunc(GL_DST_ALPHA, GL_ONE); if (lightcubemap) R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value, color2); @@ -1155,7 +1356,7 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element color[1] = bound(0, color2[1], 1); color[2] = bound(0, color2[2], 1); GL_Color(color[0], color[1], color[2], 1); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; } @@ -1163,47 +1364,39 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && lightcubemap) { // 1/2/2 3D combine path (original Radeon) - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture); - R_Mesh_TextureState(&m); + m.pointer_texcoord[0] = varray_texcoord3f[0]; + R_Mesh_State_Texture(&m); qglColorMask(0,0,0,1); - qglDisable(GL_BLEND); - GL_Color(1,1,1,1); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); + GL_BlendFunc(GL_ONE, GL_ZERO); R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0], numverts, vertex3f, matrix_modeltoattenuationxyz); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(bumptexture); - m.tex3d[0] = 0; m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); m.texcombinergb[0] = GL_REPLACE; m.texcombinergb[1] = GL_DOT3_RGBA_ARB; - R_Mesh_TextureState(&m); - qglBlendFunc(GL_DST_ALPHA, GL_ZERO); - qglEnable(GL_BLEND); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = varray_texcoord3f[1]; + R_Mesh_State_Texture(&m); + GL_BlendFunc(GL_DST_ALPHA, GL_ZERO); R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(basetexture); m.texcubemap[1] = R_GetTexture(lightcubemap); - m.texcombinergb[0] = GL_MODULATE; - m.texcombinergb[1] = GL_MODULATE; - R_Mesh_TextureState(&m); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = lightcubemap ? varray_texcoord3f[1] : NULL; + R_Mesh_State_Texture(&m); qglColorMask(1,1,1,0); - qglBlendFunc(GL_DST_ALPHA, GL_ONE); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + GL_BlendFunc(GL_DST_ALPHA, GL_ONE); if (lightcubemap) R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value, color2); @@ -1213,7 +1406,7 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element color[1] = bound(0, color2[1], 1); color[2] = bound(0, color2[2], 1); GL_Color(color[0], color[1], color[2], 1); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; } @@ -1221,37 +1414,29 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && !lightcubemap) { // 2/2 3D combine path (original Radeon) - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(bumptexture); m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); m.texcombinergb[0] = GL_REPLACE; m.texcombinergb[1] = GL_DOT3_RGBA_ARB; - R_Mesh_TextureState(&m); - GL_Color(1,1,1,1); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = varray_texcoord3f[1]; + R_Mesh_State_Texture(&m); qglColorMask(0,0,0,1); - qglDisable(GL_BLEND); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + GL_BlendFunc(GL_ONE, GL_ZERO); R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(basetexture); m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture); - m.texcubemap[1] = 0; - m.texcombinergb[0] = GL_MODULATE; - m.texcombinergb[1] = GL_MODULATE; - R_Mesh_TextureState(&m); - R_Mesh_GetSpace(numverts); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = varray_texcoord3f[1]; + R_Mesh_State_Texture(&m); qglColorMask(1,1,1,0); - qglBlendFunc(GL_DST_ALPHA, GL_ONE); - qglEnable(GL_BLEND); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + GL_BlendFunc(GL_DST_ALPHA, GL_ONE); R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltoattenuationxyz); VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value, color2); for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) @@ -1260,7 +1445,7 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element color[1] = bound(0, color2[1], 1); color[2] = bound(0, color2[2], 1); GL_Color(color[0], color[1], color[2], 1); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; } @@ -1268,41 +1453,35 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element else if (r_textureunits.integer >= 4) { // 4/2 2D combine path (Geforce3, Radeon 8500) - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(bumptexture); m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); m.texcombinergb[0] = GL_REPLACE; m.texcombinergb[1] = GL_DOT3_RGBA_ARB; m.tex[2] = R_GetTexture(r_shadow_attenuation2dtexture); m.tex[3] = R_GetTexture(r_shadow_attenuation2dtexture); - R_Mesh_TextureState(&m); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = varray_texcoord3f[1]; + m.pointer_texcoord[2] = varray_texcoord2f[2]; + m.pointer_texcoord[3] = varray_texcoord2f[3]; + R_Mesh_State_Texture(&m); qglColorMask(0,0,0,1); - qglDisable(GL_BLEND); - GL_Color(1,1,1,1); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + GL_BlendFunc(GL_ONE, GL_ZERO); R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[2], numverts, vertex3f, matrix_modeltoattenuationxyz); R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[3], numverts, vertex3f, matrix_modeltoattenuationz); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(basetexture); m.texcubemap[1] = R_GetTexture(lightcubemap); - m.texcombinergb[0] = GL_MODULATE; - m.texcombinergb[1] = GL_MODULATE; - m.tex[2] = 0; - m.tex[3] = 0; - R_Mesh_TextureState(&m); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = lightcubemap ? varray_texcoord3f[1] : NULL; + R_Mesh_State_Texture(&m); qglColorMask(1,1,1,0); - qglBlendFunc(GL_DST_ALPHA, GL_ONE); - qglEnable(GL_BLEND); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + GL_BlendFunc(GL_DST_ALPHA, GL_ONE); if (lightcubemap) R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value, color2); @@ -1312,7 +1491,7 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element color[1] = bound(0, color2[1], 1); color[2] = bound(0, color2[2], 1); GL_Color(color[0], color[1], color[2], 1); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; } @@ -1320,49 +1499,42 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element else { // 2/2/2 2D combine path (any dot3 card) - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture); m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture); - R_Mesh_TextureState(&m); + m.pointer_texcoord[0] = varray_texcoord2f[0]; + m.pointer_texcoord[1] = varray_texcoord2f[1]; + R_Mesh_State_Texture(&m); qglColorMask(0,0,0,1); - qglDisable(GL_BLEND); - GL_Color(1,1,1,1); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); + GL_BlendFunc(GL_ONE, GL_ZERO); R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[0], numverts, vertex3f, matrix_modeltoattenuationxyz); R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationz); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(bumptexture); - m.tex[1] = 0; m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); m.texcombinergb[0] = GL_REPLACE; m.texcombinergb[1] = GL_DOT3_RGBA_ARB; - R_Mesh_TextureState(&m); - qglBlendFunc(GL_DST_ALPHA, GL_ZERO); - qglEnable(GL_BLEND); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = varray_texcoord3f[1]; + R_Mesh_State_Texture(&m); + GL_BlendFunc(GL_DST_ALPHA, GL_ZERO); R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(basetexture); m.texcubemap[1] = R_GetTexture(lightcubemap); - m.texcombinergb[0] = GL_MODULATE; - m.texcombinergb[1] = GL_MODULATE; - R_Mesh_TextureState(&m); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = lightcubemap ? varray_texcoord3f[1] : NULL; + R_Mesh_State_Texture(&m); qglColorMask(1,1,1,0); - qglBlendFunc(GL_DST_ALPHA, GL_ONE); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + GL_BlendFunc(GL_DST_ALPHA, GL_ONE); if (lightcubemap) R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value, color2); @@ -1372,7 +1544,7 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element color[1] = bound(0, color2[1], 1); color[2] = bound(0, color2[2], 1); GL_Color(color[0], color[1], color[2], 1); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; } @@ -1380,70 +1552,34 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element } else { + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); + GL_DepthTest(true); + GL_ColorPointer(varray_color4f); + VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value, color2); + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(basetexture); + m.pointer_texcoord[0] = texcoord2f; if (r_textureunits.integer >= 2) { // voodoo2 - //R_Mesh_EndBatch(); -#if 1 - m.tex[0] = R_GetTexture(basetexture); - m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture); - R_Mesh_TextureState(&m); - qglBlendFunc(GL_SRC_ALPHA, GL_ONE); - qglEnable(GL_BLEND); -#else - m.tex[0] = R_GetTexture(basetexture); m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; - R_Mesh_State(&m); -#endif - VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value, color2); - for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) - { - color[0] = bound(0, color2[0], 1); - color[1] = bound(0, color2[1], 1); - color[2] = bound(0, color2[2], 1); - GL_UseColorArray(); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); - R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationxyz); - R_Shadow_VertexLightingWithXYAttenuationTexture(numverts, vertex3f, normal3f, color, matrix_modeltofilter); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - } + m.pointer_texcoord[1] = varray_texcoord2f[1]; + R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationxyz); } - else + R_Mesh_State_Texture(&m); + for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) { - // voodoo1 - //R_Mesh_EndBatch(); -#if 1 - m.tex[0] = R_GetTexture(basetexture); - R_Mesh_TextureState(&m); - qglBlendFunc(GL_SRC_ALPHA, GL_ONE); - qglEnable(GL_BLEND); -#else - m.tex[0] = R_GetTexture(basetexture); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; - R_Mesh_State(&m); -#endif - VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value, color2); - for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) - { - color[0] = bound(0, color2[0], 1); - color[1] = bound(0, color2[1], 1); - color[2] = bound(0, color2[2], 1); - GL_UseColorArray(); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + color[0] = bound(0, color2[0], 1); + color[1] = bound(0, color2[1], 1); + color[2] = bound(0, color2[2], 1); + if (r_textureunits.integer >= 2) + R_Shadow_VertexLightingWithXYAttenuationTexture(numverts, vertex3f, normal3f, color, matrix_modeltofilter); + else R_Shadow_VertexLighting(numverts, vertex3f, normal3f, color, matrix_modeltofilter); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - } + R_Mesh_Draw(numverts, numtriangles, elements); + c_rt_lightmeshes++; + c_rt_lighttris += numtriangles; } } } @@ -1455,75 +1591,65 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen rmeshstate_t m; if (!gl_dot3arb || !gl_texturecubemap || !gl_combine.integer || !gl_stencil) return; - memset(&m, 0, sizeof(m)); if (!bumptexture) bumptexture = r_shadow_blankbumptexture; if (!glosstexture) glosstexture = r_shadow_blankglosstexture; if (r_shadow_gloss.integer >= 2 || (r_shadow_gloss.integer >= 1 && glosstexture != r_shadow_blankglosstexture)) { + GL_VertexPointer(vertex3f); + GL_Color(1,1,1,1); if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && lightcubemap /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare! { // 2/0/0/1/2 3D combine blendsquare path - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(bumptexture); m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); m.texcombinergb[1] = GL_DOT3_RGBA_ARB; - R_Mesh_TextureState(&m); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = varray_texcoord3f[1]; + R_Mesh_State_Texture(&m); qglColorMask(0,0,0,1); // this squares the result - qglEnable(GL_BLEND); - qglBlendFunc(GL_SRC_ALPHA, GL_ZERO); - GL_Color(1,1,1,1); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO); R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); - m.tex[0] = 0; - m.texcubemap[1] = 0; - m.texcombinergb[1] = GL_MODULATE; - R_Mesh_TextureState(&m); + memset(&m, 0, sizeof(m)); + R_Mesh_State_Texture(&m); // square alpha in framebuffer a few times to make it shiny - qglBlendFunc(GL_ZERO, GL_DST_ALPHA); + GL_BlendFunc(GL_ZERO, GL_DST_ALPHA); // these comments are a test run through this math for intensity 0.5 // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier) // 0.25 * 0.25 = 0.0625 (this is another pass) // 0.0625 * 0.0625 = 0.00390625 (this is another pass) - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture); - R_Mesh_TextureState(&m); - qglBlendFunc(GL_DST_ALPHA, GL_ZERO); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); + m.pointer_texcoord[0] = varray_texcoord3f[0]; + R_Mesh_State_Texture(&m); + GL_BlendFunc(GL_DST_ALPHA, GL_ZERO); R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0], numverts, vertex3f, matrix_modeltoattenuationxyz); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); - m.tex3d[0] = 0; + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(glosstexture); m.texcubemap[1] = R_GetTexture(lightcubemap); - R_Mesh_TextureState(&m); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = lightcubemap ? varray_texcoord3f[1] : NULL; + R_Mesh_State_Texture(&m); qglColorMask(1,1,1,0); - qglBlendFunc(GL_DST_ALPHA, GL_ONE); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + GL_BlendFunc(GL_DST_ALPHA, GL_ONE); if (lightcubemap) R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value * 0.25f, color2); @@ -1533,7 +1659,7 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen color[1] = bound(0, color2[1], 1); color[2] = bound(0, color2[2], 1); GL_Color(color[0], color[1], color[2], 1); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; } @@ -1541,56 +1667,44 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && !lightcubemap /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare! { // 2/0/0/2 3D combine blendsquare path - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(bumptexture); m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); m.texcombinergb[1] = GL_DOT3_RGBA_ARB; - R_Mesh_TextureState(&m); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = varray_texcoord3f[1]; + R_Mesh_State_Texture(&m); qglColorMask(0,0,0,1); // this squares the result - qglEnable(GL_BLEND); - qglBlendFunc(GL_SRC_ALPHA, GL_ZERO); - GL_Color(1,1,1,1); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO); R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); - m.tex[0] = 0; - m.texcubemap[1] = 0; - m.texcombinergb[1] = GL_MODULATE; - R_Mesh_TextureState(&m); + memset(&m, 0, sizeof(m)); + R_Mesh_State_Texture(&m); // square alpha in framebuffer a few times to make it shiny - qglBlendFunc(GL_ZERO, GL_DST_ALPHA); + GL_BlendFunc(GL_ZERO, GL_DST_ALPHA); // these comments are a test run through this math for intensity 0.5 // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier) // 0.25 * 0.25 = 0.0625 (this is another pass) // 0.0625 * 0.0625 = 0.00390625 (this is another pass) - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(glosstexture); m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture); - R_Mesh_TextureState(&m); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = varray_texcoord3f[1]; + R_Mesh_State_Texture(&m); qglColorMask(1,1,1,0); - qglBlendFunc(GL_DST_ALPHA, GL_ONE); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + GL_BlendFunc(GL_DST_ALPHA, GL_ONE); R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltoattenuationxyz); VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value * 0.25f, color2); for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) @@ -1599,7 +1713,7 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen color[1] = bound(0, color2[1], 1); color[2] = bound(0, color2[2], 1); GL_Color(color[0], color[1], color[2], 1); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; } @@ -1607,66 +1721,57 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen else if (r_textureunits.integer >= 2 /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare! { // 2/0/0/2/2 2D combine blendsquare path - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(bumptexture); m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); m.texcombinergb[1] = GL_DOT3_RGBA_ARB; - R_Mesh_TextureState(&m); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = varray_texcoord3f[1]; + R_Mesh_State_Texture(&m); qglColorMask(0,0,0,1); // this squares the result - qglEnable(GL_BLEND); - qglBlendFunc(GL_SRC_ALPHA, GL_ZERO); - GL_Color(1,1,1,1); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO); R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); - m.tex[0] = 0; - m.texcubemap[1] = 0; - m.texcombinergb[1] = GL_MODULATE; - R_Mesh_TextureState(&m); + memset(&m, 0, sizeof(m)); + R_Mesh_State_Texture(&m); // square alpha in framebuffer a few times to make it shiny - qglBlendFunc(GL_ZERO, GL_DST_ALPHA); + GL_BlendFunc(GL_ZERO, GL_DST_ALPHA); // these comments are a test run through this math for intensity 0.5 // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier) // 0.25 * 0.25 = 0.0625 (this is another pass) // 0.0625 * 0.0625 = 0.00390625 (this is another pass) - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture); m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture); - R_Mesh_TextureState(&m); - qglBlendFunc(GL_DST_ALPHA, GL_ZERO); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); + m.pointer_texcoord[0] = varray_texcoord2f[0]; + m.pointer_texcoord[1] = varray_texcoord2f[1]; + R_Mesh_State_Texture(&m); + GL_BlendFunc(GL_DST_ALPHA, GL_ZERO); R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[0], numverts, vertex3f, matrix_modeltoattenuationxyz); R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationz); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - //R_Mesh_EndBatch(); + memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(glosstexture); m.texcubemap[1] = R_GetTexture(lightcubemap); - R_Mesh_TextureState(&m); + m.pointer_texcoord[0] = texcoord2f; + m.pointer_texcoord[1] = lightcubemap ? varray_texcoord3f[1] : NULL; + R_Mesh_State_Texture(&m); qglColorMask(1,1,1,0); - qglBlendFunc(GL_DST_ALPHA, GL_ONE); - R_Mesh_GetSpace(numverts); - R_Mesh_CopyVertex3f(vertex3f, numverts); - R_Mesh_CopyTexCoord2f(0, texcoord2f, numverts); + GL_BlendFunc(GL_DST_ALPHA, GL_ONE); if (lightcubemap) R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value * 0.25f, color2); @@ -1676,7 +1781,7 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen color[1] = bound(0, color2[1], 1); color[2] = bound(0, color2[2], 1); GL_Color(color[0], color[1], color[2], 1); - R_Mesh_Draw_NoBatching(numverts, numtriangles, elements); + R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; } @@ -1852,13 +1957,12 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style for (j = 0;j < e->numsurfaces;j++) if (e->surfaces[j]->castshadow == castshadowcount) for (surfmesh = e->surfaces[j]->mesh;surfmesh;surfmesh = surfmesh->chain) - Mod_ShadowMesh_AddMesh(r_shadow_mempool, castmesh, surfmesh->numverts, surfmesh->vertex3f, surfmesh->numtriangles, surfmesh->element3i); + Mod_ShadowMesh_AddMesh(r_shadow_mempool, castmesh, surfmesh->vertex3f, surfmesh->numtriangles, surfmesh->element3i); castmesh = Mod_ShadowMesh_Finish(r_shadow_mempool, castmesh); // cast shadow volume from castmesh for (mesh = castmesh;mesh;mesh = mesh->next) { - R_Shadow_ResizeTriangleFacingLight(castmesh->numtriangles); R_Shadow_ResizeShadowElements(castmesh->numtriangles); if (maxverts < castmesh->numverts * 2) @@ -1871,12 +1975,10 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style if (vertex3f == NULL && maxverts > 0) vertex3f = Mem_Alloc(r_shadow_mempool, maxverts * sizeof(float[3])); - // now that we have the buffers big enough, construct shadow volume mesh - memcpy(vertex3f, castmesh->vertex3f, castmesh->numverts * sizeof(float[3])); - tris = R_Shadow_MakeTriangleShadowFlags_Vertex3f(castmesh->element3i, vertex3f, castmesh->numtriangles, trianglefacinglight, trianglefacinglightlist, e->origin); - tris = R_Shadow_BuildShadowVolume(castmesh->element3i, castmesh->neighbor3i, castmesh->numverts, trianglefacinglight, trianglefacinglightlist, tris, shadowelements, vertex3f, e->origin, r_shadow_projectdistance.value); - // add the constructed shadow volume mesh - Mod_ShadowMesh_AddMesh(r_shadow_mempool, e->shadowvolume, castmesh->numverts, vertex3f, tris, shadowelements); + // now that we have the buffers big enough, construct and add + // the shadow volume mesh + if ((tris = R_Shadow_ConstructShadowVolume(castmesh->numverts, 0, castmesh->numtriangles, castmesh->element3i, castmesh->neighbor3i, castmesh->vertex3f, NULL, shadowelements, vertex3f, e->origin, r_shadow_projectdistance.value))) + Mod_ShadowMesh_AddMesh(r_shadow_mempool, e->shadowvolume, vertex3f, tris, shadowelements); } if (vertex3f) Mem_Free(vertex3f); @@ -1926,35 +2028,12 @@ void R_Shadow_SelectLight(worldlight_t *light) r_shadow_selectedlight->selected = true; } - -void R_DrawLightSprite(int texnum, const vec3_t origin, vec_t scale, float cr, float cg, float cb, float ca) -{ - rmeshstate_t m; - float diff[3]; - - if (fogenabled) - { - VectorSubtract(origin, r_origin, diff); - ca *= 1 - exp(fogdensity/DotProduct(diff,diff)); - } - - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; - m.tex[0] = texnum; - R_Mesh_Matrix(&r_identitymatrix); - R_Mesh_State(&m); - - GL_Color(cr * r_colorscale, cg * r_colorscale, cb * r_colorscale, ca); - R_DrawSpriteMesh(origin, vright, vup, scale, -scale, -scale, scale); -} +rtexture_t *lighttextures[5]; void R_Shadow_DrawCursorCallback(const void *calldata1, int calldata2) { - cachepic_t *pic; - pic = Draw_CachePic("gfx/crosshair1.tga"); - if (pic) - R_DrawLightSprite(R_GetTexture(pic->tex), r_editlights_cursorlocation, r_editlights_cursorgrid.value * 0.5f, 1, 1, 1, 0.5); + float scale = r_editlights_cursorgrid.value * 0.5f; + R_DrawSprite(GL_SRC_ALPHA, GL_ONE, lighttextures[0], false, r_editlights_cursorlocation, vright, vup, scale, -scale, -scale, scale, 1, 1, 1, 0.5f); } void R_Shadow_DrawLightSpriteCallback(const void *calldata1, int calldata2) @@ -1965,29 +2044,26 @@ void R_Shadow_DrawLightSpriteCallback(const void *calldata1, int calldata2) intensity = 0.5; if (light->selected) intensity = 0.75 + 0.25 * sin(realtime * M_PI * 4.0); - if (light->shadowvolume) - R_DrawLightSprite(calldata2, light->origin, 8, intensity, intensity, intensity, 0.5); - else - R_DrawLightSprite(calldata2, light->origin, 8, intensity * 0.5, intensity * 0.5, intensity * 0.5, 0.5); + if (!light->shadowvolume) + intensity *= 0.5f; + R_DrawSprite(GL_SRC_ALPHA, GL_ONE, lighttextures[calldata2], false, light->origin, vright, vup, 8, -8, -8, 8, intensity, intensity, intensity, 0.5); } void R_Shadow_DrawLightSprites(void) { - int i, texnums[5]; + int i; cachepic_t *pic; worldlight_t *light; for (i = 0;i < 5;i++) { - pic = Draw_CachePic(va("gfx/crosshair%i.tga", i + 1)); - if (pic) - texnums[i] = R_GetTexture(pic->tex); - else - texnums[i] = 0; + lighttextures[i] = NULL; + if ((pic = Draw_CachePic(va("gfx/crosshair%i.tga", i + 1)))) + lighttextures[i] = pic->tex; } for (light = r_shadow_worldlightchain;light;light = light->next) - R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSpriteCallback, light, texnums[((int) light) % 5]); + R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSpriteCallback, light, ((int) light) % 5); R_MeshQueue_AddTransparent(r_editlights_cursorlocation, R_Shadow_DrawCursorCallback, NULL, 0); } diff --git a/r_shadow.h b/r_shadow.h index d6f13244..20a3f360 100644 --- a/r_shadow.h +++ b/r_shadow.h @@ -13,7 +13,7 @@ extern cvar_t r_shadow_bumpscale_bumpmap; extern cvar_t r_shadow_bumpscale_basetexture; void R_Shadow_Init(void); -void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float lightradius, float projectdistance); +void R_Shadow_Volume(int numverts, int numtris, const float *invertex3f, int *elements, int *neighbors, vec3_t relativelightorigin, float lightradius, float projectdistance); void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *elements, const float *vertices, const float *svectors, const float *tvectors, const float *normals, const float *texcoords, const float *relativelightorigin, float lightradius, const float *lightcolor, const matrix4x4_t *matrix_worldtofilter, const matrix4x4_t *matrix_worldtoattenuationxyz, const matrix4x4_t *matrix_worldtoattenuationz, rtexture_t *basetexture, rtexture_t *bumptexture, rtexture_t *lightcubemap); void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elements, const float *vertices, const float *svectors, const float *tvectors, const float *normals, const float *texcoords, const float *relativelightorigin, const float *relativeeyeorigin, float lightradius, const float *lightcolor, const matrix4x4_t *matrix_worldtofilter, const matrix4x4_t *matrix_worldtoattenuationxyz, const matrix4x4_t *matrix_worldtoattenuationz, rtexture_t *glosstexture, rtexture_t *bumptexture, rtexture_t *lightcubemap); void R_Shadow_ClearStencil(void); diff --git a/r_sky.c b/r_sky.c index 68be51fa..78241767 100644 --- a/r_sky.c +++ b/r_sky.c @@ -116,77 +116,113 @@ void LoadSky_f (void) } } +float skyboxvertex3f[6*4*3] = +{ + // skyside[0] + 16, 16, 16, + 16, 16, -16, + -16, 16, -16, + -16, 16, 16, + // skyside[1] + -16, 16, 16, + -16, 16, -16, + -16, -16, -16, + -16, -16, 16, + // skyside[2] + -16, -16, 16, + -16, -16, -16, + 16, -16, -16, + 16, -16, 16, + // skyside[3] + 16, -16, 16, + 16, -16, -16, + 16, 16, -16, + 16, 16, 16, + // skyside[4] + 16, -16, 16, + 16, 16, 16, + -16, 16, 16, + -16, -16, 16, + // skyside[5] + 16, 16, -16, + 16, -16, -16, + -16, -16, -16, + -16, 16, -16 +}; + +float skyboxtexcoord2f[6*4*2] = +{ + // skyside[0] + 1, 0, + 1, 1, + 0, 1, + 0, 0, + // skyside[1] + 1, 0, + 1, 1, + 0, 1, + 0, 0, + // skyside[2] + 1, 0, + 1, 1, + 0, 1, + 0, 0, + // skyside[3] + 1, 0, + 1, 1, + 0, 1, + 0, 0, + // skyside[4] + 1, 0, + 1, 1, + 0, 1, + 0, 0, + // skyside[5] + 1, 0, + 1, 1, + 0, 1, + 0, 0 +}; + +int skyboxelements[6*2*3] = +{ + // skyside[0] + 8, 9, 10, + 8, 10, 11, + // skyside[1] + 4, 5, 6, + 4, 6, 7, + // skyside[2] + 12, 13, 14, + 12, 14, 15, + // skyside[3] + 0, 1, 2, + 0, 2, 3, + // skyside[4] + 16, 17, 18, + 16, 18, 19, + // skyside[5] + 20, 21, 22, + 20, 22, 23 +}; + static void R_SkyBox(void) { + int i; rmeshstate_t m; - -#define R_SkyBoxPolyVec(i,s,t,x,y,z) \ - varray_vertex3f[i * 3 + 0] = (x) * 16.0f;\ - varray_vertex3f[i * 3 + 1] = (y) * 16.0f;\ - varray_vertex3f[i * 3 + 2] = (z) * 16.0f;\ - varray_texcoord2f[0][i * 2 + 0] = (s);\ - varray_texcoord2f[0][i * 2 + 1] = (t); - GL_Color(r_colorscale, r_colorscale, r_colorscale, 1); - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; - m.depthdisable = true; // don't modify or read zbuffer - - m.tex[0] = R_GetTexture(skyboxside[3]); // front - R_Mesh_State(&m); - R_Mesh_GetSpace(4); - R_SkyBoxPolyVec(0, 1, 0, 1, -1, 1); - R_SkyBoxPolyVec(1, 1, 1, 1, -1, -1); - R_SkyBoxPolyVec(2, 0, 1, 1, 1, -1); - R_SkyBoxPolyVec(3, 0, 0, 1, 1, 1); - R_Mesh_Draw(4, 2, polygonelements); - - m.tex[0] = R_GetTexture(skyboxside[1]); // back - R_Mesh_TextureState(&m); - R_Mesh_GetSpace(4); - R_SkyBoxPolyVec(0, 1, 0, -1, 1, 1); - R_SkyBoxPolyVec(1, 1, 1, -1, 1, -1); - R_SkyBoxPolyVec(2, 0, 1, -1, -1, -1); - R_SkyBoxPolyVec(3, 0, 0, -1, -1, 1); - R_Mesh_Draw(4, 2, polygonelements); - - m.tex[0] = R_GetTexture(skyboxside[0]); // right - R_Mesh_TextureState(&m); - R_Mesh_GetSpace(4); - R_SkyBoxPolyVec(0, 1, 0, 1, 1, 1); - R_SkyBoxPolyVec(1, 1, 1, 1, 1, -1); - R_SkyBoxPolyVec(2, 0, 1, -1, 1, -1); - R_SkyBoxPolyVec(3, 0, 0, -1, 1, 1); - R_Mesh_Draw(4, 2, polygonelements); - - m.tex[0] = R_GetTexture(skyboxside[2]); // left - R_Mesh_TextureState(&m); - R_Mesh_GetSpace(4); - R_SkyBoxPolyVec(0, 1, 0, -1, -1, 1); - R_SkyBoxPolyVec(1, 1, 1, -1, -1, -1); - R_SkyBoxPolyVec(2, 0, 1, 1, -1, -1); - R_SkyBoxPolyVec(3, 0, 0, 1, -1, 1); - R_Mesh_Draw(4, 2, polygonelements); - - m.tex[0] = R_GetTexture(skyboxside[4]); // up - R_Mesh_TextureState(&m); - R_Mesh_GetSpace(4); - R_SkyBoxPolyVec(0, 1, 0, 1, -1, 1); - R_SkyBoxPolyVec(1, 1, 1, 1, 1, 1); - R_SkyBoxPolyVec(2, 0, 1, -1, 1, 1); - R_SkyBoxPolyVec(3, 0, 0, -1, -1, 1); - R_Mesh_Draw(4, 2, polygonelements); - - m.tex[0] = R_GetTexture(skyboxside[5]); // down - R_Mesh_TextureState(&m); - R_Mesh_GetSpace(4); - R_SkyBoxPolyVec(0, 1, 0, 1, 1, -1); - R_SkyBoxPolyVec(1, 1, 1, 1, -1, -1); - R_SkyBoxPolyVec(2, 0, 1, -1, -1, -1); - R_SkyBoxPolyVec(3, 0, 0, -1, 1, -1); - R_Mesh_Draw(4, 2, polygonelements); + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); + GL_DepthTest(false); // don't modify or read zbuffer + GL_VertexPointer(skyboxvertex3f); + m.pointer_texcoord[0] = skyboxtexcoord2f; + for (i = 0;i < 6;i++) + { + m.tex[0] = R_GetTexture(skyboxside[i]); + R_Mesh_State_Texture(&m); + R_Mesh_Draw(4, 2, skyboxelements + i * 6); + } } #define skygridx 32 @@ -253,7 +289,7 @@ static void R_SkySphere(void) float speedscale; static qboolean skysphereinitialized = false; rmeshstate_t m; - rcachearrayrequest_t request; + matrix4x4_t scroll1matrix, scroll2matrix, identitymatrix; if (!skysphereinitialized) { skysphereinitialized = true; @@ -265,105 +301,46 @@ static void R_SkySphere(void) // wrap the scroll just to be extra kind to float accuracy speedscale -= (int)speedscale; + // scroll the lower cloud layer twice as fast (just like quake did) + Matrix4x4_CreateTranslate(&scroll1matrix, speedscale, speedscale, 0); + Matrix4x4_CreateTranslate(&scroll2matrix, speedscale * 2, speedscale * 2, 0); + Matrix4x4_CreateIdentity(&identitymatrix); + + GL_VertexPointer(skysphere_vertex3f); + GL_Color(r_colorscale, r_colorscale, r_colorscale, 1); + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); + GL_DepthTest(false); // don't modify or read zbuffer + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(solidskytexture); + m.pointer_texcoord[0] = skysphere_texcoord2f; + R_Mesh_TextureMatrix(0, &scroll1matrix); if (r_colorscale == 1 && r_textureunits.integer >= 2) { // one pass using GL_DECAL or GL_INTERPOLATE_ARB for alpha layer // LordHavoc: note that color is not set here because it does not // matter with GL_REPLACE - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; - m.depthdisable = true; // don't modify or read zbuffer - m.tex[0] = R_GetTexture(solidskytexture); m.tex[1] = R_GetTexture(alphaskytexture); - m.texcombinergb[0] = GL_REPLACE; m.texcombinergb[1] = gl_combine.integer ? GL_INTERPOLATE_ARB : GL_DECAL; - if (gl_mesh_copyarrays.integer) - { - R_Mesh_State(&m); - R_Mesh_GetSpace(skysphere_numverts); - R_Mesh_CopyVertex3f(skysphere_vertex3f, skysphere_numverts); - R_ScrollTexCoord2f(varray_texcoord2f[0], skysphere_texcoord2f, skysphere_numverts, speedscale, speedscale); - R_ScrollTexCoord2f(varray_texcoord2f[1], skysphere_texcoord2f, skysphere_numverts, speedscale*2, speedscale*2); - } - else - { - m.pointervertexcount = skysphere_numverts; - m.pointer_vertex = skysphere_vertex3f; - memset(&request, 0, sizeof(request)); - request.data_size = skysphere_numverts * sizeof(float[2]); - request.id_pointer1 = skysphere_texcoord2f; - request.id_number1 = CRC_Block((void *)&speedscale, sizeof(speedscale)); - if (R_Mesh_CacheArray(&request)) - R_ScrollTexCoord2f(request.data, skysphere_texcoord2f, skysphere_numverts, speedscale, speedscale); - m.pointer_texcoord[0] = request.data; - speedscale *= 2; - request.id_number1 = CRC_Block((void *)&speedscale, sizeof(speedscale)); - if (R_Mesh_CacheArray(&request)) - R_ScrollTexCoord2f(request.data, skysphere_texcoord2f, skysphere_numverts, speedscale, speedscale); - m.pointer_texcoord[1] = request.data; - R_Mesh_State(&m); - } + m.pointer_texcoord[1] = skysphere_texcoord2f; + R_Mesh_State_Texture(&m); + R_Mesh_TextureMatrix(1, &scroll2matrix); R_Mesh_Draw(skysphere_numverts, skysphere_numtriangles, skysphere_element3i); + R_Mesh_TextureMatrix(1, &identitymatrix); } else { // two pass - GL_Color(r_colorscale, r_colorscale, r_colorscale, 1); - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; - m.depthdisable = true; // don't modify or read zbuffer - m.tex[0] = R_GetTexture(solidskytexture); - if (gl_mesh_copyarrays.integer) - { - R_Mesh_State(&m); - R_Mesh_GetSpace(skysphere_numverts); - R_Mesh_CopyVertex3f(skysphere_vertex3f, skysphere_numverts); - R_ScrollTexCoord2f(varray_texcoord2f[0], skysphere_texcoord2f, skysphere_numverts, speedscale, speedscale); - } - else - { - m.pointervertexcount = skysphere_numverts; - m.pointer_vertex = skysphere_vertex3f; - memset(&request, 0, sizeof(request)); - request.data_size = skysphere_numverts * sizeof(float[2]); - request.id_pointer1 = skysphere_texcoord2f; - request.id_number1 = CRC_Block((void *)&speedscale, sizeof(speedscale)); - if (R_Mesh_CacheArray(&request)) - R_ScrollTexCoord2f(request.data, skysphere_texcoord2f, skysphere_numverts, speedscale, speedscale); - m.pointer_texcoord[0] = request.data; - R_Mesh_State(&m); - } + R_Mesh_State_Texture(&m); R_Mesh_Draw(skysphere_numverts, skysphere_numtriangles, skysphere_element3i); - // scroll the lower cloud layer twice as fast (just like quake did) - speedscale *= 2; - - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); m.tex[0] = R_GetTexture(alphaskytexture); - if (gl_mesh_copyarrays.integer) - { - R_Mesh_State(&m); - R_Mesh_GetSpace(skysphere_numverts); - R_Mesh_CopyVertex3f(skysphere_vertex3f, skysphere_numverts); - R_ScrollTexCoord2f(varray_texcoord2f[0], skysphere_texcoord2f, skysphere_numverts, speedscale, speedscale); - } - else - { - m.pointervertexcount = skysphere_numverts; - m.pointer_vertex = skysphere_vertex3f; - request.data_size = skysphere_numverts * sizeof(float[2]); - request.id_pointer1 = skysphere_texcoord2f; - request.id_number1 = CRC_Block((void *)&speedscale, sizeof(speedscale)); - if (R_Mesh_CacheArray(&request)) - R_ScrollTexCoord2f(request.data, skysphere_texcoord2f, skysphere_numverts, speedscale, speedscale); - m.pointer_texcoord[0] = request.data; - R_Mesh_State(&m); - } + R_Mesh_State_Texture(&m); + R_Mesh_TextureMatrix(0, &scroll2matrix); R_Mesh_Draw(skysphere_numverts, skysphere_numtriangles, skysphere_element3i); } + R_Mesh_TextureMatrix(0, &identitymatrix); } void R_Sky(void) @@ -389,7 +366,6 @@ void R_Sky(void) // this modifies the depth buffer so we have to clear it afterward //R_SkyRoom(); // clear the depthbuffer that was used while rendering the skyroom - //R_Mesh_EndBatch(); //qglClear(GL_DEPTH_BUFFER_BIT); } */ @@ -515,3 +491,4 @@ void R_Sky_Init(void) Cvar_RegisterVariable (&r_sky); R_RegisterModule("R_Sky", r_sky_start, r_sky_shutdown, r_sky_newmap); } + diff --git a/r_sprites.c b/r_sprites.c index d839057b..47e9fb20 100644 --- a/r_sprites.c +++ b/r_sprites.c @@ -78,20 +78,10 @@ static int R_SpriteSetup (const entity_render_t *ent, int type, float org[3], fl return false; } -static void R_DrawSpriteImage (int additive, mspriteframe_t *frame, int texture, vec3_t origin, vec3_t up, vec3_t left, float red, float green, float blue, float alpha) +static void R_DrawSpriteImage (int additive, mspriteframe_t *frame, rtexture_t *texture, vec3_t origin, vec3_t up, vec3_t left, float red, float green, float blue, float alpha) { - rmeshstate_t m; - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - if (additive) - m.blendfunc2 = GL_ONE; - m.tex[0] = texture; - R_Mesh_State(&m); - - GL_Color(red * r_colorscale, green * r_colorscale, blue * r_colorscale, alpha); // FIXME: negate left and right in loader - R_DrawSpriteMesh(origin, left, up, frame->left, frame->right, frame->down, frame->up); + R_DrawSprite(GL_SRC_ALPHA, additive ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, texture, false, origin, left, up, frame->left, frame->right, frame->down, frame->up, red, green, blue, alpha); } void R_DrawSpriteModelCallback(const void *calldata1, int calldata2) @@ -131,9 +121,9 @@ void R_DrawSpriteModelCallback(const void *calldata1, int calldata2) if (ent->frameblend[i].lerp >= 0.01f) { frame = ent->model->sprdata_frames + ent->frameblend[i].frame; - R_DrawSpriteImage((ent->effects & EF_ADDITIVE) || (ent->model->flags & EF_ADDITIVE), frame, R_GetTexture(frame->texture), org, up, left, color[0] * ifog, color[1] * ifog, color[2] * ifog, ent->alpha * ent->frameblend[i].lerp); + R_DrawSpriteImage((ent->effects & EF_ADDITIVE) || (ent->model->flags & EF_ADDITIVE), frame, frame->texture, org, up, left, color[0] * ifog, color[1] * ifog, color[2] * ifog, ent->alpha * ent->frameblend[i].lerp); if (fog * ent->frameblend[i].lerp >= 0.01f) - R_DrawSpriteImage(true, frame, R_GetTexture(frame->fogtexture), org, up, left, fogcolor[0],fogcolor[1],fogcolor[2], fog * ent->alpha * ent->frameblend[i].lerp); + R_DrawSpriteImage(true, frame, frame->fogtexture, org, up, left, fogcolor[0],fogcolor[1],fogcolor[2], fog * ent->alpha * ent->frameblend[i].lerp); } } #else @@ -142,9 +132,9 @@ void R_DrawSpriteModelCallback(const void *calldata1, int calldata2) for (i = 0;i < 4 && ent->frameblend[i].lerp;i++) frame = ent->model->sprdata_frames + ent->frameblend[i].frame; - R_DrawSpriteImage((ent->effects & EF_ADDITIVE) || (ent->model->flags & EF_ADDITIVE), frame, R_GetTexture(frame->texture), org, up, left, color[0] * ifog, color[1] * ifog, color[2] * ifog, ent->alpha); + R_DrawSpriteImage((ent->effects & EF_ADDITIVE) || (ent->model->flags & EF_ADDITIVE), frame, frame->texture, org, up, left, color[0] * ifog, color[1] * ifog, color[2] * ifog, ent->alpha); if (fog * ent->frameblend[i].lerp >= 0.01f) - R_DrawSpriteImage(true, frame, R_GetTexture(frame->fogtexture), org, up, left, fogcolor[0],fogcolor[1],fogcolor[2], fog * ent->alpha); + R_DrawSpriteImage(true, frame, frame->fogtexture, org, up, left, fogcolor[0],fogcolor[1],fogcolor[2], fog * ent->alpha); #endif } diff --git a/render.h b/render.h index 982760b3..5e84178a 100644 --- a/render.h +++ b/render.h @@ -161,13 +161,13 @@ void R_TimeReport_Start(void); void R_TimeReport_End(void); // r_stain -void R_Stain (const vec3_t origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2); +void R_Stain(const vec3_t origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2); void R_DrawWorldCrosshair(void); void R_Draw2DCrosshair(void); -void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width); -void R_DrawSpriteMesh(const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2); +void R_CalcBeam_Vertex3f(float *vert, const vec3_t org1, const vec3_t org2, float width); +void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca); #endif diff --git a/vid_shared.c b/vid_shared.c index 8f337264..044995fc 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -94,7 +94,8 @@ const char *gl_platformextensions; char gl_driver[256]; // GL_ARB_multitexture -//void (GLAPIENTRY *qglMultiTexCoord2f) (GLenum, GLfloat, GLfloat); +void (GLAPIENTRY *qglMultiTexCoord2f) (GLenum, GLfloat, GLfloat); +void (GLAPIENTRY *qglMultiTexCoord3f) (GLenum, GLfloat, GLfloat, GLfloat); void (GLAPIENTRY *qglActiveTexture) (GLenum); void (GLAPIENTRY *qglClientActiveTexture) (GLenum); @@ -122,7 +123,7 @@ void (GLAPIENTRY *qglCullFace)(GLenum mode); //void (GLAPIENTRY *qglReadBuffer)(GLenum mode); void (GLAPIENTRY *qglEnable)(GLenum cap); void (GLAPIENTRY *qglDisable)(GLenum cap); -//GLboolean GLAPIENTRY *qglIsEnabled)(GLenum cap); +GLboolean (GLAPIENTRY *qglIsEnabled)(GLenum cap); void (GLAPIENTRY *qglEnableClientState)(GLenum cap); void (GLAPIENTRY *qglDisableClientState)(GLenum cap); @@ -140,23 +141,25 @@ void (GLAPIENTRY *qglFlush)(void); void (GLAPIENTRY *qglClearDepth)(GLclampd depth); void (GLAPIENTRY *qglDepthFunc)(GLenum func); void (GLAPIENTRY *qglDepthMask)(GLboolean flag); -//void (GLAPIENTRY *qglDepthRange)(GLclampd near_val, GLclampd far_val); +void (GLAPIENTRY *qglDepthRange)(GLclampd near_val, GLclampd far_val); void (GLAPIENTRY *qglColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); 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 *qglVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -//void (GLAPIENTRY *qglNormalPointer)(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 *qglArrayElement)(GLint i); void (GLAPIENTRY *qglColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -//void (GLAPIENTRY *qglTexCoord2f)(GLfloat s, GLfloat t); -//void (GLAPIENTRY *qglVertex2f)(GLfloat x, GLfloat y); -//void (GLAPIENTRY *qglVertex3f)(GLfloat x, GLfloat y, GLfloat z); -//void (GLAPIENTRY *qglBegin)(GLenum mode); -//void (GLAPIENTRY *qglEnd)(void); +void (GLAPIENTRY *qglTexCoord2f)(GLfloat s, GLfloat t); +void (GLAPIENTRY *qglTexCoord2f)(GLfloat s, GLfloat t); +void (GLAPIENTRY *qglTexCoord3f)(GLfloat s, GLfloat t, GLfloat r); +void (GLAPIENTRY *qglVertex2f)(GLfloat x, GLfloat y); +void (GLAPIENTRY *qglVertex3f)(GLfloat x, GLfloat y, GLfloat z); +void (GLAPIENTRY *qglBegin)(GLenum mode); +void (GLAPIENTRY *qglEnd)(void); void (GLAPIENTRY *qglMatrixMode)(GLenum mode); void (GLAPIENTRY *qglOrtho)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val); @@ -272,7 +275,7 @@ static dllfunction_t opengl110funcs[] = // {"glReadBuffer", (void **) &qglReadBuffer}, {"glEnable", (void **) &qglEnable}, {"glDisable", (void **) &qglDisable}, -// {"glIsEnabled", (void **) &qglIsEnabled}, + {"glIsEnabled", (void **) &qglIsEnabled}, {"glEnableClientState", (void **) &qglEnableClientState}, {"glDisableClientState", (void **) &qglDisableClientState}, // {"glGetBooleanv", (void **) &qglGetBooleanv}, @@ -286,20 +289,21 @@ static dllfunction_t opengl110funcs[] = {"glClearDepth", (void **) &qglClearDepth}, {"glDepthFunc", (void **) &qglDepthFunc}, {"glDepthMask", (void **) &qglDepthMask}, -// {"glDepthRange", (void **) &qglDepthRange}, + {"glDepthRange", (void **) &qglDepthRange}, {"glDrawElements", (void **) &qglDrawElements}, {"glColorMask", (void **) &qglColorMask}, {"glVertexPointer", (void **) &qglVertexPointer}, -// {"glNormalPointer", (void **) &qglNormalPointer}, + {"glNormalPointer", (void **) &qglNormalPointer}, {"glColorPointer", (void **) &qglColorPointer}, {"glTexCoordPointer", (void **) &qglTexCoordPointer}, -// {"glArrayElement", (void **) &qglArrayElement}, + {"glArrayElement", (void **) &qglArrayElement}, {"glColor4f", (void **) &qglColor4f}, -// {"glTexCoord2f", (void **) &qglTexCoord2f}, -// {"glVertex2f", (void **) &qglVertex2f}, -// {"glVertex3f", (void **) &qglVertex3f}, -// {"glBegin", (void **) &qglBegin}, -// {"glEnd", (void **) &qglEnd}, + {"glTexCoord2f", (void **) &qglTexCoord2f}, + {"glTexCoord3f", (void **) &qglTexCoord3f}, + {"glVertex2f", (void **) &qglVertex2f}, + {"glVertex3f", (void **) &qglVertex3f}, + {"glBegin", (void **) &qglBegin}, + {"glEnd", (void **) &qglEnd}, {"glMatrixMode", (void **) &qglMatrixMode}, {"glOrtho", (void **) &qglOrtho}, {"glFrustum", (void **) &qglFrustum}, @@ -362,7 +366,8 @@ static dllfunction_t drawrangeelementsextfuncs[] = static dllfunction_t multitexturefuncs[] = { - //{"glMultiTexCoord2fARB", (void **) &qglMultiTexCoord2f}, + {"glMultiTexCoord2fARB", (void **) &qglMultiTexCoord2f}, + {"glMultiTexCoord3fARB", (void **) &qglMultiTexCoord3f}, {"glActiveTextureARB", (void **) &qglActiveTexture}, {"glClientActiveTextureARB", (void **) &qglClientActiveTexture}, {NULL, NULL}