diff --git a/code/renderergl2/tr_glsl.c b/code/renderergl2/tr_glsl.c index bf93a2f4..39223bf6 100644 --- a/code/renderergl2/tr_glsl.c +++ b/code/renderergl2/tr_glsl.c @@ -968,6 +968,15 @@ void GLSL_InitGPUShaders(void) startTime = ri.Milliseconds(); + // OpenGL ES may not have enough attributes to fit ones used for vertex animation + if ( glRefConfig.maxVertexAttribs > ATTR_INDEX_NORMAL2 ) { + ri.Printf(PRINT_ALL, "Using GPU vertex animation\n"); + glRefConfig.gpuVertexAnimation = qtrue; + } else { + ri.Printf(PRINT_ALL, "Using CPU vertex animation\n"); + glRefConfig.gpuVertexAnimation = qfalse; + } + for (i = 0; i < GENERICDEF_COUNT; i++) { if ((i & GENERICDEF_USE_VERTEX_ANIMATION) && (i & GENERICDEF_USE_BONE_ANIMATION)) @@ -990,6 +999,9 @@ void GLSL_InitGPUShaders(void) if (i & GENERICDEF_USE_VERTEX_ANIMATION) { + if (!glRefConfig.gpuVertexAnimation) + continue; + Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n"); attribs |= ATTR_POSITION2 | ATTR_NORMAL2; } @@ -1041,6 +1053,9 @@ void GLSL_InitGPUShaders(void) if ((i & FOGDEF_USE_VERTEX_ANIMATION) && (i & FOGDEF_USE_BONE_ANIMATION)) continue; + if ((i & FOGDEF_USE_VERTEX_ANIMATION) && !glRefConfig.gpuVertexAnimation) + continue; + if ((i & FOGDEF_USE_BONE_ANIMATION) && !glRefConfig.glslMaxAnimatedBones) continue; @@ -1221,12 +1236,17 @@ void GLSL_InitGPUShaders(void) if (i & LIGHTDEF_ENTITY_VERTEX_ANIMATION) { - Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n#define USE_MODELMATRIX\n"); - attribs |= ATTR_POSITION2 | ATTR_NORMAL2; + Q_strcat(extradefines, 1024, "#define USE_MODELMATRIX\n"); - if (r_normalMapping->integer) + if (glRefConfig.gpuVertexAnimation) { - attribs |= ATTR_TANGENT2; + Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n"); + attribs |= ATTR_POSITION2 | ATTR_NORMAL2; + + if (r_normalMapping->integer) + { + attribs |= ATTR_TANGENT2; + } } } else if (i & LIGHTDEF_ENTITY_BONE_ANIMATION) @@ -1261,6 +1281,9 @@ void GLSL_InitGPUShaders(void) if ((i & SHADOWMAPDEF_USE_VERTEX_ANIMATION) && (i & SHADOWMAPDEF_USE_BONE_ANIMATION)) continue; + if ((i & SHADOWMAPDEF_USE_VERTEX_ANIMATION) && !glRefConfig.gpuVertexAnimation) + continue; + if ((i & SHADOWMAPDEF_USE_BONE_ANIMATION) && !glRefConfig.glslMaxAnimatedBones) continue; @@ -1521,7 +1544,7 @@ void GLSL_ShutdownGPUShaders(void) ri.Printf(PRINT_ALL, "------- GLSL_ShutdownGPUShaders -------\n"); - for (i = 0; i < ATTR_INDEX_COUNT; i++) + for (i = 0; i < ATTR_INDEX_COUNT && i < glRefConfig.maxVertexAttribs; i++) qglDisableVertexAttribArray(i); GL_BindNullProgram(); diff --git a/code/renderergl2/tr_init.c b/code/renderergl2/tr_init.c index 12570392..aad662c5 100644 --- a/code/renderergl2/tr_init.c +++ b/code/renderergl2/tr_init.c @@ -279,6 +279,9 @@ static void InitOpenGL( void ) qglGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS, &temp ); glConfig.numTextureUnits = temp; + qglGetIntegerv( GL_MAX_VERTEX_ATTRIBS, &temp ); + glRefConfig.maxVertexAttribs = temp; + // reserve 160 components for other uniforms qglGetIntegerv( GL_MAX_VERTEX_UNIFORM_COMPONENTS, &temp ); glRefConfig.glslMaxAnimatedBones = Com_Clamp( 0, IQM_MAX_JOINTS, ( temp - 160 ) / 16 ); diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index eab069e1..9f46866f 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -1433,6 +1433,9 @@ typedef struct { qboolean vertexArrayObject; qboolean directStateAccess; + int maxVertexAttribs; + qboolean gpuVertexAnimation; + GLenum vaoCacheGlIndexType; // GL_UNSIGNED_INT or GL_UNSIGNED_SHORT size_t vaoCacheGlIndexSize; // must be <= sizeof( vaoCacheGlIndex_t ) diff --git a/code/renderergl2/tr_mesh.c b/code/renderergl2/tr_mesh.c index 4f2c6724..222b06d0 100644 --- a/code/renderergl2/tr_mesh.c +++ b/code/renderergl2/tr_mesh.c @@ -282,9 +282,10 @@ R_AddMD3Surfaces */ void R_AddMD3Surfaces( trRefEntity_t *ent ) { int i; - mdvModel_t *model = NULL; - mdvSurface_t *surface = NULL; - shader_t *shader = NULL; + mdvModel_t *model; + mdvSurface_t *surface; + void *drawSurf; + shader_t *shader; int cull; int lod; int fogNum; @@ -382,6 +383,12 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) { shader = tr.shaders[ surface->shaderIndexes[ ent->e.skinNum % surface->numShaderIndexes ] ]; } + if ( model->numVaoSurfaces > 0 ) { + drawSurf = &model->vaoSurfaces[i]; + } else { + drawSurf = surface; + } + // we will add shadows even if the main object isn't visible in the view // stencil shadows can't do personal models unless I polyhedron clip @@ -390,7 +397,7 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) { && fogNum == 0 && !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) ) && shader->sort == SS_OPAQUE ) { - R_AddDrawSurf( (void *)&model->vaoSurfaces[i], tr.shadowShader, 0, qfalse, qfalse, 0 ); + R_AddDrawSurf( drawSurf, tr.shadowShader, 0, qfalse, qfalse, 0 ); } // projection shadows work fine with personal models @@ -398,12 +405,12 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) { && fogNum == 0 && (ent->e.renderfx & RF_SHADOW_PLANE ) && shader->sort == SS_OPAQUE ) { - R_AddDrawSurf( (void *)&model->vaoSurfaces[i], tr.projectionShadowShader, 0, qfalse, qfalse, 0 ); + R_AddDrawSurf( drawSurf, tr.projectionShadowShader, 0, qfalse, qfalse, 0 ); } // don't add third_person objects if not viewing through a portal if ( !personalModel ) { - R_AddDrawSurf((void *)&model->vaoSurfaces[i], shader, fogNum, qfalse, qfalse, cubemapIndex ); + R_AddDrawSurf( drawSurf, shader, fogNum, qfalse, qfalse, cubemapIndex ); } surface++; diff --git a/code/renderergl2/tr_model.c b/code/renderergl2/tr_model.c index 0fdf60d8..7201be1b 100644 --- a/code/renderergl2/tr_model.c +++ b/code/renderergl2/tr_model.c @@ -664,6 +664,12 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize, surf++; } + if (mdvModel->numFrames > 1 && !glRefConfig.gpuVertexAnimation) + { + mdvModel->numVaoSurfaces = 0; + mdvModel->vaoSurfaces = NULL; + } + else { srfVaoMdvMesh_t *vaoSurf;