- Change all sky drawing code use to use the sky drawers

- Add support for drawing repeating skies in the sky drawers
- Add the old 4 column sky fade optimization to the 1 column variant (fixes speed regression when 4col was removed)
- Remove skyplane globals
- Remove walldraw code used to draw the old skies
This commit is contained in:
Magnus Norddahl 2017-01-19 00:02:51 +01:00
parent 590781d4a6
commit 8788a9e788
10 changed files with 314 additions and 445 deletions

View file

@ -134,8 +134,8 @@ namespace swrenderer
virtual void DrawWallAddClampColumn() = 0;
virtual void DrawWallSubClampColumn() = 0;
virtual void DrawWallRevSubClampColumn() = 0;
virtual void DrawSingleSkyColumn(uint32_t solid_top, uint32_t solid_bottom) = 0;
virtual void DrawDoubleSkyColumn(uint32_t solid_top, uint32_t solid_bottom) = 0;
virtual void DrawSingleSkyColumn(uint32_t solid_top, uint32_t solid_bottom, bool fadeSky) = 0;
virtual void DrawDoubleSkyColumn(uint32_t solid_top, uint32_t solid_bottom, bool fadeSky) = 0;
virtual void DrawColumn() = 0;
virtual void FillColumn() = 0;
virtual void FillAddColumn() = 0;

View file

