mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-11 05:01:09 +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
|
#ifdef X86_ASM
|
||||||
if (!r_swtruecolor && ds_cursource != ds_source)
|
if (!r_swtruecolor && ds_cursource != ds_source)
|
||||||
{
|
{
|
||||||
R_SetSpanSource_ASM(pixels);
|
R_SetSpanSource_ASM(ds_source);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ extern void (*R_DrawTranslatedColumn)(void);
|
||||||
extern void (*R_DrawSpan)(void);
|
extern void (*R_DrawSpan)(void);
|
||||||
void R_SetupSpanBits(FTexture *tex);
|
void R_SetupSpanBits(FTexture *tex);
|
||||||
void R_SetSpanColormap(FDynamicColormap *colormap, int shade);
|
void R_SetSpanColormap(FDynamicColormap *colormap, int shade);
|
||||||
void R_SetSpanSource(const BYTE *pixels);
|
void R_SetSpanSource(FTexture *tex);
|
||||||
|
|
||||||
// Span drawing for masked textures.
|
// Span drawing for masked textures.
|
||||||
extern void (*R_DrawSpanMasked)(void);
|
extern void (*R_DrawSpanMasked)(void);
|
||||||
|
|
|
@ -59,6 +59,7 @@ extern int wallshade;
|
||||||
|
|
||||||
CVAR(Bool, r_multithreaded, true, 0)
|
CVAR(Bool, r_multithreaded, true, 0)
|
||||||
CVAR(Bool, r_bilinear, true, 0)
|
CVAR(Bool, r_bilinear, true, 0)
|
||||||
|
CVAR(Bool, r_mipmap, true, 0)
|
||||||
|
|
||||||
#ifndef NO_SSE
|
#ifndef NO_SSE
|
||||||
|
|
||||||
|
@ -1502,6 +1503,7 @@ class DrawSpanRGBACommand : public DrawerCommand
|
||||||
BYTE * RESTRICT _destorg;
|
BYTE * RESTRICT _destorg;
|
||||||
fixed_t _light;
|
fixed_t _light;
|
||||||
ShadeConstants _shade_constants;
|
ShadeConstants _shade_constants;
|
||||||
|
bool _magnifying;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DrawSpanRGBACommand()
|
DrawSpanRGBACommand()
|
||||||
|
@ -1519,6 +1521,7 @@ public:
|
||||||
_destorg = dc_destorg;
|
_destorg = dc_destorg;
|
||||||
_light = ds_light;
|
_light = ds_light;
|
||||||
_shade_constants = ds_shade_constants;
|
_shade_constants = ds_shade_constants;
|
||||||
|
_magnifying = !span_sampler_setup(_source, _xbits, _ybits, _xstep, _ystep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute(DrawerThread *thread) override
|
void Execute(DrawerThread *thread) override
|
||||||
|
@ -1548,12 +1551,7 @@ public:
|
||||||
uint32_t light = calc_light_multiplier(_light);
|
uint32_t light = calc_light_multiplier(_light);
|
||||||
ShadeConstants shade_constants = _shade_constants;
|
ShadeConstants shade_constants = _shade_constants;
|
||||||
|
|
||||||
fixed_t xmagnitude = abs((fixed_t)xstep) >> (32 - _xbits - FRACBITS);
|
if (_magnifying)
|
||||||
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 (_xbits == 6 && _ybits == 6)
|
if (_xbits == 6 && _ybits == 6)
|
||||||
{
|
{
|
||||||
|
@ -1634,6 +1632,7 @@ class DrawSpanMaskedRGBACommand : public DrawerCommand
|
||||||
fixed_t _ystep;
|
fixed_t _ystep;
|
||||||
int _xbits;
|
int _xbits;
|
||||||
int _ybits;
|
int _ybits;
|
||||||
|
bool _magnifying;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DrawSpanMaskedRGBACommand()
|
DrawSpanMaskedRGBACommand()
|
||||||
|
@ -1651,6 +1650,7 @@ public:
|
||||||
_ystep = ds_ystep;
|
_ystep = ds_ystep;
|
||||||
_xbits = ds_xbits;
|
_xbits = ds_xbits;
|
||||||
_ybits = ds_ybits;
|
_ybits = ds_ybits;
|
||||||
|
_magnifying = !span_sampler_setup(_source, _xbits, _ybits, _xstep, _ystep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute(DrawerThread *thread) override
|
void Execute(DrawerThread *thread) override
|
||||||
|
@ -1680,12 +1680,7 @@ public:
|
||||||
xstep = _xstep;
|
xstep = _xstep;
|
||||||
ystep = _ystep;
|
ystep = _ystep;
|
||||||
|
|
||||||
fixed_t xmagnitude = abs((fixed_t)xstep) >> (32 - _xbits - FRACBITS);
|
if (_magnifying)
|
||||||
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 (_xbits == 6 && _ybits == 6)
|
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()
|
void R_BeginDrawerCommands()
|
||||||
{
|
{
|
||||||
DrawerCommandQueue::Begin();
|
DrawerCommandQueue::Begin();
|
||||||
|
|
|
@ -108,6 +108,9 @@ void tmvline4_revsubclamp_rgba();
|
||||||
void R_FillColumnHoriz_rgba();
|
void R_FillColumnHoriz_rgba();
|
||||||
void R_FillSpan_rgba();
|
void R_FillSpan_rgba();
|
||||||
|
|
||||||
|
void R_SetMipmappedSpanSource(FTexture *tex);
|
||||||
|
void R_ClearMipmapCache();
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// Multithreaded rendering infrastructure:
|
// Multithreaded rendering infrastructure:
|
||||||
|
|
||||||
|
@ -185,6 +188,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
EXTERN_CVAR(Bool, r_multithreaded)
|
EXTERN_CVAR(Bool, r_multithreaded)
|
||||||
|
EXTERN_CVAR(Bool, r_mipmap)
|
||||||
|
|
||||||
// Manages queueing up commands and executing them on worker threads
|
// Manages queueing up commands and executing them on worker threads
|
||||||
class DrawerCommandQueue
|
class DrawerCommandQueue
|
||||||
|
@ -426,6 +430,35 @@ FORCEINLINE uint32_t alpha_blend(uint32_t fg, uint32_t bg)
|
||||||
return 0xff000000 | (red << 16) | (green << 8) | blue;
|
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)
|
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);
|
uint32_t half = 1 << (ybits - 1);
|
||||||
|
|
|
@ -25,6 +25,7 @@ class VecCommand(DrawSpanRGBA) : public DrawerCommand
|
||||||
BYTE * RESTRICT _destorg;
|
BYTE * RESTRICT _destorg;
|
||||||
fixed_t _light;
|
fixed_t _light;
|
||||||
ShadeConstants _shade_constants;
|
ShadeConstants _shade_constants;
|
||||||
|
bool _magnifying;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VecCommand(DrawSpanRGBA)()
|
VecCommand(DrawSpanRGBA)()
|
||||||
|
@ -42,6 +43,7 @@ public:
|
||||||
_destorg = dc_destorg;
|
_destorg = dc_destorg;
|
||||||
_light = ds_light;
|
_light = ds_light;
|
||||||
_shade_constants = ds_shade_constants;
|
_shade_constants = ds_shade_constants;
|
||||||
|
_magnifying = !span_sampler_setup(_source, _xbits, _ybits, _xstep, _ystep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute(DrawerThread *thread) override
|
void Execute(DrawerThread *thread) override
|
||||||
|
@ -71,12 +73,7 @@ public:
|
||||||
uint32_t light = calc_light_multiplier(_light);
|
uint32_t light = calc_light_multiplier(_light);
|
||||||
ShadeConstants shade_constants = _shade_constants;
|
ShadeConstants shade_constants = _shade_constants;
|
||||||
|
|
||||||
fixed_t xmagnitude = abs((fixed_t)xstep) >> (32 - _xbits - FRACBITS);
|
if (_magnifying)
|
||||||
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 (_xbits == 6 && _ybits == 6)
|
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);
|
R_SetupSpanBits(tex);
|
||||||
double xscale = pl->xform.xScale * tex->Scale.X;
|
double xscale = pl->xform.xScale * tex->Scale.X;
|
||||||
double yscale = pl->xform.yScale * tex->Scale.Y;
|
double yscale = pl->xform.yScale * tex->Scale.Y;
|
||||||
if (r_swtruecolor)
|
R_SetSpanSource(tex);
|
||||||
ds_source = (const BYTE*)tex->GetPixelsBgra();
|
|
||||||
else
|
|
||||||
ds_source = tex->GetPixels();
|
|
||||||
|
|
||||||
basecolormap = pl->colormap;
|
basecolormap = pl->colormap;
|
||||||
planeshade = LIGHT2SHADE(pl->lightlevel);
|
planeshade = LIGHT2SHADE(pl->lightlevel);
|
||||||
|
|
|
@ -170,6 +170,7 @@ void FSoftwareRenderer::RenderView(player_t *player)
|
||||||
R_InitColumnDrawers();
|
R_InitColumnDrawers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
R_ClearMipmapCache();
|
||||||
R_BeginDrawerCommands();
|
R_BeginDrawerCommands();
|
||||||
R_RenderActorView (player->mo);
|
R_RenderActorView (player->mo);
|
||||||
// [RH] Let cameras draw onto textures that were visible this frame.
|
// [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));
|
R_SetSpanColormap(colormap, clamp(shade >> FRACBITS, 0, NUMCOLORMAPS - 1));
|
||||||
else
|
else
|
||||||
R_SetSpanColormap(&identitycolormap, 0);
|
R_SetSpanColormap(&identitycolormap, 0);
|
||||||
R_SetSpanSource(r_swtruecolor ? (const BYTE*)tex->GetPixelsBgra() : tex->GetPixels());
|
R_SetSpanSource(tex);
|
||||||
scalex = double(1u << (32 - ds_xbits)) / scalex;
|
scalex = double(1u << (32 - ds_xbits)) / scalex;
|
||||||
scaley = double(1u << (32 - ds_ybits)) / scaley;
|
scaley = double(1u << (32 - ds_ybits)) / scaley;
|
||||||
ds_xstep = xs_RoundToInt(cosrot * scalex);
|
ds_xstep = xs_RoundToInt(cosrot * scalex);
|
||||||
|
|
Loading…
Reference in a new issue