From dce3a1c81cff8ec7f16b61d4218ceec504766b98 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 11 Jan 2017 15:41:42 +0100 Subject: [PATCH] Move remaining parts of r_things into r_visiblesprite --- src/CMakeLists.txt | 1 - src/polyrenderer/scene/poly_playersprite.cpp | 1 - src/swrenderer/drawers/r_draw_pal.cpp | 1 - src/swrenderer/line/r_fogboundary.cpp | 1 - src/swrenderer/plane/r_flatplane.cpp | 1 - src/swrenderer/plane/r_skyplane.cpp | 1 - src/swrenderer/plane/r_slopeplane.cpp | 1 - src/swrenderer/plane/r_visibleplane.cpp | 1 - src/swrenderer/r_main.cpp | 1 - src/swrenderer/scene/r_bsp.cpp | 1 - src/swrenderer/scene/r_portal.cpp | 2 +- src/swrenderer/scene/r_things.cpp | 760 ------------------- src/swrenderer/scene/r_things.h | 53 -- src/swrenderer/segments/r_clipsegment.cpp | 1 - src/swrenderer/segments/r_drawsegment.cpp | 4 +- src/swrenderer/segments/r_portalsegment.cpp | 1 - src/swrenderer/things/r_decal.cpp | 3 +- src/swrenderer/things/r_particle.cpp | 3 +- src/swrenderer/things/r_playersprite.cpp | 2 +- src/swrenderer/things/r_sprite.cpp | 2 +- src/swrenderer/things/r_visiblesprite.cpp | 656 ++++++++++++++++ src/swrenderer/things/r_visiblesprite.h | 14 + src/swrenderer/things/r_voxel.cpp | 6 +- src/swrenderer/things/r_voxel.h | 1 + src/swrenderer/things/r_wallsprite.cpp | 3 +- 25 files changed, 686 insertions(+), 835 deletions(-) delete mode 100644 src/swrenderer/scene/r_things.cpp delete mode 100644 src/swrenderer/scene/r_things.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4415a027b0..74d1183564 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -847,7 +847,6 @@ set( FASTMATH_PCH_SOURCES swrenderer/drawers/r_thread.cpp swrenderer/scene/r_3dfloors.cpp swrenderer/scene/r_bsp.cpp - swrenderer/scene/r_things.cpp swrenderer/scene/r_portal.cpp swrenderer/line/r_line.cpp swrenderer/line/r_walldraw.cpp diff --git a/src/polyrenderer/scene/poly_playersprite.cpp b/src/polyrenderer/scene/poly_playersprite.cpp index 5baa7bda3e..03e22f1d1c 100644 --- a/src/polyrenderer/scene/poly_playersprite.cpp +++ b/src/polyrenderer/scene/poly_playersprite.cpp @@ -27,7 +27,6 @@ #include "r_data/r_translate.h" #include "poly_playersprite.h" #include "polyrenderer/poly_renderer.h" -#include "swrenderer/scene/r_things.h" // for pspritexscale EXTERN_CVAR(Bool, r_drawplayersprites) EXTERN_CVAR(Bool, r_deathcamera) diff --git a/src/swrenderer/drawers/r_draw_pal.cpp b/src/swrenderer/drawers/r_draw_pal.cpp index a55705cb7d..13f6219acf 100644 --- a/src/swrenderer/drawers/r_draw_pal.cpp +++ b/src/swrenderer/drawers/r_draw_pal.cpp @@ -46,7 +46,6 @@ #include "r_defs.h" #include "r_draw.h" #include "swrenderer/r_main.h" -#include "swrenderer/scene/r_things.h" #include "v_video.h" #include "r_draw_pal.h" diff --git a/src/swrenderer/line/r_fogboundary.cpp b/src/swrenderer/line/r_fogboundary.cpp index f5aff03529..1c8c92160a 100644 --- a/src/swrenderer/line/r_fogboundary.cpp +++ b/src/swrenderer/line/r_fogboundary.cpp @@ -19,7 +19,6 @@ #include "doomdef.h" #include "doomstat.h" #include "swrenderer/r_main.h" -#include "swrenderer/scene/r_things.h" #include "r_sky.h" #include "stats.h" #include "v_video.h" diff --git a/src/swrenderer/plane/r_flatplane.cpp b/src/swrenderer/plane/r_flatplane.cpp index ba88dd7189..af4c377975 100644 --- a/src/swrenderer/plane/r_flatplane.cpp +++ b/src/swrenderer/plane/r_flatplane.cpp @@ -19,7 +19,6 @@ #include "doomdef.h" #include "doomstat.h" #include "swrenderer/r_main.h" -#include "swrenderer/scene/r_things.h" #include "r_sky.h" #include "stats.h" #include "v_video.h" diff --git a/src/swrenderer/plane/r_skyplane.cpp b/src/swrenderer/plane/r_skyplane.cpp index 0079d5af5c..b31445c140 100644 --- a/src/swrenderer/plane/r_skyplane.cpp +++ b/src/swrenderer/plane/r_skyplane.cpp @@ -19,7 +19,6 @@ #include "doomdef.h" #include "doomstat.h" #include "swrenderer/r_main.h" -#include "swrenderer/scene/r_things.h" #include "r_sky.h" #include "stats.h" #include "v_video.h" diff --git a/src/swrenderer/plane/r_slopeplane.cpp b/src/swrenderer/plane/r_slopeplane.cpp index e68cee2ab1..85afd1d33e 100644 --- a/src/swrenderer/plane/r_slopeplane.cpp +++ b/src/swrenderer/plane/r_slopeplane.cpp @@ -19,7 +19,6 @@ #include "doomdef.h" #include "doomstat.h" #include "swrenderer/r_main.h" -#include "swrenderer/scene/r_things.h" #include "r_sky.h" #include "stats.h" #include "v_video.h" diff --git a/src/swrenderer/plane/r_visibleplane.cpp b/src/swrenderer/plane/r_visibleplane.cpp index d1b3084be0..df937ffdfa 100644 --- a/src/swrenderer/plane/r_visibleplane.cpp +++ b/src/swrenderer/plane/r_visibleplane.cpp @@ -30,7 +30,6 @@ #include "gl/dynlights/gl_dynlight.h" #include "swrenderer/r_main.h" #include "swrenderer/scene/r_bsp.h" -#include "swrenderer/scene/r_things.h" #include "swrenderer/scene/r_3dfloors.h" #include "swrenderer/scene/r_portal.h" #include "swrenderer/plane/r_flatplane.h" diff --git a/src/swrenderer/r_main.cpp b/src/swrenderer/r_main.cpp index 771653fff6..630edc9aa2 100644 --- a/src/swrenderer/r_main.cpp +++ b/src/swrenderer/r_main.cpp @@ -35,7 +35,6 @@ #include "m_random.h" #include "m_bbox.h" #include "r_main.h" -#include "scene/r_things.h" #include "drawers/r_draw.h" #include "plane/r_flatplane.h" #include "scene/r_bsp.h" diff --git a/src/swrenderer/scene/r_bsp.cpp b/src/swrenderer/scene/r_bsp.cpp index bd18ab41ef..5aa15e3cc6 100644 --- a/src/swrenderer/scene/r_bsp.cpp +++ b/src/swrenderer/scene/r_bsp.cpp @@ -39,7 +39,6 @@ #include "swrenderer/things/r_particle.h" #include "swrenderer/segments/r_clipsegment.h" #include "swrenderer/line/r_wallsetup.h" -#include "r_things.h" #include "r_3dfloors.h" #include "r_portal.h" #include "a_sharedglobal.h" diff --git a/src/swrenderer/scene/r_portal.cpp b/src/swrenderer/scene/r_portal.cpp index 092eac4c9f..5ca458b309 100644 --- a/src/swrenderer/scene/r_portal.cpp +++ b/src/swrenderer/scene/r_portal.cpp @@ -43,12 +43,12 @@ #include "p_setup.h" #include "version.h" #include "r_utility.h" -#include "r_things.h" #include "r_3dfloors.h" #include "swrenderer/drawers/r_draw_rgba.h" #include "swrenderer/segments/r_clipsegment.h" #include "swrenderer/segments/r_drawsegment.h" #include "swrenderer/plane/r_visibleplane.h" +#include "swrenderer/things/r_visiblesprite.h" #include "swrenderer/scene/r_bsp.h" #include "swrenderer/r_main.h" #include "swrenderer/r_memory.h" diff --git a/src/swrenderer/scene/r_things.cpp b/src/swrenderer/scene/r_things.cpp deleted file mode 100644 index 84dfc44ec7..0000000000 --- a/src/swrenderer/scene/r_things.cpp +++ /dev/null @@ -1,760 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// $Id:$ -// -// Copyright (C) 1993-1996 by id Software, Inc. -// -// This source is available for distribution and/or modification -// only under the terms of the DOOM Source Code License as -// published by id Software. All rights reserved. -// -// The source is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License -// for more details. -// -// $Log:$ -// -// DESCRIPTION: -// Refresh of things, i.e. objects represented by sprites. -// -//----------------------------------------------------------------------------- - -#include -#include -#include - -#include "p_lnspec.h" -#include "templates.h" -#include "doomdef.h" -#include "m_swap.h" -#include "i_system.h" -#include "w_wad.h" -#include "swrenderer/r_main.h" -#include "swrenderer/scene/r_things.h" -#include "c_console.h" -#include "c_cvars.h" -#include "c_dispatch.h" -#include "doomstat.h" -#include "v_video.h" -#include "sc_man.h" -#include "s_sound.h" -#include "sbar.h" -#include "gi.h" -#include "r_sky.h" -#include "cmdlib.h" -#include "g_level.h" -#include "d_net.h" -#include "colormatcher.h" -#include "d_netinf.h" -#include "p_effect.h" -#include "r_bsp.h" -#include "r_3dfloors.h" -#include "swrenderer/drawers/r_draw_rgba.h" -#include "swrenderer/drawers/r_draw_pal.h" -#include "v_palette.h" -#include "r_data/r_translate.h" -#include "r_data/colormaps.h" -#include "r_data/voxels.h" -#include "p_local.h" -#include "p_maputl.h" -#include "swrenderer/things/r_voxel.h" -#include "swrenderer/segments/r_drawsegment.h" -#include "r_portal.h" -#include "swrenderer/things/r_particle.h" -#include "swrenderer/things/r_playersprite.h" -#include "swrenderer/things/r_wallsprite.h" -#include "swrenderer/things/r_sprite.h" -#include "swrenderer/plane/r_visibleplane.h" -#include "swrenderer/r_memory.h" -#include "g_levellocals.h" - -EXTERN_CVAR(Int, r_drawfuzz) -EXTERN_CVAR(Bool, r_drawvoxels) -EXTERN_CVAR(Bool, r_blendmethod) - -CVAR(Bool, r_fullbrightignoresectorcolor, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); -CVAR(Bool, r_splitsprites, true, CVAR_ARCHIVE) - -namespace swrenderer -{ - -bool DrewAVoxel; - -static vissprite_t **spritesorter; -static int spritesortersize = 0; -static int vsprcount; - - - - -void R_DeinitSprites() -{ - R_DeinitVisSprites(); - R_DeinitRenderVoxel(); - - // Free vissprites sorter - if (spritesorter != NULL) - { - delete[] spritesorter; - spritesortersize = 0; - spritesorter = NULL; - } -} - -// -// R_ClearSprites -// Called at frame start. -// -void R_ClearSprites (void) -{ - R_ClearVisSprites(); - DrewAVoxel = false; -} - -static TArray portaldrawsegs; - -static inline void R_CollectPortals() -{ - // This function collects all drawsegs that may be of interest to R_ClipSpriteColumnWithPortals - // Having that function over the entire list of drawsegs can break down performance quite drastically. - // This is doing the costly stuff only once so that R_ClipSpriteColumnWithPortals can - // a) exit early if no relevant info is found and - // b) skip most of the collected drawsegs which have no portal attached. - portaldrawsegs.Clear(); - for (drawseg_t* seg = ds_p; seg-- > firstdrawseg; ) // copied code from killough below - { - // I don't know what makes this happen (some old top-down portal code or possibly skybox code? something adds null lines...) - // crashes at the first frame of the first map of Action2.wad - if (!seg->curline) continue; - - line_t* line = seg->curline->linedef; - // ignore minisegs from GL nodes. - if (!line) continue; - - // check if this line will clip sprites to itself - if (!line->isVisualPortal() && line->special != Line_Mirror) - continue; - - // don't clip sprites with portal's back side (it's transparent) - if (seg->curline->sidedef != line->sidedef[0]) - continue; - - portaldrawsegs.Push(seg); - } -} - -bool R_ClipSpriteColumnWithPortals(int x, vissprite_t* spr) -{ - RenderPortal *renderportal = RenderPortal::Instance(); - - // [ZZ] 10.01.2016: don't clip sprites from the root of a skybox. - if (renderportal->CurrentPortalInSkybox) - return false; - - for (drawseg_t *seg : portaldrawsegs) - { - // ignore segs from other portals - if (seg->CurrentPortalUniq != renderportal->CurrentPortalUniq) - continue; - - // (all checks that are already done in R_CollectPortals have been removed for performance reasons.) - - // don't clip if the sprite is in front of the portal - if (!P_PointOnLineSidePrecise(spr->gpos.X, spr->gpos.Y, seg->curline->linedef)) - continue; - - // now if current column is covered by this drawseg, we clip it away - if ((x >= seg->x1) && (x < seg->x2)) - return true; - } - - return false; -} - - -// -// R_SortVisSprites -// -// [RH] The old code for this function used a bubble sort, which was far less -// than optimal with large numbers of sprites. I changed it to use the -// stdlib qsort() function instead, and now it is a *lot* faster; the -// more vissprites that need to be sorted, the better the performance -// gain compared to the old function. -// -// Sort vissprites by depth, far to near - -// This is the standard version, which does a simple test based on depth. -static bool sv_compare(vissprite_t *a, vissprite_t *b) -{ - return a->idepth > b->idepth; -} - -// This is an alternate version, for when one or more voxel is in view. -// It does a 2D distance test based on whichever one is furthest from -// the viewpoint. -static bool sv_compare2d(vissprite_t *a, vissprite_t *b) -{ - return DVector2(a->deltax, a->deltay).LengthSquared() < - DVector2(b->deltax, b->deltay).LengthSquared(); -} - -#ifdef __GNUC__ -static void swap(vissprite_t *&a, vissprite_t *&b) -{ - vissprite_t *t = a; - a = b; - b = t; -} -#endif - -void R_SortVisSprites (bool (*compare)(vissprite_t *, vissprite_t *), size_t first) -{ - int i; - vissprite_t **spr; - - vsprcount = int(vissprite_p - &vissprites[first]); - - if (vsprcount == 0) - return; - - if (spritesortersize < MaxVisSprites) - { - if (spritesorter != NULL) - delete[] spritesorter; - spritesorter = new vissprite_t *[MaxVisSprites]; - spritesortersize = MaxVisSprites; - } - - if (!(i_compatflags & COMPATF_SPRITESORT)) - { - for (i = 0, spr = firstvissprite; i < vsprcount; i++, spr++) - { - spritesorter[i] = *spr; - } - } - else - { - // If the compatibility option is on sprites of equal distance need to - // be sorted in inverse order. This is most easily achieved by - // filling the sort array backwards before the sort. - for (i = 0, spr = firstvissprite + vsprcount-1; i < vsprcount; i++, spr--) - { - spritesorter[i] = *spr; - } - } - - std::stable_sort(&spritesorter[0], &spritesorter[vsprcount], compare); -} - -// -// R_DrawSprite -// -void R_DrawSprite (vissprite_t *spr) -{ - static short clipbot[MAXWIDTH]; - static short cliptop[MAXWIDTH]; - drawseg_t *ds; - int i; - int x1, x2; - int r1, r2; - short topclip, botclip; - short *clip1, *clip2; - FSWColormap *colormap = spr->Style.BaseColormap; - int colormapnum = spr->Style.ColormapNum; - F3DFloor *rover; - FDynamicColormap *mybasecolormap; - - Clip3DFloors *clip3d = Clip3DFloors::Instance(); - - // [RH] Check for particles - if (!spr->bIsVoxel && spr->pic == NULL) - { - // kg3D - reject invisible parts - if ((clip3d->fake3D & FAKE3D_CLIPBOTTOM) && spr->gpos.Z <= clip3d->sclipBottom) return; - if ((clip3d->fake3D & FAKE3D_CLIPTOP) && spr->gpos.Z >= clip3d->sclipTop) return; - R_DrawParticle (spr); - return; - } - - x1 = spr->x1; - x2 = spr->x2; - - // [RH] Quickly reject sprites with bad x ranges. - if (x1 >= x2) - return; - - // [RH] Sprites split behind a one-sided line can also be discarded. - if (spr->sector == NULL) - return; - - // kg3D - reject invisible parts - if ((clip3d->fake3D & FAKE3D_CLIPBOTTOM) && spr->gzt <= clip3d->sclipBottom) return; - if ((clip3d->fake3D & FAKE3D_CLIPTOP) && spr->gzb >= clip3d->sclipTop) return; - - // kg3D - correct colors now - if (!fixedcolormap && fixedlightlev < 0 && spr->sector->e && spr->sector->e->XFloor.lightlist.Size()) - { - if (!(clip3d->fake3D & FAKE3D_CLIPTOP)) - { - clip3d->sclipTop = spr->sector->ceilingplane.ZatPoint(ViewPos); - } - sector_t *sec = NULL; - for (i = spr->sector->e->XFloor.lightlist.Size() - 1; i >= 0; i--) - { - if (clip3d->sclipTop <= spr->sector->e->XFloor.lightlist[i].plane.Zat0()) - { - rover = spr->sector->e->XFloor.lightlist[i].caster; - if (rover) - { - if (rover->flags & FF_DOUBLESHADOW && clip3d->sclipTop <= rover->bottom.plane->Zat0()) - { - break; - } - sec = rover->model; - if (rover->flags & FF_FADEWALLS) - { - mybasecolormap = sec->ColorMap; - } - else - { - mybasecolormap = spr->sector->e->XFloor.lightlist[i].extra_colormap; - } - } - break; - } - } - // found new values, recalculate - if (sec) - { - INTBOOL invertcolormap = (spr->Style.RenderStyle.Flags & STYLEF_InvertOverlay); - - if (spr->Style.RenderStyle.Flags & STYLEF_InvertSource) - { - invertcolormap = !invertcolormap; - } - - // Sprites that are added to the scene must fade to black. - if (spr->Style.RenderStyle == LegacyRenderStyles[STYLE_Add] && mybasecolormap->Fade != 0) - { - mybasecolormap = GetSpecialLights(mybasecolormap->Color, 0, mybasecolormap->Desaturate); - } - - if (spr->Style.RenderStyle.Flags & STYLEF_FadeToBlack) - { - if (invertcolormap) - { // Fade to white - mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(255,255,255), mybasecolormap->Desaturate); - invertcolormap = false; - } - else - { // Fade to black - mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(0,0,0), mybasecolormap->Desaturate); - } - } - - // get light level - if (invertcolormap) - { - mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate); - } - if (fixedlightlev >= 0) - { - spr->Style.BaseColormap = mybasecolormap; - spr->Style.ColormapNum = fixedlightlev >> COLORMAPSHIFT; - } - else if (!foggy && (spr->renderflags & RF_FULLBRIGHT)) - { // full bright - spr->Style.BaseColormap = (r_fullbrightignoresectorcolor) ? &FullNormalLight : mybasecolormap; - spr->Style.ColormapNum = 0; - } - else - { // diminished light - int spriteshade = LIGHT2SHADE(sec->lightlevel + r_actualextralight); - spr->Style.BaseColormap = mybasecolormap; - spr->Style.ColormapNum = GETPALOOKUP(r_SpriteVisibility / MAX(MINZ, (double)spr->depth), spriteshade); - } - } - } - - // [RH] Initialize the clipping arrays to their largest possible range - // instead of using a special "not clipped" value. This eliminates - // visual anomalies when looking down and should be faster, too. - topclip = 0; - botclip = viewheight; - - // killough 3/27/98: - // Clip the sprite against deep water and/or fake ceilings. - // [RH] rewrote this to be based on which part of the sector is really visible - - double scale = InvZtoScale * spr->idepth; - double hzb = DBL_MIN, hzt = DBL_MAX; - - if (spr->bIsVoxel && spr->floorclip != 0) - { - hzb = spr->gzb; - } - - if (spr->heightsec && !(spr->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC)) - { // only things in specially marked sectors - if (spr->FakeFlatStat != WaterFakeSide::AboveCeiling) - { - double hz = spr->heightsec->floorplane.ZatPoint(spr->gpos); - int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale); - - if (spr->FakeFlatStat == WaterFakeSide::BelowFloor) - { // seen below floor: clip top - if (!spr->bIsVoxel && h > topclip) - { - topclip = short(MIN(h, viewheight)); - } - hzt = MIN(hzt, hz); - } - else - { // seen in the middle: clip bottom - if (!spr->bIsVoxel && h < botclip) - { - botclip = MAX (0, h); - } - hzb = MAX(hzb, hz); - } - } - if (spr->FakeFlatStat != WaterFakeSide::BelowFloor && !(spr->heightsec->MoreFlags & SECF_FAKEFLOORONLY)) - { - double hz = spr->heightsec->ceilingplane.ZatPoint(spr->gpos); - int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale); - - if (spr->FakeFlatStat == WaterFakeSide::AboveCeiling) - { // seen above ceiling: clip bottom - if (!spr->bIsVoxel && h < botclip) - { - botclip = MAX (0, h); - } - hzb = MAX(hzb, hz); - } - else - { // seen in the middle: clip top - if (!spr->bIsVoxel && h > topclip) - { - topclip = MIN(h, viewheight); - } - hzt = MIN(hzt, hz); - } - } - } - // killough 3/27/98: end special clipping for deep water / fake ceilings - else if (!spr->bIsVoxel && spr->floorclip) - { // [RH] Move floorclip stuff from R_DrawVisSprite to here - //int clip = ((FLOAT2FIXED(CenterY) - FixedMul (spr->texturemid - (spr->pic->GetHeight() << FRACBITS) + spr->floorclip, spr->yscale)) >> FRACBITS); - int clip = xs_RoundToInt(CenterY - (spr->texturemid - spr->pic->GetHeight() + spr->floorclip) * spr->yscale); - if (clip < botclip) - { - botclip = MAX(0, clip); - } - } - - if (clip3d->fake3D & FAKE3D_CLIPBOTTOM) - { - if (!spr->bIsVoxel) - { - double hz = clip3d->sclipBottom; - if (spr->fakefloor) - { - double floorz = spr->fakefloor->top.plane->Zat0(); - if (ViewPos.Z > floorz && floorz == clip3d->sclipBottom ) - { - hz = spr->fakefloor->bottom.plane->Zat0(); - } - } - int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale); - if (h < botclip) - { - botclip = MAX(0, h); - } - } - hzb = MAX(hzb, clip3d->sclipBottom); - } - if (clip3d->fake3D & FAKE3D_CLIPTOP) - { - if (!spr->bIsVoxel) - { - double hz = clip3d->sclipTop; - if (spr->fakeceiling != NULL) - { - double ceilingZ = spr->fakeceiling->bottom.plane->Zat0(); - if (ViewPos.Z < ceilingZ && ceilingZ == clip3d->sclipTop) - { - hz = spr->fakeceiling->top.plane->Zat0(); - } - } - int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale); - if (h > topclip) - { - topclip = short(MIN(h, viewheight)); - } - } - hzt = MIN(hzt, clip3d->sclipTop); - } - - if (topclip >= botclip) - { - spr->Style.BaseColormap = colormap; - spr->Style.ColormapNum = colormapnum; - return; - } - - i = x2 - x1; - clip1 = clipbot + x1; - clip2 = cliptop + x1; - do - { - *clip1++ = botclip; - *clip2++ = topclip; - } while (--i); - - // Scan drawsegs from end to start for obscuring segs. - // The first drawseg that is closer than the sprite is the clip seg. - - // Modified by Lee Killough: - // (pointer check was originally nonportable - // and buggy, by going past LEFT end of array): - - // for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code - - for (ds = ds_p; ds-- > firstdrawseg; ) // new -- killough - { - // [ZZ] portal handling here - //if (ds->CurrentPortalUniq != spr->CurrentPortalUniq) - // continue; - // [ZZ] WARNING: uncommenting the two above lines, totally breaks sprite clipping - - // kg3D - no clipping on fake segs - if (ds->fake) continue; - // determine if the drawseg obscures the sprite - if (ds->x1 >= x2 || ds->x2 <= x1 || - (!(ds->silhouette & SIL_BOTH) && ds->maskedtexturecol == -1 && - !ds->bFogBoundary) ) - { - // does not cover sprite - continue; - } - - r1 = MAX (ds->x1, x1); - r2 = MIN (ds->x2, x2); - - float neardepth, fardepth; - if (!spr->bWallSprite) - { - if (ds->sz1 < ds->sz2) - { - neardepth = ds->sz1, fardepth = ds->sz2; - } - else - { - neardepth = ds->sz2, fardepth = ds->sz1; - } - } - - - // Check if sprite is in front of draw seg: - if ((!spr->bWallSprite && neardepth > spr->depth) || ((spr->bWallSprite || fardepth > spr->depth) && - (spr->gpos.Y - ds->curline->v1->fY()) * (ds->curline->v2->fX() - ds->curline->v1->fX()) - - (spr->gpos.X - ds->curline->v1->fX()) * (ds->curline->v2->fY() - ds->curline->v1->fY()) <= 0)) - { - RenderPortal *renderportal = RenderPortal::Instance(); - - // seg is behind sprite, so draw the mid texture if it has one - if (ds->CurrentPortalUniq == renderportal->CurrentPortalUniq && // [ZZ] instead, portal uniq check is made here - (ds->maskedtexturecol != -1 || ds->bFogBoundary)) - R_RenderMaskedSegRange (ds, r1, r2); - - continue; - } - - // clip this piece of the sprite - // killough 3/27/98: optimized and made much shorter - // [RH] Optimized further (at least for VC++; - // other compilers should be at least as good as before) - - if (ds->silhouette & SIL_BOTTOM) //bottom sil - { - clip1 = clipbot + r1; - clip2 = openings + ds->sprbottomclip + r1 - ds->x1; - i = r2 - r1; - do - { - if (*clip1 > *clip2) - *clip1 = *clip2; - clip1++; - clip2++; - } while (--i); - } - - if (ds->silhouette & SIL_TOP) // top sil - { - clip1 = cliptop + r1; - clip2 = openings + ds->sprtopclip + r1 - ds->x1; - i = r2 - r1; - do - { - if (*clip1 < *clip2) - *clip1 = *clip2; - clip1++; - clip2++; - } while (--i); - } - } - - // all clipping has been performed, so draw the sprite - - if (!spr->bIsVoxel) - { - if (!spr->bWallSprite) - { - R_DrawVisSprite(spr, clipbot, cliptop); - } - else - { - R_DrawWallSprite(spr, clipbot, cliptop); - } - } - else - { - // If it is completely clipped away, don't bother drawing it. - if (cliptop[x2] >= clipbot[x2]) - { - for (i = x1; i < x2; ++i) - { - if (cliptop[i] < clipbot[i]) - { - break; - } - } - if (i == x2) - { - spr->Style.BaseColormap = colormap; - spr->Style.ColormapNum = colormapnum; - return; - } - } - // Add everything outside the left and right edges to the clipping array - // for R_DrawVisVoxel(). - if (x1 > 0) - { - fillshort(cliptop, x1, viewheight); - } - if (x2 < viewwidth - 1) - { - fillshort(cliptop + x2, viewwidth - x2, viewheight); - } - int minvoxely = spr->gzt <= hzt ? 0 : xs_RoundToInt((spr->gzt - hzt) / spr->yscale); - int maxvoxely = spr->gzb > hzb ? INT_MAX : xs_RoundToInt((spr->gzt - hzb) / spr->yscale); - R_DrawVisVoxel(spr, minvoxely, maxvoxely, cliptop, clipbot); - } - spr->Style.BaseColormap = colormap; - spr->Style.ColormapNum = colormapnum; -} - -// kg3D: -// R_DrawMasked contains sorting -// original renamed to R_DrawMaskedSingle - -void R_DrawMaskedSingle (bool renew) -{ - drawseg_t *ds; - int i; - - RenderPortal *renderportal = RenderPortal::Instance(); - - for (i = vsprcount; i > 0; i--) - { - if (spritesorter[i-1]->CurrentPortalUniq != renderportal->CurrentPortalUniq) - continue; // probably another time - R_DrawSprite (spritesorter[i-1]); - } - - // render any remaining masked mid textures - - // Modified by Lee Killough: - // (pointer check was originally nonportable - // and buggy, by going past LEFT end of array): - - // for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code - - if (renew) - { - Clip3DFloors::Instance()->fake3D |= FAKE3D_REFRESHCLIP; - } - for (ds = ds_p; ds-- > firstdrawseg; ) // new -- killough - { - // [ZZ] the same as above - if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq) - continue; - // kg3D - no fake segs - if (ds->fake) continue; - if (ds->maskedtexturecol != -1 || ds->bFogBoundary) - { - R_RenderMaskedSegRange (ds, ds->x1, ds->x2); - } - } -} - -void R_DrawMasked () -{ - R_CollectPortals(); - R_SortVisSprites (DrewAVoxel ? sv_compare2d : sv_compare, firstvissprite - vissprites); - - Clip3DFloors *clip3d = Clip3DFloors::Instance(); - if (clip3d->height_top == NULL) - { // kg3D - no visible 3D floors, normal rendering - R_DrawMaskedSingle(false); - } - else - { // kg3D - correct sorting - HeightLevel *hl; - - // ceilings - for (hl = clip3d->height_cur; hl != NULL && hl->height >= ViewPos.Z; hl = hl->prev) - { - if (hl->next) - { - clip3d->fake3D = FAKE3D_CLIPBOTTOM | FAKE3D_CLIPTOP; - clip3d->sclipTop = hl->next->height; - } - else - { - clip3d->fake3D = FAKE3D_CLIPBOTTOM; - } - clip3d->sclipBottom = hl->height; - R_DrawMaskedSingle(true); - R_DrawHeightPlanes(hl->height); - } - - // floors - clip3d->fake3D = FAKE3D_DOWN2UP | FAKE3D_CLIPTOP; - clip3d->sclipTop = clip3d->height_top->height; - R_DrawMaskedSingle(true); - hl = clip3d->height_top; - for (hl = clip3d->height_top; hl != NULL && hl->height < ViewPos.Z; hl = hl->next) - { - R_DrawHeightPlanes(hl->height); - if (hl->next) - { - clip3d->fake3D = FAKE3D_DOWN2UP | FAKE3D_CLIPTOP | FAKE3D_CLIPBOTTOM; - clip3d->sclipTop = hl->next->height; - } - else - { - clip3d->fake3D = FAKE3D_DOWN2UP | FAKE3D_CLIPBOTTOM; - } - clip3d->sclipBottom = hl->height; - R_DrawMaskedSingle(true); - } - clip3d->DeleteHeights(); - clip3d->fake3D = 0; - } - R_DrawPlayerSprites(); -} - -} diff --git a/src/swrenderer/scene/r_things.h b/src/swrenderer/scene/r_things.h deleted file mode 100644 index 1b3186acb3..0000000000 --- a/src/swrenderer/scene/r_things.h +++ /dev/null @@ -1,53 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// $Id:$ -// -// Copyright (C) 1993-1996 by id Software, Inc. -// -// This source is available for distribution and/or modification -// only under the terms of the DOOM Source Code License as -// published by id Software. All rights reserved. -// -// The source is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License -// for more details. -// -// DESCRIPTION: -// Rendering of moving objects, sprites. -// -//----------------------------------------------------------------------------- - - -#ifndef __R_THINGS__ -#define __R_THINGS__ - -#include "swrenderer/things/r_visiblesprite.h" -#include "swrenderer/scene/r_bsp.h" - -struct particle_t; -struct FVoxel; - - -EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); - -namespace swrenderer -{ - -bool R_ClipSpriteColumnWithPortals(int x, vissprite_t* spr); - - -void R_CacheSprite (spritedef_t *sprite); -void R_SortVisSprites (int (*compare)(const void *, const void *), size_t first); -void R_DrawSprites (); -void R_ClearSprites (); -void R_DrawMasked (); - -void R_ClipVisSprite (vissprite_t *vis, int xl, int xh); - -extern bool DrewAVoxel; - -} - -#endif diff --git a/src/swrenderer/segments/r_clipsegment.cpp b/src/swrenderer/segments/r_clipsegment.cpp index 04bef89077..c1cc94de66 100644 --- a/src/swrenderer/segments/r_clipsegment.cpp +++ b/src/swrenderer/segments/r_clipsegment.cpp @@ -20,7 +20,6 @@ #include "p_setup.h" #include "swrenderer/r_main.h" #include "swrenderer/drawers/r_draw.h" -#include "swrenderer/scene/r_things.h" #include "swrenderer/scene/r_3dfloors.h" #include "a_sharedglobal.h" #include "g_level.h" diff --git a/src/swrenderer/segments/r_drawsegment.cpp b/src/swrenderer/segments/r_drawsegment.cpp index ca875c6317..18530e157d 100644 --- a/src/swrenderer/segments/r_drawsegment.cpp +++ b/src/swrenderer/segments/r_drawsegment.cpp @@ -31,7 +31,6 @@ #include "swrenderer/r_main.h" #include "swrenderer/r_memory.h" #include "swrenderer/drawers/r_draw.h" -#include "swrenderer/scene/r_things.h" #include "swrenderer/scene/r_3dfloors.h" #include "swrenderer/scene/r_bsp.h" #include "swrenderer/scene/r_portal.h" @@ -39,6 +38,9 @@ #include "swrenderer/line/r_walldraw.h" #include "swrenderer/line/r_fogboundary.h" #include "swrenderer/segments/r_drawsegment.h" +#include "swrenderer/things/r_visiblesprite.h" + +EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); namespace swrenderer { diff --git a/src/swrenderer/segments/r_portalsegment.cpp b/src/swrenderer/segments/r_portalsegment.cpp index 4e7a2b5336..476e6b0a35 100644 --- a/src/swrenderer/segments/r_portalsegment.cpp +++ b/src/swrenderer/segments/r_portalsegment.cpp @@ -20,7 +20,6 @@ #include "p_setup.h" #include "swrenderer/r_main.h" #include "swrenderer/drawers/r_draw.h" -#include "swrenderer/scene/r_things.h" #include "swrenderer/scene/r_3dfloors.h" #include "a_sharedglobal.h" #include "g_level.h" diff --git a/src/swrenderer/things/r_decal.cpp b/src/swrenderer/things/r_decal.cpp index 1483e42120..9e2d0b8939 100644 --- a/src/swrenderer/things/r_decal.cpp +++ b/src/swrenderer/things/r_decal.cpp @@ -20,7 +20,6 @@ #include "doomdata.h" #include "p_lnspec.h" #include "swrenderer/r_main.h" -#include "swrenderer/scene/r_things.h" #include "r_sky.h" #include "v_video.h" #include "m_swap.h" @@ -42,6 +41,8 @@ #include "swrenderer/things/r_wallsprite.h" #include "swrenderer/r_memory.h" +EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); + namespace swrenderer { void R_RenderDecals(side_t *sidedef, drawseg_t *draw_segment, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC) diff --git a/src/swrenderer/things/r_particle.cpp b/src/swrenderer/things/r_particle.cpp index 4daf1d799f..b256ffc38f 100644 --- a/src/swrenderer/things/r_particle.cpp +++ b/src/swrenderer/things/r_particle.cpp @@ -21,7 +21,6 @@ #include "i_system.h" #include "w_wad.h" #include "swrenderer/r_main.h" -#include "swrenderer/scene/r_things.h" #include "swrenderer/things/r_particle.h" #include "c_console.h" #include "c_cvars.h" @@ -54,6 +53,8 @@ #include "swrenderer/scene/r_portal.h" #include "swrenderer/r_memory.h" +EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); + namespace swrenderer { void R_ProjectParticle(particle_t *particle, const sector_t *sector, int shade, WaterFakeSide fakeside) diff --git a/src/swrenderer/things/r_playersprite.cpp b/src/swrenderer/things/r_playersprite.cpp index d37320c39b..bf648e851c 100644 --- a/src/swrenderer/things/r_playersprite.cpp +++ b/src/swrenderer/things/r_playersprite.cpp @@ -21,7 +21,6 @@ #include "i_system.h" #include "w_wad.h" #include "swrenderer/r_main.h" -#include "swrenderer/scene/r_things.h" #include "swrenderer/things/r_playersprite.h" #include "c_console.h" #include "c_cvars.h" @@ -60,6 +59,7 @@ EXTERN_CVAR(Bool, st_scale) EXTERN_CVAR(Bool, r_drawplayersprites) EXTERN_CVAR(Bool, r_deathcamera) EXTERN_CVAR(Bool, r_shadercolormaps) +EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor) namespace swrenderer { diff --git a/src/swrenderer/things/r_sprite.cpp b/src/swrenderer/things/r_sprite.cpp index 8c1553f6de..e65aac6bfe 100644 --- a/src/swrenderer/things/r_sprite.cpp +++ b/src/swrenderer/things/r_sprite.cpp @@ -21,7 +21,6 @@ #include "i_system.h" #include "w_wad.h" #include "swrenderer/r_main.h" -#include "swrenderer/scene/r_things.h" #include "swrenderer/things/r_wallsprite.h" #include "c_console.h" #include "c_cvars.h" @@ -56,6 +55,7 @@ #include "swrenderer/r_memory.h" EXTERN_CVAR(Bool, r_drawvoxels) +EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor) namespace swrenderer { diff --git a/src/swrenderer/things/r_visiblesprite.cpp b/src/swrenderer/things/r_visiblesprite.cpp index 567eae89d5..492fa3eab0 100644 --- a/src/swrenderer/things/r_visiblesprite.cpp +++ b/src/swrenderer/things/r_visiblesprite.cpp @@ -20,8 +20,26 @@ #include "m_swap.h" #include "i_system.h" #include "w_wad.h" +#include "g_levellocals.h" +#include "p_maputl.h" #include "swrenderer/r_main.h" #include "swrenderer/things/r_visiblesprite.h" +#include "swrenderer/things/r_voxel.h" +#include "swrenderer/things/r_particle.h" +#include "swrenderer/things/r_sprite.h" +#include "swrenderer/things/r_wallsprite.h" +#include "swrenderer/things/r_playersprite.h" +#include "swrenderer/segments/r_drawsegment.h" +#include "swrenderer/scene/r_portal.h" +#include "swrenderer/plane/r_visibleplane.h" +#include "swrenderer/r_memory.h" + +EXTERN_CVAR(Int, r_drawfuzz) +EXTERN_CVAR(Bool, r_drawvoxels) +EXTERN_CVAR(Bool, r_blendmethod) + +CVAR(Bool, r_fullbrightignoresectorcolor, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); +CVAR(Bool, r_splitsprites, true, CVAR_ARCHIVE) namespace swrenderer { @@ -31,6 +49,17 @@ namespace swrenderer vissprite_t **vissprite_p; vissprite_t **lastvissprite; + bool DrewAVoxel; + + namespace + { + vissprite_t **spritesorter; + int spritesortersize = 0; + int vsprcount; + + TArray portaldrawsegs; + } + void R_DeinitVisSprites() { // Free vissprites @@ -73,4 +102,631 @@ namespace swrenderer vissprite_p++; return *(vissprite_p - 1); } + + void R_DeinitSprites() + { + R_DeinitVisSprites(); + R_DeinitRenderVoxel(); + + // Free vissprites sorter + if (spritesorter != nullptr) + { + delete[] spritesorter; + spritesortersize = 0; + spritesorter = nullptr; + } + } + + void R_ClearSprites() + { + R_ClearVisSprites(); + DrewAVoxel = false; + } + + void R_CollectPortals() + { + // This function collects all drawsegs that may be of interest to R_ClipSpriteColumnWithPortals + // Having that function over the entire list of drawsegs can break down performance quite drastically. + // This is doing the costly stuff only once so that R_ClipSpriteColumnWithPortals can + // a) exit early if no relevant info is found and + // b) skip most of the collected drawsegs which have no portal attached. + portaldrawsegs.Clear(); + for (drawseg_t* seg = ds_p; seg-- > firstdrawseg; ) // copied code from killough below + { + // I don't know what makes this happen (some old top-down portal code or possibly skybox code? something adds null lines...) + // crashes at the first frame of the first map of Action2.wad + if (!seg->curline) continue; + + line_t* line = seg->curline->linedef; + // ignore minisegs from GL nodes. + if (!line) continue; + + // check if this line will clip sprites to itself + if (!line->isVisualPortal() && line->special != Line_Mirror) + continue; + + // don't clip sprites with portal's back side (it's transparent) + if (seg->curline->sidedef != line->sidedef[0]) + continue; + + portaldrawsegs.Push(seg); + } + } + + bool R_ClipSpriteColumnWithPortals(int x, vissprite_t* spr) + { + RenderPortal *renderportal = RenderPortal::Instance(); + + // [ZZ] 10.01.2016: don't clip sprites from the root of a skybox. + if (renderportal->CurrentPortalInSkybox) + return false; + + for (drawseg_t *seg : portaldrawsegs) + { + // ignore segs from other portals + if (seg->CurrentPortalUniq != renderportal->CurrentPortalUniq) + continue; + + // (all checks that are already done in R_CollectPortals have been removed for performance reasons.) + + // don't clip if the sprite is in front of the portal + if (!P_PointOnLineSidePrecise(spr->gpos.X, spr->gpos.Y, seg->curline->linedef)) + continue; + + // now if current column is covered by this drawseg, we clip it away + if ((x >= seg->x1) && (x < seg->x2)) + return true; + } + + return false; + } + + // This is the standard version, which does a simple test based on depth. + bool sv_compare(vissprite_t *a, vissprite_t *b) + { + return a->idepth > b->idepth; + } + + // This is an alternate version, for when one or more voxel is in view. + // It does a 2D distance test based on whichever one is furthest from + // the viewpoint. + bool sv_compare2d(vissprite_t *a, vissprite_t *b) + { + return DVector2(a->deltax, a->deltay).LengthSquared() < DVector2(b->deltax, b->deltay).LengthSquared(); + } + + void R_SortVisSprites(bool(*compare)(vissprite_t *, vissprite_t *), size_t first) + { + int i; + vissprite_t **spr; + + vsprcount = int(vissprite_p - &vissprites[first]); + + if (vsprcount == 0) + return; + + if (spritesortersize < MaxVisSprites) + { + if (spritesorter != nullptr) + delete[] spritesorter; + spritesorter = new vissprite_t *[MaxVisSprites]; + spritesortersize = MaxVisSprites; + } + + if (!(i_compatflags & COMPATF_SPRITESORT)) + { + for (i = 0, spr = firstvissprite; i < vsprcount; i++, spr++) + { + spritesorter[i] = *spr; + } + } + else + { + // If the compatibility option is on sprites of equal distance need to + // be sorted in inverse order. This is most easily achieved by + // filling the sort array backwards before the sort. + for (i = 0, spr = firstvissprite + vsprcount - 1; i < vsprcount; i++, spr--) + { + spritesorter[i] = *spr; + } + } + + std::stable_sort(&spritesorter[0], &spritesorter[vsprcount], compare); + } + + void R_DrawSprite(vissprite_t *spr) + { + static short clipbot[MAXWIDTH]; + static short cliptop[MAXWIDTH]; + drawseg_t *ds; + int i; + int x1, x2; + int r1, r2; + short topclip, botclip; + short *clip1, *clip2; + FSWColormap *colormap = spr->Style.BaseColormap; + int colormapnum = spr->Style.ColormapNum; + F3DFloor *rover; + FDynamicColormap *mybasecolormap; + + Clip3DFloors *clip3d = Clip3DFloors::Instance(); + + // [RH] Check for particles + if (!spr->bIsVoxel && spr->pic == nullptr) + { + // kg3D - reject invisible parts + if ((clip3d->fake3D & FAKE3D_CLIPBOTTOM) && spr->gpos.Z <= clip3d->sclipBottom) return; + if ((clip3d->fake3D & FAKE3D_CLIPTOP) && spr->gpos.Z >= clip3d->sclipTop) return; + R_DrawParticle(spr); + return; + } + + x1 = spr->x1; + x2 = spr->x2; + + // [RH] Quickly reject sprites with bad x ranges. + if (x1 >= x2) + return; + + // [RH] Sprites split behind a one-sided line can also be discarded. + if (spr->sector == nullptr) + return; + + // kg3D - reject invisible parts + if ((clip3d->fake3D & FAKE3D_CLIPBOTTOM) && spr->gzt <= clip3d->sclipBottom) return; + if ((clip3d->fake3D & FAKE3D_CLIPTOP) && spr->gzb >= clip3d->sclipTop) return; + + // kg3D - correct colors now + if (!fixedcolormap && fixedlightlev < 0 && spr->sector->e && spr->sector->e->XFloor.lightlist.Size()) + { + if (!(clip3d->fake3D & FAKE3D_CLIPTOP)) + { + clip3d->sclipTop = spr->sector->ceilingplane.ZatPoint(ViewPos); + } + sector_t *sec = nullptr; + for (i = spr->sector->e->XFloor.lightlist.Size() - 1; i >= 0; i--) + { + if (clip3d->sclipTop <= spr->sector->e->XFloor.lightlist[i].plane.Zat0()) + { + rover = spr->sector->e->XFloor.lightlist[i].caster; + if (rover) + { + if (rover->flags & FF_DOUBLESHADOW && clip3d->sclipTop <= rover->bottom.plane->Zat0()) + { + break; + } + sec = rover->model; + if (rover->flags & FF_FADEWALLS) + { + mybasecolormap = sec->ColorMap; + } + else + { + mybasecolormap = spr->sector->e->XFloor.lightlist[i].extra_colormap; + } + } + break; + } + } + // found new values, recalculate + if (sec) + { + INTBOOL invertcolormap = (spr->Style.RenderStyle.Flags & STYLEF_InvertOverlay); + + if (spr->Style.RenderStyle.Flags & STYLEF_InvertSource) + { + invertcolormap = !invertcolormap; + } + + // Sprites that are added to the scene must fade to black. + if (spr->Style.RenderStyle == LegacyRenderStyles[STYLE_Add] && mybasecolormap->Fade != 0) + { + mybasecolormap = GetSpecialLights(mybasecolormap->Color, 0, mybasecolormap->Desaturate); + } + + if (spr->Style.RenderStyle.Flags & STYLEF_FadeToBlack) + { + if (invertcolormap) + { // Fade to white + mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(255, 255, 255), mybasecolormap->Desaturate); + invertcolormap = false; + } + else + { // Fade to black + mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(0, 0, 0), mybasecolormap->Desaturate); + } + } + + // get light level + if (invertcolormap) + { + mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate); + } + if (fixedlightlev >= 0) + { + spr->Style.BaseColormap = mybasecolormap; + spr->Style.ColormapNum = fixedlightlev >> COLORMAPSHIFT; + } + else if (!foggy && (spr->renderflags & RF_FULLBRIGHT)) + { // full bright + spr->Style.BaseColormap = (r_fullbrightignoresectorcolor) ? &FullNormalLight : mybasecolormap; + spr->Style.ColormapNum = 0; + } + else + { // diminished light + int spriteshade = LIGHT2SHADE(sec->lightlevel + r_actualextralight); + spr->Style.BaseColormap = mybasecolormap; + spr->Style.ColormapNum = GETPALOOKUP(r_SpriteVisibility / MAX(MINZ, (double)spr->depth), spriteshade); + } + } + } + + // [RH] Initialize the clipping arrays to their largest possible range + // instead of using a special "not clipped" value. This eliminates + // visual anomalies when looking down and should be faster, too. + topclip = 0; + botclip = viewheight; + + // killough 3/27/98: + // Clip the sprite against deep water and/or fake ceilings. + // [RH] rewrote this to be based on which part of the sector is really visible + + double scale = InvZtoScale * spr->idepth; + double hzb = DBL_MIN, hzt = DBL_MAX; + + if (spr->bIsVoxel && spr->floorclip != 0) + { + hzb = spr->gzb; + } + + if (spr->heightsec && !(spr->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC)) + { // only things in specially marked sectors + if (spr->FakeFlatStat != WaterFakeSide::AboveCeiling) + { + double hz = spr->heightsec->floorplane.ZatPoint(spr->gpos); + int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale); + + if (spr->FakeFlatStat == WaterFakeSide::BelowFloor) + { // seen below floor: clip top + if (!spr->bIsVoxel && h > topclip) + { + topclip = short(MIN(h, viewheight)); + } + hzt = MIN(hzt, hz); + } + else + { // seen in the middle: clip bottom + if (!spr->bIsVoxel && h < botclip) + { + botclip = MAX(0, h); + } + hzb = MAX(hzb, hz); + } + } + if (spr->FakeFlatStat != WaterFakeSide::BelowFloor && !(spr->heightsec->MoreFlags & SECF_FAKEFLOORONLY)) + { + double hz = spr->heightsec->ceilingplane.ZatPoint(spr->gpos); + int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale); + + if (spr->FakeFlatStat == WaterFakeSide::AboveCeiling) + { // seen above ceiling: clip bottom + if (!spr->bIsVoxel && h < botclip) + { + botclip = MAX(0, h); + } + hzb = MAX(hzb, hz); + } + else + { // seen in the middle: clip top + if (!spr->bIsVoxel && h > topclip) + { + topclip = MIN(h, viewheight); + } + hzt = MIN(hzt, hz); + } + } + } + // killough 3/27/98: end special clipping for deep water / fake ceilings + else if (!spr->bIsVoxel && spr->floorclip) + { // [RH] Move floorclip stuff from R_DrawVisSprite to here + //int clip = ((FLOAT2FIXED(CenterY) - FixedMul (spr->texturemid - (spr->pic->GetHeight() << FRACBITS) + spr->floorclip, spr->yscale)) >> FRACBITS); + int clip = xs_RoundToInt(CenterY - (spr->texturemid - spr->pic->GetHeight() + spr->floorclip) * spr->yscale); + if (clip < botclip) + { + botclip = MAX(0, clip); + } + } + + if (clip3d->fake3D & FAKE3D_CLIPBOTTOM) + { + if (!spr->bIsVoxel) + { + double hz = clip3d->sclipBottom; + if (spr->fakefloor) + { + double floorz = spr->fakefloor->top.plane->Zat0(); + if (ViewPos.Z > floorz && floorz == clip3d->sclipBottom) + { + hz = spr->fakefloor->bottom.plane->Zat0(); + } + } + int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale); + if (h < botclip) + { + botclip = MAX(0, h); + } + } + hzb = MAX(hzb, clip3d->sclipBottom); + } + if (clip3d->fake3D & FAKE3D_CLIPTOP) + { + if (!spr->bIsVoxel) + { + double hz = clip3d->sclipTop; + if (spr->fakeceiling != nullptr) + { + double ceilingZ = spr->fakeceiling->bottom.plane->Zat0(); + if (ViewPos.Z < ceilingZ && ceilingZ == clip3d->sclipTop) + { + hz = spr->fakeceiling->top.plane->Zat0(); + } + } + int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale); + if (h > topclip) + { + topclip = short(MIN(h, viewheight)); + } + } + hzt = MIN(hzt, clip3d->sclipTop); + } + + if (topclip >= botclip) + { + spr->Style.BaseColormap = colormap; + spr->Style.ColormapNum = colormapnum; + return; + } + + i = x2 - x1; + clip1 = clipbot + x1; + clip2 = cliptop + x1; + do + { + *clip1++ = botclip; + *clip2++ = topclip; + } while (--i); + + // Scan drawsegs from end to start for obscuring segs. + // The first drawseg that is closer than the sprite is the clip seg. + + // Modified by Lee Killough: + // (pointer check was originally nonportable + // and buggy, by going past LEFT end of array): + + // for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code + + for (ds = ds_p; ds-- > firstdrawseg; ) // new -- killough + { + // [ZZ] portal handling here + //if (ds->CurrentPortalUniq != spr->CurrentPortalUniq) + // continue; + // [ZZ] WARNING: uncommenting the two above lines, totally breaks sprite clipping + + // kg3D - no clipping on fake segs + if (ds->fake) continue; + // determine if the drawseg obscures the sprite + if (ds->x1 >= x2 || ds->x2 <= x1 || + (!(ds->silhouette & SIL_BOTH) && ds->maskedtexturecol == -1 && + !ds->bFogBoundary)) + { + // does not cover sprite + continue; + } + + r1 = MAX(ds->x1, x1); + r2 = MIN(ds->x2, x2); + + float neardepth, fardepth; + if (!spr->bWallSprite) + { + if (ds->sz1 < ds->sz2) + { + neardepth = ds->sz1, fardepth = ds->sz2; + } + else + { + neardepth = ds->sz2, fardepth = ds->sz1; + } + } + + + // Check if sprite is in front of draw seg: + if ((!spr->bWallSprite && neardepth > spr->depth) || ((spr->bWallSprite || fardepth > spr->depth) && + (spr->gpos.Y - ds->curline->v1->fY()) * (ds->curline->v2->fX() - ds->curline->v1->fX()) - + (spr->gpos.X - ds->curline->v1->fX()) * (ds->curline->v2->fY() - ds->curline->v1->fY()) <= 0)) + { + RenderPortal *renderportal = RenderPortal::Instance(); + + // seg is behind sprite, so draw the mid texture if it has one + if (ds->CurrentPortalUniq == renderportal->CurrentPortalUniq && // [ZZ] instead, portal uniq check is made here + (ds->maskedtexturecol != -1 || ds->bFogBoundary)) + R_RenderMaskedSegRange(ds, r1, r2); + + continue; + } + + // clip this piece of the sprite + // killough 3/27/98: optimized and made much shorter + // [RH] Optimized further (at least for VC++; + // other compilers should be at least as good as before) + + if (ds->silhouette & SIL_BOTTOM) //bottom sil + { + clip1 = clipbot + r1; + clip2 = openings + ds->sprbottomclip + r1 - ds->x1; + i = r2 - r1; + do + { + if (*clip1 > *clip2) + *clip1 = *clip2; + clip1++; + clip2++; + } while (--i); + } + + if (ds->silhouette & SIL_TOP) // top sil + { + clip1 = cliptop + r1; + clip2 = openings + ds->sprtopclip + r1 - ds->x1; + i = r2 - r1; + do + { + if (*clip1 < *clip2) + *clip1 = *clip2; + clip1++; + clip2++; + } while (--i); + } + } + + // all clipping has been performed, so draw the sprite + + if (!spr->bIsVoxel) + { + if (!spr->bWallSprite) + { + R_DrawVisSprite(spr, clipbot, cliptop); + } + else + { + R_DrawWallSprite(spr, clipbot, cliptop); + } + } + else + { + // If it is completely clipped away, don't bother drawing it. + if (cliptop[x2] >= clipbot[x2]) + { + for (i = x1; i < x2; ++i) + { + if (cliptop[i] < clipbot[i]) + { + break; + } + } + if (i == x2) + { + spr->Style.BaseColormap = colormap; + spr->Style.ColormapNum = colormapnum; + return; + } + } + // Add everything outside the left and right edges to the clipping array + // for R_DrawVisVoxel(). + if (x1 > 0) + { + fillshort(cliptop, x1, viewheight); + } + if (x2 < viewwidth - 1) + { + fillshort(cliptop + x2, viewwidth - x2, viewheight); + } + int minvoxely = spr->gzt <= hzt ? 0 : xs_RoundToInt((spr->gzt - hzt) / spr->yscale); + int maxvoxely = spr->gzb > hzb ? INT_MAX : xs_RoundToInt((spr->gzt - hzb) / spr->yscale); + R_DrawVisVoxel(spr, minvoxely, maxvoxely, cliptop, clipbot); + } + spr->Style.BaseColormap = colormap; + spr->Style.ColormapNum = colormapnum; + } + + void R_DrawMaskedSingle(bool renew) + { + RenderPortal *renderportal = RenderPortal::Instance(); + + for (int i = vsprcount; i > 0; i--) + { + if (spritesorter[i - 1]->CurrentPortalUniq != renderportal->CurrentPortalUniq) + continue; // probably another time + R_DrawSprite(spritesorter[i - 1]); + } + + // render any remaining masked mid textures + + // Modified by Lee Killough: + // (pointer check was originally nonportable + // and buggy, by going past LEFT end of array): + + // for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code + + if (renew) + { + Clip3DFloors::Instance()->fake3D |= FAKE3D_REFRESHCLIP; + } + for (drawseg_t *ds = ds_p; ds-- > firstdrawseg; ) // new -- killough + { + // [ZZ] the same as above + if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq) + continue; + // kg3D - no fake segs + if (ds->fake) continue; + if (ds->maskedtexturecol != -1 || ds->bFogBoundary) + { + R_RenderMaskedSegRange(ds, ds->x1, ds->x2); + } + } + } + + void R_DrawMasked() + { + R_CollectPortals(); + R_SortVisSprites(DrewAVoxel ? sv_compare2d : sv_compare, firstvissprite - vissprites); + + Clip3DFloors *clip3d = Clip3DFloors::Instance(); + if (clip3d->height_top == nullptr) + { // kg3D - no visible 3D floors, normal rendering + R_DrawMaskedSingle(false); + } + else + { // kg3D - correct sorting + // ceilings + for (HeightLevel *hl = clip3d->height_cur; hl != nullptr && hl->height >= ViewPos.Z; hl = hl->prev) + { + if (hl->next) + { + clip3d->fake3D = FAKE3D_CLIPBOTTOM | FAKE3D_CLIPTOP; + clip3d->sclipTop = hl->next->height; + } + else + { + clip3d->fake3D = FAKE3D_CLIPBOTTOM; + } + clip3d->sclipBottom = hl->height; + R_DrawMaskedSingle(true); + R_DrawHeightPlanes(hl->height); + } + + // floors + clip3d->fake3D = FAKE3D_DOWN2UP | FAKE3D_CLIPTOP; + clip3d->sclipTop = clip3d->height_top->height; + R_DrawMaskedSingle(true); + for (HeightLevel *hl = clip3d->height_top; hl != nullptr && hl->height < ViewPos.Z; hl = hl->next) + { + R_DrawHeightPlanes(hl->height); + if (hl->next) + { + clip3d->fake3D = FAKE3D_DOWN2UP | FAKE3D_CLIPTOP | FAKE3D_CLIPBOTTOM; + clip3d->sclipTop = hl->next->height; + } + else + { + clip3d->fake3D = FAKE3D_DOWN2UP | FAKE3D_CLIPBOTTOM; + } + clip3d->sclipBottom = hl->height; + R_DrawMaskedSingle(true); + } + clip3d->DeleteHeights(); + clip3d->fake3D = 0; + } + R_DrawPlayerSprites(); + } } diff --git a/src/swrenderer/things/r_visiblesprite.h b/src/swrenderer/things/r_visiblesprite.h index db40aa1cdd..6a540d1ab3 100644 --- a/src/swrenderer/things/r_visiblesprite.h +++ b/src/swrenderer/things/r_visiblesprite.h @@ -92,7 +92,21 @@ namespace swrenderer extern vissprite_t **vissprites, **firstvissprite; extern vissprite_t **vissprite_p; + extern bool DrewAVoxel; + void R_DeinitVisSprites(); void R_ClearVisSprites(); vissprite_t *R_NewVisSprite(); + + void R_DeinitSprites(); + void R_ClearSprites(); + void R_CollectPortals(); + bool R_ClipSpriteColumnWithPortals(int x, vissprite_t* spr); + void R_SortVisSprites(bool(*compare)(vissprite_t *, vissprite_t *), size_t first); + void R_DrawSprite(vissprite_t *spr); + void R_DrawMaskedSingle(bool renew); + void R_DrawMasked(); + + bool sv_compare(vissprite_t *a, vissprite_t *b); + bool sv_compare2d(vissprite_t *a, vissprite_t *b); } diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index c02e9ac8f4..67f1e47e88 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -31,12 +31,12 @@ #include "r_data/sprites.h" #include "d_net.h" #include "po_man.h" -#include "swrenderer/scene/r_things.h" +#include "r_utility.h" #include "swrenderer/drawers/r_draw.h" #include "swrenderer/drawers/r_thread.h" -#include "r_utility.h" +#include "swrenderer/things/r_visiblesprite.h" +#include "swrenderer/things/r_voxel.h" #include "swrenderer/r_main.h" -#include "r_voxel.h" namespace swrenderer { diff --git a/src/swrenderer/things/r_voxel.h b/src/swrenderer/things/r_voxel.h index 7d566394d5..e8f97cdd96 100644 --- a/src/swrenderer/things/r_voxel.h +++ b/src/swrenderer/things/r_voxel.h @@ -24,6 +24,7 @@ #pragma once struct kvxslab_t; +struct FVoxelMipLevel; namespace swrenderer { diff --git a/src/swrenderer/things/r_wallsprite.cpp b/src/swrenderer/things/r_wallsprite.cpp index d3ba5fee9e..9ddd7bfd1f 100644 --- a/src/swrenderer/things/r_wallsprite.cpp +++ b/src/swrenderer/things/r_wallsprite.cpp @@ -21,7 +21,6 @@ #include "i_system.h" #include "w_wad.h" #include "swrenderer/r_main.h" -#include "swrenderer/scene/r_things.h" #include "swrenderer/things/r_wallsprite.h" #include "c_console.h" #include "c_cvars.h" @@ -56,6 +55,8 @@ #include "swrenderer/line/r_walldraw.h" #include "swrenderer/r_memory.h" +EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); + namespace swrenderer { void R_ProjectWallSprite(AActor *thing, const DVector3 &pos, FTextureID picnum, const DVector2 &scale, int renderflags, int spriteshade)