From c936e43420b26b26fefce15a1bab5c8cf72e7c84 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Sat, 29 Feb 2020 06:11:46 +0100 Subject: [PATCH] GL3: Use one projection-view matrix in shaders instead of separate projection and view matrices - this way there is one less mat4 multiplication in the 3D vertex shaders. --- src/client/refresh/gl3/gl3_main.c | 11 ++++++++--- src/client/refresh/gl3/gl3_mesh.c | 14 ++++++++------ src/client/refresh/gl3/gl3_shaders.c | 24 ++++++++++-------------- src/client/refresh/gl3/header/local.h | 5 +++-- 4 files changed, 29 insertions(+), 25 deletions(-) diff --git a/src/client/refresh/gl3/gl3_main.c b/src/client/refresh/gl3/gl3_main.c index 41849ade..330f78df 100644 --- a/src/client/refresh/gl3/gl3_main.c +++ b/src/client/refresh/gl3/gl3_main.c @@ -1316,6 +1316,7 @@ GL3_MYgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zF // the following emulates glFrustum(left, right, bottom, top, zNear, zFar) // see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFrustum.xml + // or http://docs.gl/gl2/glFrustum#description (looks better in non-Firefox browsers) A = (right+left)/(right-left); B = (top+bottom)/(top-bottom); C = -(zFar+zNear)/(zFar-zNear); @@ -1431,7 +1432,7 @@ SetupGL(void) { float screenaspect = (float)gl3_newrefdef.width / gl3_newrefdef.height; float dist = (r_farsee->value == 0) ? 4096.0f : 8192.0f; - gl3state.uni3DData.transProjMat4 = GL3_MYgluPerspective(gl3_newrefdef.fov_y, screenaspect, 4, dist); + gl3state.projMat3D = GL3_MYgluPerspective(gl3_newrefdef.fov_y, screenaspect, 4, dist); } glCullFace(GL_FRONT); @@ -1440,7 +1441,7 @@ SetupGL(void) { // first put Z axis going up hmm_mat4 viewMat = {{ - { 0, 0, -1, 0 }, // first *column* (the matrix is colum-major) + { 0, 0, -1, 0 }, // first *column* (the matrix is column-major) { -1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 1 } @@ -1455,9 +1456,13 @@ SetupGL(void) hmm_vec3 trans = HMM_Vec3(-gl3_newrefdef.vieworg[0], -gl3_newrefdef.vieworg[1], -gl3_newrefdef.vieworg[2]); viewMat = HMM_MultiplyMat4( viewMat, HMM_Translate(trans) ); - gl3state.uni3DData.transViewMat4 = viewMat; + gl3state.viewMat3D = viewMat; } + // just use one projection-view-matrix (premultiplied here) + // so we have one less mat4 multiplication in the 3D shaders + gl3state.uni3DData.transProjViewMat4 = HMM_MultiplyMat4(gl3state.projMat3D, gl3state.viewMat3D); + gl3state.uni3DData.transModelMat4 = gl3_identityMat4; gl3state.uni3DData.time = gl3_newrefdef.time; diff --git a/src/client/refresh/gl3/gl3_mesh.c b/src/client/refresh/gl3/gl3_mesh.c index d2ce080c..0d2a371e 100644 --- a/src/client/refresh/gl3/gl3_mesh.c +++ b/src/client/refresh/gl3/gl3_mesh.c @@ -650,7 +650,7 @@ GL3_DrawAliasModel(entity_t *entity) vec3_t shadelight; vec3_t shadevector; gl3image_t *skin; - hmm_mat4 origProjMat = {0}; // use for left-handed rendering + hmm_mat4 origProjViewMat = {0}; // use for left-handed rendering // used to restore ModelView matrix after changing it for this entities position/rotation hmm_mat4 origModelMat = {0}; @@ -817,19 +817,20 @@ GL3_DrawAliasModel(entity_t *entity) { extern hmm_mat4 GL3_MYgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar); - origProjMat = gl3state.uni3DData.transProjMat4; + origProjViewMat = gl3state.uni3DData.transProjViewMat4; // render weapon with a different FOV (r_gunfov) so it's not distorted at high view FOV float screenaspect = (float)gl3_newrefdef.width / gl3_newrefdef.height; float dist = (r_farsee->value == 0) ? 4096.0f : 8192.0f; + hmm_mat4 projMat; if (r_gunfov->value < 0) { - gl3state.uni3DData.transProjMat4 = GL3_MYgluPerspective(gl3_newrefdef.fov_y, screenaspect, 4, dist); + projMat = GL3_MYgluPerspective(gl3_newrefdef.fov_y, screenaspect, 4, dist); } else { - gl3state.uni3DData.transProjMat4 = GL3_MYgluPerspective(r_gunfov->value, screenaspect, 4, dist); + projMat = GL3_MYgluPerspective(r_gunfov->value, screenaspect, 4, dist); } if(gl_lefthand->value == 1.0F) @@ -838,12 +839,13 @@ GL3_DrawAliasModel(entity_t *entity) // of projection matrix for(int i=0; i<4; ++i) { - gl3state.uni3DData.transProjMat4.Elements[0][i] = -gl3state.uni3DData.transProjMat4.Elements[0][i]; + projMat.Elements[0][i] = - projMat.Elements[0][i]; } //GL3_UpdateUBO3D(); Note: GL3_RotateForEntity() will call this,no need to do it twice before drawing glCullFace(GL_BACK); } + gl3state.uni3DData.transProjViewMat4 = HMM_MultiplyMat4(projMat, gl3state.viewMat3D); } @@ -916,7 +918,7 @@ GL3_DrawAliasModel(entity_t *entity) if (entity->flags & RF_WEAPONMODEL) { - gl3state.uni3DData.transProjMat4 = origProjMat; + gl3state.uni3DData.transProjViewMat4 = origProjViewMat; GL3_UpdateUBO3D(); if(gl_lefthand->value == 1.0F) glCullFace(GL_FRONT); diff --git a/src/client/refresh/gl3/gl3_shaders.c b/src/client/refresh/gl3/gl3_shaders.c index d8ee7333..cd874133 100644 --- a/src/client/refresh/gl3/gl3_shaders.c +++ b/src/client/refresh/gl3/gl3_shaders.c @@ -359,8 +359,7 @@ static const char* vertexCommon3D = MULTILINE_STRING( // for UBO shared between all 3D shaders layout (std140) uniform uni3D { - mat4 transProj; - mat4 transView; + mat4 transProjView; mat4 transModel; float scroll; // for SURF_FLOWING @@ -388,13 +387,11 @@ static const char* fragmentCommon3D = MULTILINE_STRING( float intensity2D; // for HUD, menus etc vec4 color; // really? - }; // for UBO shared between all 3D shaders layout (std140) uniform uni3D { - mat4 transProj; - mat4 transView; + mat4 transProjView; mat4 transModel; float scroll; // for SURF_FLOWING @@ -415,7 +412,7 @@ static const char* vertexSrc3D = MULTILINE_STRING( void main() { passTexCoord = texCoord; - gl_Position = transProj * transView * transModel * vec4(position, 1.0); + gl_Position = transProjView * transModel * vec4(position, 1.0); } ); @@ -426,7 +423,7 @@ static const char* vertexSrc3Dflow = MULTILINE_STRING( void main() { passTexCoord = texCoord + vec2(scroll, 0); - gl_Position = transProj * transView * transModel * vec4(position, 1.0); + gl_Position = transProjView * transModel * vec4(position, 1.0); } ); @@ -449,7 +446,7 @@ static const char* vertexSrc3Dlm = MULTILINE_STRING( passNormal = normalize(worldNormal.xyz); passLightFlags = lightFlags; - gl_Position = transProj * transView * worldCoord; + gl_Position = transProjView * worldCoord; } ); @@ -472,7 +469,7 @@ static const char* vertexSrc3DlmFlow = MULTILINE_STRING( passNormal = normalize(worldNormal.xyz); passLightFlags = lightFlags; - gl_Position = transProj * transView * worldCoord; + gl_Position = transProjView * worldCoord; } ); @@ -771,7 +768,7 @@ static const char* vertexSrc3Dwater = MULTILINE_STRING( { passTexCoord = texCoord; - gl_Position = transProj * transView * transModel * vec4(position, 1.0); + gl_Position = transProjView * transModel * vec4(position, 1.0); } ); @@ -785,7 +782,7 @@ static const char* vertexSrcAlias = MULTILINE_STRING( { passColor = vertColor*overbrightbits; passTexCoord = texCoord; - gl_Position = transProj * transView * transModel * vec4(position, 1.0); + gl_Position = transProjView* transModel * vec4(position, 1.0); } ); @@ -838,7 +835,7 @@ static const char* vertexSrcParticles = MULTILINE_STRING( void main() { passColor = vertColor; - gl_Position = transProj * transView * transModel * vec4(position, 1.0); + gl_Position = transProjView * transModel * vec4(position, 1.0); // abusing texCoord for pointSize, pointDist for particles float pointDist = texCoord.y*0.1; // with factor 0.1 it looks good. @@ -1167,8 +1164,7 @@ static void initUBOs(void) glBufferData(GL_UNIFORM_BUFFER, sizeof(gl3state.uni2DData), &gl3state.uni2DData, GL_DYNAMIC_DRAW); // the matrices will be set to something more useful later, before being used - gl3state.uni3DData.transProjMat4 = HMM_Mat4(); - gl3state.uni3DData.transViewMat4 = HMM_Mat4(); + gl3state.uni3DData.transProjViewMat4 = HMM_Mat4(); gl3state.uni3DData.transModelMat4 = gl3_identityMat4; gl3state.uni3DData.scroll = 0.0f; gl3state.uni3DData.time = 0.0f; diff --git a/src/client/refresh/gl3/header/local.h b/src/client/refresh/gl3/header/local.h index 45d0e503..c4becbd4 100644 --- a/src/client/refresh/gl3/header/local.h +++ b/src/client/refresh/gl3/header/local.h @@ -155,8 +155,7 @@ typedef struct typedef struct { - hmm_mat4 transProjMat4; - hmm_mat4 transViewMat4; + hmm_mat4 transProjViewMat4; // gl3state.projMat3D * gl3state.viewMat3D - so we don't have to do this in the shader hmm_mat4 transModelMat4; GLfloat scroll; // for SURF_FLOWING @@ -269,6 +268,8 @@ typedef struct GLuint uni3DUBO; GLuint uniLightsUBO; + hmm_mat4 projMat3D; + hmm_mat4 viewMat3D; } gl3state_t; extern gl3config_t gl3config;