Support lights "nospecular" parm (if explicitly enabled)

based on https://github.com/dhewm/dhewm3/pull/254

The "nospecular" parm will only be used if either
r_supportNoSpecular is set to 1
or r_supportNoSpecular is set to -1 (the default) and the maps spawnargs
contain "allow_nospecular" "1"

This probably doesn't work with (time)demos yet, because I think when
they're being played I can't access the worldspawn entity
This commit is contained in:
Daniel Gibson 2025-01-19 06:29:56 +01:00
parent ab333c68c3
commit 2d068377ae
4 changed files with 57 additions and 7 deletions

View file

@ -41,6 +41,7 @@ If you have questions concerning this license or the applicable additional terms
#include "renderer/tr_local.h"
#include "framework/GameCallbacks_local.h"
#include "framework/Game.h"
// Vista OpenGL wrapper check
#ifdef _WIN32
@ -171,6 +172,13 @@ idCVar r_forceLoadImages( "r_forceLoadImages", "0", CVAR_RENDERER | CVAR_ARCHIVE
idCVar r_orderIndexes( "r_orderIndexes", "1", CVAR_RENDERER | CVAR_BOOL, "perform index reorganization to optimize vertex use" );
idCVar r_lightAllBackFaces( "r_lightAllBackFaces", "0", CVAR_RENDERER | CVAR_BOOL, "light all the back faces, even when they would be shadowed" );
// DG: added this to support "nospecular" param of lights
// NOTE: if you're developing a standalone game, you'll probably want to use "1" as default value
idCVar r_supportNoSpecular( "r_supportNoSpecular", "-1", CVAR_RENDERER | CVAR_INTEGER | CVAR_ARCHIVE,
"Support 'nospecular' parm on lights. Vanilla Doom3 didn't, so the original maps are probably "
"expecting it to not do anything. -1: Only support in maps that have have \"allow_nospecular\" \"1\" set in worldspawn (default), "
"0: never respect 'nospecular' parm 1: support 'nospecular' in all maps", -1, 1 );
// visual debugging info
idCVar r_showPortals( "r_showPortals", "0", CVAR_RENDERER | CVAR_BOOL, "draw portal outlines in color based on passed / not passed" );
idCVar r_showUnsmoothedTangents( "r_showUnsmoothedTangents", "0", CVAR_RENDERER | CVAR_BOOL, "if 1, put all nvidia register combiner programming in display lists" );
@ -2330,6 +2338,7 @@ void idRenderSystemLocal::Clear( void ) {
guiModel = NULL;
demoGuiModel = NULL;
takingScreenshot = false;
allowNoSpecular = false;
}
/*
@ -2439,6 +2448,23 @@ void idRenderSystemLocal::EndLevelLoad( void ) {
if ( r_forceLoadImages.GetBool() ) {
RB_ShowImages();
}
// DG: check if the levels worldspawn has "allow_nospecular" set, which tells us that
// the map author wants "nospecular" parms of lights to be respected by the renderer
// (Vanilla Doom3 didn't, even though some official levels have it set, so to not
// change the look of the original game it must be enabled in the worldspawn of new maps)
// See also the r_supportNoSpecular CVar (the allowNoSpecular set here only makes
// a difference if r_supportNoSpecular is -1, which is the default)
allowNoSpecular = false;
if ( gameEdit != NULL ) {
idEntity* ent = gameEdit->FindEntity( "world" ); // the worldspawn always called "world"
const idDict* ws = gameEdit->EntityGetSpawnArgs( ent );
if ( ws != NULL ) {
allowNoSpecular = ws->GetBool( "allow_nospecular", "0" );
if ( allowNoSpecular ) {
common->Printf( "This map allows lights to use the 'nospecular' parm on lights\n" );
}
}
}
}
/*

View file

@ -491,6 +491,9 @@ bool idRenderWorldLocal::InitFromMap( const char *name ) {
return true;
}
// DG: this must be set to false somewhere as a default, here feels safe
// (it will be properly set in idRenderSystemLocal::EndLevelLoad())
tr.allowNoSpecular = false;
// load it
filename = name;

View file

@ -805,6 +805,10 @@ public:
// so they can be reset in EndFrame() (Editors tend to mess up the viewport by using BeginFrame())
int origWidth;
int origHeight;
// DG: taken from the current map's worldspawn ("allow_nospecular")
// true if (unlike in Vanilla Doom3) the "nospecular" parm of a light should be respected
bool allowNoSpecular;
};
extern backEndState_t backEnd;
@ -882,6 +886,8 @@ extern idCVar r_useEntityCallbacks; // if 0, issue the callback immediately at
extern idCVar r_lightAllBackFaces; // light all the back faces, even when they would be shadowed
extern idCVar r_useDepthBoundsTest; // use depth bounds test to reduce shadow fill
extern idCVar r_supportNoSpecular; // support nospecular parm of lights
extern idCVar r_skipPostProcess; // skip all post-process renderings
extern idCVar r_skipSuppress; // ignore the per-view suppressions
extern idCVar r_skipInteractions; // skip all light/surface interaction drawing

View file

@ -706,6 +706,16 @@ void RB_CreateSingleDrawInteractions( const drawSurf_t *surf, void (*DrawInterac
return;
}
// DG: support lights nospecular parm, if desired by mapper and/or user
int noSpecVar = r_supportNoSpecular.GetInteger();
bool allowNoSpecular = (noSpecVar == 1);
if ( noSpecVar == -1 ) {
// r_supportNoSpecular -1 only allows nospecular if the map enables
// it in the worldspawn by setting "allow_nospecular" "1"
// the value of that is saved in tr.allowNoSpecular by idRenderSystemLocal::EndLevelLoad()
allowNoSpecular = tr.allowNoSpecular;
}
// change the matrix and light projection vectors if needed
if ( surf->space != backEnd.currentSpace ) {
backEnd.currentSpace = surf->space;
@ -823,13 +833,18 @@ void RB_CreateSingleDrawInteractions( const drawSurf_t *surf, void (*DrawInterac
if ( inter.specularImage ) {
RB_SubmittInteraction( &inter, DrawInteraction );
}
R_SetDrawInteraction( surfaceStage, surfaceRegs, &inter.specularImage,
inter.specularMatrix, inter.specularColor.ToFloatPtr() );
inter.specularColor[0] *= lightColor[0];
inter.specularColor[1] *= lightColor[1];
inter.specularColor[2] *= lightColor[2];
inter.specularColor[3] *= lightColor[3];
inter.vertexColor = surfaceStage->vertexColor;
// jmarshall - add no specular support(great for fill lighting).
if ( !allowNoSpecular || !vLight->lightDef->parms.noSpecular )
{
R_SetDrawInteraction( surfaceStage, surfaceRegs, &inter.specularImage,
inter.specularMatrix, inter.specularColor.ToFloatPtr() );
inter.specularColor[0] *= lightColor[0];
inter.specularColor[1] *= lightColor[1];
inter.specularColor[2] *= lightColor[2];
inter.specularColor[3] *= lightColor[3];
inter.vertexColor = surfaceStage->vertexColor;
}
// jmarshall end
break;
}
}