@ -560,7 +560,7 @@ namespace swrenderer
/////////////////////////////////////////////////////////////////////////
PalSkyCommand::PalSkyCommand(uint32_t solid_top, uint32_t solid_bottom) : solid_top(solid_top), solid_bottom(solid_bottom)
PalSkyCommand::PalSkyCommand(uint32_t solid_top, uint32_t solid_bottom, bool fadeSky) : solid_top(solid_top), solid_bottom(solid_bottom), fadeSky(fadeSky)
{
using namespace drawerargs;
@ -588,7 +588,39 @@ namespace swrenderer
int32_t frac = _texturefrac[0];
int32_t fracstep = _iscale[0];
// Find bands for top solid color, top fade, center textured, bottom fade, bottom solid color:
int start_fade = 2; // How fast it should fade out
int fade_length = (1 << (24 - start_fade));
int start_fadetop_y = (-frac) / fracstep;
int end_fadetop_y = (fade_length - frac) / fracstep;
int start_fadebottom_y = ((2 << 24) - fade_length - frac) / fracstep;
int end_fadebottom_y = ((2 << 24) - frac) / fracstep;
start_fadetop_y = clamp(start_fadetop_y, 0, count);
end_fadetop_y = clamp(end_fadetop_y, 0, count);
start_fadebottom_y = clamp(start_fadebottom_y, 0, count);
end_fadebottom_y = clamp(end_fadebottom_y, 0, count);
int num_cores = thread->num_cores;
int skipped = thread->skipped_by_thread(_dest_y);
dest = thread->dest_for_thread(_dest_y, pitch, dest);
frac += fracstep * skipped;
fracstep *= num_cores;
pitch *= num_cores;
if (!fadeSky)
{
count = thread->count_for_thread(_dest_y, count);
for (int index = 0; index < count; index++)
{
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
*dest = source0[sample_index];
dest += pitch;
frac += fracstep;
}
return;
}
int solid_top_r = RPART(solid_top);
int solid_top_g = GPART(solid_top);
@ -596,49 +628,83 @@ namespace swrenderer
int solid_bottom_r = RPART(solid_bottom);
int solid_bottom_g = GPART(solid_bottom);
int solid_bottom_b = BPART(solid_bottom);
uint8_t solid_top_fill = RGB32k.RGB[(solid_top_r >> 3)][(solid_top_g >> 3)][(solid_top_b >> 3)];
uint8_t solid_bottom_fill = RGB32k.RGB[(solid_bottom_r >> 3)][(solid_bottom_g >> 3)][(solid_bottom_b >> 3)];
count = thread->count_for_thread(_dest_y, count);
if (count <= 0)
return;
const uint32_t *palette = (const uint32_t *)GPalette.BaseColors;
int skipped = thread->skipped_by_thread(_dest_y);
dest = thread->dest_for_thread(_dest_y, pitch, dest);
frac += fracstep * skipped;
fracstep *= thread->num_cores;
pitch *= thread->num_cores;
int index = skipped;
for (int index = 0; index < count; index++)
// Top solid color:
while (index < start_fadetop_y)
{
*dest = solid_top_fill;
dest += pitch;
frac += fracstep;
index += num_cores;
}
// Top fade:
while (index < end_fadetop_y)
{
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[sample_index];
uint32_t c = palette[fg];
int alpha_top = MAX(MIN(frac >> (16 - start_fade), 256), 0);
int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0);
if (alpha_top == 256 && alpha_bottom == 256)
{
*dest = fg;
}
else
{
int inv_alpha_top = 256 - alpha_top;
int inv_alpha_bottom = 256 - alpha_bottom;
const auto &c = GPalette.BaseColors[fg];
int c_red = c.r;
int c_green = c.g;
int c_blue = c.b;
c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8;
c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8;
c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8;
c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8;
c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8;
c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8;
*dest = RGB256k.RGB[(c_red >> 2)][(c_green >> 2)][(c_blue >> 2)];
}
int inv_alpha_top = 256 - alpha_top;
int c_red = RPART(c);
int c_green = GPART(c);
int c_blue = BPART(c);
c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8;
c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8;
c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8;
*dest = RGB256k.RGB[(c_red >> 2)][(c_green >> 2)][(c_blue >> 2)];
frac += fracstep;
dest += pitch;
index += num_cores;
}
// Textured center:
while (index < start_fadebottom_y)
{
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
*dest = source0[sample_index];
frac += fracstep;
dest += pitch;
index += num_cores;
}
// Fade bottom:
while (index < end_fadebottom_y)
{
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[sample_index];
uint32_t c = palette[fg];
int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0);
int inv_alpha_bottom = 256 - alpha_bottom;
int c_red = RPART(c);
int c_green = GPART(c);
int c_blue = BPART(c);
c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8;
c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8;
c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8;
*dest = RGB256k.RGB[(c_red >> 2)][(c_green >> 2)][(c_blue >> 2)];
frac += fracstep;
dest += pitch;
index += num_cores;
}
// Bottom solid color:
while (index < count)
{
*dest = solid_bottom_fill;
dest += pitch;
index += num_cores;
}
}
@ -655,7 +721,46 @@ namespace swrenderer
int32_t frac = _texturefrac[0];
int32_t fracstep = _iscale[0];
// Find bands for top solid color, top fade, center textured, bottom fade, bottom solid color:
int start_fade = 2; // How fast it should fade out
int fade_length = (1 << (24 - start_fade));
int start_fadetop_y = (-frac) / fracstep;
int end_fadetop_y = (fade_length - frac) / fracstep;
int start_fadebottom_y = ((2 << 24) - fade_length - frac) / fracstep;
int end_fadebottom_y = ((2 << 24) - frac) / fracstep;
start_fadetop_y = clamp(start_fadetop_y, 0, count);
end_fadetop_y = clamp(end_fadetop_y, 0, count);
start_fadebottom_y = clamp(start_fadebottom_y, 0, count);
end_fadebottom_y = clamp(end_fadebottom_y, 0, count);
int num_cores = thread->num_cores;
int skipped = thread->skipped_by_thread(_dest_y);
dest = thread->dest_for_thread(_dest_y, pitch, dest);
frac += fracstep * skipped;
fracstep *= num_cores;
pitch *= num_cores;
if (!fadeSky)
{
count = thread->count_for_thread(_dest_y, count);
for (int index = 0; index < count; index++)
{
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[sample_index];
if (fg == 0)
{
uint32_t sample_index2 = MIN(sample_index, maxtextureheight1);
fg = source1[sample_index2];
}
*dest = fg;
dest += pitch;
frac += fracstep;
}
return;
}
int solid_top_r = RPART(solid_top);
int solid_top_g = GPART(solid_top);
@ -663,18 +768,24 @@ namespace swrenderer
int solid_bottom_r = RPART(solid_bottom);
int solid_bottom_g = GPART(solid_bottom);
int solid_bottom_b = BPART(solid_bottom);
uint8_t solid_top_fill = RGB32k.RGB[(solid_top_r >> 3)][(solid_top_g >> 3)][(solid_top_b >> 3)];
uint8_t solid_bottom_fill = RGB32k.RGB[(solid_bottom_r >> 3)][(solid_bottom_g >> 3)][(solid_bottom_b >> 3)];
count = thread->count_for_thread(_dest_y, count);
if (count <= 0)
return;
const uint32_t *palette = (const uint32_t *)GPalette.BaseColors;
int skipped = thread->skipped_by_thread(_dest_y);
dest = thread->dest_for_thread(_dest_y, pitch, dest);
frac += fracstep * skipped;
fracstep *= thread->num_cores;
pitch *= thread->num_cores;
int index = skipped;
for (int index = 0; index < count; index++)
// Top solid color:
while (index < start_fadetop_y)
{
*dest = solid_top_fill;
dest += pitch;
frac += fracstep;
index += num_cores;
}
// Top fade:
while (index < end_fadetop_y)
{
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[sample_index];
@ -684,33 +795,72 @@ namespace swrenderer
fg = source1[sample_index2];
}
uint32_t c = palette[fg];
int alpha_top = MAX(MIN(frac >> (16 - start_fade), 256), 0);
int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0);
if (alpha_top == 256 && alpha_bottom == 256)
{
*dest = fg;
}
else
{
int inv_alpha_top = 256 - alpha_top;
int inv_alpha_bottom = 256 - alpha_bottom;
const auto &c = GPalette.BaseColors[fg];
int c_red = c.r;
int c_green = c.g;
int c_blue = c.b;
c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8;
c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8;
c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8;
c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8;
c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8;
c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8;
*dest = RGB256k.RGB[(c_red >> 2)][(c_green >> 2)][(c_blue >> 2)];
}
int inv_alpha_top = 256 - alpha_top;
int c_red = RPART(c);
int c_green = GPART(c);
int c_blue = BPART(c);
c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8;
c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8;
c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8;
*dest = RGB256k.RGB[(c_red >> 2)][(c_green >> 2)][(c_blue >> 2)];
frac += fracstep;
dest += pitch;
index += num_cores;
}
// Textured center:
while (index < start_fadebottom_y)
{
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[sample_index];
if (fg == 0)
{
uint32_t sample_index2 = MIN(sample_index, maxtextureheight1);
fg = source1[sample_index2];
}
*dest = fg;
frac += fracstep;
dest += pitch;
index += num_cores;
}
// Fade bottom:
while (index < end_fadebottom_y)
{
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[sample_index];
if (fg == 0)
{
uint32_t sample_index2 = MIN(sample_index, maxtextureheight1);
fg = source1[sample_index2];
}
uint32_t c = palette[fg];
int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0);
int inv_alpha_bottom = 256 - alpha_bottom;
int c_red = RPART(c);
int c_green = GPART(c);
int c_blue = BPART(c);
c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8;
c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8;
c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8;
*dest = RGB256k.RGB[(c_red >> 2)][(c_green >> 2)][(c_blue >> 2)];
frac += fracstep;
dest += pitch;
index += num_cores;
}
// Bottom solid color:
while (index < count)
{
*dest = solid_bottom_fill;
dest += pitch;
index += num_cores;
}
}

