From 1de5046623e3b97e580ebdf2fc88d573ece0cda6 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 6 Mar 2023 04:52:43 -0800 Subject: [PATCH 1/7] Add cv_debugrender_contrast, adjusts contrast of level geometry debugrender_contrast -1.0 to 1.0, default 0.0 (no change). Higher values add more contrast (darkens the level), lower values add less (brighten). Does not affect thing drawing. Software mode only. Adds r_debug.cpp --- src/CMakeLists.txt | 1 + src/r_debug.cpp | 38 ++++++++++++++++++++++++++++++++++++++ src/r_main.c | 4 ++++ src/r_main.h | 7 +++++++ src/r_plane.c | 2 ++ src/r_segs.c | 18 ++++++++++++++---- 6 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/r_debug.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4e68db60b..8e6233429 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 tables.c r_bsp.c r_data.c + r_debug.cpp r_draw.c r_fps.c r_main.c diff --git a/src/r_debug.cpp b/src/r_debug.cpp new file mode 100644 index 000000000..d090d230e --- /dev/null +++ b/src/r_debug.cpp @@ -0,0 +1,38 @@ +// RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by James Robert Roman. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_debug.cpp +/// \brief Software renderer debugging + +#include // std::clamp + +#include "cxxutil.hpp" + +#include "command.h" +#include "m_fixed.h" +#include "r_main.h" + +namespace +{ + +CV_PossibleValue_t contrast_cons_t[] = {{-FRACUNIT, "MIN"}, {FRACUNIT, "MAX"}, {}}; + +}; // namespace + +consvar_t cv_debugrender_contrast = + CVAR_INIT("debugrender_contrast", "0.0", CV_CHEAT | CV_FLOAT, contrast_cons_t, nullptr); + +INT32 R_AdjustLightLevel(INT32 light) +{ + constexpr fixed_t kRange = (LIGHTLEVELS - 1) * FRACUNIT; + const fixed_t adjust = FixedMul(cv_debugrender_contrast.value, kRange); + + light = std::clamp((light * FRACUNIT) - adjust, 0, kRange); + + return light / FRACUNIT; +} diff --git a/src/r_main.c b/src/r_main.c index b00717810..1e5e7a430 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1656,4 +1656,8 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_fpscap); CV_RegisterVar(&cv_drawpickups); + + // debugging + + CV_RegisterVar(&cv_debugrender_contrast); } diff --git a/src/r_main.h b/src/r_main.h index 01a0d9b31..df17342a2 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -123,6 +123,13 @@ extern consvar_t cv_skybox; extern consvar_t cv_tailspickup; extern consvar_t cv_drawpickups; +// debugging + +INT32 R_AdjustLightLevel(INT32 light); + +extern consvar_t + cv_debugrender_contrast; + // Called by startup code. void R_Init(void); diff --git a/src/r_plane.c b/src/r_plane.c index 4472c9fc3..4638a4081 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -1030,6 +1030,8 @@ void R_DrawSinglePlane(visplane_t *pl) if (light < 0) light = 0; + light = R_AdjustLightLevel(light); + if (pl->slope) { mapfunc = R_MapTiltedPlane; diff --git a/src/r_segs.c b/src/r_segs.c index c00330a4d..b7a25daa0 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -298,6 +298,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) else if (P_ApplyLightOffset(lightnum)) lightnum += curline->lightOffset; + lightnum = R_AdjustLightLevel(lightnum); + if (lightnum < 0) walllights = scalelight[0]; else if (lightnum >= LIGHTLEVELS) @@ -413,12 +415,14 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if ((rlight->flags & FOF_NOSHADE)) continue; - if (rlight->lightnum < 0) + lightnum = R_AdjustLightLevel(rlight->lightnum); + + if (lightnum < 0) xwalllights = scalelight[0]; - else if (rlight->lightnum >= LIGHTLEVELS) + else if (lightnum >= LIGHTLEVELS) xwalllights = scalelight[LIGHTLEVELS-1]; else - xwalllights = scalelight[rlight->lightnum]; + xwalllights = scalelight[lightnum]; pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; @@ -789,6 +793,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) else if (P_ApplyLightOffset(lightnum)) lightnum += curline->lightOffset; + lightnum = R_AdjustLightLevel(lightnum); + if (lightnum < 0) walllights = scalelight[0]; else if (lightnum >= LIGHTLEVELS) @@ -963,7 +969,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) lighteffect = !(dc_lightlist[i].flags & FOF_NOSHADE); if (lighteffect) { - lightnum = rlight->lightnum; + lightnum = R_AdjustLightLevel(rlight->lightnum); if (lightnum < 0) xwalllights = scalelight[0]; @@ -1379,6 +1385,8 @@ static void R_RenderSegLoop (void) else if (P_ApplyLightOffset(lightnum)) lightnum += curline->lightOffset; + lightnum = R_AdjustLightLevel(lightnum); + if (lightnum < 0) xwalllights = scalelight[0]; else if (lightnum >= LIGHTLEVELS) @@ -2425,6 +2433,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (P_ApplyLightOffset(lightnum)) lightnum += curline->lightOffset; + lightnum = R_AdjustLightLevel(lightnum); + if (lightnum < 0) walllights = scalelight[0]; else if (lightnum >= LIGHTLEVELS) From 53b2922fbbc128319415a1f0f238c0693f97b6fe Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 6 Mar 2023 05:10:58 -0800 Subject: [PATCH 2/7] Add the debugrender_highlight command, highlight specific rendering in flat colors Software mode only. The command is used like this: debugrender_highlight planes sprites debugrender_highlight pl spr debugrender_highlight none (Abbreviations work.) Supported rendering to flag: planes - sector floor/ceiling fofplanes - FOF top/bottom fofsides - FOF sides midtextures - pegged midtexture walls - sector upper/lower texture, one-sided linedefs sprites - sprites sky - skybox --- src/CMakeLists.txt | 1 + src/r_debug.cpp | 62 ++++++++++++++++++++++++++- src/r_debug_detail.hpp | 42 +++++++++++++++++++ src/r_debug_parser.cpp | 95 ++++++++++++++++++++++++++++++++++++++++++ src/r_draw.c | 4 ++ src/r_draw.h | 9 ++++ src/r_draw8_flat.c | 79 +++++++++++++++++++++++++++++++++++ src/r_main.c | 2 + src/r_main.h | 17 ++++++++ src/r_plane.c | 29 +++++++++---- src/r_segs.c | 13 ++++++ src/r_things.c | 6 +++ src/screen.c | 31 ++++++++++++-- src/screen.h | 1 + 14 files changed, 380 insertions(+), 11 deletions(-) create mode 100644 src/r_debug_detail.hpp create mode 100644 src/r_debug_parser.cpp create mode 100644 src/r_draw8_flat.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8e6233429..2817abb01 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,6 +65,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 r_bsp.c r_data.c r_debug.cpp + r_debug_parser.cpp r_draw.c r_fps.c r_main.c diff --git a/src/r_debug.cpp b/src/r_debug.cpp index d090d230e..e12eb33b1 100644 --- a/src/r_debug.cpp +++ b/src/r_debug.cpp @@ -12,11 +12,15 @@ #include // std::clamp #include "cxxutil.hpp" +#include "r_debug_detail.hpp" #include "command.h" #include "m_fixed.h" +#include "r_draw.h" #include "r_main.h" +using namespace srb2::r_debug; + namespace { @@ -27,12 +31,68 @@ CV_PossibleValue_t contrast_cons_t[] = {{-FRACUNIT, "MIN"}, {FRACUNIT, "MAX"}, { consvar_t cv_debugrender_contrast = CVAR_INIT("debugrender_contrast", "0.0", CV_CHEAT | CV_FLOAT, contrast_cons_t, nullptr); +UINT32 debugrender_highlight; + +void R_CheckDebugHighlight(debugrender_highlight_t k) +{ + // If highlighting is enabled for anything, surfaces + // must be highlighted in one of two colors, depending on + // whether they fall under focus of the debug. + + if (debugrender_highlight) + { + r8_flatcolor = (debugrender_highlight & (1 << k)) ? detail::kHighlightOptions[k].color : 0x1F; + } +} + INT32 R_AdjustLightLevel(INT32 light) { constexpr fixed_t kRange = (LIGHTLEVELS - 1) * FRACUNIT; const fixed_t adjust = FixedMul(cv_debugrender_contrast.value, kRange); - light = std::clamp((light * FRACUNIT) - adjust, 0, kRange); + if (debugrender_highlight) + { + light = (kRange / 2) - (adjust / 2); + + SRB2_ASSERT(light >= 0); + SRB2_ASSERT(light <= kRange); + } + else + { + light = std::clamp((light * FRACUNIT) - adjust, 0, kRange); + } return light / FRACUNIT; } + +void Command_Debugrender_highlight(void) +{ + const bool changes = COM_Argc() > 1; + + if (!CV_CheatsEnabled()) + { + CONS_Printf("Cheats must be enabled.\n"); + return; + } + + if (changes) + { + const char* arg = COM_Argv(1); + + debugrender_highlight = 0; // always reset + + if (COM_Argc() > 2 || + // approximate match "none" + strncasecmp(arg, "none", strlen(arg))) + { + char* p = COM_Args(); + + while (p) + { + p = detail::parse_highlight_arg(p); + } + } + } + + detail::highlight_help(changes); +} diff --git a/src/r_debug_detail.hpp b/src/r_debug_detail.hpp new file mode 100644 index 000000000..7d495db47 --- /dev/null +++ b/src/r_debug_detail.hpp @@ -0,0 +1,42 @@ +// RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by James Robert Roman. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_debug_detail.cpp +/// \brief Software renderer debugging, internal header + +#ifndef __R_DEBUG_DETAIL__ +#define __R_DEBUG_DETAIL__ + +#include "r_main.h" + +namespace srb2::r_debug::detail +{ + +struct HighlightDesc +{ + uint8_t color; + const char* label; + const char* description; +}; + +constexpr HighlightDesc kHighlightOptions[NUM_SW_HI] = { + {0x96, "planes", "Sector floor/ceiling"}, + {0x49, "fofplanes", "FOF top/bottom"}, + {0xB6, "fofsides", "FOF sides"}, + {0x7A, "midtextures", "Two-sided midtexture"}, + {0xC9, "walls", "Sector upper/lower texture, one-sided midtexture"}, + {0x23, "sprites", "Sprites"}, + {0x0F, "sky", "Sky texture"}}; + +char* skip_alnum(char* p, int mode); +char* parse_highlight_arg(char* p); +void highlight_help(bool only_on); + +}; // srb2::r_debug::detail + +#endif // __R_DEBUG_DETAIL__ diff --git a/src/r_debug_parser.cpp b/src/r_debug_parser.cpp new file mode 100644 index 000000000..8d1d30080 --- /dev/null +++ b/src/r_debug_parser.cpp @@ -0,0 +1,95 @@ +// RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by James Robert Roman. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_debug_parser.cpp +/// \brief Helper functions for the debugrender_highlight command + +#include "r_debug_detail.hpp" + +#include "doomdef.h" +#include "r_main.h" + +using namespace srb2::r_debug; +using namespace srb2::r_debug::detail; + +char* detail::skip_alnum(char* p, int mode) +{ + while (*p != '\0' && !isalnum(*p) == !mode) + { + p++; + } + + return p; +} + +char* detail::parse_highlight_arg(char* p) +{ + INT32 k; + const HighlightDesc* key; + + const auto old = static_cast(debugrender_highlight); + + char* t; + int c; + + p = skip_alnum(p, 0); // skip "whitespace" + + if (*p == '\0') + { + return NULL; + } + + t = skip_alnum(p, 1); // find end of word + + c = *t; // save to restore afterward + *t = '\0'; // isolate word string + + for (k = 0; (key = &kHighlightOptions[k]), k < NUM_SW_HI; ++k) + { + // allow an approximate match + if (!strncasecmp(p, key->label, (t - p))) + { + debugrender_highlight |= (1 << k); + // keep going to match multiple with same + // prefix + } + } + + if (debugrender_highlight == old) + { + // no change? Foolish user + CONS_Alert(CONS_WARNING, "\"%s\" makes no sense\n", p); + } + + *t = c; // restore + + return t; // skip to end of word +} + +void detail::highlight_help(bool only_on) +{ + int32_t k; + const HighlightDesc* key; + + for (k = 0; (key = &kHighlightOptions[k]), k < NUM_SW_HI; ++k) + { + const bool on = (debugrender_highlight & (1 << k)) != 0; + + if (!only_on || on) + { + CONS_Printf("%s\x80 \x87%s\x80 - %s\n", on ? "\x83 ON" : "\x85OFF", key->label, key->description); + } + } + + if (!only_on) + { + CONS_Printf("\nYou can change the highlights by using a command like:\n\n" + "\x87 debugrender_highlight planes sprites\n" + "\x87 debugrender_highlight none\n"); + } +} diff --git a/src/r_draw.c b/src/r_draw.c index 6eb5d6cfb..44959c9d7 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -68,6 +68,8 @@ INT32 columnofs[MAXVIDWIDTH*4]; UINT8 *topleft; +UINT8 r8_flatcolor; + // ========================================================================= // COLUMN DRAWING CODE STUFF // ========================================================================= @@ -81,6 +83,7 @@ UINT8 dc_hires; // under MSVC boolean is a byte, while on other systems, it a bi // soo lets make it a byte on all system for the ASM code UINT8 *dc_source; UINT8 *dc_brightmap; +UINT8 *dc_lightmap; // ----------------------- // translucency stuff here @@ -638,6 +641,7 @@ void R_DrawViewBorder(void) #include "r_draw8.c" #include "r_draw8_npo2.c" +#include "r_draw8_flat.c" // ========================================================================== // INCLUDE 16bpp DRAWING CODE HERE diff --git a/src/r_draw.h b/src/r_draw.h index beb19b739..200ad5183 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -30,6 +30,7 @@ extern UINT8 *ylookup3[MAXVIDHEIGHT*4]; extern UINT8 *ylookup4[MAXVIDHEIGHT*4]; extern INT32 columnofs[MAXVIDWIDTH*4]; extern UINT8 *topleft; +extern UINT8 r8_flatcolor; // ------------------------- // COLUMN DRAWING CODE STUFF @@ -43,6 +44,7 @@ extern UINT8 dc_hires; extern UINT8 *dc_source; // first pixel in a column extern UINT8 *dc_brightmap; // brightmap texture column, can be NULL +extern UINT8 *dc_lightmap; // lighting only // translucency stuff here extern UINT8 *dc_transmap; @@ -76,6 +78,8 @@ extern UINT8 *ds_source; extern UINT8 *ds_brightmap; extern UINT8 *ds_transmap; +extern UINT8 ds_flatcolor; + struct floatv3_t { float x, y, z; }; @@ -232,6 +236,11 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void); void R_DrawTranslucentWaterSpan_NPO2_8(void); void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void); +// Debugging - highlight surfaces in flat colors +void R_DrawColumn_Flat_8(void); +void R_DrawSpan_Flat_8(void); +void R_DrawTiltedSpan_Flat_8(void); + #ifdef USEASM void ASMCALL R_DrawColumn_8_ASM(void); void ASMCALL R_DrawShadeColumn_8_ASM(void); diff --git a/src/r_draw8_flat.c b/src/r_draw8_flat.c new file mode 100644 index 000000000..20372d2c4 --- /dev/null +++ b/src/r_draw8_flat.c @@ -0,0 +1,79 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 2023 by Kart Krew. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_draw8_flat.c +/// \brief 8bpp span/column drawer functions for debugging (draws in flat colors only) +/// \note no includes because this is included as part of r_draw.c + +void R_DrawColumn_Flat_8 (void) +{ + INT32 count; + UINT8 color = dc_lightmap[r8_flatcolor]; + register UINT8 *dest; + + count = dc_yh - dc_yl; + + if (count < 0) // Zero length, column does not exceed a pixel. + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + return; +#endif + + // Framebuffer destination address. + // Use ylookup LUT to avoid multiply with ScreenWidth. + // Use columnofs LUT for subwindows? + + //dest = ylookup[dc_yl] + columnofs[dc_x]; + dest = &topleft[dc_yl*vid.width + dc_x]; + + count++; + + do + { + *dest = color; + dest += vid.width; + } while (--count); +} + +void R_DrawSpan_Flat_8 (void) +{ + UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1]; + + memset(dest, ds_colormap[r8_flatcolor], (ds_x2 - ds_x1) + 1); +} + +void R_DrawTiltedSpan_Flat_8 (void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + + UINT8 *dest = ylookup[ds_y]; + + // Lighting is simple. It's just linear interpolation from start to end + { + float planelightfloat = PLANELIGHTFLOAT; + float lightstart, lightend; + + lightend = (iz + ds_szp->x*width) * planelightfloat; + lightstart = iz * planelightfloat; + + R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); + //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); + } + + while (ds_x1 <= ds_x2) + { + dest[ds_x1] = planezlight[tiltlighting[ds_x1]][r8_flatcolor]; + ds_x1++; + } +} diff --git a/src/r_main.c b/src/r_main.c index 1e5e7a430..e380b7d28 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1660,4 +1660,6 @@ void R_RegisterEngineStuff(void) // debugging CV_RegisterVar(&cv_debugrender_contrast); + + COM_AddCommand("debugrender_highlight", Command_Debugrender_highlight); } diff --git a/src/r_main.h b/src/r_main.h index df17342a2..07bda7e02 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -125,8 +125,25 @@ extern consvar_t cv_drawpickups; // debugging +typedef enum { + SW_HI_PLANES, + SW_HI_FOFPLANES, + SW_HI_FOFSIDES, + SW_HI_MIDTEXTURES, + SW_HI_WALLS, + SW_HI_THINGS, + SW_HI_SKY, + + NUM_SW_HI +} debugrender_highlight_t; + +extern UINT32 debugrender_highlight; + +void R_CheckDebugHighlight(debugrender_highlight_t type); INT32 R_AdjustLightLevel(INT32 light); +void Command_Debugrender_highlight(void); + extern consvar_t cv_debugrender_contrast; diff --git a/src/r_plane.c b/src/r_plane.c index 4638a4081..be4ecd02d 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -208,14 +208,17 @@ static void R_MapPlane(INT32 y, INT32 x1, INT32 x2) pindex = MAXLIGHTZ - 1; ds_colormap = planezlight[pindex]; - if (currentplane->extra_colormap) - ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps); - - ds_fullbright = colormaps; - if (encoremap && !currentplane->noencore) + if (!debugrender_highlight) { - ds_colormap += COLORMAP_REMAPOFFSET; - ds_fullbright += COLORMAP_REMAPOFFSET; + if (currentplane->extra_colormap) + ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps); + + ds_fullbright = colormaps; + if (encoremap && !currentplane->noencore) + { + ds_colormap += COLORMAP_REMAPOFFSET; + ds_fullbright += COLORMAP_REMAPOFFSET; + } } ds_y = y; @@ -613,6 +616,8 @@ static void R_DrawSkyPlane(visplane_t *pl) INT32 x; INT32 angle; + R_CheckDebugHighlight(SW_HI_SKY); + // Reset column drawer function (note: couldn't we just call walldrawerfunc directly?) // (that is, unless we'll need to switch drawers in future for some reason) R_SetColumnFunc(BASEDRAWFUNC, false); @@ -631,6 +636,7 @@ static void R_DrawSkyPlane(visplane_t *pl) dc_colormap += COLORMAP_REMAPOFFSET; dc_fullbright += COLORMAP_REMAPOFFSET; } + dc_lightmap = colormaps; dc_texturemid = skytexturemid; dc_texheight = textureheight[skytexture] >>FRACBITS; @@ -831,6 +837,7 @@ void R_DrawSinglePlane(visplane_t *pl) INT32 x, stop; ffloor_t *rover; INT32 type, spanfunctype = BASEDRAWFUNC; + debugrender_highlight_t debug = 0; void (*mapfunc)(INT32, INT32, INT32) = R_MapPlane; if (!(pl->minx <= pl->maxx)) @@ -911,10 +918,16 @@ void R_DrawSinglePlane(visplane_t *pl) light = (pl->lightlevel >> LIGHTSEGSHIFT); } else light = (pl->lightlevel >> LIGHTSEGSHIFT); + + debug = SW_HI_FOFPLANES; } else + { light = (pl->lightlevel >> LIGHTSEGSHIFT); + debug = SW_HI_PLANES; + } + #ifndef NOWATER if (pl->ripple) { @@ -1085,6 +1098,8 @@ void R_DrawSinglePlane(visplane_t *pl) } + R_CheckDebugHighlight(debug); + // Use the correct span drawer depending on the powers-of-twoness R_SetSpanFunc(spanfunctype, !ds_powersoftwo, ds_brightmap != NULL); diff --git a/src/r_segs.c b/src/r_segs.c index b7a25daa0..0dee4fae3 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -185,6 +185,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) transtable = 0; } + R_CheckDebugHighlight(SW_HI_MIDTEXTURES); + if (blendmode == AST_FOG) { R_SetColumnFunc(COLDRAWFUNC_FOG, bmnum != 0); @@ -440,6 +442,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (height <= windowtop) { dc_colormap = rlight->rcolormap; + dc_lightmap = xwalllights[pindex]; dc_fullbright = colormaps; if (encoremap && !(ldef->flags & ML_TFERLINE)) { @@ -465,6 +468,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) colfunc_2s(col, bmCol, -1); windowtop = windowbottom + 1; dc_colormap = rlight->rcolormap; + dc_lightmap = xwalllights[pindex]; dc_fullbright = colormaps; if (encoremap && !(ldef->flags & ML_TFERLINE)) { @@ -487,6 +491,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; + dc_lightmap = walllights[pindex]; dc_fullbright = colormaps; if (encoremap && !(ldef->flags & ML_TFERLINE)) { @@ -642,6 +647,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture); bmnum = R_GetTextureBrightmap(texnum); + R_CheckDebugHighlight(SW_HI_FOFSIDES); + R_SetColumnFunc(BASEDRAWFUNC, bmnum != 0); if (pfloor->master->flags & ML_TFERLINE) @@ -1033,6 +1040,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (lighteffect) { dc_colormap = rlight->rcolormap; + dc_lightmap = xwalllights[pindex]; dc_fullbright = colormaps; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) { @@ -1069,6 +1077,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (lighteffect) { dc_colormap = rlight->rcolormap; + dc_lightmap = xwalllights[pindex]; dc_fullbright = colormaps; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) { @@ -1093,6 +1102,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; + dc_lightmap = walllights[pindex]; dc_fullbright = colormaps; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) @@ -1359,6 +1369,7 @@ static void R_RenderSegLoop (void) pindex = MAXLIGHTSCALE-1; dc_colormap = walllights[pindex]; + dc_lightmap = walllights[pindex]; dc_fullbright = colormaps; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) { @@ -1626,6 +1637,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) memset(&segleft, 0x00, sizeof(segleft)); memset(&segright, 0x00, sizeof(segright)); + R_CheckDebugHighlight(SW_HI_WALLS); + R_SetColumnFunc(BASEDRAWFUNC, false); if (ds_p == drawsegs+maxdrawsegs) diff --git a/src/r_things.c b/src/r_things.c index 92f9148ee..a1e32c3b2 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -939,6 +939,8 @@ static void R_DrawVisSprite(vissprite_t *vis) if (!dc_colormap) dc_colormap = colormaps; + dc_lightmap = colormaps; + dc_fullbright = colormaps; if (encoremap && !vis->mobj->color && !(vis->mobj->flags & MF_DONTENCOREMAP)) @@ -1143,6 +1145,8 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) dc_fullbright += COLORMAP_REMAPOFFSET; } + dc_lightmap = colormaps; + dc_iscale = FixedDiv(FRACUNIT, vis->scale); dc_texturemid = FixedDiv(vis->texturemid, this_scale); dc_texheight = 0; @@ -3210,6 +3214,8 @@ static void R_DrawSprite(vissprite_t *spr) mfloorclip = spr->clipbot; mceilingclip = spr->cliptop; + R_CheckDebugHighlight(SW_HI_THINGS); + if (spr->cut & SC_BBOX) R_DrawThingBoundingBox(spr); else if (spr->cut & SC_SPLAT) diff --git a/src/screen.c b/src/screen.c index 2b78d03f1..90ccd4bac 100644 --- a/src/screen.c +++ b/src/screen.c @@ -64,6 +64,7 @@ void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void); #ifdef USE_COL_SPAN_ASM void (*spanfuncs_asm[SPANDRAWFUNC_MAX])(void); #endif +void (*spanfuncs_flat[SPANDRAWFUNC_MAX])(void); // ------------------ // global video state @@ -170,6 +171,22 @@ void SCR_SetDrawFuncs(void) spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_FOG] = NULL; // Not needed + // Debugging - highlight surfaces in flat colors + spanfuncs_flat[BASEDRAWFUNC] = R_DrawSpan_Flat_8; + spanfuncs_flat[SPANDRAWFUNC_TRANS] = R_DrawSpan_Flat_8; + spanfuncs_flat[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_Flat_8; + spanfuncs_flat[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedSpan_Flat_8; + spanfuncs_flat[SPANDRAWFUNC_SPLAT] = R_DrawSpan_Flat_8; + spanfuncs_flat[SPANDRAWFUNC_TRANSSPLAT] = R_DrawSpan_Flat_8; + spanfuncs_flat[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSpan_Flat_8; + spanfuncs_flat[SPANDRAWFUNC_SPRITE] = R_DrawSpan_Flat_8; + spanfuncs_flat[SPANDRAWFUNC_TRANSSPRITE] = R_DrawSpan_Flat_8; + spanfuncs_flat[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedSpan_Flat_8; + spanfuncs_flat[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedSpan_Flat_8; + spanfuncs_flat[SPANDRAWFUNC_WATER] = R_DrawSpan_Flat_8; + spanfuncs_flat[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedSpan_Flat_8; + spanfuncs_flat[SPANDRAWFUNC_FOG] = R_DrawSpan_Flat_8; // Not needed + #if (defined(RUSEASM) && defined(USE_COL_SPAN_ASM)) if (R_ASM) { @@ -220,13 +237,17 @@ void R_SetColumnFunc(size_t id, boolean brightmapped) colfunctype = id; + if (debugrender_highlight != 0) + { + colfunc = R_DrawColumn_Flat_8; + } #ifdef USE_COL_SPAN_ASM - if (colfuncs_asm[id] != NULL && brightmapped == false) + else if (colfuncs_asm[id] != NULL && brightmapped == false) { colfunc = colfuncs_asm[id]; } - else #endif + else { colfunc = colfuncs[id]; } @@ -236,7 +257,11 @@ void R_SetSpanFunc(size_t id, boolean npo2, boolean brightmapped) { I_Assert(id < SPANDRAWFUNC_MAX); - if (spanfuncs_npo2[id] != NULL && npo2 == true) + if (spanfuncs_flat[id] != NULL && debugrender_highlight != 0) + { + spanfunc = spanfuncs_flat[id]; + } + else if (spanfuncs_npo2[id] != NULL && npo2 == true) { spanfunc = spanfuncs_npo2[id]; } diff --git a/src/screen.h b/src/screen.h index f76fe05a3..e9cfc7d59 100644 --- a/src/screen.h +++ b/src/screen.h @@ -179,6 +179,7 @@ extern void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void); #ifdef USE_COL_SPAN_ASM extern void (*spanfuncs_asm[SPANDRAWFUNC_MAX])(void); #endif +extern void (*spanfuncs_flat[SPANDRAWFUNC_MAX])(void); // ----- // CPUID From aed9fe996c9c577b139b18e11e804faeff4f2500 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 6 Mar 2023 05:14:57 -0800 Subject: [PATCH 3/7] Add cv_debugrender_spriteclip, toggle sprite clipping This cvar can be used to reveal which sprites are technically drawn but clipped completely by level geometry. --- src/r_debug.cpp | 2 ++ src/r_main.c | 1 + src/r_main.h | 3 ++- src/r_things.c | 20 ++++++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/r_debug.cpp b/src/r_debug.cpp index e12eb33b1..570cc3754 100644 --- a/src/r_debug.cpp +++ b/src/r_debug.cpp @@ -31,6 +31,8 @@ CV_PossibleValue_t contrast_cons_t[] = {{-FRACUNIT, "MIN"}, {FRACUNIT, "MAX"}, { consvar_t cv_debugrender_contrast = CVAR_INIT("debugrender_contrast", "0.0", CV_CHEAT | CV_FLOAT, contrast_cons_t, nullptr); +consvar_t cv_debugrender_spriteclip = CVAR_INIT("debugrender_spriteclip", "Off", CV_CHEAT, CV_OnOff, nullptr); + UINT32 debugrender_highlight; void R_CheckDebugHighlight(debugrender_highlight_t k) diff --git a/src/r_main.c b/src/r_main.c index e380b7d28..bf5fd78fe 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1660,6 +1660,7 @@ void R_RegisterEngineStuff(void) // debugging CV_RegisterVar(&cv_debugrender_contrast); + CV_RegisterVar(&cv_debugrender_spriteclip); COM_AddCommand("debugrender_highlight", Command_Debugrender_highlight); } diff --git a/src/r_main.h b/src/r_main.h index 07bda7e02..208d846a9 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -145,7 +145,8 @@ INT32 R_AdjustLightLevel(INT32 light); void Command_Debugrender_highlight(void); extern consvar_t - cv_debugrender_contrast; + cv_debugrender_contrast, + cv_debugrender_spriteclip; // Called by startup code. void R_Init(void); diff --git a/src/r_things.c b/src/r_things.c index a1e32c3b2..5f29920a5 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2982,6 +2982,16 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps for (r2 = head->next; r2 != head; r2 = r2->next) { + if (cv_debugrender_spriteclip.value) + { + // Only sort behind other sprites; sorts in + // front of everything else. + if (!r2->sprite) + { + continue; + } + } + if (r2->plane) { fixed_t planeobjectz, planecameraz; @@ -3244,6 +3254,16 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal) fixed_t lowscale; INT32 silhouette; + if (cv_debugrender_spriteclip.value) + { + for (x = x1; x <= x2; x++) + { + spr->clipbot[x] = (INT16)viewheight; + spr->cliptop[x] = (INT16)con_clipviewtop; + } + return; + } + for (x = x1; x <= x2; x++) { spr->clipbot[x] = spr->cliptop[x] = CLIP_UNDEF; From f71ba63cd3f1217a2b2f7112f270f96bea4e5680 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 6 Mar 2023 05:56:00 -0800 Subject: [PATCH 4/7] Add RF_ALWAYSONTOP, renders sprite through walls Specifically, it avoids sorting or clipping the sprite against stuff like FOF planes, which are notorious for messing up sprites. Useful for debug stuff which absolutely must be visible. --- src/deh_tables.c | 1 + src/r_defs.h | 2 ++ src/r_things.c | 16 ++++++++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index de88639e8..14d4696f8 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -6303,6 +6303,7 @@ struct int_const_s const INT_CONST[] = { {"RF_FULLDARK",RF_FULLDARK}, {"RF_SEMIBRIGHT",RF_SEMIBRIGHT}, {"RF_NOCOLORMAPS",RF_NOCOLORMAPS}, + {"RF_ALWAYSONTOP",RF_ALWAYSONTOP}, {"RF_SPRITETYPEMASK",RF_SPRITETYPEMASK}, {"RF_PAPERSPRITE",RF_PAPERSPRITE}, {"RF_FLOORSPRITE",RF_FLOORSPRITE}, diff --git a/src/r_defs.h b/src/r_defs.h index d4606c8ad..4e947616b 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -932,6 +932,8 @@ typedef enum RF_NOCOLORMAPS = 0x00000400, // Sprite is not drawn with colormaps + RF_ALWAYSONTOP = 0x00000800, // Sprite is drawn on top of level geometry + RF_SPRITETYPEMASK = 0x00003000, // --Different sprite types RF_PAPERSPRITE = 0x00001000, // Paper sprite RF_FLOORSPRITE = 0x00002000, // Floor sprite diff --git a/src/r_things.c b/src/r_things.c index 5f29920a5..458eaac4e 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2975,6 +2975,9 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps for (rover = vsprsortedhead.prev; rover != &vsprsortedhead; rover = rover->prev) { + const boolean alwaysontop = cv_debugrender_spriteclip.value || (rover->renderflags & RF_ALWAYSONTOP); + const INT32 ontopflag = cv_debugrender_spriteclip.value ? 0 : (rover->renderflags & RF_ALWAYSONTOP); + if (rover->szt > vid.height || rover->sz < 0) continue; @@ -2982,7 +2985,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps for (r2 = head->next; r2 != head; r2 = r2->next) { - if (cv_debugrender_spriteclip.value) + if (alwaysontop) { // Only sort behind other sprites; sorts in // front of everything else. @@ -2990,6 +2993,15 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps { continue; } + + // Only sort behind other RF_ALWAYSONTOP sprites. + // This avoids sorting behind a sprite that is + // behind level geometry and thus sorting this + // one behind level geometry too. + if (r2->sprite->renderflags ^ ontopflag) + { + continue; + } } if (r2->plane) @@ -3254,7 +3266,7 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal) fixed_t lowscale; INT32 silhouette; - if (cv_debugrender_spriteclip.value) + if ((spr->renderflags & RF_ALWAYSONTOP) || cv_debugrender_spriteclip.value) { for (x = x1; x <= x2; x++) { From 99362bc9b283d0b6a5cdf31d8dae1be42572a9dc Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 6 Mar 2023 05:58:07 -0800 Subject: [PATCH 5/7] Give debugwaypoints orb and radius RF_ALWAYSONTOP Makes the radius always visible in full. --- src/k_waypoint.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/k_waypoint.c b/src/k_waypoint.c index cf70c1dcd..27465856a 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -578,7 +578,7 @@ static void K_DebugWaypointDrawRadius(waypoint_t *const waypoint) spawnX = waypointmobj->x; spawnY = waypointmobj->y; - spawnZ = waypointmobj->z + 16*mapobjectscale; + spawnZ = waypointmobj->z; radiusOrb = P_SpawnMobj(spawnX, spawnY, spawnZ, MT_SPARK); @@ -588,6 +588,7 @@ static void K_DebugWaypointDrawRadius(waypoint_t *const waypoint) radiusOrb->frame &= ~FF_TRANSMASK; radiusOrb->frame |= FF_FULLBRIGHT; radiusOrb->color = SKINCOLOR_PURPLE; + radiusOrb->renderflags |= RF_ALWAYSONTOP; radiusOrb->destscale = FixedDiv(waypointmobj->radius, spriteRadius); P_SetScale(radiusOrb, radiusOrb->destscale); @@ -627,6 +628,7 @@ void K_DebugWaypointsVisualise(void) debugmobj->frame &= ~FF_TRANSMASK; debugmobj->frame |= FF_FULLBRIGHT; //FF_TRANS20 + debugmobj->renderflags |= RF_ALWAYSONTOP; // There's a waypoint setup for this mobj! So draw that it's a valid waypoint and draw lines to its connections if (waypoint != NULL) From c1fabe8e355cdbac5b433cf8cabacfd8add35f86 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 6 Mar 2023 06:22:47 -0800 Subject: [PATCH 6/7] Make debugwaypoints radius reverse subtractive --- src/k_waypoint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 27465856a..ca4746357 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -586,7 +586,7 @@ static void K_DebugWaypointDrawRadius(waypoint_t *const waypoint) radiusOrb->tics = 1; radiusOrb->frame &= ~FF_TRANSMASK; - radiusOrb->frame |= FF_FULLBRIGHT; + radiusOrb->frame |= FF_FULLBRIGHT|FF_REVERSESUBTRACT; radiusOrb->color = SKINCOLOR_PURPLE; radiusOrb->renderflags |= RF_ALWAYSONTOP; From 154cc7718667fa546f85005626d920dbd22ee723 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 6 Mar 2023 07:05:42 -0800 Subject: [PATCH 7/7] Return quickly from R_AdjustLightLevel if possible --- src/r_debug.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/r_debug.cpp b/src/r_debug.cpp index 570cc3754..8fbe9390d 100644 --- a/src/r_debug.cpp +++ b/src/r_debug.cpp @@ -49,6 +49,11 @@ void R_CheckDebugHighlight(debugrender_highlight_t k) INT32 R_AdjustLightLevel(INT32 light) { + if (!debugrender_highlight && cv_debugrender_contrast.value == 0) + { + return light; + } + constexpr fixed_t kRange = (LIGHTLEVELS - 1) * FRACUNIT; const fixed_t adjust = FixedMul(cv_debugrender_contrast.value, kRange);