diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1fa9367d9..e59a0fce4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -829,6 +829,7 @@ set( FASTMATH_PCH_SOURCES swrenderer/scene/r_visible_sprite.cpp swrenderer/scene/r_particle.cpp swrenderer/scene/r_playersprite.cpp + swrenderer/scene/r_wallsprite.cpp polyrenderer/poly_renderer.cpp polyrenderer/scene/poly_scene.cpp polyrenderer/scene/poly_portal.cpp diff --git a/src/swrenderer/scene/r_segs.cpp b/src/swrenderer/scene/r_segs.cpp index 40ad2bc52..0d6a9276c 100644 --- a/src/swrenderer/scene/r_segs.cpp +++ b/src/swrenderer/scene/r_segs.cpp @@ -51,6 +51,7 @@ #include "r_walldraw.h" #include "r_draw_segment.h" #include "r_portal.h" +#include "r_wallsprite.h" #include "swrenderer/r_memory.h" #define WALLYREPEAT 8 @@ -138,7 +139,6 @@ FTexture *rw_pic; static fixed_t *maskedtexturecol; static void R_RenderDecal (side_t *wall, DBaseDecal *first, drawseg_t *clipper, int pass); -static void WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)); inline bool IsFogBoundary (sector_t *front, sector_t *back) { @@ -2246,10 +2246,10 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, sprflipvert = false; } - MaskedScaleY = float(1 / yscale); + float maskedScaleY = float(1 / yscale); do { - dc_x = x1; + int x = x1; bool visible = R_SetPatchStyle (decal->RenderStyle, (float)decal->Alpha, decal->Translation, decal->AlphaColor); @@ -2261,14 +2261,14 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, if (visible) { - while (dc_x < x2) + while (x < x2) { if (calclighting) { // calculate lighting R_SetColorMapLight(usecolormap, rw_light, wallshade); } - R_WallSpriteColumn (); - dc_x++; + R_WallSpriteColumn(x, maskedScaleY); + x++; } } diff --git a/src/swrenderer/scene/r_things.cpp b/src/swrenderer/scene/r_things.cpp index bfc550ed8..b97472206 100644 --- a/src/swrenderer/scene/r_things.cpp +++ b/src/swrenderer/scene/r_things.cpp @@ -72,6 +72,7 @@ #include "r_portal.h" #include "r_particle.h" #include "r_playersprite.h" +#include "r_wallsprite.h" #include "swrenderer/r_memory.h" EXTERN_CVAR(Int, r_drawfuzz) @@ -109,7 +110,6 @@ struct FCoverageBuffer }; extern double globaluclip, globaldclip; -extern float MaskedScaleY; // // Sprite rotation 0 is facing the viewer, @@ -151,7 +151,6 @@ static vissprite_t **spritesorter; static int spritesortersize = 0; static int vsprcount; -static void R_ProjectWallSprite(AActor *thing, const DVector3 &pos, FTextureID picnum, const DVector2 &scale, INTBOOL flip); @@ -530,114 +529,6 @@ void R_DrawVisSprite (vissprite_t *vis) NetUpdate (); } -void R_DrawWallSprite(vissprite_t *spr) -{ - int x1, x2; - double iyscale; - - x1 = MAX(spr->x1, spr->wallc.sx1); - x2 = MIN(spr->x2, spr->wallc.sx2); - if (x1 >= x2) - return; - WallT.InitFromWallCoords(&spr->wallc); - PrepWall(swall, lwall, spr->pic->GetWidth() << FRACBITS, x1, x2); - iyscale = 1 / spr->yscale; - dc_texturemid = (spr->gzt - ViewPos.Z) * iyscale; - if (spr->renderflags & RF_XFLIP) - { - int right = (spr->pic->GetWidth() << FRACBITS) - 1; - - for (int i = x1; i < x2; i++) - { - lwall[i] = right - lwall[i]; - } - } - // Prepare lighting - bool calclighting = false; - FDynamicColormap *usecolormap = basecolormap; - bool rereadcolormap = true; - - // Decals that are added to the scene must fade to black. - if (spr->Style.RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0) - { - usecolormap = GetSpecialLights(usecolormap->Color, 0, usecolormap->Desaturate); - rereadcolormap = false; - } - - int shade = LIGHT2SHADE(spr->sector->lightlevel + r_actualextralight); - GlobVis = r_WallVisibility; - rw_lightleft = float (GlobVis / spr->wallc.sz1); - rw_lightstep = float((GlobVis / spr->wallc.sz2 - rw_lightleft) / (spr->wallc.sx2 - spr->wallc.sx1)); - rw_light = rw_lightleft + (x1 - spr->wallc.sx1) * rw_lightstep; - if (fixedlightlev >= 0) - R_SetColorMapLight(usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); - else if (fixedcolormap != NULL) - R_SetColorMapLight(fixedcolormap, 0, 0); - else if (!foggy && (spr->renderflags & RF_FULLBRIGHT)) - R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : usecolormap, 0, 0); - else - calclighting = true; - - // Draw it - WallSpriteTile = spr->pic; - if (spr->renderflags & RF_YFLIP) - { - sprflipvert = true; - iyscale = -iyscale; - dc_texturemid -= spr->pic->GetHeight(); - } - else - { - sprflipvert = false; - } - - MaskedScaleY = (float)iyscale; - - dc_x = x1; - - bool visible = R_SetPatchStyle (spr->Style.RenderStyle, spr->Style.Alpha, spr->Translation, spr->FillColor); - - // R_SetPatchStyle can modify basecolormap. - if (rereadcolormap) - { - usecolormap = basecolormap; - } - - if (!visible) - { - return; - } - else - { - while (dc_x < x2) - { - if (calclighting) - { // calculate lighting - R_SetColorMapLight(usecolormap, rw_light, shade); - } - if (!R_ClipSpriteColumnWithPortals(spr)) - R_WallSpriteColumn(); - dc_x++; - } - } - R_FinishSetPatchStyle(); -} - -void R_WallSpriteColumn () -{ - float iscale = swall[dc_x] * MaskedScaleY; - dc_iscale = FLOAT2FIXED(iscale); - spryscale = 1 / iscale; - if (sprflipvert) - sprtopscreen = CenterY + dc_texturemid * spryscale; - else - sprtopscreen = CenterY - dc_texturemid * spryscale; - - dc_texturefrac = 0; - R_DrawMaskedColumn(WallSpriteTile, lwall[dc_x]); - rw_light += rw_lightstep; -} - #if 0 void R_DrawVisVoxel(vissprite_t *spr, int minslabz, int maxslabz, short *cliptop, short *clipbot) { @@ -1142,80 +1033,6 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor } } -static void R_ProjectWallSprite(AActor *thing, const DVector3 &pos, FTextureID picnum, const DVector2 &scale, int renderflags) -{ - FWallCoords wallc; - double x1, x2; - DVector2 left, right; - double gzb, gzt, tz; - FTexture *pic = TexMan(picnum, true); - DAngle ang = thing->Angles.Yaw + 90; - double angcos = ang.Cos(); - double angsin = ang.Sin(); - vissprite_t *vis; - - // Determine left and right edges of sprite. The sprite's angle is its normal, - // so the edges are 90 degrees each side of it. - x2 = pic->GetScaledWidth(); - x1 = pic->GetScaledLeftOffset(); - - x1 *= scale.X; - x2 *= scale.X; - - left.X = pos.X - x1 * angcos - ViewPos.X; - left.Y = pos.Y - x1 * angsin - ViewPos.Y; - right.X = left.X + x2 * angcos; - right.Y = right.Y + x2 * angsin; - - // Is it off-screen? - if (wallc.Init(left, right, TOO_CLOSE_Z)) - return; - - if (wallc.sx1 >= WindowRight || wallc.sx2 <= WindowLeft) - return; - - // Sprite sorting should probably treat these as walls, not sprites, - // but right now, I just want to get them drawing. - tz = (pos.X - ViewPos.X) * ViewTanCos + (pos.Y - ViewPos.Y) * ViewTanSin; - - int scaled_to = pic->GetScaledTopOffset(); - int scaled_bo = scaled_to - pic->GetScaledHeight(); - gzt = pos.Z + scale.Y * scaled_to; - gzb = pos.Z + scale.Y * scaled_bo; - - vis = R_NewVisSprite(); - vis->CurrentPortalUniq = CurrentPortalUniq; - vis->x1 = wallc.sx1 < WindowLeft ? WindowLeft : wallc.sx1; - vis->x2 = wallc.sx2 >= WindowRight ? WindowRight : wallc.sx2; - vis->yscale = (float)scale.Y; - vis->idepth = float(1 / tz); - vis->depth = (float)tz; - vis->sector = thing->Sector; - vis->heightsec = NULL; - vis->gpos = { (float)pos.X, (float)pos.Y, (float)pos.Z }; - vis->gzb = (float)gzb; - vis->gzt = (float)gzt; - vis->deltax = float(pos.X - ViewPos.X); - vis->deltay = float(pos.Y - ViewPos.Y); - vis->renderflags = renderflags; - if(thing->flags5 & MF5_BRIGHT) vis->renderflags |= RF_FULLBRIGHT; // kg3D - vis->Style.RenderStyle = thing->RenderStyle; - vis->FillColor = thing->fillcolor; - vis->Translation = thing->Translation; - vis->FakeFlatStat = 0; - vis->Style.Alpha = float(thing->Alpha); - vis->fakefloor = NULL; - vis->fakeceiling = NULL; - vis->bInMirror = MirrorFlags & RF_XFLIP; - vis->pic = pic; - vis->bIsVoxel = false; - vis->bWallSprite = true; - vis->Style.ColormapNum = GETPALOOKUP( - r_SpriteVisibility / MAX(tz, MINZ), spriteshade); - vis->Style.BaseColormap = basecolormap; - vis->wallc = wallc; -} - // // R_AddSprites // During BSP traversal, this adds sprites by sector. diff --git a/src/swrenderer/scene/r_things.h b/src/swrenderer/scene/r_things.h index a110b355c..d3b3d5ebd 100644 --- a/src/swrenderer/scene/r_things.h +++ b/src/swrenderer/scene/r_things.h @@ -60,7 +60,6 @@ extern int spriteshade; bool R_ClipSpriteColumnWithPortals(vissprite_t* spr); void R_DrawMaskedColumn (FTexture *texture, fixed_t column, bool unmasked = false); -void R_WallSpriteColumn (); void R_CacheSprite (spritedef_t *sprite); void R_SortVisSprites (int (*compare)(const void *, const void *), size_t first); diff --git a/src/swrenderer/scene/r_wallsprite.cpp b/src/swrenderer/scene/r_wallsprite.cpp new file mode 100644 index 000000000..e4718bdbe --- /dev/null +++ b/src/swrenderer/scene/r_wallsprite.cpp @@ -0,0 +1,234 @@ + +#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 "swrenderer/scene/r_wallsprite.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_plane.h" +#include "r_segs.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 "r_voxel.h" +#include "r_draw_segment.h" +#include "r_portal.h" +#include "swrenderer/r_memory.h" + +namespace swrenderer +{ + void R_ProjectWallSprite(AActor *thing, const DVector3 &pos, FTextureID picnum, const DVector2 &scale, int renderflags) + { + FWallCoords wallc; + double x1, x2; + DVector2 left, right; + double gzb, gzt, tz; + FTexture *pic = TexMan(picnum, true); + DAngle ang = thing->Angles.Yaw + 90; + double angcos = ang.Cos(); + double angsin = ang.Sin(); + vissprite_t *vis; + + // Determine left and right edges of sprite. The sprite's angle is its normal, + // so the edges are 90 degrees each side of it. + x2 = pic->GetScaledWidth(); + x1 = pic->GetScaledLeftOffset(); + + x1 *= scale.X; + x2 *= scale.X; + + left.X = pos.X - x1 * angcos - ViewPos.X; + left.Y = pos.Y - x1 * angsin - ViewPos.Y; + right.X = left.X + x2 * angcos; + right.Y = right.Y + x2 * angsin; + + // Is it off-screen? + if (wallc.Init(left, right, TOO_CLOSE_Z)) + return; + + if (wallc.sx1 >= WindowRight || wallc.sx2 <= WindowLeft) + return; + + // Sprite sorting should probably treat these as walls, not sprites, + // but right now, I just want to get them drawing. + tz = (pos.X - ViewPos.X) * ViewTanCos + (pos.Y - ViewPos.Y) * ViewTanSin; + + int scaled_to = pic->GetScaledTopOffset(); + int scaled_bo = scaled_to - pic->GetScaledHeight(); + gzt = pos.Z + scale.Y * scaled_to; + gzb = pos.Z + scale.Y * scaled_bo; + + vis = R_NewVisSprite(); + vis->CurrentPortalUniq = CurrentPortalUniq; + vis->x1 = wallc.sx1 < WindowLeft ? WindowLeft : wallc.sx1; + vis->x2 = wallc.sx2 >= WindowRight ? WindowRight : wallc.sx2; + vis->yscale = (float)scale.Y; + vis->idepth = float(1 / tz); + vis->depth = (float)tz; + vis->sector = thing->Sector; + vis->heightsec = NULL; + vis->gpos = { (float)pos.X, (float)pos.Y, (float)pos.Z }; + vis->gzb = (float)gzb; + vis->gzt = (float)gzt; + vis->deltax = float(pos.X - ViewPos.X); + vis->deltay = float(pos.Y - ViewPos.Y); + vis->renderflags = renderflags; + if (thing->flags5 & MF5_BRIGHT) vis->renderflags |= RF_FULLBRIGHT; // kg3D + vis->Style.RenderStyle = thing->RenderStyle; + vis->FillColor = thing->fillcolor; + vis->Translation = thing->Translation; + vis->FakeFlatStat = 0; + vis->Style.Alpha = float(thing->Alpha); + vis->fakefloor = NULL; + vis->fakeceiling = NULL; + vis->bInMirror = MirrorFlags & RF_XFLIP; + vis->pic = pic; + vis->bIsVoxel = false; + vis->bWallSprite = true; + vis->Style.ColormapNum = GETPALOOKUP( + r_SpriteVisibility / MAX(tz, MINZ), spriteshade); + vis->Style.BaseColormap = basecolormap; + vis->wallc = wallc; + } + + void R_DrawWallSprite(vissprite_t *spr) + { + int x1, x2; + double iyscale; + + x1 = MAX(spr->x1, spr->wallc.sx1); + x2 = MIN(spr->x2, spr->wallc.sx2); + if (x1 >= x2) + return; + WallT.InitFromWallCoords(&spr->wallc); + PrepWall(swall, lwall, spr->pic->GetWidth() << FRACBITS, x1, x2); + iyscale = 1 / spr->yscale; + dc_texturemid = (spr->gzt - ViewPos.Z) * iyscale; + if (spr->renderflags & RF_XFLIP) + { + int right = (spr->pic->GetWidth() << FRACBITS) - 1; + + for (int i = x1; i < x2; i++) + { + lwall[i] = right - lwall[i]; + } + } + // Prepare lighting + bool calclighting = false; + FDynamicColormap *usecolormap = basecolormap; + bool rereadcolormap = true; + + // Decals that are added to the scene must fade to black. + if (spr->Style.RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0) + { + usecolormap = GetSpecialLights(usecolormap->Color, 0, usecolormap->Desaturate); + rereadcolormap = false; + } + + int shade = LIGHT2SHADE(spr->sector->lightlevel + r_actualextralight); + GlobVis = r_WallVisibility; + rw_lightleft = float(GlobVis / spr->wallc.sz1); + rw_lightstep = float((GlobVis / spr->wallc.sz2 - rw_lightleft) / (spr->wallc.sx2 - spr->wallc.sx1)); + rw_light = rw_lightleft + (x1 - spr->wallc.sx1) * rw_lightstep; + if (fixedlightlev >= 0) + R_SetColorMapLight(usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); + else if (fixedcolormap != NULL) + R_SetColorMapLight(fixedcolormap, 0, 0); + else if (!foggy && (spr->renderflags & RF_FULLBRIGHT)) + R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : usecolormap, 0, 0); + else + calclighting = true; + + // Draw it + WallSpriteTile = spr->pic; + if (spr->renderflags & RF_YFLIP) + { + sprflipvert = true; + iyscale = -iyscale; + dc_texturemid -= spr->pic->GetHeight(); + } + else + { + sprflipvert = false; + } + + float maskedScaleY = (float)iyscale; + + int x = x1; + + bool visible = R_SetPatchStyle(spr->Style.RenderStyle, spr->Style.Alpha, spr->Translation, spr->FillColor); + + // R_SetPatchStyle can modify basecolormap. + if (rereadcolormap) + { + usecolormap = basecolormap; + } + + if (!visible) + { + return; + } + else + { + while (x < x2) + { + if (calclighting) + { // calculate lighting + R_SetColorMapLight(usecolormap, rw_light, shade); + } + if (!R_ClipSpriteColumnWithPortals(spr)) + R_WallSpriteColumn(x, maskedScaleY); + x++; + } + } + R_FinishSetPatchStyle(); + } + + void R_WallSpriteColumn(int x, float maskedScaleY) + { + using namespace drawerargs; + + dc_x = x; + + float iscale = swall[dc_x] * maskedScaleY; + dc_iscale = FLOAT2FIXED(iscale); + spryscale = 1 / iscale; + if (sprflipvert) + sprtopscreen = CenterY + dc_texturemid * spryscale; + else + sprtopscreen = CenterY - dc_texturemid * spryscale; + + dc_texturefrac = 0; + R_DrawMaskedColumn(WallSpriteTile, lwall[dc_x]); + rw_light += rw_lightstep; + } +} diff --git a/src/swrenderer/scene/r_wallsprite.h b/src/swrenderer/scene/r_wallsprite.h new file mode 100644 index 000000000..934c7d8eb --- /dev/null +++ b/src/swrenderer/scene/r_wallsprite.h @@ -0,0 +1,11 @@ + +#pragma once + +#include "r_visible_sprite.h" + +namespace swrenderer +{ + void R_ProjectWallSprite(AActor *thing, const DVector3 &pos, FTextureID picnum, const DVector2 &scale, int renderflags); + void R_DrawWallSprite(vissprite_t *spr); + void R_WallSpriteColumn(int x, float maskedScaleY); +}