mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-14 08:30:50 +00:00
Fix mipmap generation bug
Fix crash due to dc_source2 not always being set Add r_lod_bias to control mipmap selection Improve LOD calculations to take the U texture coordinate into account
This commit is contained in:
parent
d4aed28260
commit
d084f77546
7 changed files with 50 additions and 25 deletions
|
@ -411,5 +411,6 @@ EXTERN_CVAR(Bool, r_multithreaded);
|
||||||
EXTERN_CVAR(Bool, r_magfilter);
|
EXTERN_CVAR(Bool, r_magfilter);
|
||||||
EXTERN_CVAR(Bool, r_minfilter);
|
EXTERN_CVAR(Bool, r_minfilter);
|
||||||
EXTERN_CVAR(Bool, r_mipmap);
|
EXTERN_CVAR(Bool, r_mipmap);
|
||||||
|
EXTERN_CVAR(Float, r_lod_bias);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -60,6 +60,9 @@ CVAR(Bool, r_minfilter, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||||
// Use mipmapped textures
|
// Use mipmapped textures
|
||||||
CVAR(Bool, r_mipmap, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
CVAR(Bool, r_mipmap, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||||
|
|
||||||
|
// Level of detail texture bias
|
||||||
|
CVAR(Float, r_lod_bias, -1.5, 0); // To do: add CVAR_ARCHIVE | CVAR_GLOBALCONFIG when a good default has been decided
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class DrawSpanLLVMCommand : public DrawerCommand
|
class DrawSpanLLVMCommand : public DrawerCommand
|
||||||
|
@ -377,7 +380,7 @@ public:
|
||||||
if (dc_shade_constants.simple_shade)
|
if (dc_shade_constants.simple_shade)
|
||||||
args.flags |= DrawColumnArgs::simple_shade;
|
args.flags |= DrawColumnArgs::simple_shade;
|
||||||
if (args.source2 == nullptr)
|
if (args.source2 == nullptr)
|
||||||
args.flags |= DrawWallArgs::nearest_filter;
|
args.flags |= DrawColumnArgs::nearest_filter;
|
||||||
|
|
||||||
DetectRangeError(args.dest, args.dest_y, args.count);
|
DetectRangeError(args.dest, args.dest_y, args.count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
struct FSpecialColormap;
|
struct FSpecialColormap;
|
||||||
|
|
||||||
EXTERN_CVAR(Bool, r_mipmap)
|
EXTERN_CVAR(Bool, r_mipmap)
|
||||||
|
EXTERN_CVAR(Float, r_lod_bias)
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// Drawer functions:
|
// Drawer functions:
|
||||||
|
|
|
@ -99,7 +99,7 @@ public:
|
||||||
if (dc_shade_constants.simple_shade)
|
if (dc_shade_constants.simple_shade)
|
||||||
args.flags |= DrawColumnArgs::simple_shade;
|
args.flags |= DrawColumnArgs::simple_shade;
|
||||||
if (args.source2 == nullptr)
|
if (args.source2 == nullptr)
|
||||||
args.flags |= DrawWallArgs::nearest_filter;
|
args.flags |= DrawColumnArgs::nearest_filter;
|
||||||
|
|
||||||
DetectRangeError(args.dest, args.dest_y, args.count);
|
DetectRangeError(args.dest, args.dest_y, args.count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1070,7 +1070,7 @@ EXTERN_CVAR(Bool, r_mipmap)
|
||||||
struct WallscanSampler
|
struct WallscanSampler
|
||||||
{
|
{
|
||||||
WallscanSampler() { }
|
WallscanSampler() { }
|
||||||
WallscanSampler(int y1, float swal, double yrepeat, fixed_t xoffset, FTexture *texture, const BYTE*(*getcol)(FTexture *texture, int x));
|
WallscanSampler(int y1, float swal, double yrepeat, fixed_t xoffset, double xmagnitude, FTexture *texture, const BYTE*(*getcol)(FTexture *texture, int x));
|
||||||
|
|
||||||
uint32_t uv_pos;
|
uint32_t uv_pos;
|
||||||
uint32_t uv_step;
|
uint32_t uv_step;
|
||||||
|
@ -1082,8 +1082,10 @@ struct WallscanSampler
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
};
|
};
|
||||||
|
|
||||||
WallscanSampler::WallscanSampler(int y1, float swal, double yrepeat, fixed_t xoffset, FTexture *texture, const BYTE*(*getcol)(FTexture *texture, int x))
|
WallscanSampler::WallscanSampler(int y1, float swal, double yrepeat, fixed_t xoffset, double xmagnitude, FTexture *texture, const BYTE*(*getcol)(FTexture *texture, int x))
|
||||||
{
|
{
|
||||||
|
xoffset += FLOAT2FIXED(xmagnitude * 0.5);
|
||||||
|
|
||||||
if (!r_swtruecolor)
|
if (!r_swtruecolor)
|
||||||
{
|
{
|
||||||
height = texture->GetHeight();
|
height = texture->GetHeight();
|
||||||
|
@ -1147,8 +1149,11 @@ WallscanSampler::WallscanSampler(int y1, float swal, double yrepeat, fixed_t xof
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double magnitude = fabs(uv_stepd * 2);
|
double ymagnitude = fabs(uv_stepd);
|
||||||
bool magnifying = magnitude < 1.0f;
|
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 mipmap_offset = 0;
|
||||||
int mip_width = texture->GetWidth();
|
int mip_width = texture->GetWidth();
|
||||||
|
@ -1156,12 +1161,12 @@ WallscanSampler::WallscanSampler(int y1, float swal, double yrepeat, fixed_t xof
|
||||||
if (r_mipmap && texture->Mipmapped() && mip_width > 1 && mip_height > 1)
|
if (r_mipmap && texture->Mipmapped() && mip_width > 1 && mip_height > 1)
|
||||||
{
|
{
|
||||||
uint32_t xpos = (uint32_t)((((uint64_t)xoffset) << FRACBITS) / mip_width);
|
uint32_t xpos = (uint32_t)((((uint64_t)xoffset) << FRACBITS) / mip_width);
|
||||||
double texture_bias = 1.7f;
|
|
||||||
double level = MAX(magnitude - 3.0, 0.0);
|
int level = (int)lod;
|
||||||
while (level > texture_bias && mip_width > 1 && mip_height > 1)
|
while (level > 0 && mip_width > 1 && mip_height > 1)
|
||||||
{
|
{
|
||||||
mipmap_offset += mip_width * mip_height;
|
mipmap_offset += mip_width * mip_height;
|
||||||
level *= 0.5f;
|
level--;
|
||||||
mip_width = MAX(mip_width >> 1, 1);
|
mip_width = MAX(mip_width >> 1, 1);
|
||||||
mip_height = MAX(mip_height >> 1, 1);
|
mip_height = MAX(mip_height >> 1, 1);
|
||||||
}
|
}
|
||||||
|
@ -1411,6 +1416,8 @@ void wallscan_any(
|
||||||
int aligned_x1 = clamp((x1 + 3) / 4 * 4, x1, x2);
|
int aligned_x1 = clamp((x1 + 3) / 4 * 4, x1, x2);
|
||||||
int aligned_x2 = clamp(x2 / 4 * 4, x1, x2);
|
int aligned_x2 = clamp(x2 / 4 * 4, x1, x2);
|
||||||
|
|
||||||
|
double xmagnitude = 1.0;
|
||||||
|
|
||||||
// First unaligned columns:
|
// First unaligned columns:
|
||||||
for (int x = x1; x < aligned_x1; x++, light += rw_lightstep)
|
for (int x = x1; x < aligned_x1; x++, light += rw_lightstep)
|
||||||
{
|
{
|
||||||
|
@ -1422,7 +1429,9 @@ void wallscan_any(
|
||||||
if (!fixed)
|
if (!fixed)
|
||||||
R_SetColorMapLight(basecolormap, light, wallshade);
|
R_SetColorMapLight(basecolormap, light, wallshade);
|
||||||
|
|
||||||
WallscanSampler sampler(y1, swal[x], yrepeat, lwal[x] + xoffset, rw_pic, getcol);
|
if (x + 1 < x2) xmagnitude = fabs(FIXED2DBL(lwal[x + 1]) - FIXED2DBL(lwal[x]));
|
||||||
|
|
||||||
|
WallscanSampler sampler(y1, swal[x], yrepeat, lwal[x] + xoffset, xmagnitude, rw_pic, getcol);
|
||||||
wallscan_drawcol1(x, y1, y2, sampler, draw1column);
|
wallscan_drawcol1(x, y1, y2, sampler, draw1column);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1442,7 +1451,10 @@ void wallscan_any(
|
||||||
|
|
||||||
WallscanSampler sampler[4];
|
WallscanSampler sampler[4];
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
sampler[i] = WallscanSampler(y1[i], swal[x + i], yrepeat, lwal[x + i] + xoffset, rw_pic, getcol);
|
{
|
||||||
|
if (x + i + 1 < x2) xmagnitude = fabs(FIXED2DBL(lwal[x + i + 1]) - FIXED2DBL(lwal[x + i]));
|
||||||
|
sampler[i] = WallscanSampler(y1[i], swal[x + i], yrepeat, lwal[x + i] + xoffset, xmagnitude, rw_pic, getcol);
|
||||||
|
}
|
||||||
|
|
||||||
// Figure out where we vertically can start and stop drawing 4 columns in one go
|
// Figure out where we vertically can start and stop drawing 4 columns in one go
|
||||||
int middle_y1 = y1[0];
|
int middle_y1 = y1[0];
|
||||||
|
@ -1529,7 +1541,9 @@ void wallscan_any(
|
||||||
if (!fixed)
|
if (!fixed)
|
||||||
R_SetColorMapLight(basecolormap, light, wallshade);
|
R_SetColorMapLight(basecolormap, light, wallshade);
|
||||||
|
|
||||||
WallscanSampler sampler(y1, swal[x], yrepeat, lwal[x] + xoffset, rw_pic, getcol);
|
if (x + 1 < x2) xmagnitude = fabs(FIXED2DBL(lwal[x + 1]) - FIXED2DBL(lwal[x]));
|
||||||
|
|
||||||
|
WallscanSampler sampler(y1, swal[x], yrepeat, lwal[x] + xoffset, xmagnitude, rw_pic, getcol);
|
||||||
wallscan_drawcol1(x, y1, y2, sampler, draw1column);
|
wallscan_drawcol1(x, y1, y2, sampler, draw1column);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -264,8 +264,13 @@ void R_DrawMaskedColumnBgra(FTexture *tex, fixed_t col, bool useRt, bool unmaske
|
||||||
|
|
||||||
// Texture mipmap and filter selection:
|
// Texture mipmap and filter selection:
|
||||||
fixed_t xoffset = col;
|
fixed_t xoffset = col;
|
||||||
double magnitude = fabs(uv_stepd * 2);
|
|
||||||
bool magnifying = magnitude < 1.0f;
|
double xmagnitude = 1.0; // To do: pass this into R_DrawMaskedColumn
|
||||||
|
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 mipmap_offset = 0;
|
||||||
int mip_width = tex->GetWidth();
|
int mip_width = tex->GetWidth();
|
||||||
|
@ -273,12 +278,11 @@ void R_DrawMaskedColumnBgra(FTexture *tex, fixed_t col, bool useRt, bool unmaske
|
||||||
if (r_mipmap && tex->Mipmapped() && mip_width > 1 && mip_height > 1)
|
if (r_mipmap && tex->Mipmapped() && mip_width > 1 && mip_height > 1)
|
||||||
{
|
{
|
||||||
uint32_t xpos = (uint32_t)((((uint64_t)xoffset) << FRACBITS) / mip_width);
|
uint32_t xpos = (uint32_t)((((uint64_t)xoffset) << FRACBITS) / mip_width);
|
||||||
double texture_bias = 1.7f;
|
int level = (int)lod;
|
||||||
double level = MAX(magnitude - 3.0, 0.0);
|
while (level > 0 && mip_width > 1 && mip_height > 1)
|
||||||
while (level > texture_bias && mip_width > 1 && mip_height > 1)
|
|
||||||
{
|
{
|
||||||
mipmap_offset += mip_width * mip_height;
|
mipmap_offset += mip_width * mip_height;
|
||||||
level *= 0.5f;
|
level--;
|
||||||
mip_width = MAX(mip_width >> 1, 1);
|
mip_width = MAX(mip_width >> 1, 1);
|
||||||
mip_height = MAX(mip_height >> 1, 1);
|
mip_height = MAX(mip_height >> 1, 1);
|
||||||
}
|
}
|
||||||
|
@ -424,6 +428,7 @@ void R_DrawMaskedColumn (FTexture *tex, fixed_t col, bool useRt, bool unmasked)
|
||||||
{
|
{
|
||||||
dc_texturefrac = FLOAT2FIXED((dc_yl + 0.5 - sprtopscreen) / spryscale);
|
dc_texturefrac = FLOAT2FIXED((dc_yl + 0.5 - sprtopscreen) / spryscale);
|
||||||
dc_source = column;
|
dc_source = column;
|
||||||
|
dc_source2 = nullptr;
|
||||||
dc_dest = (ylookup[dc_yl] + dc_x) * pixelsize + dc_destorg;
|
dc_dest = (ylookup[dc_yl] + dc_x) * pixelsize + dc_destorg;
|
||||||
dc_count = dc_yh - dc_yl + 1;
|
dc_count = dc_yh - dc_yl + 1;
|
||||||
|
|
||||||
|
@ -3215,6 +3220,7 @@ void R_DrawVoxel(const FVector3 &globalpos, FAngle viewangle,
|
||||||
dc_x = lxt + x;
|
dc_x = lxt + x;
|
||||||
rt_initcols(OffscreenColorBuffer + (dc_x & ~3) * OffscreenBufferHeight);
|
rt_initcols(OffscreenColorBuffer + (dc_x & ~3) * OffscreenBufferHeight);
|
||||||
dc_source = col;
|
dc_source = col;
|
||||||
|
dc_source2 = nullptr;
|
||||||
dc_texturefrac = yplc[xxl];
|
dc_texturefrac = yplc[xxl];
|
||||||
hcolfunc_pre();
|
hcolfunc_pre();
|
||||||
}
|
}
|
||||||
|
|
|
@ -456,7 +456,7 @@ void FTexture::GenerateBgraMipmaps()
|
||||||
Color4f src11 = src[sy1 + sx1 * srch];
|
Color4f src11 = src[sy1 + sx1 * srch];
|
||||||
Color4f c = (src00 + src01 + src10 + src11) * 0.25f;
|
Color4f c = (src00 + src01 + src10 + src11) * 0.25f;
|
||||||
|
|
||||||
dest[y + x * h] = src00;
|
dest[y + x * h] = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +483,7 @@ void FTexture::GenerateBgraMipmaps()
|
||||||
smoothed[y + x * h] = c;
|
smoothed[y + x * h] = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float k = 0.04f;
|
float k = 0.08f;
|
||||||
for (int j = 0; j < w * h; j++)
|
for (int j = 0; j < w * h; j++)
|
||||||
dest[j] = dest[j] + (dest[j] - smoothed[j]) * k;
|
dest[j] = dest[j] + (dest[j] - smoothed[j]) * k;
|
||||||
|
|
||||||
|
@ -502,10 +502,10 @@ void FTexture::GenerateBgraMipmaps()
|
||||||
int h = MAX(Height >> i, 1);
|
int h = MAX(Height >> i, 1);
|
||||||
for (int j = 0; j < w * h; j++)
|
for (int j = 0; j < w * h; j++)
|
||||||
{
|
{
|
||||||
uint32_t a = (uint32_t)clamp(powf(src[j].a, 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
uint32_t a = (uint32_t)clamp(powf(MAX(src[j].a, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
||||||
uint32_t r = (uint32_t)clamp(powf(src[j].r, 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
uint32_t r = (uint32_t)clamp(powf(MAX(src[j].r, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
||||||
uint32_t g = (uint32_t)clamp(powf(src[j].g, 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
uint32_t g = (uint32_t)clamp(powf(MAX(src[j].g, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
||||||
uint32_t b = (uint32_t)clamp(powf(src[j].b, 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
uint32_t b = (uint32_t)clamp(powf(MAX(src[j].b, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
||||||
dest[j] = (a << 24) | (r << 16) | (g << 8) | b;
|
dest[j] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||||
}
|
}
|
||||||
src += w * h;
|
src += w * h;
|
||||||
|
|
Loading…
Reference in a new issue