mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-03 01:13:22 +00:00
Added mipmap support for floor and ceiling
This commit is contained in:
parent
c1b5ba5b90
commit
d15af1524c
8 changed files with 150 additions and 27 deletions
|
@ -1062,13 +1062,13 @@ extern "C" BYTE *ds_curcolormap, *ds_cursource, *ds_curtiltedsource;
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void R_SetSpanSource(const BYTE *pixels)
|
||||
void R_SetSpanSource(FTexture *tex)
|
||||
{
|
||||
ds_source = pixels;
|
||||
R_SetMipmappedSpanSource(tex);
|
||||
#ifdef X86_ASM
|
||||
if (!r_swtruecolor && ds_cursource != ds_source)
|
||||
{
|
||||
R_SetSpanSource_ASM(pixels);
|
||||
R_SetSpanSource_ASM(ds_source);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ extern void (*R_DrawTranslatedColumn)(void);
|
|||
extern void (*R_DrawSpan)(void);
|
||||
void R_SetupSpanBits(FTexture *tex);
|
||||
void R_SetSpanColormap(FDynamicColormap *colormap, int shade);
|
||||
void R_SetSpanSource(const BYTE *pixels);
|
||||
void R_SetSpanSource(FTexture *tex);
|
||||
|
||||
// Span drawing for masked textures.
|
||||
extern void (*R_DrawSpanMasked)(void);
|
||||
|
|
|
@ -59,6 +59,7 @@ extern int wallshade;
|
|||
|
||||
CVAR(Bool, r_multithreaded, true, 0)
|
||||
CVAR(Bool, r_bilinear, true, 0)
|
||||
CVAR(Bool, r_mipmap, true, 0)
|
||||
|
||||
#ifndef NO_SSE
|
||||
|
||||
|
@ -1502,6 +1503,7 @@ class DrawSpanRGBACommand : public DrawerCommand
|
|||
BYTE * RESTRICT _destorg;
|
||||
fixed_t _light;
|
||||
ShadeConstants _shade_constants;
|
||||
bool _magnifying;
|
||||
|
||||
public:
|
||||
DrawSpanRGBACommand()
|
||||
|
@ -1519,6 +1521,7 @@ public:
|
|||
_destorg = dc_destorg;
|
||||
_light = ds_light;
|
||||
_shade_constants = ds_shade_constants;
|
||||
_magnifying = !span_sampler_setup(_source, _xbits, _ybits, _xstep, _ystep);
|
||||
}
|
||||
|
||||
void Execute(DrawerThread *thread) override
|
||||
|
@ -1548,12 +1551,7 @@ public:
|
|||
uint32_t light = calc_light_multiplier(_light);
|
||||
ShadeConstants shade_constants = _shade_constants;
|
||||
|
||||
fixed_t xmagnitude = abs((fixed_t)xstep) >> (32 - _xbits - FRACBITS);
|
||||
fixed_t ymagnitude = abs((fixed_t)ystep) >> (32 - _ybits - FRACBITS);
|
||||
fixed_t magnitude = xmagnitude + ymagnitude;
|
||||
|
||||
bool magnifying = !r_bilinear || magnitude >> (FRACBITS - 1) == 0;
|
||||
if (magnifying)
|
||||
if (_magnifying)
|
||||
{
|
||||
if (_xbits == 6 && _ybits == 6)
|
||||
{
|
||||
|
@ -1634,6 +1632,7 @@ class DrawSpanMaskedRGBACommand : public DrawerCommand
|
|||
fixed_t _ystep;
|
||||
int _xbits;
|
||||
int _ybits;
|
||||
bool _magnifying;
|
||||
|
||||
public:
|
||||
DrawSpanMaskedRGBACommand()
|
||||
|
@ -1651,6 +1650,7 @@ public:
|
|||
_ystep = ds_ystep;
|
||||
_xbits = ds_xbits;
|
||||
_ybits = ds_ybits;
|
||||
_magnifying = !span_sampler_setup(_source, _xbits, _ybits, _xstep, _ystep);
|
||||
}
|
||||
|
||||
void Execute(DrawerThread *thread) override
|
||||
|
@ -1680,12 +1680,7 @@ public:
|
|||
xstep = _xstep;
|
||||
ystep = _ystep;
|
||||
|
||||
fixed_t xmagnitude = abs((fixed_t)xstep) >> (32 - _xbits - FRACBITS);
|
||||
fixed_t ymagnitude = abs((fixed_t)ystep) >> (32 - _ybits - FRACBITS);
|
||||
fixed_t magnitude = xmagnitude + ymagnitude;
|
||||
|
||||
bool magnifying = !r_bilinear || magnitude >> (FRACBITS - 1) == 0;
|
||||
if (magnifying)
|
||||
if (_magnifying)
|
||||
{
|
||||
if (_xbits == 6 && _ybits == 6)
|
||||
{
|
||||
|
@ -3677,6 +3672,106 @@ void ApplySpecialColormapRGBACommand::Execute(DrawerThread *thread)
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <map>
|
||||
|
||||
class MipmappedTexture
|
||||
{
|
||||
public:
|
||||
MipmappedTexture(FTexture *texture)
|
||||
{
|
||||
const uint32_t *base_texture = texture->GetPixelsBgra();
|
||||
Width = texture->GetWidth();
|
||||
Height = texture->GetHeight();
|
||||
Levels = MAX(texture->WidthBits, texture->HeightBits);
|
||||
|
||||
// I bet there is a better way to calculate this..
|
||||
int buffersize = 0;
|
||||
for (int i = 0; i < Levels; i++)
|
||||
{
|
||||
int w = MAX(Width >> i, 2); // 2 instead of 1 because we texelGather in 2x2 blocks
|
||||
int h = MAX(Height >> i, 2);
|
||||
buffersize += w * h;
|
||||
}
|
||||
Pixels.resize(buffersize);
|
||||
|
||||
// Base level:
|
||||
memcpy(Pixels.data(), base_texture, Width * Height * 4);
|
||||
|
||||
// Mipmap levels:
|
||||
uint32_t *src = Pixels.data();
|
||||
uint32_t *dest = src + Width * Height;
|
||||
for (int i = 1; i < Levels; i++)
|
||||
{
|
||||
int srch = MAX(Height >> (i - 1), 2);
|
||||
int w = MAX(Width >> i, 2);
|
||||
int h = MAX(Height >> i, 2);
|
||||
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
uint32_t src00 = src[y * 2 + x * 2 * srch];
|
||||
uint32_t src01 = src[y * 2 + 1 + x * 2 * srch];
|
||||
uint32_t src10 = src[y * 2 + (x * 2 + 1) * srch];
|
||||
uint32_t src11 = src[y * 2 + 1 + (x * 2 + 1) * srch];
|
||||
|
||||
uint32_t alpha = (APART(src00) + APART(src01) + APART(src10) + APART(src11) + 2) / 4;
|
||||
uint32_t red = (RPART(src00) + RPART(src01) + RPART(src10) + RPART(src11) + 2) / 4;
|
||||
uint32_t green = (GPART(src00) + GPART(src01) + GPART(src10) + GPART(src11) + 2) / 4;
|
||||
uint32_t blue = (BPART(src00) + BPART(src01) + BPART(src10) + BPART(src11) + 2) / 4;
|
||||
|
||||
dest[y + x * h] = (alpha << 24) | (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
}
|
||||
|
||||
src = dest;
|
||||
dest += w * h;
|
||||
}
|
||||
}
|
||||
|
||||
int Width = 0;
|
||||
int Height = 0;
|
||||
int Levels = 0;
|
||||
std::vector<uint32_t> Pixels;
|
||||
};
|
||||
|
||||
class TextureMipmapper
|
||||
{
|
||||
public:
|
||||
static std::map<FTexture*, std::shared_ptr<MipmappedTexture>> &Textures()
|
||||
{
|
||||
static std::map<FTexture*, std::shared_ptr<MipmappedTexture>> textures;
|
||||
return textures;
|
||||
}
|
||||
};
|
||||
|
||||
void R_SetMipmappedSpanSource(FTexture *tex)
|
||||
{
|
||||
if (r_swtruecolor)
|
||||
{
|
||||
if (r_mipmap)
|
||||
{
|
||||
auto &mipmap = TextureMipmapper::Textures()[tex];
|
||||
if (!mipmap)
|
||||
mipmap = std::make_shared<MipmappedTexture>(tex);
|
||||
ds_source = (const BYTE*)mipmap->Pixels.data();
|
||||
}
|
||||
else
|
||||
{
|
||||
ds_source = (const BYTE*)tex->GetPixelsBgra();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ds_source = tex->GetPixels();
|
||||
}
|
||||
}
|
||||
|
||||
void R_ClearMipmapCache()
|
||||
{
|
||||
TextureMipmapper::Textures().clear();
|
||||
}
|
||||
|
||||
void R_BeginDrawerCommands()
|
||||
{
|
||||
DrawerCommandQueue::Begin();
|
||||
|
|
|
@ -108,6 +108,9 @@ void tmvline4_revsubclamp_rgba();
|
|||
void R_FillColumnHoriz_rgba();
|
||||
void R_FillSpan_rgba();
|
||||
|
||||
void R_SetMipmappedSpanSource(FTexture *tex);
|
||||
void R_ClearMipmapCache();
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Multithreaded rendering infrastructure:
|
||||
|
||||
|
@ -185,6 +188,7 @@ public:
|
|||
};
|
||||
|
||||
EXTERN_CVAR(Bool, r_multithreaded)
|
||||
EXTERN_CVAR(Bool, r_mipmap)
|
||||
|
||||
// Manages queueing up commands and executing them on worker threads
|
||||
class DrawerCommandQueue
|
||||
|
@ -426,6 +430,35 @@ FORCEINLINE uint32_t alpha_blend(uint32_t fg, uint32_t bg)
|
|||
return 0xff000000 | (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
|
||||
inline bool span_sampler_setup(const uint32_t *&source, int &xbits, int &ybits, fixed_t xstep, fixed_t ystep)
|
||||
{
|
||||
if (!r_bilinear)
|
||||
return false;
|
||||
|
||||
// Is this a magfilter or minfilter?
|
||||
fixed_t xmagnitude = abs(xstep) >> (32 - xbits - FRACBITS);
|
||||
fixed_t ymagnitude = abs(ystep) >> (32 - ybits - FRACBITS);
|
||||
fixed_t magnitude = (xmagnitude + ymagnitude) * 3 + (1 << (FRACBITS -1));
|
||||
if (magnitude >> FRACBITS == 0)
|
||||
return false;
|
||||
|
||||
if (r_mipmap)
|
||||
{
|
||||
int level = magnitude >> (FRACBITS + 1);
|
||||
while (level != 0)
|
||||
{
|
||||
if (xbits <= 2 || ybits <= 2)
|
||||
break;
|
||||
|
||||
source += (1 << (xbits)) * (1 << (ybits));
|
||||
xbits -= 1;
|
||||
ybits -= 1;
|
||||
level >>= 1;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FORCEINLINE uint32_t sample_bilinear(const uint32_t *col0, const uint32_t *col1, uint32_t texturefracx, uint32_t texturefracy, int ybits)
|
||||
{
|
||||
uint32_t half = 1 << (ybits - 1);
|
||||
|
|
|
@ -25,6 +25,7 @@ class VecCommand(DrawSpanRGBA) : public DrawerCommand
|
|||
BYTE * RESTRICT _destorg;
|
||||
fixed_t _light;
|
||||
ShadeConstants _shade_constants;
|
||||
bool _magnifying;
|
||||
|
||||
public:
|
||||
VecCommand(DrawSpanRGBA)()
|
||||
|
@ -42,6 +43,7 @@ public:
|
|||
_destorg = dc_destorg;
|
||||
_light = ds_light;
|
||||
_shade_constants = ds_shade_constants;
|
||||
_magnifying = !span_sampler_setup(_source, _xbits, _ybits, _xstep, _ystep);
|
||||
}
|
||||
|
||||
void Execute(DrawerThread *thread) override
|
||||
|
@ -71,12 +73,7 @@ public:
|
|||
uint32_t light = calc_light_multiplier(_light);
|
||||
ShadeConstants shade_constants = _shade_constants;
|
||||
|
||||
fixed_t xmagnitude = abs((fixed_t)xstep) >> (32 - _xbits - FRACBITS);
|
||||
fixed_t ymagnitude = abs((fixed_t)ystep) >> (32 - _ybits - FRACBITS);
|
||||
fixed_t magnitude = xmagnitude + ymagnitude;
|
||||
|
||||
bool magnifying = !r_bilinear || magnitude >> (FRACBITS - 1) == 0;
|
||||
if (magnifying)
|
||||
if (_magnifying)
|
||||
{
|
||||
if (_xbits == 6 && _ybits == 6)
|
||||
{
|
||||
|
|
|
@ -1178,10 +1178,7 @@ void R_DrawSinglePlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
|
|||
R_SetupSpanBits(tex);
|
||||
double xscale = pl->xform.xScale * tex->Scale.X;
|
||||
double yscale = pl->xform.yScale * tex->Scale.Y;
|
||||
if (r_swtruecolor)
|
||||
ds_source = (const BYTE*)tex->GetPixelsBgra();
|
||||
else
|
||||
ds_source = tex->GetPixels();
|
||||
R_SetSpanSource(tex);
|
||||
|
||||
basecolormap = pl->colormap;
|
||||
planeshade = LIGHT2SHADE(pl->lightlevel);
|
||||
|
|
|
@ -170,6 +170,7 @@ void FSoftwareRenderer::RenderView(player_t *player)
|
|||
R_InitColumnDrawers();
|
||||
}
|
||||
|
||||
R_ClearMipmapCache();
|
||||
R_BeginDrawerCommands();
|
||||
R_RenderActorView (player->mo);
|
||||
// [RH] Let cameras draw onto textures that were visible this frame.
|
||||
|
|
|
@ -1404,7 +1404,7 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
|
|||
R_SetSpanColormap(colormap, clamp(shade >> FRACBITS, 0, NUMCOLORMAPS - 1));
|
||||
else
|
||||
R_SetSpanColormap(&identitycolormap, 0);
|
||||
R_SetSpanSource(r_swtruecolor ? (const BYTE*)tex->GetPixelsBgra() : tex->GetPixels());
|
||||
R_SetSpanSource(tex);
|
||||
scalex = double(1u << (32 - ds_xbits)) / scalex;
|
||||
scaley = double(1u << (32 - ds_ybits)) / scaley;
|
||||
ds_xstep = xs_RoundToInt(cosrot * scalex);
|
||||
|
|
Loading…
Reference in a new issue