View file

@ -42,12 +42,13 @@ namespace swrenderer
class PalSkyCommand : public DrawerCommand
{
public:
PalSkyCommand(uint32_t solid_top, uint32_t solid_bottom);
PalSkyCommand(uint32_t solid_top, uint32_t solid_bottom, bool fadeSky);
FString DebugInfo() override { return "PalSkyCommand"; }
protected:
uint32_t solid_top;
uint32_t solid_bottom;
bool fadeSky;
uint8_t *_dest;
int _count;
@ -249,8 +250,8 @@ namespace swrenderer
void DrawWallAddClampColumn() override { DrawerCommandQueue::QueueCommand<DrawWallAddClamp1PalCommand>(); }
void DrawWallSubClampColumn() override { DrawerCommandQueue::QueueCommand<DrawWallSubClamp1PalCommand>(); }
void DrawWallRevSubClampColumn() override { DrawerCommandQueue::QueueCommand<DrawWallRevSubClamp1PalCommand>(); }
void DrawSingleSkyColumn(uint32_t solid_top, uint32_t solid_bottom) override { DrawerCommandQueue::QueueCommand<DrawSingleSky1PalCommand>(solid_top, solid_bottom); }
void DrawDoubleSkyColumn(uint32_t solid_top, uint32_t solid_bottom) override { DrawerCommandQueue::QueueCommand<DrawDoubleSky1PalCommand>(solid_top, solid_bottom); }
void DrawSingleSkyColumn(uint32_t solid_top, uint32_t solid_bottom, bool fadeSky) override { DrawerCommandQueue::QueueCommand<DrawSingleSky1PalCommand>(solid_top, solid_bottom, fadeSky); }
void DrawDoubleSkyColumn(uint32_t solid_top, uint32_t solid_bottom, bool fadeSky) override { DrawerCommandQueue::QueueCommand<DrawDoubleSky1PalCommand>(solid_top, solid_bottom, fadeSky); }
void DrawColumn() override { DrawerCommandQueue::QueueCommand<DrawColumnPalCommand>(); }
void FillColumn() override { DrawerCommandQueue::QueueCommand<FillColumnPalCommand>(); }
void FillAddColumn() override { DrawerCommandQueue::QueueCommand<FillColumnAddPalCommand>(); }

View file

@ -310,7 +310,7 @@ namespace swrenderer
return d;
}
DrawSkyLLVMCommand::DrawSkyLLVMCommand(uint32_t solid_top, uint32_t solid_bottom)
DrawSkyLLVMCommand::DrawSkyLLVMCommand(uint32_t solid_top, uint32_t solid_bottom, bool fadeSky)
{
using namespace drawerargs;

View file

@ -157,7 +157,7 @@ namespace swrenderer
WorkerThreadData ThreadData(DrawerThread *thread);
public:
DrawSkyLLVMCommand(uint32_t solid_top, uint32_t solid_bottom);
DrawSkyLLVMCommand(uint32_t solid_top, uint32_t solid_bottom, bool fadeSky);
FString DebugInfo() override;
};
@ -353,8 +353,8 @@ namespace swrenderer
void DrawWallAddClampColumn() override { DrawerCommandQueue::QueueCommand<DrawWallAddClamp1LLVMCommand>(); }
void DrawWallSubClampColumn() override { DrawerCommandQueue::QueueCommand<DrawWallSubClamp1LLVMCommand>(); }
void DrawWallRevSubClampColumn() override { DrawerCommandQueue::QueueCommand<DrawWallRevSubClamp1LLVMCommand>(); }
void DrawSingleSkyColumn(uint32_t solid_top, uint32_t solid_bottom) override { DrawerCommandQueue::QueueCommand<DrawSingleSky1LLVMCommand>(solid_top, solid_bottom); }
void DrawDoubleSkyColumn(uint32_t solid_top, uint32_t solid_bottom) override { DrawerCommandQueue::QueueCommand<DrawDoubleSky1LLVMCommand>(solid_top, solid_bottom); }
void DrawSingleSkyColumn(uint32_t solid_top, uint32_t solid_bottom, bool skyFade) override { DrawerCommandQueue::QueueCommand<DrawSingleSky1LLVMCommand>(solid_top, solid_bottom, skyFade); }
void DrawDoubleSkyColumn(uint32_t solid_top, uint32_t solid_bottom, bool skyFade) override { DrawerCommandQueue::QueueCommand<DrawDoubleSky1LLVMCommand>(solid_top, solid_bottom, skyFade); }
void DrawColumn() override { DrawerCommandQueue::QueueCommand<DrawColumnLLVMCommand>(); }
void FillColumn() override { DrawerCommandQueue::QueueCommand<FillColumnLLVMCommand>(); }
void FillAddColumn() override { DrawerCommandQueue::QueueCommand<FillColumnAddLLVMCommand>(); }

