OpenGL2: Use CPU vertex animation if too few vertex attributes

OpenGL ES has a minimum of 8 vertex attributes while desktop OpenGL has
a minimum of 16. Vertex animation uses attributes 10 to 12.
This commit is contained in:
Zack Middleton 2018-07-20 23:40:48 -05:00
parent b25a3c6e4d
commit 98b9008c0d
5 changed files with 53 additions and 11 deletions

View file

@ -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();

View file

@ -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 );

View file

@ -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 )

View file

@ -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++;

View file

@ -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;