From afd0858b4d3a024b65fad944b1d20083018a6492 Mon Sep 17 00:00:00 2001 From: Hannu Hanhi Date: Thu, 16 Jul 2020 22:11:36 +0300 Subject: [PATCH] More work on sprite-texture model uv adjustment --- src/hardware/hw_md2.c | 17 +++------ src/hardware/hw_model.h | 4 ++ src/hardware/r_opengl/r_opengl.c | 65 ++++++++++++++++++++++---------- 3 files changed, 55 insertions(+), 31 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index abb5267a9..05afff37f 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1200,10 +1200,7 @@ static void adjustTextureCoords(model_t *model, GLPatch_t *gpatch) // if originaluvs points to uvs, we need to allocate new memory for adjusted uvs // the old uvs are kept around for use in possible readjustments if (mesh->uvs == mesh->originaluvs) - { - CONS_Printf("Debug: allocating memory for adjusted uvs\n"); mesh->uvs = Z_Malloc(numVertices * 2 * sizeof(float), PU_STATIC, NULL); - } uvWritePtr = mesh->uvs; @@ -1349,10 +1346,13 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) if (md2->model) { md2_printModelInfo(md2->model); - // if model uses sprite patch as texture, then + // If model uses sprite patch as texture, then // adjust texture coordinates to take power of two textures into account if (!gpatch || !gpatch->mipmap->format) adjustTextureCoords(md2->model, spr->gpatch); + // note down the max_s and max_t that end up in the VBO + md2->model->vbo_max_s = md2->model->max_s; + md2->model->vbo_max_t = md2->model->max_t; HWD.pfnCreateModelVBOs(md2->model); } else @@ -1408,15 +1408,10 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) gpatch = spr->gpatch; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE); // Check if sprite dimensions are different from previously used sprite. // If so, uvs need to be readjusted. + // Comparing floats with the != operator here should be okay because they + // are just copies of glpatches' max_s and max_t values. if (gpatch->max_s != md2->model->max_s || gpatch->max_t != md2->model->max_t) - { - CONS_Printf("Debug: Readjusting uvs!\n"); adjustTextureCoords(md2->model, gpatch); - // The vbo(s) are now wrong, so recreate them. - // If this turns out to be slow, then could try updating the vbos instead of - // deleting and creating new ones. - HWD.pfnCreateModelVBOs(md2->model); - } HWR_GetMappedPatch(gpatch, spr->colormap); } diff --git a/src/hardware/hw_model.h b/src/hardware/hw_model.h index 0b1834b52..6b39eb24d 100644 --- a/src/hardware/hw_model.h +++ b/src/hardware/hw_model.h @@ -109,6 +109,10 @@ typedef struct model_s // (if a sprite is used as a texture) float max_s; float max_t; + // These are the values that the uvs in the VBO have been adjusted to. + // If they are not same as max_s and max_t, then the VBO won't be used. + float vbo_max_s; + float vbo_max_t; } model_t; extern int numModels; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 08d688e1d..a837b5e03 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2626,6 +2626,8 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 boolean useTinyFrames; + boolean useVBO = true; + int i; // Because otherwise, scaling the screen negatively vertically breaks the lighting @@ -2766,6 +2768,13 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 if (useTinyFrames) pglScalef(1 / 64.0f, 1 / 64.0f, 1 / 64.0f); + // Don't use the VBO if it does not have the correct texture coordinates. + // (Can happen when model uses a sprite as a texture and the sprite changes) + // Comparing floats with the != operator here should be okay because they + // are just copies of glpatches' max_s and max_t values. + if (model->vbo_max_s != model->max_s || model->vbo_max_t != model->max_t) + useVBO = false; + pglEnableClientState(GL_NORMAL_ARRAY); for (i = 0; i < model->numMeshes; i++) @@ -2782,13 +2791,24 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 if (!nextframe || fpclassify(pol) == FP_ZERO) { - pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); - pglVertexPointer(3, GL_SHORT, sizeof(vbotiny_t), BUFFER_OFFSET(0)); - pglNormalPointer(GL_BYTE, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short)*3)); - pglTexCoordPointer(2, GL_FLOAT, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short) * 3 + sizeof(char) * 6)); + if (useVBO) + { + pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); + pglVertexPointer(3, GL_SHORT, sizeof(vbotiny_t), BUFFER_OFFSET(0)); + pglNormalPointer(GL_BYTE, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short)*3)); + pglTexCoordPointer(2, GL_FLOAT, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short) * 3 + sizeof(char) * 6)); - pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); - pglBindBuffer(GL_ARRAY_BUFFER, 0); + pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); + pglBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + //CONS_Printf("non-vbo tinyframe\n"); + pglVertexPointer(3, GL_SHORT, 0, frame->vertices); + pglNormalPointer(GL_BYTE, 0, frame->normals); + pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); + pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); + } } else { @@ -2824,21 +2844,26 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 if (!nextframe || fpclassify(pol) == FP_ZERO) { - // Zoom! Take advantage of just shoving the entire arrays to the GPU. -/* pglVertexPointer(3, GL_FLOAT, 0, frame->vertices); - pglNormalPointer(GL_FLOAT, 0, frame->normals); - pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); - pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3);*/ + if (useVBO) + { + pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); + pglVertexPointer(3, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(0)); + pglNormalPointer(GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 3)); + pglTexCoordPointer(2, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 6)); - pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); - pglVertexPointer(3, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(0)); - pglNormalPointer(GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 3)); - pglTexCoordPointer(2, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 6)); - - pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3); - // No tinyframes, no mesh indices - //pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); - pglBindBuffer(GL_ARRAY_BUFFER, 0); + pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3); + // No tinyframes, no mesh indices + //pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); + pglBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + //CONS_Printf("non-vbo frame\n"); + pglVertexPointer(3, GL_FLOAT, 0, frame->vertices); + pglNormalPointer(GL_FLOAT, 0, frame->normals); + pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); + pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3); + } } else {