View file

@ -59,24 +59,7 @@ namespace swrenderer
FTexture *rw_pic;
}
static const uint8_t *R_GetColumn(FTexture *tex, int col)
{
int width;
// If the texture's width isn't a power of 2, then we need to make it a
// positive offset for proper clamping.
if (col < 0 && (width = tex->GetWidth()) != (1 << tex->WidthBits))
{
col = width + (col % width);
}
if (r_swtruecolor)
return (const uint8_t *)tex->GetColumnBgra(col, nullptr);
else
return tex->GetColumn(col, nullptr);
}
WallSampler::WallSampler(int y1, double texturemid, float swal, double yrepeat, fixed_t xoffset, double xmagnitude, FTexture *texture, const BYTE*(*getcol)(FTexture *texture, int x))
WallSampler::WallSampler(int y1, double texturemid, float swal, double yrepeat, fixed_t xoffset, double xmagnitude, FTexture *texture)
{
xoffset += FLOAT2FIXED(xmagnitude * 0.5);
@ -109,7 +92,21 @@ namespace swrenderer
uv_max = 1;
}
source = getcol(texture, xoffset >> FRACBITS);
int col = xoffset >> FRACBITS;
// If the texture's width isn't a power of 2, then we need to make it a
// positive offset for proper clamping.
int width;
if (col < 0 && (width = texture->GetWidth()) != (1 << texture->WidthBits))
{
col = width + (col % width);
}
if (r_swtruecolor)
source = (const uint8_t *)texture->GetColumnBgra(col, nullptr);
else
source = texture->GetColumn(col, nullptr);
source2 = nullptr;
texturefracx = 0;
}
@ -134,64 +131,54 @@ namespace swrenderer
uv_max = 0;
// Texture mipmap and filter selection:
if (getcol != R_GetColumn)
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 = texture->GetWidth();
int mip_height = texture->GetHeight();
if (r_mipmap && texture->Mipmapped() && mip_width > 1 && mip_height > 1)
{
source = getcol(texture, xoffset >> FRACBITS);
uint32_t xpos = (uint32_t)((((uint64_t)xoffset) << FRACBITS) / mip_width);
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 = texture->GetPixelsBgra() + mipmap_offset;
bool filter_nearest = (magnifying && !r_magfilter) || (!magnifying && !r_minfilter);
if (filter_nearest)
{
int tx = (xoffset >> FRACBITS) % mip_width;
if (tx < 0)
tx += mip_width;
source = (BYTE*)(pixels + tx * mip_height);
source2 = nullptr;
height = texture->GetHeight();
height = mip_height;
texturefracx = 0;
}
else
{
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 = texture->GetWidth();
int mip_height = texture->GetHeight();
if (r_mipmap && texture->Mipmapped() && mip_width > 1 && mip_height > 1)
{
uint32_t xpos = (uint32_t)((((uint64_t)xoffset) << FRACBITS) / mip_width);
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 = texture->GetPixelsBgra() + mipmap_offset;
bool filter_nearest = (magnifying && !r_magfilter) || (!magnifying && !r_minfilter);
if (filter_nearest)
{
int tx = (xoffset >> FRACBITS) % mip_width;
if (tx < 0)
tx += mip_width;
source = (BYTE*)(pixels + tx * mip_height);
source2 = nullptr;
height = mip_height;
texturefracx = 0;
}
else
{
xoffset -= FRACUNIT / 2;
int tx0 = (xoffset >> FRACBITS) % mip_width;
if (tx0 < 0)
tx0 += mip_width;
int tx1 = (tx0 + 1) % mip_width;
source = (BYTE*)(pixels + tx0 * mip_height);
source2 = (BYTE*)(pixels + tx1 * mip_height);
height = mip_height;
texturefracx = (xoffset >> (FRACBITS - 4)) & 15;
}
xoffset -= FRACUNIT / 2;
int tx0 = (xoffset >> FRACBITS) % mip_width;
if (tx0 < 0)
tx0 += mip_width;
int tx1 = (tx0 + 1) % mip_width;
source = (BYTE*)(pixels + tx0 * mip_height);
source2 = (BYTE*)(pixels + tx1 * mip_height);
height = mip_height;
texturefracx = (xoffset >> (FRACBITS - 4)) & 15;
}
}
}
@ -339,7 +326,7 @@ namespace swrenderer
const FWallCoords &WallC,
int x1, int x2, short *uwal, short *dwal, double texturemid, float *swal, fixed_t *lwal, double yrepeat, int wallshade, fixed_t xoffset, float light, float lightstep, FDynamicColormap *basecolormap,
FLightNode *light_list,
const BYTE *(*getcol)(FTexture *tex, int x), DrawerFunc drawcolumn)
DrawerFunc drawcolumn)
{
if (rw_pic->UseType == FTexture::TEX_Null)
return;
@ -394,41 +381,41 @@ namespace swrenderer
if (x + 1 < x2) xmagnitude = fabs(FIXED2DBL(lwal[x + 1]) - FIXED2DBL(lwal[x]));
WallSampler sampler(y1, texturemid, swal[x], yrepeat, lwal[x] + xoffset, xmagnitude, rw_pic, getcol);
WallSampler sampler(y1, texturemid, swal[x], yrepeat, lwal[x] + xoffset, xmagnitude, rw_pic);
Draw1Column(WallC, x, y1, y2, sampler, light_list, drawcolumn);
}
NetUpdate();
}
static void ProcessNormalWall(const FWallCoords &WallC, int x1, int x2, short *uwal, short *dwal, double texturemid, float *swal, fixed_t *lwal, double yrepeat, int wallshade, fixed_t xoffset, float light, float lightstep, FDynamicColormap *basecolormap, FLightNode *light_list, const BYTE *(*getcol)(FTexture *tex, int x) = R_GetColumn)
static void ProcessNormalWall(const FWallCoords &WallC, int x1, int x2, short *uwal, short *dwal, double texturemid, float *swal, fixed_t *lwal, double yrepeat, int wallshade, fixed_t xoffset, float light, float lightstep, FDynamicColormap *basecolormap, FLightNode *light_list)
{
ProcessWallWorker(WallC, x1, x2, uwal, dwal, texturemid, swal, lwal, yrepeat, wallshade, xoffset, light, lightstep, basecolormap, light_list, getcol, &SWPixelFormatDrawers::DrawWallColumn);
ProcessWallWorker(WallC, x1, x2, uwal, dwal, texturemid, swal, lwal, yrepeat, wallshade, xoffset, light, lightstep, basecolormap, light_list, &SWPixelFormatDrawers::DrawWallColumn);
}
static void ProcessMaskedWall(const FWallCoords &WallC, int x1, int x2, short *uwal, short *dwal, double texturemid, float *swal, fixed_t *lwal, double yrepeat, int wallshade, fixed_t xoffset, float light, float lightstep, FDynamicColormap *basecolormap, FLightNode *light_list, const BYTE *(*getcol)(FTexture *tex, int x) = R_GetColumn)
static void ProcessMaskedWall(const FWallCoords &WallC, int x1, int x2, short *uwal, short *dwal, double texturemid, float *swal, fixed_t *lwal, double yrepeat, int wallshade, fixed_t xoffset, float light, float lightstep, FDynamicColormap *basecolormap, FLightNode *light_list)
{
if (!rw_pic->bMasked) // Textures that aren't masked can use the faster ProcessNormalWall.
{
ProcessNormalWall(WallC, x1, x2, uwal, dwal, texturemid, swal, lwal, yrepeat, wallshade, xoffset, light, lightstep, basecolormap, light_list, getcol);
ProcessNormalWall(WallC, x1, x2, uwal, dwal, texturemid, swal, lwal, yrepeat, wallshade, xoffset, light, lightstep, basecolormap, light_list);
}
else
{
ProcessWallWorker(WallC, x1, x2, uwal, dwal, texturemid, swal, lwal, yrepeat, wallshade, xoffset, light, lightstep, basecolormap, light_list, getcol, &SWPixelFormatDrawers::DrawWallMaskedColumn);
ProcessWallWorker(WallC, x1, x2, uwal, dwal, texturemid, swal, lwal, yrepeat, wallshade, xoffset, light, lightstep, basecolormap, light_list, &SWPixelFormatDrawers::DrawWallMaskedColumn);
}
}
static void ProcessTranslucentWall(const FWallCoords &WallC, int x1, int x2, short *uwal, short *dwal, double texturemid, float *swal, fixed_t *lwal, double yrepeat, int wallshade, fixed_t xoffset, float light, float lightstep, FDynamicColormap *basecolormap, FLightNode *light_list, const BYTE *(*getcol)(FTexture *tex, int x) = R_GetColumn)
static void ProcessTranslucentWall(const FWallCoords &WallC, int x1, int x2, short *uwal, short *dwal, double texturemid, float *swal, fixed_t *lwal, double yrepeat, int wallshade, fixed_t xoffset, float light, float lightstep, FDynamicColormap *basecolormap, FLightNode *light_list)
{
DrawerFunc drawcol1 = R_GetTransMaskDrawer();
if (drawcol1 == nullptr)
{
// The current translucency is unsupported, so draw with regular ProcessMaskedWall instead.
ProcessMaskedWall(WallC, x1, x2, uwal, dwal, texturemid, swal, lwal, yrepeat, wallshade, xoffset, light, lightstep, basecolormap, light_list, getcol);
ProcessMaskedWall(WallC, x1, x2, uwal, dwal, texturemid, swal, lwal, yrepeat, wallshade, xoffset, light, lightstep, basecolormap, light_list);
}
else
{
ProcessWallWorker(WallC, x1, x2, uwal, dwal, texturemid, swal, lwal, yrepeat, wallshade, xoffset, light, lightstep, basecolormap, light_list, getcol, drawcol1);
ProcessWallWorker(WallC, x1, x2, uwal, dwal, texturemid, swal, lwal, yrepeat, wallshade, xoffset, light, lightstep, basecolormap, light_list, drawcol1);
}
}
@ -608,11 +595,4 @@ namespace swrenderer
ProcessWall(frontsector, curline, WallC, x1, x2, walltop, wallbottom, texturemid, swall, lwall, yscale, wallshade, xoffset, light, lightstep, false, foggy, basecolormap, light_list);
}
}
void R_DrawSkySegment(FTexture *pic, int x1, int x2, short *uwal, short *dwal, double texturemid, float *swal, fixed_t *lwal, double yrepeat, int wallshade, fixed_t xoffset, float light, float lightstep, FDynamicColormap *basecolormap, const uint8_t *(*getcol)(FTexture *tex, int x))
{
rw_pic = pic;
FWallCoords wallC; // Not used. To do: don't use r_walldraw to draw the sky!!
ProcessNormalWall(wallC, x1, x2, uwal, dwal, texturemid, swal, lwal, yrepeat, wallshade, xoffset, light, lightstep, basecolormap, nullptr, getcol);
}
}

