diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 04d1c6040..e0313a411 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,8 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 tables.c 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/deh_tables.c b/src/deh_tables.c index 1745d9a7d..9cae9323e 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -6307,6 +6307,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/k_waypoint.c b/src/k_waypoint.c index b0ed8b39b..0322b5548 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -601,7 +601,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); @@ -609,8 +609,9 @@ 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; radiusOrb->destscale = FixedDiv(waypointmobj->radius, spriteRadius); P_SetScale(radiusOrb, radiusOrb->destscale); @@ -650,6 +651,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) diff --git a/src/r_debug.cpp b/src/r_debug.cpp new file mode 100644 index 000000000..8fbe9390d --- /dev/null +++ b/src/r_debug.cpp @@ -0,0 +1,105 @@ +// 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 "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 +{ + +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); + +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) +{ + // 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) +{ + 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); + + 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_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_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 2b9105c05..d019af9a2 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1674,4 +1674,11 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_fpscap); CV_RegisterVar(&cv_drawpickups); + + // 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 01a0d9b31..208d846a9 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -123,6 +123,31 @@ extern consvar_t cv_skybox; extern consvar_t cv_tailspickup; 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, + cv_debugrender_spriteclip; + // Called by startup code. void R_Init(void); diff --git a/src/r_plane.c b/src/r_plane.c index 4472c9fc3..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) { @@ -1030,6 +1043,8 @@ void R_DrawSinglePlane(visplane_t *pl) if (light < 0) light = 0; + light = R_AdjustLightLevel(light); + if (pl->slope) { mapfunc = R_MapTiltedPlane; @@ -1083,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 c00330a4d..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); @@ -298,6 +300,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 +417,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; @@ -436,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)) { @@ -461,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)) { @@ -483,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)) { @@ -638,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) @@ -789,6 +800,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 +976,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]; @@ -1027,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)) { @@ -1063,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)) { @@ -1087,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)) @@ -1353,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)) { @@ -1379,6 +1396,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) @@ -1618,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) @@ -2425,6 +2446,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) diff --git a/src/r_things.c b/src/r_things.c index 92f9148ee..458eaac4e 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; @@ -2971,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; @@ -2978,6 +2985,25 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps for (r2 = head->next; r2 != head; r2 = r2->next) { + if (alwaysontop) + { + // Only sort behind other sprites; sorts in + // front of everything else. + if (!r2->sprite) + { + 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) { fixed_t planeobjectz, planecameraz; @@ -3210,6 +3236,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) @@ -3238,6 +3266,16 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal) fixed_t lowscale; INT32 silhouette; + if ((spr->renderflags & RF_ALWAYSONTOP) || 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; 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