Skip to content

Commit

Permalink
OpenGL2: Use CPU vertex animation if too few vertex attributes
Browse files Browse the repository at this point in the history
OpenGL ES has a minimum of 8 vertex attributes while desktop OpenGL has
a minimum of 16. Vertex animation uses attributes 10 to 12.

taken from ioq3: ioquake/ioq3#664
  • Loading branch information
zturtleman authored and mgerhardy committed Jul 21, 2018
1 parent 91ca9e3 commit e06a11b
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 8 deletions.
32 changes: 27 additions & 5 deletions code/renderergl2/tr_glsl.c
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,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))
continue;
Expand All @@ -883,6 +892,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;
} else if (i & GENERICDEF_USE_BONE_ANIMATION) {
Expand Down Expand Up @@ -931,6 +943,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;

Expand Down Expand Up @@ -1094,11 +1109,15 @@ 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) {
attribs |= ATTR_TANGENT2;
if (glRefConfig.gpuVertexAnimation) {
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) {
Q_strcat(extradefines, 1024, "#define USE_MODELMATRIX\n");
Expand Down Expand Up @@ -1131,6 +1150,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;

Expand Down Expand Up @@ -1373,7 +1395,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();
Expand Down
3 changes: 3 additions & 0 deletions code/renderergl2/tr_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,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);
Expand Down
3 changes: 3 additions & 0 deletions code/renderergl2/tr_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,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 )

Expand Down
13 changes: 10 additions & 3 deletions code/renderergl2/tr_mesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ void R_AddMD3Surfaces(trRefEntity_t *ent) {
int i;
mdvModel_t *model = NULL;
mdvSurface_t *surface = NULL;
void *drawSurf;
shader_t *shader = NULL;
int cull;
int lod;
Expand Down Expand Up @@ -347,23 +348,29 @@ 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
if (!personalModel && r_shadows->integer == 2 && 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
if (r_shadows->integer == 3 && 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++;
Expand Down
6 changes: 6 additions & 0 deletions code/renderergl2/tr_model.c
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,12 @@ static qboolean R_LoadMD3(model_t *mod, int lod, void *buffer, int bufferSize, c
surf++;
}

if (mdvModel->numFrames > 1 && !glRefConfig.gpuVertexAnimation)
{
mdvModel->numVaoSurfaces = 0;
mdvModel->vaoSurfaces = NULL;
}
else
{
srfVaoMdvMesh_t *vaoSurf;

Expand Down

0 comments on commit e06a11b

Please sign in to comment.