From 6f601d5f1163dc138258aab4f779515897c87e5f Mon Sep 17 00:00:00 2001 From: slipher Date: Sat, 14 Feb 2026 21:11:19 -0600 Subject: [PATCH 1/2] Skip visited check for BSP entity surfaces There is some code to skip a world surface if it has already been added in the current view. Don't do this for BSP entities because it is useless. Also if the gamelogic wants to draw more than one instance of a BSP entity in different places, it should be allowed to. Also skip per-surface culling for BSP entity surfaces since we already did culling for the BSP entity as a whole. This is more debatable since the entity could be huge with many sub-surfaces, but the single check seems like enough to me. --- src/engine/renderer/tr_world.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/renderer/tr_world.cpp b/src/engine/renderer/tr_world.cpp index a8bac11e42..a24b58322e 100644 --- a/src/engine/renderer/tr_world.cpp +++ b/src/engine/renderer/tr_world.cpp @@ -194,7 +194,8 @@ void R_AddBSPModelSurfaces( trRefEntity_t *ent ) for ( i = 0; i < bspModel->numSurfaces; i++ ) { - R_AddWorldSurface( bspModel->firstSurface + i, fogNum, -1, FRUSTUM_CLIPALL ); + bspSurface_t *surf = bspModel->firstSurface + i; + R_AddDrawSurf( surf->data, surf->shader, surf->lightmapNum, fogNum, true ); } } From 102659a6da0ee9e4ecd9d4758e0d6c4c58327814 Mon Sep 17 00:00:00 2001 From: slipher Date: Sat, 14 Feb 2026 21:11:19 -0600 Subject: [PATCH 2/2] Fix lighting for BSP model entities Make sure to use the model matrix in the lightMapping shader, so that they get correct normals and dynamic light locations. The bug was that a code path without a model matrix was used when the shader's USE_BSP_SURFACE macro was enabled. Change it to always use the model matrix. Fixes https://github.com/Unvanquished/Unvanquished/issues/3474 --- .../renderer/glsl_source/lightMapping_vp.glsl | 24 ++++------------ src/engine/renderer/tr_shade.cpp | 28 ++++++------------- 2 files changed, 15 insertions(+), 37 deletions(-) diff --git a/src/engine/renderer/glsl_source/lightMapping_vp.glsl b/src/engine/renderer/glsl_source/lightMapping_vp.glsl index 125ff94070..0afe4de3cc 100644 --- a/src/engine/renderer/glsl_source/lightMapping_vp.glsl +++ b/src/engine/renderer/glsl_source/lightMapping_vp.glsl @@ -40,10 +40,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA uniform mat3x2 u_TextureMatrix; #endif -#if defined(USE_MODEL_SURFACE) - uniform mat4 u_ModelMatrix; -#endif - +uniform mat4 u_ModelMatrix; uniform mat4 u_ModelViewProjectionMatrix; uniform float u_Time; @@ -84,21 +81,12 @@ void main() // transform vertex position into homogenous clip-space gl_Position = u_ModelViewProjectionMatrix * position; - #if defined(USE_BSP_SURFACE) - // assign vertex Position - var_Position = position.xyz; + // transform position into world space + var_Position = (u_ModelMatrix * position).xyz; - var_Tangent = LB.tangent; - var_Binormal = LB.binormal; - var_Normal = LB.normal; - #else - // transform position into world space - var_Position = (u_ModelMatrix * position).xyz; - - var_Tangent = (u_ModelMatrix * vec4(LB.tangent, 0.0)).xyz; - var_Binormal = (u_ModelMatrix * vec4(LB.binormal, 0.0)).xyz; - var_Normal = (u_ModelMatrix * vec4(LB.normal, 0.0)).xyz; - #endif + var_Tangent = (u_ModelMatrix * vec4(LB.tangent, 0.0)).xyz; + var_Binormal = (u_ModelMatrix * vec4(LB.binormal, 0.0)).xyz; + var_Normal = (u_ModelMatrix * vec4(LB.normal, 0.0)).xyz; #if defined(USE_LIGHT_MAPPING) || defined(USE_DELUXE_MAPPING) var_TexLight = lmCoord; diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index 7d1a1d5c15..3d7ba302a4 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -1057,32 +1057,22 @@ void Render_lightMapping( shaderStage_t *pStage ) // end choose right shader program ------------------------------ // now we are ready to set the shader program uniforms - vec3_t viewOrigin; - if ( tess.bspSurface ) + if ( glConfig.vboVertexSkinningAvailable && tess.vboVertexSkinning ) { - VectorCopy( backEnd.orientation.viewOrigin, viewOrigin ); // in world space + gl_lightMappingShader->SetUniform_Bones( tess.numBones, tess.bones ); } - else - { - VectorCopy( backEnd.viewParms.orientation.origin, viewOrigin ); // in world space - if ( glConfig.vboVertexSkinningAvailable && tess.vboVertexSkinning ) - { - gl_lightMappingShader->SetUniform_Bones( tess.numBones, tess.bones ); - } - - // u_VertexInterpolation - if ( tess.vboVertexAnimation ) - { - gl_lightMappingShader->SetUniform_VertexInterpolation( glState.vertexAttribsInterpolation ); - } - - gl_lightMappingShader->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); + // u_VertexInterpolation + if ( tess.vboVertexAnimation ) + { + gl_lightMappingShader->SetUniform_VertexInterpolation( glState.vertexAttribsInterpolation ); } + gl_lightMappingShader->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); + // u_ViewOrigin - gl_lightMappingShader->SetUniform_ViewOrigin( viewOrigin ); + gl_lightMappingShader->SetUniform_ViewOrigin( backEnd.viewParms.orientation.origin ); gl_lightMappingShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] );