View file

@ -25,7 +25,7 @@ namespace swrenderer
struct WallSampler
{
WallSampler() { }
WallSampler(int y1, double texturemid, float swal, double yrepeat, fixed_t xoffset, double xmagnitude, FTexture *texture, const BYTE*(*getcol)(FTexture *texture, int x));
WallSampler(int y1, double texturemid, float swal, double yrepeat, fixed_t xoffset, double xmagnitude, FTexture *texture);
uint32_t uv_pos;
uint32_t uv_step;
@ -38,6 +38,5 @@ namespace swrenderer
};
void R_DrawWallSegment(sector_t *frontsector, seg_t *curline, const FWallCoords &WallC, FTexture *rw_pic, int x1, int x2, short *walltop, short *wallbottom, double texturemid, float *swall, fixed_t *lwall, double yscale, double top, double bottom, bool mask, int wallshade, fixed_t xoffset, float light, float lightstep, FLightNode *light_list, bool foggy, FDynamicColormap *basecolormap);
void R_DrawSkySegment(FTexture *rw_pic, int x1, int x2, short *uwal, short *dwal, double texturemid, float *swal, fixed_t *lwal, double yrepeat, int wallshade, fixed_t xoffset, float light, float lightstep, FDynamicColormap *basecolormap, const uint8_t *(*getcol)(FTexture *tex, int col));
void R_DrawDrawSeg(sector_t *frontsector, seg_t *curline, const FWallCoords &WallC, FTexture *rw_pic, drawseg_t *ds, int x1, int x2, short *uwal, short *dwal, double texturemid, float *swal, fixed_t *lwal, double yrepeat, int wallshade, fixed_t xoffset, float light, float lightstep, bool foggy, FDynamicColormap *basecolormap);
}

