Skip to content

Commit ca05136

Browse files
committed
Frustum cull fogs
Use CPU-side frustum culling to avoid drawing fogs when possible. Also don't recalculate the near plane distance (for checking if fogs are too close to the camera) every iteration when looping fogs.
1 parent 149c3c6 commit ca05136

File tree

3 files changed

+20
-9
lines changed

3 files changed

+20
-9
lines changed

src/engine/renderer/tr_local.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2823,7 +2823,7 @@ inline bool checkGLErrors()
28232823
void R_LocalNormalToWorld( const vec3_t local, vec3_t world );
28242824
void R_LocalPointToWorld( const vec3_t local, vec3_t world );
28252825

2826-
cullResult_t R_CullBox( vec3_t worldBounds[ 2 ] );
2826+
cullResult_t R_CullBox( const vec3_t worldBounds[ 2 ], int lastPlane = FRUSTUM_NEAR );
28272827
cullResult_t R_CullLocalBox( vec3_t bounds[ 2 ] );
28282828
cullResult_t R_CullLocalPointAndRadius( vec3_t origin, float radius );
28292829
cullResult_t R_CullPointAndRadius( vec3_t origin, float radius );

src/engine/renderer/tr_main.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ R_CullBox
341341
Returns CULL_IN, CULL_CLIP, or CULL_OUT
342342
=================
343343
*/
344-
cullResult_t R_CullBox( vec3_t worldBounds[ 2 ] )
344+
cullResult_t R_CullBox( const vec3_t worldBounds[ 2 ], int lastPlane )
345345
{
346346
bool anyClip;
347347
cplane_t *frust;
@@ -355,7 +355,7 @@ cullResult_t R_CullBox( vec3_t worldBounds[ 2 ] )
355355
// check against frustum planes
356356
anyClip = false;
357357

358-
for ( i = 0; i < FRUSTUM_PLANES; i++ )
358+
for ( i = 0; i <= lastPlane; i++ )
359359
{
360360
frust = &tr.viewParms.frustum[ i ];
361361

@@ -837,7 +837,7 @@ static void R_SetupFrustum()
837837
MatrixAffineInverse(tr.viewParms.world.viewMatrix, invTransform);
838838

839839
//transform planes back to world space for culling
840-
for (int i = 0; i <= FRUSTUM_NEAR; i++)
840+
for (int i = 0; i < FRUSTUM_PLANES; i++)
841841
{
842842
plane_t plane;
843843
VectorCopy(tr.viewParms.portalFrustum[i].normal, plane.normal);
@@ -881,13 +881,18 @@ static void R_SetupFrustum()
881881
SetPlaneSignbits( &tr.viewParms.frustum[ i ] );
882882
}
883883

884-
// Tr3B: set extra near plane which is required by the dynamic occlusion culling
885884
tr.viewParms.frustum[ FRUSTUM_NEAR ].type = PLANE_NON_AXIAL;
886885
VectorCopy( tr.viewParms.orientation.axis[ 0 ], tr.viewParms.frustum[ FRUSTUM_NEAR ].normal );
887886

888887
VectorMA( tr.viewParms.orientation.origin, r_znear->value, tr.viewParms.frustum[ FRUSTUM_NEAR ].normal, planeOrigin );
889888
tr.viewParms.frustum[ FRUSTUM_NEAR ].dist = DotProduct( planeOrigin, tr.viewParms.frustum[ FRUSTUM_NEAR ].normal );
890889
SetPlaneSignbits( &tr.viewParms.frustum[ FRUSTUM_NEAR ] );
890+
891+
tr.viewParms.frustum[ FRUSTUM_FAR ].type = PLANE_NON_AXIAL;
892+
VectorCopy( tr.viewParms.orientation.axis[ 0 ], tr.viewParms.frustum[ FRUSTUM_FAR ].normal );
893+
tr.viewParms.frustum[ FRUSTUM_FAR ].dist = tr.viewParms.zFar +
894+
DotProduct( tr.viewParms.orientation.origin, tr.viewParms.frustum[ FRUSTUM_FAR ].normal );
895+
SetPlaneSignbits( &tr.viewParms.frustum[ FRUSTUM_FAR ] );
891896
}
892897
}
893898

src/engine/renderer/tr_scene.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,12 @@ static float NearPlaneCornerDist()
229229
// issue on the surface plane, since the GLSL calcs chop off overhang there. Note that
230230
// with original Q3 you are required to construct the fog so that it is impossible to pass
231231
// through non-surface planes at all.
232-
static bool R_InsideFog( int fognum )
232+
static bool R_InsideFog( int fognum, float tol )
233233
{
234234
// TODO: with portals this should use the point at the view frustum near plane instead
235235
const vec3_t &origin = tr.viewParms.orientation.origin;
236236

237237
const auto &bounds = tr.world->fogs[ fognum ].bounds;
238-
float tol = NearPlaneCornerDist() + 0.1f;
239238

240239
for ( int i = 0; i < 3; i++ )
241240
{
@@ -250,11 +249,18 @@ static bool R_InsideFog( int fognum )
250249

251250
void R_AddFogBrushSurfaces()
252251
{
253-
// TODO: incorporate them in the BSP?
252+
float tol = NearPlaneCornerDist() + 0.1f;
253+
254254
for ( int i = 1; i < tr.world->numFogs; i++ )
255255
{
256256
const fog_t &fog = tr.world->fogs[ i ];
257-
shader_t *shader = R_InsideFog( i )
257+
258+
if ( R_CullBox( fog.bounds, FRUSTUM_FAR ) == cullResult_t::CULL_OUT )
259+
{
260+
continue;
261+
}
262+
263+
shader_t *shader = R_InsideFog( i, tol )
258264
? fog.shader->fogInnerShader
259265
: fog.shader->fogOuterShader;
260266
R_AddDrawSurf( ( surfaceType_t *)&fog.surf, shader, -1 );

0 commit comments

Comments
 (0)