From c029ea2df24cda86997a115d58a2416ca4a13a82 Mon Sep 17 00:00:00 2001 From: Victor Luchits Date: Fri, 25 Apr 2014 23:06:03 +0400 Subject: [PATCH] Pack lightmap coordinates into two vertex attributes --- glsl/defaultMaterial.glsl | 37 ++++---- glsl/defaultQ3AShader.glsl | 27 +++--- glsl/include/attributes.glsl | 11 ++- source/ref_gl/r_backend.c | 35 ++++---- source/ref_gl/r_local.h | 3 +- source/ref_gl/r_program.c | 22 +++-- source/ref_gl/r_vattribs.h | 12 ++- source/ref_gl/r_vbo.c | 163 ++++++++++++++++++++++++++--------- 8 files changed, 192 insertions(+), 118 deletions(-) diff --git a/glsl/defaultMaterial.glsl b/glsl/defaultMaterial.glsl index 1e95b2f4ea..0f0d1fbb25 100644 --- a/glsl/defaultMaterial.glsl +++ b/glsl/defaultMaterial.glsl @@ -18,7 +18,10 @@ qf_varying vec2 v_TexCoord; #ifdef NUM_LIGHTMAPS -qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +qf_varying qf_lmvec01 v_LightmapTexCoord01; +#if NUM_LIGHTMAPS > 2 +qf_varying qf_lmvec23 v_LightmapTexCoord23; +#endif #endif qf_varying vec3 v_Position; @@ -66,16 +69,10 @@ void main() v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); #ifdef NUM_LIGHTMAPS - v_LightmapTexCoord[0] = a_LightmapCoord0; -#if NUM_LIGHTMAPS >= 2 - v_LightmapTexCoord[1] = a_LightmapCoord1; -#if NUM_LIGHTMAPS >= 3 - v_LightmapTexCoord[2] = a_LightmapCoord2; -#if NUM_LIGHTMAPS >= 4 - v_LightmapTexCoord[3] = a_LightmapCoord3; -#endif // NUM_LIGHTMAPS >= 4 -#endif // NUM_LIGHTMAPS >= 3 -#endif // NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord01 = a_LightmapCoord01; +#if NUM_LIGHTMAPS > 2 + v_LightmapTexCoord23 = a_LightmapCoord23; +#endif // NUM_LIGHTMAPS > 2 #endif // NUM_LIGHTMAPS v_StrMatrix[0] = Tangent; @@ -268,19 +265,19 @@ void main() #ifdef NUM_LIGHTMAPS // get light normal - diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord01.st+vec2(u_DeluxemapOffset[0], 0.0))) - myhalf3 (0.5)); // calculate directional shading diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); #ifdef APPLY_FBLIGHTMAP weightedDiffuseNormalModelspace = diffuseNormalModelspace; // apply lightmap color - color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord01.st))); #else #define NORMALIZE_DIFFUSE_NORMAL weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; // apply lightmap color - color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord01.st)); #endif // APPLY_FBLIGHTMAP #ifdef APPLY_AMBIENT_COMPENSATION @@ -289,20 +286,20 @@ void main() #endif #if NUM_LIGHTMAPS >= 2 - diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], v_LightmapTexCoord01.pq+vec2(u_DeluxemapOffset[1],0.0))) - myhalf3 (0.5)); diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; - color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord01.pq)); #if NUM_LIGHTMAPS >= 3 - diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], v_LightmapTexCoord23.st+vec2(u_DeluxemapOffset[2],0.0))) - myhalf3 (0.5)); diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; - color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord23.st)); #if NUM_LIGHTMAPS >= 4 - diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], v_LightmapTexCoord23.pq+vec2(u_DeluxemapOffset[3],0.0))) - myhalf3 (0.5)); diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; - color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord23.pq)); #endif // NUM_LIGHTMAPS >= 4 #endif // NUM_LIGHTMAPS >= 3 #endif // NUM_LIGHTMAPS >= 2 diff --git a/glsl/defaultQ3AShader.glsl b/glsl/defaultQ3AShader.glsl index 0671ca9eb9..b13d438c17 100644 --- a/glsl/defaultQ3AShader.glsl +++ b/glsl/defaultQ3AShader.glsl @@ -34,7 +34,10 @@ qf_varying vec2 v_TexCoord; #endif #ifdef NUM_LIGHTMAPS -qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +qf_varying qf_lmvec01 v_LightmapTexCoord01; +#if NUM_LIGHTMAPS > 2 +qf_varying qf_lmvec23 v_LightmapTexCoord23; +#endif #endif #if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) @@ -104,16 +107,10 @@ void main(void) #endif #ifdef NUM_LIGHTMAPS - v_LightmapTexCoord[0] = a_LightmapCoord0; -#if NUM_LIGHTMAPS >= 2 - v_LightmapTexCoord[1] = a_LightmapCoord1; -#if NUM_LIGHTMAPS >= 3 - v_LightmapTexCoord[2] = a_LightmapCoord2; -#if NUM_LIGHTMAPS >= 4 - v_LightmapTexCoord[3] = a_LightmapCoord3; -#endif // NUM_LIGHTMAPS >= 4 -#endif // NUM_LIGHTMAPS >= 3 -#endif // NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord01 = a_LightmapCoord01; +#if NUM_LIGHTMAPS > 2 + v_LightmapTexCoord23 = a_LightmapCoord23; +#endif // NUM_LIGHTMAPS > 2 #endif // NUM_LIGHTMAPS gl_Position = u_ModelViewProjectionMatrix * Position; @@ -157,13 +154,13 @@ void main(void) #ifdef NUM_LIGHTMAPS color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); - color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord01.st)) * u_LightstyleColor[0]; #if NUM_LIGHTMAPS >= 2 - color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord01.pq)) * u_LightstyleColor[1]; #if NUM_LIGHTMAPS >= 3 - color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord23.st)) * u_LightstyleColor[2]; #if NUM_LIGHTMAPS >= 4 - color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord23.pq)) * u_LightstyleColor[3]; #endif // NUM_LIGHTMAPS >= 4 #endif // NUM_LIGHTMAPS >= 3 #endif // NUM_LIGHTMAPS >= 2 diff --git a/glsl/include/attributes.glsl b/glsl/include/attributes.glsl index 1c002cb4d3..72b8252f78 100644 --- a/glsl/include/attributes.glsl +++ b/glsl/include/attributes.glsl @@ -1,8 +1,15 @@ #ifdef VERTEX_SHADER + qf_attribute vec4 a_Position; qf_attribute vec4 a_SVector; qf_attribute vec4 a_Normal; qf_attribute vec4 a_Color; qf_attribute vec2 a_TexCoord; -qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; -#endif +# ifdef NUM_LIGHTMAPS +qf_attribute qf_lmvec01 a_LightmapCoord01; +# if NUM_LIGHTMAPS > 2 +qf_attribute qf_lmvec23 a_LightmapCoord23; +# endif // NUM_LIGHTMAPS > 2 +#endif // NUM_LIGHTMAPS + +#endif // VERTEX_SHADER diff --git a/source/ref_gl/r_backend.c b/source/ref_gl/r_backend.c index 77d075a311..2f6325b5d0 100644 --- a/source/ref_gl/r_backend.c +++ b/source/ref_gl/r_backend.c @@ -1031,7 +1031,6 @@ void RB_EndBatch( void ) */ static void RB_EnableVertexAttribs( void ) { - int i; vattribmask_t vattribs = rb.currentVAttribs; mesh_vbo_t *vbo = rb.currentVBO; vattribmask_t hfa = vbo->halfFloatAttribs; @@ -1106,30 +1105,30 @@ static void RB_EnableVertexAttribs( void ) ( const GLvoid * )vbo->bonesWeightsOffset ); } else { + int i; + vattrib_t lmattr; + vattribbit_t lmattrbit; + GL_EnableVertexAttrib( VATTRIB_BONESINDICES, qfalse ); GL_EnableVertexAttrib( VATTRIB_BONESWEIGHTS, qfalse ); // lightmap texture coordinates - if( vattribs & VATTRIB_LMCOORDS0_BIT ) { - GL_EnableVertexAttrib( VATTRIB_LMCOORDS0, qtrue ); - qglVertexAttribPointerARB( VATTRIB_LMCOORDS0, 2, FLOAT_VATTRIB_TYPE( VATTRIB_LMCOORDS0_BIT, hfa ), GL_FALSE, 0, - ( const GLvoid * )vbo->lmstOffset[0] ); - } - else { - GL_EnableVertexAttrib( VATTRIB_LMCOORDS0, qfalse ); - } - - for( i = 0; i < MAX_LIGHTMAPS-1; i++ ) { - vattribbit_t lmvattrib = ( vattribbit_t ) (VATTRIB_LMCOORDS1_BIT<lmstOffset[i+1] ); + lmattr = VATTRIB_LMCOORDS01; + lmattrbit = VATTRIB_LMCOORDS0_BIT; + + for( i = 0; i < MAX_LIGHTMAPS/2; i++ ) { + if( vattribs & lmattrbit ) { + GL_EnableVertexAttrib( lmattr, qtrue ); + qglVertexAttribPointerARB( lmattr, vbo->lmstSize[i], + FLOAT_VATTRIB_TYPE( VATTRIB_LMCOORDS0_BIT, hfa ), + GL_FALSE, 0, ( const GLvoid * )vbo->lmstOffset[i] ); } else { - GL_EnableVertexAttrib( VATTRIB_LMCOORDS1+i, qfalse ); + GL_EnableVertexAttrib( lmattr, qfalse ); } + + lmattr++; + lmattrbit <<= 2; } } diff --git a/source/ref_gl/r_local.h b/source/ref_gl/r_local.h index 5208394eae..b3c218ab3c 100644 --- a/source/ref_gl/r_local.h +++ b/source/ref_gl/r_local.h @@ -731,7 +731,8 @@ typedef struct mesh_vbo_s size_t normalsOffset; size_t sVectorsOffset; size_t stOffset; - size_t lmstOffset[MAX_LIGHTMAPS]; + size_t lmstOffset[MAX_LIGHTMAPS/2]; + size_t lmstSize[MAX_LIGHTMAPS/2]; size_t colorsOffset[MAX_LIGHTMAPS]; size_t bonesIndicesOffset; size_t bonesWeightsOffset; diff --git a/source/ref_gl/r_program.c b/source/ref_gl/r_program.c index 9677d0a7fd..2ef6ddb61c 100644 --- a/source/ref_gl/r_program.c +++ b/source/ref_gl/r_program.c @@ -448,10 +448,10 @@ static const glsl_feature_t glsl_features_material[] = { GLSL_SHADER_COMMON_INSTANCED_ATTRIB_TRASNFORMS, "#define APPLY_INSTANCED_TRANSFORMS\n" "#define APPLY_INSTANCED_ATTRIB_TRASNFORMS\n", "_instanced_va" }, - { GLSL_SHADER_MATERIAL_LIGHTSTYLE3, "#define NUM_LIGHTMAPS 4\n", "_ls3" }, - { GLSL_SHADER_MATERIAL_LIGHTSTYLE2, "#define NUM_LIGHTMAPS 3\n", "_ls2" }, - { GLSL_SHADER_MATERIAL_LIGHTSTYLE1, "#define NUM_LIGHTMAPS 2\n", "_ls1" }, - { GLSL_SHADER_MATERIAL_LIGHTSTYLE0, "#define NUM_LIGHTMAPS 1\n", "_ls0" }, + { GLSL_SHADER_MATERIAL_LIGHTSTYLE3, "#define NUM_LIGHTMAPS 4\n#define qf_lmvec23 vec4\n", "_ls3" }, + { GLSL_SHADER_MATERIAL_LIGHTSTYLE2, "#define NUM_LIGHTMAPS 3\n#define qf_lmvec23 vec2\n", "_ls2" }, + { GLSL_SHADER_MATERIAL_LIGHTSTYLE1, "#define NUM_LIGHTMAPS 2\n#define qf_lmvec01 vec4\n", "_ls1" }, + { GLSL_SHADER_MATERIAL_LIGHTSTYLE0, "#define NUM_LIGHTMAPS 1\n#define qf_lmvec01 vec2\n", "_ls0" }, { GLSL_SHADER_MATERIAL_FB_LIGHTMAP, "#define APPLY_FBLIGHTMAP\n", "_fb" }, { GLSL_SHADER_MATERIAL_DIRECTIONAL_LIGHT, "#define APPLY_DIRECTIONAL_LIGHT\n", "_dirlight" }, @@ -615,10 +615,10 @@ static const glsl_feature_t glsl_features_q3a[] = { GLSL_SHADER_Q3_TC_GEN_ENV, "#define APPLY_TC_GEN_ENV\n", "_tc_env" }, { GLSL_SHADER_Q3_TC_GEN_VECTOR, "#define APPLY_TC_GEN_VECTOR\n", "_tc_vec" }, - { GLSL_SHADER_Q3_LIGHTSTYLE3, "#define NUM_LIGHTMAPS 4\n", "_ls3" }, - { GLSL_SHADER_Q3_LIGHTSTYLE2, "#define NUM_LIGHTMAPS 3\n", "_ls2" }, - { GLSL_SHADER_Q3_LIGHTSTYLE1, "#define NUM_LIGHTMAPS 2\n", "_ls1" }, - { GLSL_SHADER_Q3_LIGHTSTYLE0, "#define NUM_LIGHTMAPS 1\n", "_ls0" }, + { GLSL_SHADER_Q3_LIGHTSTYLE3, "#define NUM_LIGHTMAPS 4\n#define qf_lmvec23 vec4\n", "_ls3" }, + { GLSL_SHADER_Q3_LIGHTSTYLE2, "#define NUM_LIGHTMAPS 3\n#define qf_lmvec23 vec2\n", "_ls2" }, + { GLSL_SHADER_Q3_LIGHTSTYLE1, "#define NUM_LIGHTMAPS 2\n#define qf_lmvec01 vec4\n", "_ls1" }, + { GLSL_SHADER_Q3_LIGHTSTYLE0, "#define NUM_LIGHTMAPS 1\n#define qf_lmvec01 vec2\n", "_ls0" }, { 0, NULL, NULL } }; @@ -2203,10 +2203,8 @@ static void RF_BindAttrbibutesLocations( glsl_program_t *program ) qglBindAttribLocationARB( program->object, VATTRIB_BONESINDICES, "a_BonesIndices" ); qglBindAttribLocationARB( program->object, VATTRIB_BONESWEIGHTS, "a_BonesWeights" ); - qglBindAttribLocationARB( program->object, VATTRIB_LMCOORDS0, "a_LightmapCoord0" ); - qglBindAttribLocationARB( program->object, VATTRIB_LMCOORDS1, "a_LightmapCoord1" ); - qglBindAttribLocationARB( program->object, VATTRIB_LMCOORDS2, "a_LightmapCoord2" ); - qglBindAttribLocationARB( program->object, VATTRIB_LMCOORDS3, "a_LightmapCoord3" ); + qglBindAttribLocationARB( program->object, VATTRIB_LMCOORDS01, "a_LightmapCoord01" ); + qglBindAttribLocationARB( program->object, VATTRIB_LMCOORDS23, "a_LightmapCoord23" ); qglBindAttribLocationARB( program->object, VATTRIB_COLOR1, "a_Color1" ); qglBindAttribLocationARB( program->object, VATTRIB_COLOR2, "a_Color2" ); diff --git a/source/ref_gl/r_vattribs.h b/source/ref_gl/r_vattribs.h index 4de4455b42..8f15a1b76c 100644 --- a/source/ref_gl/r_vattribs.h +++ b/source/ref_gl/r_vattribs.h @@ -41,15 +41,13 @@ typedef enum vattrib_e VATTRIB_COLOR2 = 7, VATTRIB_COLOR3 = 8, - VATTRIB_LMCOORDS0 = 6, - VATTRIB_LMCOORDS1 = 7, - VATTRIB_LMCOORDS2 = 8, - VATTRIB_LMCOORDS3 = 9, + VATTRIB_LMCOORDS01 = 6, + VATTRIB_LMCOORDS23 = 7, - VATTRIB_INSTANCE_QUAT = 10, - VATTRIB_INSTANCE_XYZS = 11, + VATTRIB_INSTANCE_QUAT = 8, + VATTRIB_INSTANCE_XYZS = 9, - NUM_VERTEX_ATTRIBS = 12 + NUM_VERTEX_ATTRIBS = 10 } vattrib_t; #define VATTRIB_BIT(va) (1<<(va)) diff --git a/source/ref_gl/r_vbo.c b/source/ref_gl/r_vbo.c index 97e16656d9..3d0d9ef6f5 100644 --- a/source/ref_gl/r_vbo.c +++ b/source/ref_gl/r_vbo.c @@ -109,6 +109,7 @@ mesh_vbo_t *R_CreateMeshVBO( void *owner, int numVerts, int numElems, int numIns mesh_vbo_t *vbo = NULL; GLenum array_usage = VBO_ARRAY_USAGE_FOR_TAG(tag); GLenum elem_usage = VBO_ELEM_USAGE_FOR_TAG(tag); + vattribbit_t lmattrbit; if( !glConfig.ext.vertex_buffer_object ) return NULL; @@ -165,21 +166,16 @@ mesh_vbo_t *R_CreateMeshVBO( void *owner, int numVerts, int numElems, int numIns } // lightmap texture coordinates - if( vattribs & VATTRIB_LMCOORDS0_BIT ) - { - vbo->lmstOffset[0] = size; - size += numVerts * FLOAT_VATTRIB_SIZE(VATTRIB_LMCOORDS0_BIT, halfFloatVattribs) * 2; - ALIGN16( size ); - - for( i = 1; i < MAX_LIGHTMAPS; i++ ) - { - vattribbit_t lmvattrib = (vattribbit_t)(VATTRIB_LMCOORDS1_BIT<<(i-1)); - if( !(vattribs & lmvattrib) ) - break; - vbo->lmstOffset[i] = size; - size += numVerts * FLOAT_VATTRIB_SIZE(lmvattrib, halfFloatVattribs) * 2; - ALIGN16( size ); + lmattrbit = VATTRIB_LMCOORDS0_BIT; + for( i = 0; i < MAX_LIGHTMAPS/2; i++ ) { + if( !(vattribs & lmattrbit) ) { + break; } + vbo->lmstOffset[i] = size; + vbo->lmstSize[i] = vattribs & VATTRIB_LMCOORDS0_BIT<<1 ? 4 : 2; + size += numVerts * FLOAT_VATTRIB_SIZE(VATTRIB_LMCOORDS0_BIT, halfFloatVattribs) * vbo->lmstSize[i]; + ALIGN16( size ); + lmattrbit <<= 2; } // vertex colors @@ -353,7 +349,7 @@ int R_GetNumberOfActiveVBOs( void ) /* * R_HalfFloatBufferFromFloatBuffer */ -static GLhalfARB *R_HalfFloatBufferFromFloatBuffer( float *f, int numFloats ) +static GLhalfARB *R_HalfFloatBufferFromFloatBuffer( int numFloats, float *f ) { GLhalfARB *hptr = ( GLhalfARB * )R_VBOFloatBuffer( ( numFloats + 1 ) / 2 ), *h = hptr; for( ; numFloats > 0 ; numFloats-- ) { @@ -365,14 +361,86 @@ static GLhalfARB *R_HalfFloatBufferFromFloatBuffer( float *f, int numFloats ) /* * R_VattribFloatBuffer */ -static GLvoid *R_VattribFloatBuffer( vattribbit_t bit, vattribmask_t mask, float *f, int numFloats ) +static GLvoid *R_VattribFloatBuffer( vattribbit_t bit, vattribmask_t mask, int numFloats, float *f ) { if( FLOAT_VATTRIB_TYPE( bit, mask ) == GL_HALF_FLOAT ) { - return ( GLvoid * )R_HalfFloatBufferFromFloatBuffer( f, numFloats ); + return ( GLvoid * )R_HalfFloatBufferFromFloatBuffer( numFloats, f ); } return ( GLvoid * )f; } +/* +* R_VattribInterleavedFloatBuffer +*/ +static GLvoid *R_VattribInterleavedFloatBuffer( vattribbit_t bit, vattribmask_t mask, int numVerts, ... ) +{ + int i, j, k; + int numArrays; + int totalSize; + struct { + float *ptr; + int size; + } floatArray[16]; + va_list vl; + + numArrays = 0; + totalSize = 0; + + // count the number of arrays passed + va_start( vl, numVerts ); + while( 1 ) { + int size; + float *f = va_arg( vl, float * ); + if( !f ) { + break; + } + if( numArrays == sizeof(floatArray)/sizeof(floatArray[0]) ) { + va_end( vl ); + return NULL; + } + size = va_arg( vl, int ); + + floatArray[numArrays].ptr = f; + floatArray[numArrays].size = size; + + totalSize += size; + numArrays++; + } + va_end( vl ); + + if( !numArrays || !totalSize ) { + return NULL; + } + +#define fill_with_stride(type,conv) \ + { \ + type *hptr = ( type * )R_VBOFloatBuffer( ( numVerts * totalSize + sizeof(GLfloat)/sizeof(type) - 1 ) \ + / (sizeof(GLfloat)/sizeof(type)) ); \ + type *h = hptr; \ + \ + for( i = 0; i < numVerts; i++ ) { \ + for( j = 0; j < numArrays; j++ ) { \ + float *f = floatArray[j].ptr; \ + int size = floatArray[j].size; \ + for( k = 0; k < size; k++ ) { \ + *h++ = conv( *f++ ); \ + } \ + floatArray[j].ptr += size; \ + } \ + } \ + \ + return hptr; \ + } + + if( FLOAT_VATTRIB_TYPE( bit, mask ) == GL_HALF_FLOAT ) { + fill_with_stride(GLhalfARB, _mesa_float_to_half); + } + else { + fill_with_stride(GLfloat, ); + } +#undef fill_with_stride +} + /* * R_UploadVBOVertexData * @@ -415,7 +483,7 @@ vattribmask_t R_UploadVBOVertexData( mesh_vbo_t *vbo, int vertsOffset, errMask |= VATTRIB_POSITION_BIT; else qglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, 0 + vertsOffset * size, - numVerts * size, R_VattribFloatBuffer( VATTRIB_POSITION_BIT, hfa, mesh->xyzArray[0], numVerts * numFloats ) ); + numVerts * size, R_VattribFloatBuffer( VATTRIB_POSITION_BIT, hfa, numVerts * numFloats, mesh->xyzArray[0] ) ); } // upload normals data @@ -427,7 +495,7 @@ vattribmask_t R_UploadVBOVertexData( mesh_vbo_t *vbo, int vertsOffset, errMask |= VATTRIB_NORMAL_BIT; else qglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, vbo->normalsOffset + vertsOffset * size, - numVerts * size, R_VattribFloatBuffer( VATTRIB_NORMAL_BIT, hfa, mesh->normalsArray[0], numVerts * numFloats ) ); + numVerts * size, R_VattribFloatBuffer( VATTRIB_NORMAL_BIT, hfa, numVerts * numFloats, mesh->normalsArray[0] ) ); } // upload tangent vectors @@ -439,7 +507,7 @@ vattribmask_t R_UploadVBOVertexData( mesh_vbo_t *vbo, int vertsOffset, errMask |= VATTRIB_SVECTOR_BIT; else qglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, vbo->sVectorsOffset + vertsOffset * size, - numVerts * size, R_VattribFloatBuffer( VATTRIB_SVECTOR_BIT, hfa, mesh->sVectorsArray[0], numVerts * numFloats ) ); + numVerts * size, R_VattribFloatBuffer( VATTRIB_SVECTOR_BIT, hfa, numVerts * numFloats, mesh->sVectorsArray[0] ) ); } // upload texture coordinates @@ -451,37 +519,43 @@ vattribmask_t R_UploadVBOVertexData( mesh_vbo_t *vbo, int vertsOffset, errMask |= VATTRIB_TEXCOORDS_BIT; else qglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, vbo->stOffset + vertsOffset * size, - numVerts * size, R_VattribFloatBuffer( VATTRIB_TEXCOORDS_BIT, hfa, mesh->stArray[0], numVerts * numFloats ) ); + numVerts * size, R_VattribFloatBuffer( VATTRIB_TEXCOORDS_BIT, hfa, numVerts * numFloats, mesh->stArray[0] ) ); } // upload lightmap texture coordinates - if( vbo->lmstOffset[0] && (vattribs & VATTRIB_LMCOORDS0_BIT) ) { - numFloats = 2; - size = FLOAT_VATTRIB_SIZE( VATTRIB_LMCOORDS0_BIT, hfa ) * numFloats; + if( vbo->lmstOffset[0] && ( vattribs & VATTRIB_LMCOORDS0_BIT ) ) { + int i; + vattribbit_t lmattrbit; - if( mesh->lmstArray[0] ) { - qglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, vbo->lmstOffset[0] + vertsOffset * size, - numVerts * size, R_VattribFloatBuffer( VATTRIB_LMCOORDS0_BIT, hfa, mesh->lmstArray[0][0], numVerts * numFloats ) ); + lmattrbit = VATTRIB_LMCOORDS0_BIT; - for( i = 1; i < MAX_LIGHTMAPS; i++ ) { - vattribbit_t lmvattrib = (vattribbit_t)(VATTRIB_LMCOORDS1_BIT<<(i-1)); - - if( !vbo->lmstOffset[i] || ! (vattribs & lmvattrib) ) - break; + for( i = 0; i < MAX_LIGHTMAPS/2; i++ ) { + if( !(vattribs & lmattrbit) ) { + break; + } + if( !mesh->lmstArray[i*2+0] ) { + errMask |= lmattrbit; + break; + } - size = FLOAT_VATTRIB_SIZE( lmvattrib, hfa ) * 2; + size = FLOAT_VATTRIB_SIZE( VATTRIB_LMCOORDS0_BIT, hfa ) * vbo->lmstSize[i]; - if( !mesh->lmstArray[i] ) { - errMask |= VATTRIB_LMCOORDS1_BIT<<(i-1); + if( vattribs & (lmattrbit<<1) ) { + if( !mesh->lmstArray[i*2+1] ) { + errMask |= lmattrbit<<1; break; } - qglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, vbo->lmstOffset[i] + vertsOffset * size, - numVerts * size, R_VattribFloatBuffer( lmvattrib, hfa, mesh->lmstArray[i][0], numVerts * numFloats ) ); + numVerts * size, R_VattribInterleavedFloatBuffer( VATTRIB_LMCOORDS0_BIT, hfa, numVerts, + mesh->lmstArray[i*2+0][0], 2, mesh->lmstArray[i*2+1][0], 2, NULL ) ); } - } - else { - errMask |= VATTRIB_LMCOORDS0_BIT; + else { + qglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, vbo->lmstOffset[i] + vertsOffset * size, + numVerts * size, R_VattribFloatBuffer( VATTRIB_LMCOORDS0_BIT, hfa, numVerts * 2, + mesh->lmstArray[i*2][0] ) ); + } + + lmattrbit <<= 2; } } @@ -602,8 +676,10 @@ vattribmask_t R_UploadVBOVertexData( mesh_vbo_t *vbo, int vertsOffset, Vector4Copy( axes[0], axes[j] ); } - qglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, bufferOffset0, 4 * size0, R_VattribFloatBuffer( VATTRIB_AUTOSPRITE_BIT, hfa, centre[0], 4 * numFloats0 ) ); - qglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, bufferOffset1, 4 * size1, R_VattribFloatBuffer( VATTRIB_SVECTOR_BIT, hfa, axes[0], 4 * numFloats1 ) ); + qglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, bufferOffset0, 4 * size0, + R_VattribFloatBuffer( VATTRIB_AUTOSPRITE_BIT, hfa, 4 * numFloats0, centre[0] ) ); + qglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, bufferOffset1, 4 * size1, + R_VattribFloatBuffer( VATTRIB_SVECTOR_BIT, hfa, 4 * numFloats1, axes[0] ) ); bufferOffset0 += 4 * size0; bufferOffset1 += 4 * size1; @@ -631,7 +707,8 @@ vattribmask_t R_UploadVBOVertexData( mesh_vbo_t *vbo, int vertsOffset, Vector4Copy( centre[0], centre[j] ); } - qglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, bufferOffset, 4 * size, R_VattribFloatBuffer( VATTRIB_AUTOSPRITE_BIT, hfa, centre[0], 4 * numFloats ) ); + qglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, bufferOffset, 4 * size, + R_VattribFloatBuffer( VATTRIB_AUTOSPRITE_BIT, hfa, 4 * numFloats, centre[0] ) ); bufferOffset += 4 * size; } }