View file

@ -165,130 +165,6 @@ namespace swrenderer
fixedcolormap = NULL;
}
// Get a column of sky when there is only one sky texture.
const uint8_t *RenderSkyPlane::GetOneSkyColumn(FTexture *fronttex, int x)
{
int tx;
if (r_linearsky)
{
angle_t xangle = (angle_t)((0.5 - x / (double)viewwidth) * FocalTangent * ANGLE_90);
angle_t column = (skyangle + xangle) ^ skyflip;
tx = (UMulScale16(column, frontcyl) + frontpos) >> FRACBITS;
}
else
{
angle_t column = (skyangle + xtoviewangle[x]) ^ skyflip;
tx = (UMulScale16(column, frontcyl) + frontpos) >> FRACBITS;
}
if (!r_swtruecolor)
return fronttex->GetColumn(tx, NULL);
else
{
return (const uint8_t *)fronttex->GetColumnBgra(tx, NULL);
}
}
// Get a column of sky when there are two overlapping sky textures
const uint8_t *RenderSkyPlane::GetTwoSkyColumns(FTexture *fronttex, int x)
{
uint32_t ang, angle1, angle2;
if (r_linearsky)
{
angle_t xangle = (angle_t)((0.5 - x / (double)viewwidth) * FocalTangent * ANGLE_90);
ang = (skyangle + xangle) ^ skyflip;
}
else
{
ang = (skyangle + xtoviewangle[x]) ^ skyflip;
}
angle1 = (uint32_t)((UMulScale16(ang, frontcyl) + frontpos) >> FRACBITS);
angle2 = (uint32_t)((UMulScale16(ang, backcyl) + backpos) >> FRACBITS);
// Check if this column has already been built. If so, there's
// no reason to waste time building it again.
uint32_t skycol = (angle1 << 16) | angle2;
int i;
if (!r_swtruecolor)
{
for (i = 0; i < 4; ++i)
{
if (lastskycol[i] == skycol)
{
return skybuf[i];
}
}
lastskycol[skycolplace] = skycol;
uint8_t *composite = skybuf[skycolplace];
skycolplace = (skycolplace + 1) & 3;
// The ordering of the following code has been tuned to allow VC++ to optimize
// it well. In particular, this arrangement lets it keep count in a register
// instead of on the stack.
const uint8_t *front = fronttex->GetColumn(angle1, NULL);
const uint8_t *back = backskytex->GetColumn(angle2, NULL);
int count = MIN<int>(512, MIN(backskytex->GetHeight(), fronttex->GetHeight()));
i = 0;
do
{
if (front[i])
{
composite[i] = front[i];
}
else
{
composite[i] = back[i];
}
} while (++i, --count);
return composite;
}
else
{
//return GetOneSkyColumn(fronttex, x);
for (i = skycolplace_bgra - 4; i < skycolplace_bgra; ++i)
{
int ic = (i % MAXSKYBUF); // i "checker" - can wrap around the ends of the array
if (lastskycol_bgra[ic] == skycol)
{
return (uint8_t*)(skybuf_bgra[ic]);
}
}
lastskycol_bgra[skycolplace_bgra] = skycol;
uint32_t *composite = skybuf_bgra[skycolplace_bgra];
skycolplace_bgra = (skycolplace_bgra + 1) % MAXSKYBUF;
// The ordering of the following code has been tuned to allow VC++ to optimize
// it well. In particular, this arrangement lets it keep count in a register
// instead of on the stack.
const uint32_t *front = (const uint32_t *)fronttex->GetColumnBgra(angle1, NULL);
const uint32_t *back = (const uint32_t *)backskytex->GetColumnBgra(angle2, NULL);
//[SP] Paletted version is used for comparison only
const uint8_t *frontcompare = fronttex->GetColumn(angle1, NULL);
int count = MIN<int>(512, MIN(backskytex->GetHeight(), fronttex->GetHeight()));
i = 0;
do
{
if (frontcompare[i])
{
composite[i] = front[i];
}
else
{
composite[i] = back[i];
}
} while (++i, --count);
return (uint8_t*)composite;
}
}
void RenderSkyPlane::DrawSkyColumnStripe(int start_x, int y1, int y2, int columns, double scale, double texturemid, double yrepeat)
{
using namespace drawerargs;
@ -348,10 +224,12 @@ namespace swrenderer
uint32_t solid_top = frontskytex->GetSkyCapColor(false);
uint32_t solid_bottom = frontskytex->GetSkyCapColor(true);
bool fadeSky = (r_skymode == 2 && !(level.flags & LEVEL_FORCETILEDSKY));
if (!backskytex)
R_Drawers()->DrawSingleSkyColumn(solid_top, solid_bottom);
R_Drawers()->DrawSingleSkyColumn(solid_top, solid_bottom, fadeSky);
else
R_Drawers()->DrawDoubleSkyColumn(solid_top, solid_bottom);
R_Drawers()->DrawDoubleSkyColumn(solid_top, solid_bottom, fadeSky);
}
void RenderSkyPlane::DrawSkyColumn(int start_x, int y1, int y2, int columns)
@ -374,7 +252,7 @@ namespace swrenderer
}
}
void RenderSkyPlane::DrawCapSky(visplane_t *pl)
void RenderSkyPlane::DrawSky(visplane_t *pl)
{
int x1 = pl->left;
int x2 = pl->right;
@ -391,125 +269,4 @@ namespace swrenderer
DrawSkyColumn(x, y1, y2, 1);
}
}
void RenderSkyPlane::DrawSky(visplane_t *pl)
{
if (r_skymode == 2 && !(level.flags & LEVEL_FORCETILEDSKY))
{
DrawCapSky(pl);
return;
}
int x;
float swal;
if (pl->left >= pl->right)
return;
swal = skyiscale;
for (x = pl->left; x < pl->right; ++x)
{
swall[x] = swal;
}
RenderPortal *renderportal = RenderPortal::Instance();
if (renderportal->MirrorFlags & RF_XFLIP)
{
for (x = pl->left; x < pl->right; ++x)
{
lwall[x] = (viewwidth - x) << FRACBITS;
}
}
else
{
for (x = pl->left; x < pl->right; ++x)
{
lwall[x] = x << FRACBITS;
}
}
for (x = 0; x < 4; ++x)
{
lastskycol[x] = 0xffffffff;
lastskycol_bgra[x] = 0xffffffff;
}
frontyScale = frontskytex->Scale.Y;
double texturemid = skymid * frontyScale;
if (1 << frontskytex->HeightBits == frontskytex->GetHeight())
{ // The texture tiles nicely
for (x = 0; x < 4; ++x)
{
lastskycol[x] = 0xffffffff;
lastskycol_bgra[x] = 0xffffffff;
}
R_DrawSkySegment(frontskytex, pl->left, pl->right, (short *)pl->top, (short *)pl->bottom, texturemid, swall, lwall,
frontyScale, 0, 0, 0.0f, 0.0f, nullptr, backskytex == nullptr ? RenderSkyPlane::GetOneSkyColumn : RenderSkyPlane::GetTwoSkyColumns);
}
else
{ // The texture does not tile nicely
frontyScale *= skyscale;
frontiScale = 1 / frontyScale;
DrawSkyStriped(pl);
}
}
void RenderSkyPlane::DrawSkyStriped(visplane_t *pl)
{
short drawheight = short(frontskytex->GetHeight() * frontyScale);
double topfrac;
double iscale = frontiScale;
short top[MAXWIDTH], bot[MAXWIDTH];
short yl, yh;
int x;
topfrac = fmod(skymid + iscale * (1 - CenterY), frontskytex->GetHeight());
if (topfrac < 0) topfrac += frontskytex->GetHeight();
yl = 0;
yh = short((frontskytex->GetHeight() - topfrac) * frontyScale);
double texturemid = topfrac - iscale * (1 - CenterY);
while (yl < viewheight)
{
for (x = pl->left; x < pl->right; ++x)
{
top[x] = MAX(yl, (short)pl->top[x]);
bot[x] = MIN(yh, (short)pl->bottom[x]);
}
for (x = 0; x < 4; ++x)
{
lastskycol[x] = 0xffffffff;
lastskycol_bgra[x] = 0xffffffff;
}
R_DrawSkySegment(frontskytex, pl->left, pl->right, top, bot, texturemid, swall, lwall, frontskytex->Scale.Y, 0, 0, 0.0f, 0.0f, nullptr, backskytex == nullptr ? RenderSkyPlane::GetOneSkyColumn : RenderSkyPlane::GetTwoSkyColumns);
yl = yh;
yh += drawheight;
texturemid = iscale * (centery - yl - 1);
}
}
FTexture *RenderSkyPlane::frontskytex;
FTexture *RenderSkyPlane::backskytex;
angle_t RenderSkyPlane::skyflip;
int RenderSkyPlane::frontpos;
int RenderSkyPlane::backpos;
double RenderSkyPlane::frontyScale;
fixed_t RenderSkyPlane::frontcyl;
fixed_t RenderSkyPlane::backcyl;
double RenderSkyPlane::skymid;
angle_t RenderSkyPlane::skyangle;
double RenderSkyPlane::frontiScale;
// Allow for layer skies up to 512 pixels tall. This is overkill,
// since the most anyone can ever see of the sky is 500 pixels.
// We need 4 skybufs because DrawSkySegment can draw up to 4 columns at a time.
// Need two versions - one for true color and one for palette
uint8_t RenderSkyPlane::skybuf[4][512];
uint32_t RenderSkyPlane::skybuf_bgra[MAXSKYBUF][512];
uint32_t RenderSkyPlane::lastskycol[4];
uint32_t RenderSkyPlane::lastskycol_bgra[MAXSKYBUF];
int RenderSkyPlane::skycolplace;
int RenderSkyPlane::skycolplace_bgra;
}

