diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3601815dc..acb9c860e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -860,6 +860,7 @@ set( FASTMATH_PCH_SOURCES swrenderer/things/r_voxel.cpp swrenderer/things/r_particle.cpp swrenderer/things/r_playersprite.cpp + swrenderer/things/r_sprite.cpp swrenderer/things/r_wallsprite.cpp swrenderer/things/r_decal.cpp swrenderer/plane/r_visibleplane.cpp diff --git a/src/swrenderer/drawers/r_draw.cpp b/src/swrenderer/drawers/r_draw.cpp index 413e7e156..5c281f8c8 100644 --- a/src/swrenderer/drawers/r_draw.cpp +++ b/src/swrenderer/drawers/r_draw.cpp @@ -68,6 +68,9 @@ namespace swrenderer int fuzzpos; int fuzzviewheight; + short zeroarray[MAXWIDTH]; + short screenheightarray[MAXWIDTH]; + DrawerFunc colfunc; DrawerFunc basecolfunc; DrawerFunc fuzzcolfunc; @@ -630,4 +633,199 @@ namespace swrenderer if (dc_yl <= dc_yh) fuzzpos = (fuzzpos + dc_yh - dc_yl + 1) % FUZZTABLE; } + + void R_DrawMaskedColumn(int x, fixed_t iscale, FTexture *tex, fixed_t col, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, bool unmasked) + { + using namespace drawerargs; + + // Handle the linear filtered version in a different function to reduce chances of merge conflicts from zdoom. + if (r_swtruecolor && !drawer_needs_pal_input) // To do: add support to R_DrawColumnHoriz_rgba + { + R_DrawMaskedColumnBgra(x, iscale, tex, col, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, unmasked); + return; + } + + dc_x = x; + dc_iscale = iscale; + + const FTexture::Span *span; + const BYTE *column; + if (r_swtruecolor && !drawer_needs_pal_input) + column = (const BYTE *)tex->GetColumnBgra(col >> FRACBITS, &span); + else + column = tex->GetColumn(col >> FRACBITS, &span); + + FTexture::Span unmaskedSpan[2]; + if (unmasked) + { + span = unmaskedSpan; + unmaskedSpan[0].TopOffset = 0; + unmaskedSpan[0].Length = tex->GetHeight(); + unmaskedSpan[1].TopOffset = 0; + unmaskedSpan[1].Length = 0; + } + + int pixelsize = r_swtruecolor ? 4 : 1; + + while (span->Length != 0) + { + const int length = span->Length; + const int top = span->TopOffset; + + // calculate unclipped screen coordinates for post + dc_yl = (int)(sprtopscreen + spryscale * top + 0.5); + dc_yh = (int)(sprtopscreen + spryscale * (top + length) + 0.5) - 1; + + if (sprflipvert) + { + swapvalues(dc_yl, dc_yh); + } + + if (dc_yh >= mfloorclip[dc_x]) + { + dc_yh = mfloorclip[dc_x] - 1; + } + if (dc_yl < mceilingclip[dc_x]) + { + dc_yl = mceilingclip[dc_x]; + } + + if (dc_yl <= dc_yh) + { + dc_texturefrac = FLOAT2FIXED((dc_yl + 0.5 - sprtopscreen) / spryscale); + dc_source = column; + dc_source2 = nullptr; + dc_dest = (ylookup[dc_yl] + dc_x) * pixelsize + dc_destorg; + dc_count = dc_yh - dc_yl + 1; + + fixed_t maxfrac = ((top + length) << FRACBITS) - 1; + dc_texturefrac = MAX(dc_texturefrac, 0); + dc_texturefrac = MIN(dc_texturefrac, maxfrac); + if (dc_iscale > 0) + dc_count = MIN(dc_count, (maxfrac - dc_texturefrac + dc_iscale - 1) / dc_iscale); + else if (dc_iscale < 0) + dc_count = MIN(dc_count, (dc_texturefrac - dc_iscale) / (-dc_iscale)); + + (R_Drawers()->*colfunc)(); + } + span++; + } + } + + void R_DrawMaskedColumnBgra(int x, fixed_t iscale, FTexture *tex, fixed_t col, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, bool unmasked) + { + using namespace drawerargs; + + dc_x = x; + dc_iscale = iscale; + + // Normalize to 0-1 range: + double uv_stepd = FIXED2DBL(dc_iscale); + double v_step = uv_stepd / tex->GetHeight(); + + // Convert to uint32: + dc_iscale = (uint32_t)(v_step * (1 << 30)); + + // Texture mipmap and filter selection: + fixed_t xoffset = col; + + double xmagnitude = 1.0; // To do: pass this into R_DrawMaskedColumn + double ymagnitude = fabs(uv_stepd); + double magnitude = MAX(ymagnitude, xmagnitude); + double min_lod = -1000.0; + double lod = MAX(log2(magnitude) + r_lod_bias, min_lod); + bool magnifying = lod < 0.0f; + + int mipmap_offset = 0; + int mip_width = tex->GetWidth(); + int mip_height = tex->GetHeight(); + uint32_t xpos = (uint32_t)((((uint64_t)xoffset) << FRACBITS) / mip_width); + if (r_mipmap && tex->Mipmapped() && mip_width > 1 && mip_height > 1) + { + int level = (int)lod; + while (level > 0 && mip_width > 1 && mip_height > 1) + { + mipmap_offset += mip_width * mip_height; + level--; + mip_width = MAX(mip_width >> 1, 1); + mip_height = MAX(mip_height >> 1, 1); + } + } + xoffset = (xpos >> FRACBITS) * mip_width; + + const uint32_t *pixels = tex->GetPixelsBgra() + mipmap_offset; + + bool filter_nearest = (magnifying && !r_magfilter) || (!magnifying && !r_minfilter); + if (filter_nearest) + { + xoffset = MAX(MIN(xoffset, (mip_width << FRACBITS) - 1), 0); + + int tx = xoffset >> FRACBITS; + dc_source = (BYTE*)(pixels + tx * mip_height); + dc_source2 = nullptr; + dc_textureheight = mip_height; + dc_texturefracx = 0; + } + else + { + xoffset = MAX(MIN(xoffset - (FRACUNIT / 2), (mip_width << FRACBITS) - 1), 0); + + int tx0 = xoffset >> FRACBITS; + int tx1 = MIN(tx0 + 1, mip_width - 1); + dc_source = (BYTE*)(pixels + tx0 * mip_height); + dc_source2 = (BYTE*)(pixels + tx1 * mip_height); + dc_textureheight = mip_height; + dc_texturefracx = (xoffset >> (FRACBITS - 4)) & 15; + } + + // Grab the posts we need to draw + const FTexture::Span *span; + tex->GetColumnBgra(col >> FRACBITS, &span); + FTexture::Span unmaskedSpan[2]; + if (unmasked) + { + span = unmaskedSpan; + unmaskedSpan[0].TopOffset = 0; + unmaskedSpan[0].Length = tex->GetHeight(); + unmaskedSpan[1].TopOffset = 0; + unmaskedSpan[1].Length = 0; + } + + // Draw each span post + while (span->Length != 0) + { + const int length = span->Length; + const int top = span->TopOffset; + + // calculate unclipped screen coordinates for post + dc_yl = (int)(sprtopscreen + spryscale * top + 0.5); + dc_yh = (int)(sprtopscreen + spryscale * (top + length) + 0.5) - 1; + + if (sprflipvert) + { + swapvalues(dc_yl, dc_yh); + } + + if (dc_yh >= mfloorclip[dc_x]) + { + dc_yh = mfloorclip[dc_x] - 1; + } + if (dc_yl < mceilingclip[dc_x]) + { + dc_yl = mceilingclip[dc_x]; + } + + if (dc_yl <= dc_yh) + { + dc_dest = (ylookup[dc_yl] + dc_x) * 4 + dc_destorg; + dc_count = dc_yh - dc_yl + 1; + + double v = ((dc_yl + 0.5 - sprtopscreen) / spryscale) / tex->GetHeight(); + dc_texturefrac = (uint32_t)(v * (1 << 30)); + + (R_Drawers()->*colfunc)(); + } + span++; + } + } } diff --git a/src/swrenderer/drawers/r_draw.h b/src/swrenderer/drawers/r_draw.h index 195214658..bf26c8636 100644 --- a/src/swrenderer/drawers/r_draw.h +++ b/src/swrenderer/drawers/r_draw.h @@ -114,6 +114,10 @@ namespace swrenderer extern uint8_t identitymap[256]; extern FDynamicColormap identitycolormap; + // Constant arrays used for psprite clipping and initializing clipping. + extern short zeroarray[MAXWIDTH]; + extern short screenheightarray[MAXWIDTH]; + // Spectre/Invisibility. #define FUZZTABLE 50 extern int fuzzoffset[FUZZTABLE + 1]; @@ -186,6 +190,9 @@ namespace swrenderer void R_SetSpanTexture(FTexture *tex); void R_SetSpanColormap(FDynamicColormap *colormap, int shade); + void R_DrawMaskedColumn(int x, fixed_t iscale, FTexture *texture, fixed_t column, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, bool unmasked = false); + void R_DrawMaskedColumnBgra(int x, fixed_t iscale, FTexture *tex, fixed_t column, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, bool unmasked); + extern DrawerFunc colfunc; extern DrawerFunc basecolfunc; extern DrawerFunc fuzzcolfunc; diff --git a/src/swrenderer/scene/r_things.cpp b/src/swrenderer/scene/r_things.cpp index 54b93caee..57a0700fb 100644 --- a/src/swrenderer/scene/r_things.cpp +++ b/src/swrenderer/scene/r_things.cpp @@ -71,6 +71,7 @@ #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/r_memory.h" EXTERN_CVAR(Int, r_drawfuzz) @@ -123,12 +124,6 @@ int spriteshade; FTexture *WallSpriteTile; -// constant arrays -// used for psprite clipping and initializing clipping -short zeroarray[MAXWIDTH]; -short screenheightarray[MAXWIDTH]; - - // // INITIALIZATION FUNCTIONS // @@ -186,213 +181,6 @@ void R_ClearSprites (void) DrewAVoxel = false; } -// -// R_DrawMaskedColumn -// Used for sprites and masked mid textures. -// Masked means: partly transparent, i.e. stored -// in posts/runs of opaque pixels. -// -short* mfloorclip; -short* mceilingclip; - -double spryscale; -double sprtopscreen; - -bool sprflipvert; - -void R_DrawMaskedColumnBgra(FTexture *tex, fixed_t col, bool unmasked) -{ - fixed_t saved_iscale = dc_iscale; // Save this because we need to modify it for mipmaps - - // Normalize to 0-1 range: - double uv_stepd = FIXED2DBL(dc_iscale); - double v_step = uv_stepd / tex->GetHeight(); - - // Convert to uint32: - dc_iscale = (uint32_t)(v_step * (1 << 30)); - - // Texture mipmap and filter selection: - fixed_t xoffset = col; - - double xmagnitude = 1.0; // To do: pass this into R_DrawMaskedColumn - double ymagnitude = fabs(uv_stepd); - double magnitude = MAX(ymagnitude, xmagnitude); - double min_lod = -1000.0; - double lod = MAX(log2(magnitude) + r_lod_bias, min_lod); - bool magnifying = lod < 0.0f; - - int mipmap_offset = 0; - int mip_width = tex->GetWidth(); - int mip_height = tex->GetHeight(); - uint32_t xpos = (uint32_t)((((uint64_t)xoffset) << FRACBITS) / mip_width); - if (r_mipmap && tex->Mipmapped() && mip_width > 1 && mip_height > 1) - { - int level = (int)lod; - while (level > 0 && mip_width > 1 && mip_height > 1) - { - mipmap_offset += mip_width * mip_height; - level--; - mip_width = MAX(mip_width >> 1, 1); - mip_height = MAX(mip_height >> 1, 1); - } - } - xoffset = (xpos >> FRACBITS) * mip_width; - - const uint32_t *pixels = tex->GetPixelsBgra() + mipmap_offset; - - bool filter_nearest = (magnifying && !r_magfilter) || (!magnifying && !r_minfilter); - if (filter_nearest) - { - xoffset = MAX(MIN(xoffset, (mip_width << FRACBITS) - 1), 0); - - int tx = xoffset >> FRACBITS; - dc_source = (BYTE*)(pixels + tx * mip_height); - dc_source2 = nullptr; - dc_textureheight = mip_height; - dc_texturefracx = 0; - } - else - { - xoffset = MAX(MIN(xoffset - (FRACUNIT / 2), (mip_width << FRACBITS) - 1), 0); - - int tx0 = xoffset >> FRACBITS; - int tx1 = MIN(tx0 + 1, mip_width - 1); - dc_source = (BYTE*)(pixels + tx0 * mip_height); - dc_source2 = (BYTE*)(pixels + tx1 * mip_height); - dc_textureheight = mip_height; - dc_texturefracx = (xoffset >> (FRACBITS - 4)) & 15; - } - - // Grab the posts we need to draw - const FTexture::Span *span; - tex->GetColumnBgra(col >> FRACBITS, &span); - FTexture::Span unmaskedSpan[2]; - if (unmasked) - { - span = unmaskedSpan; - unmaskedSpan[0].TopOffset = 0; - unmaskedSpan[0].Length = tex->GetHeight(); - unmaskedSpan[1].TopOffset = 0; - unmaskedSpan[1].Length = 0; - } - - // Draw each span post - while (span->Length != 0) - { - const int length = span->Length; - const int top = span->TopOffset; - - // calculate unclipped screen coordinates for post - dc_yl = (int)(sprtopscreen + spryscale * top + 0.5); - dc_yh = (int)(sprtopscreen + spryscale * (top + length) + 0.5) - 1; - - if (sprflipvert) - { - swapvalues(dc_yl, dc_yh); - } - - if (dc_yh >= mfloorclip[dc_x]) - { - dc_yh = mfloorclip[dc_x] - 1; - } - if (dc_yl < mceilingclip[dc_x]) - { - dc_yl = mceilingclip[dc_x]; - } - - if (dc_yl <= dc_yh) - { - dc_dest = (ylookup[dc_yl] + dc_x) * 4 + dc_destorg; - dc_count = dc_yh - dc_yl + 1; - - double v = ((dc_yl + 0.5 - sprtopscreen) / spryscale) / tex->GetHeight(); - dc_texturefrac = (uint32_t)(v * (1 << 30)); - - (R_Drawers()->*colfunc)(); - } - span++; - } - - dc_iscale = saved_iscale; -} - -void R_DrawMaskedColumn (FTexture *tex, fixed_t col, bool unmasked) -{ - // Handle the linear filtered version in a different function to reduce chances of merge conflicts from zdoom. - if (r_swtruecolor && !drawer_needs_pal_input) // To do: add support to R_DrawColumnHoriz_rgba - { - R_DrawMaskedColumnBgra(tex, col, unmasked); - return; - } - - const FTexture::Span *span; - const BYTE *column; - if (r_swtruecolor && !drawer_needs_pal_input) - column = (const BYTE *)tex->GetColumnBgra(col >> FRACBITS, &span); - else - column = tex->GetColumn(col >> FRACBITS, &span); - - FTexture::Span unmaskedSpan[2]; - if (unmasked) - { - span = unmaskedSpan; - unmaskedSpan[0].TopOffset = 0; - unmaskedSpan[0].Length = tex->GetHeight(); - unmaskedSpan[1].TopOffset = 0; - unmaskedSpan[1].Length = 0; - } - - int pixelsize = r_swtruecolor ? 4 : 1; - - while (span->Length != 0) - { - const int length = span->Length; - const int top = span->TopOffset; - - // calculate unclipped screen coordinates for post - dc_yl = (int)(sprtopscreen + spryscale * top + 0.5); - dc_yh = (int)(sprtopscreen + spryscale * (top + length) + 0.5) - 1; - - if (sprflipvert) - { - swapvalues (dc_yl, dc_yh); - } - - if (dc_yh >= mfloorclip[dc_x]) - { - dc_yh = mfloorclip[dc_x] - 1; - } - if (dc_yl < mceilingclip[dc_x]) - { - dc_yl = mceilingclip[dc_x]; - } - - if (dc_yl <= dc_yh) - { - dc_texturefrac = FLOAT2FIXED((dc_yl + 0.5 - sprtopscreen) / spryscale); - dc_source = column; - dc_source2 = nullptr; - dc_dest = (ylookup[dc_yl] + dc_x) * pixelsize + dc_destorg; - dc_count = dc_yh - dc_yl + 1; - - fixed_t maxfrac = ((top + length) << FRACBITS) - 1; - dc_texturefrac = MAX(dc_texturefrac, 0); - dc_texturefrac = MIN(dc_texturefrac, maxfrac); - if (dc_iscale > 0) - dc_count = MIN(dc_count, (maxfrac - dc_texturefrac + dc_iscale - 1) / dc_iscale); - else if (dc_iscale < 0) - dc_count = MIN(dc_count, (dc_texturefrac - dc_iscale) / (-dc_iscale)); - - (R_Drawers()->*colfunc)(); - } - span++; - } -} - -// [ZZ] -// R_ClipSpriteColumnWithPortals -// - static TArray portaldrawsegs; static inline void R_CollectPortals() @@ -454,78 +242,6 @@ bool R_ClipSpriteColumnWithPortals(vissprite_t* spr) } -// -// R_DrawVisSprite -// mfloorclip and mceilingclip should also be set. -// -void R_DrawVisSprite (vissprite_t *vis) -{ - fixed_t frac; - FTexture *tex; - int x2; - fixed_t xiscale; - bool ispsprite = (!vis->sector && vis->gpos != FVector3(0, 0, 0)); - - if (vis->xscale == 0 || fabs(vis->yscale) < (1.0f / 32000.0f)) - { // scaled to 0; can't see - return; - } - - fixed_t centeryfrac = FLOAT2FIXED(CenterY); - R_SetColorMapLight(vis->Style.BaseColormap, 0, vis->Style.ColormapNum << FRACBITS); - - bool visible = R_SetPatchStyle (vis->Style.RenderStyle, vis->Style.Alpha, vis->Translation, vis->FillColor); - - if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Shaded]) - { // For shaded sprites, R_SetPatchStyle sets a dc_colormap to an alpha table, but - // it is the brightest one. We need to get back to the proper light level for - // this sprite. - R_SetColorMapLight(dc_fcolormap, 0, vis->Style.ColormapNum << FRACBITS); - } - - if (visible) - { - tex = vis->pic; - spryscale = vis->yscale; - sprflipvert = false; - dc_iscale = FLOAT2FIXED(1 / vis->yscale); - frac = vis->startfrac; - xiscale = vis->xiscale; - dc_texturemid = vis->texturemid; - - if (vis->renderflags & RF_YFLIP) - { - sprflipvert = true; - spryscale = -spryscale; - dc_iscale = -dc_iscale; - dc_texturemid -= vis->pic->GetHeight(); - sprtopscreen = CenterY + dc_texturemid * spryscale; - } - else - { - sprflipvert = false; - sprtopscreen = CenterY - dc_texturemid * spryscale; - } - - dc_x = vis->x1; - x2 = vis->x2; - - if (dc_x < x2) - { - while (dc_x < x2) - { - if (ispsprite || !R_ClipSpriteColumnWithPortals(vis)) - R_DrawMaskedColumn (tex, frac, false); - dc_x++; - frac += xiscale; - } - } - } - - R_FinishSetPatchStyle (); - - NetUpdate (); -} #if 0 void R_DrawVisVoxel(vissprite_t *spr, int minslabz, int maxslabz, short *cliptop, short *clipbot) @@ -1663,15 +1379,13 @@ void R_DrawSprite (vissprite_t *spr) if (!spr->bIsVoxel) { - mfloorclip = clipbot; - mceilingclip = cliptop; if (!spr->bWallSprite) { - R_DrawVisSprite(spr); + R_DrawVisSprite(spr, clipbot, cliptop); } else { - R_DrawWallSprite(spr); + R_DrawWallSprite(spr, clipbot, cliptop); } } else diff --git a/src/swrenderer/scene/r_things.h b/src/swrenderer/scene/r_things.h index 5782ea02b..97ef51cbd 100644 --- a/src/swrenderer/scene/r_things.h +++ b/src/swrenderer/scene/r_things.h @@ -38,18 +38,6 @@ EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); namespace swrenderer { -// Constant arrays used for psprite clipping -// and initializing clipping. -extern short zeroarray[MAXWIDTH]; -extern short screenheightarray[MAXWIDTH]; - -// vars for R_DrawMaskedColumn -extern short* mfloorclip; -extern short* mceilingclip; -extern double spryscale; -extern double sprtopscreen; -extern bool sprflipvert; - extern double pspritexscale; extern double pspritexiscale; extern double pspriteyscale; @@ -60,7 +48,6 @@ extern int spriteshade; bool R_ClipSpriteColumnWithPortals(vissprite_t* spr); -void R_DrawMaskedColumn (FTexture *texture, fixed_t column, bool unmasked = false); void R_CacheSprite (spritedef_t *sprite); void R_SortVisSprites (int (*compare)(const void *, const void *), size_t first); @@ -74,7 +61,7 @@ void R_CheckOffscreenBuffer(int width, int height, bool spansonly); enum { DVF_OFFSCREEN = 1, DVF_SPANSONLY = 2, DVF_MIRRORED = 4 }; void R_ClipVisSprite (vissprite_t *vis, int xl, int xh); -void R_DrawVisSprite(vissprite_t *vis); + } diff --git a/src/swrenderer/segments/r_drawsegment.cpp b/src/swrenderer/segments/r_drawsegment.cpp index c8ac27d9f..fbbff4ec3 100644 --- a/src/swrenderer/segments/r_drawsegment.cpp +++ b/src/swrenderer/segments/r_drawsegment.cpp @@ -140,7 +140,7 @@ namespace swrenderer const sector_t *sec; - sprflipvert = false; + bool sprflipvert = false; curline = ds->curline; @@ -192,8 +192,8 @@ namespace swrenderer } } - mfloorclip = openings + ds->sprbottomclip - ds->x1; - mceilingclip = openings + ds->sprtopclip - ds->x1; + short *mfloorclip = openings + ds->sprbottomclip - ds->x1; + short *mceilingclip = openings + ds->sprtopclip - ds->x1; // [RH] Draw fog partition @@ -213,7 +213,7 @@ namespace swrenderer MaskedSWall = (float *)(openings + ds->swall) - ds->x1; MaskedScaleY = ds->yscale; maskedtexturecol = (fixed_t *)(openings + ds->maskedtexturecol) - ds->x1; - spryscale = ds->iscale + ds->iscalestep * (x1 - ds->x1); + double spryscale = ds->iscale + ds->iscalestep * (x1 - ds->x1); rw_scalestep = ds->iscalestep; if (fixedlightlev >= 0) @@ -342,21 +342,21 @@ namespace swrenderer // draw the columns one at a time if (visible) { - using namespace drawerargs; - for (dc_x = x1; dc_x < x2; ++dc_x) + for (int x = x1; x < x2; ++x) { if (fixedcolormap == nullptr && fixedlightlev < 0) { R_SetColorMapLight(basecolormap, rw_light, wallshade); } - dc_iscale = xs_Fix<16>::ToFix(MaskedSWall[dc_x] * MaskedScaleY); + fixed_t iscale = xs_Fix<16>::ToFix(MaskedSWall[x] * MaskedScaleY); + double sprtopscreen; if (sprflipvert) sprtopscreen = CenterY + dc_texturemid * spryscale; else sprtopscreen = CenterY - dc_texturemid * spryscale; - R_DrawMaskedColumn(tex, maskedtexturecol[dc_x]); + R_DrawMaskedColumn(x, iscale, tex, maskedtexturecol[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip); rw_light += rw_lightstep; spryscale += rw_scalestep; @@ -463,10 +463,10 @@ namespace swrenderer rw_lightstep = ds->lightstep; rw_light = ds->light + (x1 - ds->x1) * rw_lightstep; - mfloorclip = openings + ds->sprbottomclip - ds->x1; - mceilingclip = openings + ds->sprtopclip - ds->x1; + short *mfloorclip = openings + ds->sprbottomclip - ds->x1; + short *mceilingclip = openings + ds->sprtopclip - ds->x1; - spryscale = ds->iscale + ds->iscalestep * (x1 - ds->x1); + //double spryscale = ds->iscale + ds->iscalestep * (x1 - ds->x1); float *MaskedSWall = (float *)(openings + ds->swall) - ds->x1; // find positioning @@ -558,7 +558,6 @@ namespace swrenderer double floorHeight; double ceilingHeight; - sprflipvert = false; curline = ds->curline; frontsector = curline->frontsector; diff --git a/src/swrenderer/things/r_decal.cpp b/src/swrenderer/things/r_decal.cpp index ba08cfd01..043d6e57b 100644 --- a/src/swrenderer/things/r_decal.cpp +++ b/src/swrenderer/things/r_decal.cpp @@ -39,7 +39,7 @@ #include "swrenderer/line/r_walldraw.h" #include "swrenderer/segments/r_drawsegment.h" #include "swrenderer/scene/r_portal.h" -#include "r_wallsprite.h" +#include "swrenderer/things/r_wallsprite.h" #include "swrenderer/r_memory.h" namespace swrenderer @@ -69,6 +69,8 @@ namespace swrenderer bool rereadcolormap; FDynamicColormap *usecolormap; float light = 0; + short *mfloorclip; + short *mceilingclip; if (decal->RenderFlags & RF_INVISIBLE || !viewactive || !decal->PicNum.isValid()) return; @@ -255,6 +257,7 @@ namespace swrenderer calclighting = true; // Draw it + bool sprflipvert; if (decal->RenderFlags & RF_YFLIP) { sprflipvert = true; @@ -287,7 +290,7 @@ namespace swrenderer { // calculate lighting R_SetColorMapLight(usecolormap, light, wallshade); } - R_DecalColumn(x, maskedScaleY); + R_DecalColumn(x, maskedScaleY, sprflipvert, mfloorclip, mceilingclip); light += lightstep; x++; } @@ -308,21 +311,16 @@ namespace swrenderer WallC = savecoord; } - void R_DecalColumn(int x, float maskedScaleY) + void R_DecalColumn(int x, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip) { - using namespace drawerargs; - - dc_x = x; - - float iscale = swall[dc_x] * maskedScaleY; - dc_iscale = FLOAT2FIXED(iscale); - spryscale = 1 / iscale; + float iscale = swall[x] * maskedScaleY; + double spryscale = 1 / iscale; + double sprtopscreen; if (sprflipvert) sprtopscreen = CenterY + dc_texturemid * spryscale; else sprtopscreen = CenterY - dc_texturemid * spryscale; - dc_texturefrac = 0; - R_DrawMaskedColumn(WallSpriteTile, lwall[dc_x]); + R_DrawMaskedColumn(x, FLOAT2FIXED(iscale), WallSpriteTile, lwall[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip); } } diff --git a/src/swrenderer/things/r_decal.h b/src/swrenderer/things/r_decal.h index 7bd4147fa..5399fb370 100644 --- a/src/swrenderer/things/r_decal.h +++ b/src/swrenderer/things/r_decal.h @@ -22,5 +22,5 @@ namespace swrenderer void R_RenderDecals(side_t *wall, drawseg_t *draw_segment, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC); void R_RenderDecal(side_t *wall, DBaseDecal *first, drawseg_t *clipper, int wallshade, float lightleft, float lightstep, seg_t *curline, FWallCoords wallC, int pass); - void R_DecalColumn(int x, float maskedScaleY); + void R_DecalColumn(int x, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip); } diff --git a/src/swrenderer/things/r_playersprite.cpp b/src/swrenderer/things/r_playersprite.cpp index 1316a40ca..0af6c0421 100644 --- a/src/swrenderer/things/r_playersprite.cpp +++ b/src/swrenderer/things/r_playersprite.cpp @@ -52,6 +52,7 @@ #include "r_voxel.h" #include "swrenderer/segments/r_drawsegment.h" #include "swrenderer/scene/r_portal.h" +#include "swrenderer/things/r_sprite.h" #include "swrenderer/r_memory.h" EXTERN_CVAR(Bool, st_scale) @@ -137,10 +138,6 @@ namespace swrenderer lightnum = ((floorlight + ceilinglight) >> 1) + r_actualextralight; spriteshade = LIGHT2SHADE(lightnum) - 24 * FRACUNIT; - // clip to screen bounds - mfloorclip = screenheightarray; - mceilingclip = zeroarray; - if (camera->player != NULL) { double centerhack = CenterY; @@ -566,7 +563,11 @@ namespace swrenderer } } - R_DrawVisSprite(vis); + // clip to screen bounds + short *mfloorclip = screenheightarray; + short *mceilingclip = zeroarray; + + R_DrawVisSprite(vis, mfloorclip, mceilingclip); } void R_DrawRemainingPlayerSprites() diff --git a/src/swrenderer/things/r_sprite.cpp b/src/swrenderer/things/r_sprite.cpp new file mode 100644 index 000000000..0a87d45e4 --- /dev/null +++ b/src/swrenderer/things/r_sprite.cpp @@ -0,0 +1,131 @@ +// +// 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. +// + +#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/things/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 "swrenderer/scene/r_bsp.h" +#include "swrenderer/scene/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 "swrenderer/segments/r_drawsegment.h" +#include "swrenderer/scene/r_portal.h" +#include "swrenderer/things/r_sprite.h" +#include "swrenderer/r_memory.h" + +namespace swrenderer +{ + void R_DrawVisSprite(vissprite_t *vis, const short *mfloorclip, const short *mceilingclip) + { + fixed_t frac; + FTexture *tex; + int x2; + fixed_t xiscale; + bool ispsprite = (!vis->sector && vis->gpos != FVector3(0, 0, 0)); + + double spryscale, sprtopscreen; + bool sprflipvert; + + if (vis->xscale == 0 || fabs(vis->yscale) < (1.0f / 32000.0f)) + { // scaled to 0; can't see + return; + } + + fixed_t centeryfrac = FLOAT2FIXED(CenterY); + R_SetColorMapLight(vis->Style.BaseColormap, 0, vis->Style.ColormapNum << FRACBITS); + + bool visible = R_SetPatchStyle(vis->Style.RenderStyle, vis->Style.Alpha, vis->Translation, vis->FillColor); + + if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Shaded]) + { // For shaded sprites, R_SetPatchStyle sets a dc_colormap to an alpha table, but + // it is the brightest one. We need to get back to the proper light level for + // this sprite. + R_SetColorMapLight(drawerargs::dc_fcolormap, 0, vis->Style.ColormapNum << FRACBITS); + } + + if (visible) + { + tex = vis->pic; + spryscale = vis->yscale; + sprflipvert = false; + fixed_t iscale = FLOAT2FIXED(1 / vis->yscale); + frac = vis->startfrac; + xiscale = vis->xiscale; + dc_texturemid = vis->texturemid; + + if (vis->renderflags & RF_YFLIP) + { + sprflipvert = true; + spryscale = -spryscale; + iscale = -iscale; + dc_texturemid -= vis->pic->GetHeight(); + sprtopscreen = CenterY + dc_texturemid * spryscale; + } + else + { + sprflipvert = false; + sprtopscreen = CenterY - dc_texturemid * spryscale; + } + + int x = vis->x1; + x2 = vis->x2; + + if (x < x2) + { + while (x < x2) + { + if (ispsprite || !R_ClipSpriteColumnWithPortals(vis)) + R_DrawMaskedColumn(x, iscale, tex, frac, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, false); + x++; + frac += xiscale; + } + } + } + + R_FinishSetPatchStyle(); + + NetUpdate(); + } +} diff --git a/src/swrenderer/things/r_sprite.h b/src/swrenderer/things/r_sprite.h new file mode 100644 index 000000000..5d8f898f6 --- /dev/null +++ b/src/swrenderer/things/r_sprite.h @@ -0,0 +1,21 @@ +// +// 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. +// + +#pragma once + +#include "r_visiblesprite.h" + +namespace swrenderer +{ + void R_DrawVisSprite(vissprite_t *vis, const short *mfloorclip, const short *mceilingclip); +} diff --git a/src/swrenderer/things/r_wallsprite.cpp b/src/swrenderer/things/r_wallsprite.cpp index 7699edf70..e04bdc6cb 100644 --- a/src/swrenderer/things/r_wallsprite.cpp +++ b/src/swrenderer/things/r_wallsprite.cpp @@ -134,10 +134,11 @@ namespace swrenderer vis->wallc = wallc; } - void R_DrawWallSprite(vissprite_t *spr) + void R_DrawWallSprite(vissprite_t *spr, const short *mfloorclip, const short *mceilingclip) { int x1, x2; double iyscale; + bool sprflipvert; x1 = MAX(spr->x1, spr->wallc.sx1); x2 = MIN(spr->x2, spr->wallc.sx2); @@ -221,7 +222,7 @@ namespace swrenderer R_SetColorMapLight(usecolormap, light, shade); } if (!R_ClipSpriteColumnWithPortals(spr)) - R_WallSpriteColumn(x, maskedScaleY); + R_WallSpriteColumn(x, maskedScaleY, sprflipvert, mfloorclip, mceilingclip); light += lightstep; x++; } @@ -229,21 +230,16 @@ namespace swrenderer R_FinishSetPatchStyle(); } - void R_WallSpriteColumn(int x, float maskedScaleY) + void R_WallSpriteColumn(int x, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip) { - using namespace drawerargs; - - dc_x = x; - - float iscale = swall[dc_x] * maskedScaleY; - dc_iscale = FLOAT2FIXED(iscale); - spryscale = 1 / iscale; + float iscale = swall[x] * maskedScaleY; + double spryscale = 1 / iscale; + double sprtopscreen; if (sprflipvert) sprtopscreen = CenterY + dc_texturemid * spryscale; else sprtopscreen = CenterY - dc_texturemid * spryscale; - dc_texturefrac = 0; - R_DrawMaskedColumn(WallSpriteTile, lwall[dc_x]); + R_DrawMaskedColumn(x, FLOAT2FIXED(iscale), WallSpriteTile, lwall[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip); } } diff --git a/src/swrenderer/things/r_wallsprite.h b/src/swrenderer/things/r_wallsprite.h index cecb4738d..57b96db46 100644 --- a/src/swrenderer/things/r_wallsprite.h +++ b/src/swrenderer/things/r_wallsprite.h @@ -18,6 +18,6 @@ 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); + void R_DrawWallSprite(vissprite_t *spr, const short *mfloorclip, const short *mceilingclip); + void R_WallSpriteColumn(int x, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip); } diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 5e5722030..07c3d2a13 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -46,7 +46,6 @@ #include "swrenderer/drawers/r_draw.h" #include "swrenderer/drawers/r_draw_rgba.h" #include "swrenderer/r_main.h" -#include "swrenderer/scene/r_things.h" #endif #include "r_data/r_translate.h" #include "doomstat.h" @@ -212,24 +211,25 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) // There is not enough precision in the drawing routines to keep the full // precision for y0. :( + double sprtopscreen; modf(y0, &sprtopscreen); double yscale = parms.destheight / img->GetHeight(); double iyscale = 1 / yscale; - spryscale = yscale; + double spryscale = yscale; assert(spryscale > 0); - sprflipvert = false; - //dc_iscale = FLOAT2FIXED(iyscale); - //dc_texturemid = (-y0) * iyscale; - //dc_iscale = 0xffffffffu / (unsigned)spryscale; - dc_iscale = FLOAT2FIXED(1 / spryscale); - dc_texturemid = (CenterY - 1 - sprtopscreen) * dc_iscale / 65536; + bool sprflipvert = false; + fixed_t iscale = FLOAT2FIXED(1 / spryscale); + //dc_texturemid = (CenterY - 1 - sprtopscreen) * iscale / 65536; fixed_t frac = 0; double xiscale = img->GetWidth() / parms.destwidth; double x2 = x0 + parms.destwidth; + short *mfloorclip; + short *mceilingclip; + if (bottomclipper[0] != parms.dclip) { fillshort(bottomclipper, screen->GetWidth(), (short)parms.dclip); @@ -272,14 +272,14 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) x2 = parms.rclip; } - dc_x = int(x0); + int x = int(x0); int x2_i = int(x2); fixed_t xiscale_i = FLOAT2FIXED(xiscale); - while (dc_x < x2_i) + while (x < x2_i) { - R_DrawMaskedColumn(img, frac, !parms.masked); - dc_x++; + R_DrawMaskedColumn(x, iscale, img, frac, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, !parms.masked); + x++; frac += xiscale_i; }