mirror of
https://github.com/minetest/irrlicht.git
synced 2025-07-01 07:40:26 +02:00
burning v0.53
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6364 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
@ -12,16 +12,15 @@
|
||||
#include "CBlit.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
burning_namespace_start
|
||||
|
||||
//! stretches srcRect src to dstRect dst, applying a sliding window box filter in linear color space (sRGB->linear->sRGB)
|
||||
void Resample_subSampling(eBlitter op, video::IImage* dst, const core::rect<s32>* dstRect, const video::IImage* src, const core::rect<s32>* srcRect, size_t flags);
|
||||
|
||||
//nearest pow of 2 ( 257 will be 256 not 512 )
|
||||
static inline core::dimension2d<u32> getOptimalSize(const core::dimension2d<u32>& original, const u32 allowNonPowerOfTwo, const u32 maxSize)
|
||||
static inline core::dimension2d<u32> getOptimalSize(const core::dimension2d<u32>& original,
|
||||
const u32 allowNonPowerOfTwo, const u32 maxSize
|
||||
, const interlaced_control& interlace)
|
||||
{
|
||||
u32 w, h;
|
||||
if (allowNonPowerOfTwo)
|
||||
@ -29,7 +28,17 @@ static inline core::dimension2d<u32> getOptimalSize(const core::dimension2d<u32>
|
||||
w = original.Width;
|
||||
h = original.Height;
|
||||
}
|
||||
else
|
||||
/*
|
||||
else
|
||||
{
|
||||
w = 1;
|
||||
while (w < original.Width) w *= 2;
|
||||
|
||||
h = 1;
|
||||
while (h < original.Height) h *= 2;
|
||||
}
|
||||
*/
|
||||
else if (interlace.bypass)
|
||||
{
|
||||
w = 1;
|
||||
while (w * 2 < original.Width) w *= 2;
|
||||
@ -39,18 +48,33 @@ static inline core::dimension2d<u32> getOptimalSize(const core::dimension2d<u32>
|
||||
while (h * 2 < original.Height) h *= 2;
|
||||
if (h * 2 - original.Height < original.Height - h) h *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 dw = original.Width / (interlace.tex_scalex + 1);
|
||||
u32 dh = original.Height / (interlace.tex_scaley + 1);
|
||||
|
||||
w = 1;
|
||||
while (w < dw) w *= 2;
|
||||
|
||||
h = 1;
|
||||
while (h < dh) h *= 2;
|
||||
}
|
||||
|
||||
if (maxSize && w > maxSize) w = maxSize;
|
||||
if (maxSize && h > maxSize) h = maxSize;
|
||||
return core::dimension2d<u32>(w, h);
|
||||
}
|
||||
|
||||
//Helper pointer (do not store per texture)
|
||||
const IImage* CSoftwareTexture2::original_mip0 = 0;
|
||||
|
||||
//! constructor
|
||||
CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 flags, CBurningVideoDriver* driver)
|
||||
: ITexture(name
|
||||
#if !defined(PATCH_SUPERTUX_8_0_1_with_1_9_0)
|
||||
, ETT_2D
|
||||
#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0)
|
||||
: ITexture(name),Type(ETT_2D)
|
||||
#else
|
||||
: ITexture(name, ETT_2D)
|
||||
#endif
|
||||
)
|
||||
, MipMapLOD(0), Flags(flags), Driver(driver)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
@ -65,11 +89,13 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 fl
|
||||
ColorFormat = (Flags & IS_RENDERTARGET) ? SOFTWARE_DRIVER_2_RENDERTARGET_COLOR_FORMAT : SOFTWARE_DRIVER_2_TEXTURE_COLOR_FORMAT;
|
||||
IsRenderTarget = (Flags & IS_RENDERTARGET) != 0;
|
||||
HasMipMaps = (Flags & GEN_MIPMAP) != 0;
|
||||
MipMap0_Area[0] = 1;
|
||||
MipMap0_Area[1] = 1;
|
||||
LodBIAS = 1.f;
|
||||
|
||||
for (size_t i = 0; i < array_size(MipMap); ++i) MipMap[i] = 0;
|
||||
if (!image) return;
|
||||
if (!image)
|
||||
{
|
||||
calcDerivative();
|
||||
return;
|
||||
}
|
||||
|
||||
OriginalSize = image->getDimension();
|
||||
OriginalColorFormat = image->getColorFormat();
|
||||
@ -78,14 +104,21 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 fl
|
||||
#if defined(IRRLICHT_sRGB)
|
||||
if (Flags & IMAGE_IS_LINEAR) image->set_sRGB(0);
|
||||
#else
|
||||
//guessing linear image
|
||||
|
||||
//compatible means all texture are linear
|
||||
//Flags |= TEXTURE_IS_LINEAR | IMAGE_IS_LINEAR;
|
||||
|
||||
//guessing linear image, everything else degamma
|
||||
if (name.find("light") >= 0 ||
|
||||
name.find("bump") >= 0 ||
|
||||
name.find("height") >= 0
|
||||
|| name.find("detail") >= 0 // demo detailmap3.jpg. do some s-shaping on degamma for equal center?
|
||||
)
|
||||
{
|
||||
Flags |= TEXTURE_IS_LINEAR | IMAGE_IS_LINEAR;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
bool isCompressed = IImage::isCompressedFormat(OriginalColorFormat);
|
||||
@ -103,16 +136,12 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 fl
|
||||
maxTexSize = 0;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
core::dimension2d<u32> optSize(OriginalSize.getOptimalSize(
|
||||
(Flags & ALLOW_NPOT) ? 0 : 1, // requirePowerOfTwo
|
||||
false, // requireSquare
|
||||
(Flags & ALLOW_NPOT) ? 1 : maxTexSize == SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE, // larger
|
||||
(Flags & ALLOW_NPOT) ? 0 : maxTexSize // maxValue
|
||||
)
|
||||
);
|
||||
*/
|
||||
core::dimension2d<u32> optSize(getOptimalSize(OriginalSize, Flags & ALLOW_NPOT, maxTexSize));
|
||||
|
||||
//thread-local storage if needed
|
||||
original_mip0 = 0;
|
||||
|
||||
const interlaced_control& interlaced = Driver->getInterlace();
|
||||
core::dimension2d<u32> optSize(getOptimalSize(OriginalSize, Flags & ALLOW_NPOT, maxTexSize, interlaced));
|
||||
if (OriginalSize == optSize)
|
||||
{
|
||||
MipMap[0] = new CImage(ColorFormat, image->getDimension());
|
||||
@ -132,17 +161,18 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 fl
|
||||
{
|
||||
//image->copyToScalingBoxFilter ( MipMap[0],0, false );
|
||||
Resample_subSampling(BLITTER_TEXTURE, MipMap[0], 0, image, 0, Flags);
|
||||
original_mip0 = image;
|
||||
}
|
||||
// if Original Size is used for calculation ( 2D position, font) it will be wrong
|
||||
//OriginalSize = optSize;
|
||||
}
|
||||
|
||||
// Show Information about resizing
|
||||
if (OriginalSize != optSize ||
|
||||
( OriginalColorFormat != ColorFormat &&
|
||||
if ((OriginalSize != optSize && interlaced.tex_scalex == 0) ||
|
||||
(OriginalColorFormat != ColorFormat &&
|
||||
!((OriginalColorFormat == ECF_R8G8B8 || OriginalColorFormat == ECF_A1R5G5B5) && ColorFormat == ECF_A8R8G8B8)
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
char buf[256];
|
||||
core::stringw showName(name);
|
||||
@ -157,6 +187,7 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 fl
|
||||
|
||||
//select highest mipmap 0
|
||||
regenerateMipMapLevels(image->getMipMapsData());
|
||||
original_mip0 = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -198,6 +229,8 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data)
|
||||
|
||||
if (HasMipMaps && ((Flags & GEN_MIPMAP_AUTO) || 0 == data))
|
||||
{
|
||||
const IImage* mip0 = original_mip0 ? original_mip0 : MipMap[0];
|
||||
|
||||
//need memory also if autogen mipmap disabled
|
||||
for (i = 1; i < array_size(MipMap); ++i)
|
||||
{
|
||||
@ -214,7 +247,7 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data)
|
||||
#endif
|
||||
//MipMap[i]->fill ( 0xFFFF4040 );
|
||||
//MipMap[i-1]->copyToScalingBoxFilter( MipMap[i], 0, false );
|
||||
Resample_subSampling(BLITTER_TEXTURE, MipMap[i], 0, MipMap[0], 0, Flags);
|
||||
Resample_subSampling(BLITTER_TEXTURE, MipMap[i], 0, mip0, 0, Flags);
|
||||
}
|
||||
}
|
||||
else if (HasMipMaps && data)
|
||||
@ -235,9 +268,6 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data)
|
||||
i += 1;
|
||||
} while ((origSize.Width != 1 || origSize.Height != 1) && i < array_size(MipMap));
|
||||
|
||||
//TODO: this is not true
|
||||
LodBIAS = i * 2.f;
|
||||
|
||||
origSize = OriginalSize;
|
||||
for (i = 1; i < array_size(MipMap) && mip_current < mip_end; ++i)
|
||||
{
|
||||
@ -279,10 +309,11 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data)
|
||||
|
||||
#if 0
|
||||
//visualize mipmap
|
||||
for (i = 1; i < 0 && i < array_size(MipMap); ++i)
|
||||
//if ( Flags & ( TEXTURE_IS_LINEAR | IMAGE_IS_LINEAR))
|
||||
for (i = 1; i < array_size(MipMap); ++i)
|
||||
{
|
||||
static u32 color[] = {
|
||||
0xFFFF0000,
|
||||
0xFFFFFFFF,
|
||||
0xFFFF0000,0xFF00FF00,0xFF0000FF,
|
||||
0xFFFFFF00,0xFF00FFFF,0xFFFF00FF,
|
||||
0xFFff6600,0xFF00ff66,0xFF6600FF,
|
||||
@ -296,14 +327,16 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data)
|
||||
int border = 0;
|
||||
const core::dimension2du& d = MipMap[i]->getDimension();
|
||||
core::rect<s32> p(0, 0, d.Width, d.Height);
|
||||
SColor c((color[i & 15] & 0x00FFFFFF) | 0xFF000000);
|
||||
SColor c((color[i & 15] & 0x00FFFFFF) | 0x7F000000);
|
||||
|
||||
core::rect<s32> dclip(border, border, d.Width - border, d.Height - border);
|
||||
|
||||
|
||||
Blit(BLITTER_TEXTURE_ALPHA_COLOR_BLEND, MipMap[i], &dclip, 0, MipMap[i], &p, c.color);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
//save mipmap chain
|
||||
if (0)
|
||||
{
|
||||
@ -318,14 +351,20 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data)
|
||||
//if (name[i] == '.') ext = i;
|
||||
i += 1;
|
||||
}
|
||||
for (i = 0; i < array_size(MipMap); ++i)
|
||||
if (original_mip0)
|
||||
{
|
||||
if (MipMap[i])
|
||||
{
|
||||
snprintf_irr(buf, sizeof(buf), "mip/%s_%02d.png", name + filename, (s32)i);
|
||||
Driver->writeImageToFile(MipMap[i], buf);
|
||||
}
|
||||
snprintf_irr(buf, sizeof(buf), "mip/%s_org.png", name + filename);
|
||||
Driver->writeImageToFile((IImage*)original_mip0, buf);
|
||||
}
|
||||
if (array_size(MipMap) >= 1 && MipMap[1])
|
||||
for (i = 0; i < array_size(MipMap); ++i)
|
||||
{
|
||||
if (MipMap[i])
|
||||
{
|
||||
snprintf_irr(buf, sizeof(buf), "mip/%s_%02d.png", name + filename, (s32)i);
|
||||
Driver->writeImageToFile(MipMap[i], buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
calcDerivative();
|
||||
@ -337,39 +376,48 @@ void CSoftwareTexture2::calcDerivative()
|
||||
MipMapLOD = 0;
|
||||
if (MipMap[0])
|
||||
{
|
||||
const core::dimension2du& dim = MipMap[0]->getDimension();
|
||||
MipMap0_Area[0] = dim.Width;
|
||||
MipMap0_Area[1] = dim.Height; // screensize of a triangle
|
||||
|
||||
//TA: try to mimic openGL mipmap. ( don't do this!)
|
||||
//if (MipMap0_Area[0] < 32) MipMap0_Area[0] = 32;
|
||||
//if (MipMap0_Area[1] < 32) MipMap0_Area[1] = 32;
|
||||
|
||||
Size = dim; // MipMap[MipMapLOD]->getDimension();
|
||||
Size = MipMap[MipMapLOD]->getDimension();
|
||||
Pitch = MipMap[MipMapLOD]->getPitch();
|
||||
}
|
||||
|
||||
//preCalc mipmap texel center boundaries
|
||||
|
||||
for (size_t i = 0; i < array_size(MipMap); ++i)
|
||||
{
|
||||
CSoftwareTexture2_Bound& b = TexBound[i];
|
||||
if (MipMap[i])
|
||||
{
|
||||
const core::dimension2du& dim = MipMap[i]->getDimension();
|
||||
//f32 u = 1.f / dim.Width;
|
||||
//f32 v = 1.f / dim.Height;
|
||||
|
||||
b.w = dim.Width - 1.f;
|
||||
b.h = dim.Height - 1.f;
|
||||
b.cx = 0.f; //u*0.005f;
|
||||
b.cy = 0.f; //v*0.005f;
|
||||
core::dimension2du dim(0, 0);
|
||||
if (MipMap[i] && MipMap[i]->getData()) dim = MipMap[i]->getDimension();
|
||||
|
||||
b.area = dim.Width * dim.Height;
|
||||
if (b.area < 1)
|
||||
{
|
||||
b.mat[0] = 0.f;
|
||||
b.mat[1] = 0.f;
|
||||
b.mat[2] = 0.f;
|
||||
b.mat[3] = 0.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
b.w = 0.f;
|
||||
b.h = 0.f;
|
||||
b.cx = 0.f;
|
||||
b.cy = 0.f;
|
||||
#if 0
|
||||
const f32 nu = 0.5f / dim.Width;
|
||||
const f32 nv = 0.5f / dim.Height;
|
||||
|
||||
//texture sampler! u,v repeat > 1 is wrong
|
||||
// should be [0.5/width,1-0.5/width] ,but currently can't step outside last pixel...
|
||||
// https://bartwronski.com/2021/02/15/bilinear-down-upsampling-pixel-grids-and-that-half-pixel-offset/
|
||||
|
||||
b.mat[0] = 1.f - 2 * nu;
|
||||
b.mat[1] = nu;
|
||||
b.mat[2] = 1.f - 2 * nv;
|
||||
b.mat[3] = nv;
|
||||
#endif
|
||||
//texture sampler doesn't filter from center, sub-pixel shifts sub-texel
|
||||
//wrong place here to go to pixel-dim
|
||||
b.mat[0] = dim.Width - 1.f;
|
||||
b.mat[1] = 0.f;
|
||||
b.mat[2] = dim.Height - 1.f;
|
||||
b.mat[3] = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,7 +428,7 @@ void CSoftwareTexture2::calcDerivative()
|
||||
|
||||
CSoftwareRenderTarget2::CSoftwareRenderTarget2(CBurningVideoDriver* driver) : Driver(driver)
|
||||
#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0)
|
||||
, IRenderTarget(0)
|
||||
, IRenderTarget(0), DepthStencil(0)
|
||||
#endif
|
||||
{
|
||||
DriverType = EDT_BURNINGSVIDEO;
|
||||
@ -393,9 +441,13 @@ CSoftwareRenderTarget2::~CSoftwareRenderTarget2()
|
||||
{
|
||||
if (Textures[0])
|
||||
Textures[0]->drop();
|
||||
|
||||
if (DepthStencil)
|
||||
DepthStencil->drop();
|
||||
|
||||
}
|
||||
|
||||
void CSoftwareRenderTarget2::setTextures(ITexture* const * textures, u32 numTextures, ITexture* depthStencil, const E_CUBE_SURFACE* cubeSurfaces, u32 numCubeSurfaces)
|
||||
void CSoftwareRenderTarget2::setTextures(ITexture* const* textures, u32 numTextures, ITexture* depthStencil, const E_CUBE_SURFACE* cubeSurfaces, u32 numCubeSurfaces)
|
||||
{
|
||||
if (!Textures.equals(textures, numTextures))
|
||||
{
|
||||
@ -421,8 +473,41 @@ void CSoftwareRenderTarget2::setTextures(ITexture* const * textures, u32 numText
|
||||
if (!textureDetected)
|
||||
Textures[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Set depth and stencil attachments.
|
||||
if (DepthStencil != depthStencil)
|
||||
{
|
||||
if (DepthStencil)
|
||||
{
|
||||
DepthStencil->drop();
|
||||
DepthStencil = 0;
|
||||
}
|
||||
|
||||
CSoftwareTexture2* currentTexture = (depthStencil && depthStencil->getDriverType() == DriverType) ? static_cast<CSoftwareTexture2*>(depthStencil) : 0;
|
||||
|
||||
if (currentTexture)
|
||||
{
|
||||
if (currentTexture->getType() == ETT_2D)
|
||||
{
|
||||
const ECOLOR_FORMAT textureFormat = currentTexture->getOriginalColorFormat();
|
||||
if (IImage::isDepthFormat(textureFormat))
|
||||
{
|
||||
DepthStencil = depthStencil;
|
||||
DepthStencil->grab();
|
||||
}
|
||||
else
|
||||
{
|
||||
os::Printer::log("Ignoring depth/stencil texture without depth color format.", ELL_WARNING);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
os::Printer::log("This driver doesn't support depth/stencil to cubemaps.", ELL_WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static const float srgb_8bit_to_linear_float[1 << 8] = {
|
||||
0.0f, 3.03527e-4f, 6.07054e-4f, 9.10581e-4f,
|
||||
@ -490,11 +575,28 @@ static const float srgb_8bit_to_linear_float[1 << 8] = {
|
||||
0.9386857f, 0.9473065f, 0.9559733f, 0.9646863f,
|
||||
0.9734453f, 0.9822506f, 0.9911021f, 1.0f,
|
||||
};
|
||||
/*
|
||||
|
||||
#if 0
|
||||
static void buildtable()
|
||||
{
|
||||
//sRGB x <= 0.0031308 ? x * 12.92 : (1.055 * pow(x, 1/2.4)) - 0.055
|
||||
//Rec709 x < 0.018 ? (x * 4.5) : 1.099 * pow( x, (0.45) ) - 0.099
|
||||
|
||||
printf("static const float srgb_8bit_to_linear_float[1 << 8] = {");
|
||||
for (int i = 0; i <= 255; ++i)
|
||||
{
|
||||
double x = i / 255.0;
|
||||
double linear = x < 0.04045 ? x / 12.92 : pow((x + 0.055) / 1.055, 2.4);
|
||||
linear = pow(x, 2.2);
|
||||
printf("%s%0.10lff", i & 7 ? "," : ",\n\t", linear);
|
||||
}
|
||||
printf("\n};");
|
||||
}
|
||||
|
||||
int linear_to_srgb_8bit(const float x) {
|
||||
if (x <= 0.f) return 0;
|
||||
if (x >= 1.f) return 255;
|
||||
const float *table = SRGB_8BIT_TO_LINEAR_FLOAT;
|
||||
const float* table = SRGB_8BIT_TO_LINEAR_FLOAT;
|
||||
int y = 0;
|
||||
for (int i = 128; i != 0; i >>= 1) {
|
||||
if (table[y + i] <= x)
|
||||
@ -505,24 +607,28 @@ int linear_to_srgb_8bit(const float x) {
|
||||
else
|
||||
return y + 1;
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
u32 linear_to_srgb_8bit(const float v)
|
||||
{
|
||||
if (v <= 0.f) return 0;
|
||||
else if (v >= 1.f) return 255;
|
||||
ieee754 c;
|
||||
c.f = v;
|
||||
const size_t x = c.u;
|
||||
const u32* table = (u32*)srgb_8bit_to_linear_float;
|
||||
const u32 x = c.u;
|
||||
const u32* table = (const u32*)srgb_8bit_to_linear_float;
|
||||
u32 y = 0;
|
||||
y += table[y + 128] <= x ? 128 : 0;
|
||||
y += table[y + 64] <= x ? 64 : 0;
|
||||
y += table[y + 32] <= x ? 32 : 0;
|
||||
y += table[y + 16] <= x ? 16 : 0;
|
||||
y += table[y + 8] <= x ? 8 : 0;
|
||||
y += table[y + 4] <= x ? 4 : 0;
|
||||
y += table[y + 2] <= x ? 2 : 0;
|
||||
y += table[y + 1] <= x ? 1 : 0;
|
||||
y |= table[y | 128] <= x ? 128 : 0;
|
||||
y |= table[y | 64] <= x ? 64 : 0;
|
||||
y |= table[y | 32] <= x ? 32 : 0;
|
||||
y |= table[y | 16] <= x ? 16 : 0;
|
||||
y |= table[y | 8] <= x ? 8 : 0;
|
||||
y |= table[y | 4] <= x ? 4 : 0;
|
||||
y |= table[y | 2] <= x ? 2 : 0;
|
||||
y |= table[y | 1] <= x ? 1 : 0;
|
||||
|
||||
if (srgb_8bit_to_linear_float[y + 1] - x < v - srgb_8bit_to_linear_float[y])
|
||||
y += 1;
|
||||
|
||||
return y;
|
||||
}
|
||||
@ -579,41 +685,47 @@ void Resample_subSampling(eBlitter op, video::IImage* dst, const core::rect<s32>
|
||||
const int dst_sRGB = dst->get_sRGB();
|
||||
const int src_sRGB = src->get_sRGB();
|
||||
#else
|
||||
//assuming sRGB as default
|
||||
const int dst_sRGB = (flags & CSoftwareTexture2::TEXTURE_IS_LINEAR) ? 0 : 1;
|
||||
const int src_sRGB = (flags & CSoftwareTexture2::IMAGE_IS_LINEAR) ? 0 : 1;
|
||||
#endif
|
||||
|
||||
#define ft float
|
||||
|
||||
ft scale[2];
|
||||
scale[0] = (ft)(sc.x1 - sc.x0) / (ft)(dc.x1 - dc.x0);
|
||||
scale[1] = (ft)(sc.y1 - sc.y0) / (ft)(dc.y1 - dc.y0);
|
||||
if (scale[0] < (ft)1 && scale[1] < (ft)1)
|
||||
{
|
||||
//magnify
|
||||
}
|
||||
//unweighted box filter
|
||||
const ft rs = (ft)1.0 / (scale[0] * scale[1]);
|
||||
|
||||
float scale[2];
|
||||
scale[0] = (float)(sc.x1 - sc.x0) / (float)(dc.x1 - dc.x0);
|
||||
scale[1] = (float)(sc.y1 - sc.y0) / (float)(dc.y1 - dc.y0);
|
||||
const float rs = 1.f / (scale[0] * scale[1]);
|
||||
|
||||
float sum[4];
|
||||
ft sum[4];
|
||||
u32 sbgra = 0;
|
||||
|
||||
float f[4];
|
||||
ft f[4];
|
||||
int fi[4];
|
||||
f[3] = (float)sc.y0;
|
||||
f[3] = (ft)sc.y0;
|
||||
for (int dy = dc.y0; dy < dc.y1; ++dy)
|
||||
{
|
||||
f[1] = f[3];
|
||||
f[3] = sc.y0 + (dy + 1 - dc.y0) * scale[1];
|
||||
if (f[3] >= sc.y1) f[3] = sc.y1 - 0.001f; //todo:1.f/dim should be enough
|
||||
if (f[3] >= sc.y1) f[3] = sc.y1 - (ft)0.001; //todo:1.f/dim should be enough
|
||||
|
||||
f[2] = (float)sc.x0;
|
||||
f[2] = (ft)sc.x0;
|
||||
for (int dx = dc.x0; dx < dc.x1; ++dx)
|
||||
{
|
||||
f[0] = f[2];
|
||||
f[2] = sc.x0 + (dx + 1 - dc.x0) * scale[0];
|
||||
if (f[2] >= sc.x1) f[2] = sc.x1 - 0.001f;
|
||||
if (f[2] >= sc.x1) f[2] = sc.x1 - (ft)0.001;
|
||||
|
||||
//accumulate linear color
|
||||
sum[0] = 0.f;
|
||||
sum[1] = 0.f;
|
||||
sum[2] = 0.f;
|
||||
sum[3] = 0.f;
|
||||
sum[0] = (ft)0;
|
||||
sum[1] = (ft)0;
|
||||
sum[2] = (ft)0;
|
||||
sum[3] = (ft)0;
|
||||
|
||||
//sample border
|
||||
fi[0] = (int)(f[0]);
|
||||
@ -621,20 +733,20 @@ void Resample_subSampling(eBlitter op, video::IImage* dst, const core::rect<s32>
|
||||
fi[2] = (int)(f[2]);
|
||||
fi[3] = (int)(f[3]);
|
||||
|
||||
float w[2];
|
||||
ft w[2];
|
||||
for (int fy = fi[1]; fy <= fi[3]; ++fy)
|
||||
{
|
||||
w[1] = 1.f;
|
||||
w[1] = (ft)1;
|
||||
if (fy == fi[1]) w[1] -= f[1] - fy;
|
||||
if (fy == fi[3]) w[1] -= fy + 1 - f[3];
|
||||
|
||||
for (int fx = fi[0]; fx <= fi[2]; ++fx)
|
||||
{
|
||||
w[0] = 1.f;
|
||||
w[0] = (ft)1;
|
||||
if (fx == fi[0]) w[0] -= f[0] - fx;
|
||||
if (fx == fi[2]) w[0] -= fx + 1 - f[2];
|
||||
|
||||
const float ws = w[1] * w[0] * rs;
|
||||
const ft ws = w[1] * w[0] * rs;
|
||||
|
||||
switch (srcFormat)
|
||||
{
|
||||
@ -675,17 +787,25 @@ void Resample_subSampling(eBlitter op, video::IImage* dst, const core::rect<s32>
|
||||
}
|
||||
if (dst_sRGB)
|
||||
{
|
||||
sbgra = linear_to_srgb_8bit(sum[0]) |
|
||||
linear_to_srgb_8bit(sum[1]) << 8 |
|
||||
linear_to_srgb_8bit(sum[2]) << 16 |
|
||||
sbgra = linear_to_srgb_8bit((float)sum[0]) |
|
||||
linear_to_srgb_8bit((float)sum[1]) << 8 |
|
||||
linear_to_srgb_8bit((float)sum[2]) << 16 |
|
||||
(u32)(sum[3]) << 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 b = core::s32_clamp((int)floor(sum[0] + (ft)0.5), 0, 255);
|
||||
u32 g = core::s32_clamp((int)floor(sum[1] + (ft)0.5), 0, 255);
|
||||
u32 r = core::s32_clamp((int)floor(sum[2] + (ft)0.5), 0, 255);
|
||||
u32 a = core::s32_clamp((int)floor(sum[3] + (ft)0.5), 0, 255);
|
||||
|
||||
sbgra = b | (g << 8) | (r << 16) | (a << 24);
|
||||
/*
|
||||
sbgra = (u32)(sum[0]) |
|
||||
(u32)(sum[1]) << 8 |
|
||||
(u32)(sum[2]) << 16 |
|
||||
(u32)(sum[3]) << 24;
|
||||
*/
|
||||
}
|
||||
switch (dstFormat)
|
||||
{
|
||||
@ -704,10 +824,9 @@ void Resample_subSampling(eBlitter op, video::IImage* dst, const core::rect<s32>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef ft
|
||||
}
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
burning_namespace_end
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
|
||||
|
Reference in New Issue
Block a user