View file

@ -20,40 +20,21 @@ namespace swrenderer
class RenderSkyPlane
{
public:
static void Render(visplane_t *pl);
void Render(visplane_t *pl);
private:
static void DrawSky(visplane_t *pl);
static void DrawSkyStriped(visplane_t *pl);
static void DrawCapSky(visplane_t *pl);
static void DrawSkyColumnStripe(int start_x, int y1, int y2, int columns, double scale, double texturemid, double yrepeat);
static void DrawSkyColumn(int start_x, int y1, int y2, int columns);
void DrawSky(visplane_t *pl);
void DrawSkyColumnStripe(int start_x, int y1, int y2, int columns, double scale, double texturemid, double yrepeat);
void DrawSkyColumn(int start_x, int y1, int y2, int columns);
static const uint8_t *GetOneSkyColumn(FTexture *fronttex, int x);
static const uint8_t *GetTwoSkyColumns(FTexture *fronttex, int x);
static FTexture *frontskytex;
static FTexture *backskytex;
static angle_t skyflip;
static int frontpos;
static int backpos;
static double frontyScale;
static fixed_t frontcyl;
static fixed_t backcyl;
static double skymid;
static angle_t skyangle;
static double frontiScale;
// Allow for layer skies up to 512 pixels tall. This is overkill,
// since the most anyone can ever see of the sky is 500 pixels.
// We need 4 skybufs because R_DrawSkySegment can draw up to 4 columns at a time.
// Need two versions - one for true color and one for palette
enum { MAXSKYBUF = 3072 };
static uint8_t skybuf[4][512];
static uint32_t skybuf_bgra[MAXSKYBUF][512];
static uint32_t lastskycol[4];
static uint32_t lastskycol_bgra[MAXSKYBUF];
static int skycolplace;
static int skycolplace_bgra;
FTexture *frontskytex = nullptr;
FTexture *backskytex = nullptr;
angle_t skyflip = 0;
int frontpos = 0;
int backpos = 0;
fixed_t frontcyl = 0;
fixed_t backcyl = 0;
double skymid = 0.0;
angle_t skyangle = 0;
};
}

View file

@ -82,7 +82,8 @@ namespace swrenderer
if (picnum == skyflatnum) // sky flat
{
RenderSkyPlane::Render(this);
RenderSkyPlane renderer;
renderer.Render(this);
}
else // regular flat
{