Skip to content

Commit

Permalink
ref: gl: add r_dlight_virtual_radius. It potentially fixes ugly dligh…
Browse files Browse the repository at this point in the history
…t cut off on largely scaled textures (or at least allows to tune it)

It also adds a fix found in JoeQuake (which traces back to FitzQuake, in which
it is attributed to LadyHavoc, Darkplaces author) to exactly calculate whether
the light hits the surface, so we don't wrongly enable lighting on a surface by
an increased radius.
  • Loading branch information
a1batross committed Feb 7, 2025
1 parent a955d1e commit b5cb0b9
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 19 deletions.
3 changes: 2 additions & 1 deletion ref/gl/gl_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ void R_TextureReplacementReport( const char *modelname, int gl_texturenum, const
void CL_RunLightStyles( lightstyle_t *ls );
void R_PushDlights( void );
void R_GetLightSpot( vec3_t lightspot );
void R_MarkLights( dlight_t *light, int bit, mnode_t *node );
void R_MarkLights( const dlight_t *light, int bit, const mnode_t *node );
colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lightspot, vec3_t lightvec );
colorVec R_LightPoint( const vec3_t p0 );

Expand Down Expand Up @@ -812,6 +812,7 @@ extern convar_t r_ripple;
extern convar_t r_ripple_updatetime;
extern convar_t r_ripple_spawntime;
extern convar_t r_large_lightmaps;
extern convar_t r_dlight_virtual_radius;

//
// engine shared convars
Expand Down
2 changes: 2 additions & 0 deletions ref/gl/gl_opengl.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ CVAR_DEFINE_AUTO( r_ripple, "0", FCVAR_GLCONFIG, "enable software-like water tex
CVAR_DEFINE_AUTO( r_ripple_updatetime, "0.05", FCVAR_GLCONFIG, "how fast ripple simulation is" );
CVAR_DEFINE_AUTO( r_ripple_spawntime, "0.1", FCVAR_GLCONFIG, "how fast new ripples spawn" );
CVAR_DEFINE_AUTO( r_large_lightmaps, "0", FCVAR_GLCONFIG|FCVAR_LATCH, "enable larger lightmap atlas textures (might break custom renderer mods)" );
CVAR_DEFINE_AUTO( r_dlight_virtual_radius, "3", FCVAR_GLCONFIG, "increase dlight radius virtually by this amount, should help against ugly cut off dlights on highly scaled textures" );

DEFINE_ENGINE_SHARED_CVAR_LIST()

Expand Down Expand Up @@ -1155,6 +1156,7 @@ static void GL_InitCommands( void )
gEngfuncs.Cvar_RegisterVariable( &r_vbo_overbrightmode );
gEngfuncs.Cvar_RegisterVariable( &r_vbo_detail );
gEngfuncs.Cvar_RegisterVariable( &r_large_lightmaps );
gEngfuncs.Cvar_RegisterVariable( &r_dlight_virtual_radius );

gEngfuncs.Cvar_RegisterVariable( &gl_extensions );
gEngfuncs.Cvar_RegisterVariable( &gl_texture_nearest );
Expand Down
64 changes: 46 additions & 18 deletions ref/gl/gl_rlight.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,48 +99,76 @@ void CL_RunLightStyles( lightstyle_t *ls )
R_MarkLights
=============
*/
void R_MarkLights( dlight_t *light, int bit, mnode_t *node )
void R_MarkLights( const dlight_t *light, int bit, const mnode_t *node )
{
float dist;
msurface_t *surf;
int i;
const float virtual_radius = light->radius * Q_max( 1.0f, r_dlight_virtual_radius.value );
const float maxdist = light->radius * light->radius;
float dist;
int i;
mnode_t *children[2];
int firstsurface, numsurfaces;

start:

if( !node || node->contents < 0 )
return;

dist = PlaneDiff( light->origin, node->plane );

node_children( children, node, RI.currentmodel );
firstsurface = node_firstsurface( node, RI.currentmodel );
numsurfaces = node_numsurfaces( node, RI.currentmodel );

if( dist > light->radius )
if( dist > virtual_radius )
{
R_MarkLights( light, bit, children[0] );
return;
node = children[0];
goto start;
}
if( dist < -light->radius )

if( dist < -virtual_radius )
{
R_MarkLights( light, bit, children[1] );
return;
node = children[1];
goto start;
}

// mark the polygons
surf = RI.currentmodel->surfaces + firstsurface;
firstsurface = node_firstsurface( node, RI.currentmodel );
numsurfaces = node_numsurfaces( node, RI.currentmodel );

for( i = 0; i < numsurfaces; i++, surf++ )
for( i = 0; i < numsurfaces; i++ )
{
if( !BoundsAndSphereIntersect( surf->info->mins, surf->info->maxs, light->origin, light->radius ))
continue; // no intersection
vec3_t impact;
float s, t, l;
msurface_t *surf = &RI.currentmodel->surfaces[firstsurface + i];
const mextrasurf_t *info = surf->info;

if( surf->plane->type < 3 )
{
VectorCopy( light->origin, impact );
impact[surf->plane->type] -= dist;
}
else VectorMA( light->origin, -dist, surf->plane->normal, impact );

// a1ba: the fix was taken from JoeQuake, which traces back to FitzQuake,
// which attributes it to LadyHavoc (Darkplaces author)
// clamp center of light to corner and check brightness
l = DotProduct( impact, info->lmvecs[0] ) + info->lmvecs[0][3] - info->lightmapmins[0];
s = l + 0.5;
s = bound( 0, s, info->lightextents[0] );
s = l - s;

l = DotProduct( impact, info->lmvecs[1] ) + info->lmvecs[1][3] - info->lightmapmins[1];
t = l + 0.5;
t = bound( 0, t, info->lightextents[1] );
t = l - t;

if( s * s + t * t + dist * dist >= maxdist )
continue;

if( surf->dlightframe != tr.dlightframecount )
{
surf->dlightbits = 0;
surf->dlightbits = bit;
surf->dlightframe = tr.dlightframecount;
}
surf->dlightbits |= bit;
else surf->dlightbits |= bit;
}

R_MarkLights( light, bit, children[0] );
Expand Down

0 comments on commit b5cb0b9

Please sign in to comment.