Added mipmap support for floor and ceiling

This commit is contained in:
Magnus Norddahl 2016-06-21 09:38:47 +02:00
parent c1b5ba5b90
commit d15af1524c
8 changed files with 150 additions and 27 deletions

View file

@ -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
}

View file

@ -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);

View file

@ -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();

View file

@ -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);

View file

@ -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)
{

View file

@ -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);

View file

@ -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.

View file

@ -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);