From 79f046abf739a616202f35be8945bd61fce4032c Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Mon, 20 Jan 2025 16:34:51 +0100 Subject: [PATCH] Support nospecular and allow_nospecular in demos By writing that info into the demo when recording it (when demos are played back, mylevel.map isn't read, only mylevel.proc, so the worldspawn can't be accessed to get allow_nospecular from there) --- Changelog.md | 5 +++++ Configuration.md | 5 +++++ neo/renderer/RenderWorld_demo.cpp | 25 ++++++++++++++++++++----- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index 459d26c3..1a2a2052 100644 --- a/Changelog.md +++ b/Changelog.md @@ -23,6 +23,11 @@ Note: Numbers starting with a "#" like #330 refer to the bugreport with that num * Updated Dear ImGui to 1.91.4 * Fix scaling of Grabber cursor in Resurrection of Evil in non-4:3 resolutions (#637) * Add `com_disableAutoSaves` CVar: If set to `1`, Autosaves (when starting a level) are disabled (#620) +* Add support for "nospecular" parm of lights, enabled by setting `"allow_nospecular" "1"` in a maps + worldspawn, or by setting the `r_allowNoSpecular` CVar to `1`. + Note that this required changing the format of demos. dhewm3 can still play old demos, but ones + recorded with current dhewm3 are not compatible with older dhewm3 versions, original Doom3 or + other source ports (unless they do the same change). 1.5.4 (2024-08-03) ------------------------------------------------------------------------ diff --git a/Configuration.md b/Configuration.md index ed6e9b6f..c561ce0e 100644 --- a/Configuration.md +++ b/Configuration.md @@ -225,6 +225,11 @@ This can be configured with the following CVars: - `r_useCarmacksReverse` Use Z-Fail ("Carmack's Reverse") when rendering shadows (default `1`) - `r_useStencilOpSeparate` Use glStencilOpSeparate() (if available) when rendering shadow (default `1`) - `r_scaleMenusTo43` Render full-screen menus in 4:3 by adding black bars on the left/right if necessary (default `1`) +- `r_supportNoSpecular` Allow using the "nospecular" parm of lights under certain circumstances. If set to: + - `0` "nospecular" will always be ignored, as it's the case in Vanilla Doom3 + - `1` "nospecular" is always used, even in old maps where it changes what they look like + - `-1` (the default) "nospecular" is only used in (new) maps that explicitly enable it + by setting `"allow_nospecular" "1"` in the worldspawn, existing maps continue to ignore it - `r_glDebugContext` Enable OpenGL debug context and printing warnings/errors from the graphics driver. Changing that CVar requires a `vid_restart` (or set it as startup argument) diff --git a/neo/renderer/RenderWorld_demo.cpp b/neo/renderer/RenderWorld_demo.cpp index db94772d..2149b61a 100644 --- a/neo/renderer/RenderWorld_demo.cpp +++ b/neo/renderer/RenderWorld_demo.cpp @@ -108,27 +108,41 @@ bool idRenderWorldLocal::ProcessDemoCommand( idDemoFile *readDemo, renderView_t switch( (demoCommand_t)dc ) { case DC_LOADMAP: + { // read the initial data demoHeader_t header; readDemo->ReadInt( header.version ); + // the internal version value got replaced by DS_VERSION at toplevel + // DG: bumped version to 5 for nospecular support, still support old demos though. + if ( header.version != 4 && header.version != 5 ) { + common->Error( "Demo version mismatch.\n" ); + } + readDemo->ReadInt( header.sizeofRenderEntity ); readDemo->ReadInt( header.sizeofRenderLight ); + // DG: set allowNoSpecular from demo, if it's v5 (otherwise default to false) + // when loading a normal map, this is "allow_nospecular" in the worldspawn + int allowNoSpecular = 0; + if ( header.version == 5 ) { + readDemo->ReadInt( allowNoSpecular ); + } + for ( int i = 0; i < 256; i++ ) readDemo->ReadChar( header.mapname[i] ); - // the internal version value got replaced by DS_VERSION at toplevel - if ( header.version != 4 ) { - common->Error( "Demo version mismatch.\n" ); - } if ( r_showDemo.GetBool() ) { common->Printf( "DC_LOADMAP: %s\n", header.mapname ); } InitFromMap( header.mapname ); + // DG: must be set after InitFromMap(), because that sets it to false as a default + tr.allowNoSpecular = (allowNoSpecular != 0); + newMap = true; // we will need to set demoTimeOffset break; + } case DC_RENDERVIEW: readDemo->ReadInt( renderView->viewID ); @@ -281,12 +295,13 @@ void idRenderWorldLocal::WriteLoadMap() { // so it's good if the ones behind the actual name are *all* \0 strncpy( header.mapname, mapName.c_str(), sizeof( header.mapname ) - 1 ); header.mapname[sizeof( header.mapname ) - 1] = '\0'; // make sure the last chars is also \0 - header.version = 4; + header.version = 5; // DG: bumped to 5 for nospecular support header.sizeofRenderEntity = sizeof( renderEntity_t ); header.sizeofRenderLight = sizeof( renderLight_t ); session->writeDemo->WriteInt( header.version ); session->writeDemo->WriteInt( header.sizeofRenderEntity ); session->writeDemo->WriteInt( header.sizeofRenderLight ); + session->writeDemo->WriteInt( tr.allowNoSpecular ); // DG: added for nospecular support for ( int i = 0; i < 256; i++ ) session->writeDemo->WriteChar( header.mapname[i] );