mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-01-18 23:21:41 +00:00
- 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:
parent
590781d4a6
commit
8788a9e788
10 changed files with 314 additions and 445 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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>(); }
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>(); }
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -82,7 +82,8 @@ namespace swrenderer
|
|||
|
||||
if (picnum == skyflatnum) // sky flat
|
||||
{
|
||||
RenderSkyPlane::Render(this);
|
||||
RenderSkyPlane renderer;
|
||||
renderer.Render(this);
|
||||
}
|
||||
else // regular flat
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue