Add option to renormalize mipmaps when generating them for normalmaps.
Reduces some aliasing.
This commit is contained in:
parent
dc7ed4b547
commit
6244b9e2e1
|
@ -937,7 +937,7 @@ bool Image::_can_modify(Format p_format) const {
|
|||
return p_format <= FORMAT_RGBE9995;
|
||||
}
|
||||
|
||||
template <int CC>
|
||||
template <int CC, bool renormalize>
|
||||
static void _generate_po2_mipmap(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_width, uint32_t p_height) {
|
||||
|
||||
//fast power of 2 mipmap generation
|
||||
|
@ -963,6 +963,19 @@ static void _generate_po2_mipmap(const uint8_t *p_src, uint8_t *p_dst, uint32_t
|
|||
dst_ptr[j] = val >> 2;
|
||||
}
|
||||
|
||||
if (renormalize) {
|
||||
Vector3 n(dst_ptr[0] / 255.0, dst_ptr[1] / 255.0, dst_ptr[2] / 255.0);
|
||||
n *= 2.0;
|
||||
n -= Vector3(1, 1, 1);
|
||||
n.normalize();
|
||||
n += Vector3(1, 1, 1);
|
||||
n *= 0.5;
|
||||
n *= 255;
|
||||
dst_ptr[0] = CLAMP(int(n.x), 0, 255);
|
||||
dst_ptr[1] = CLAMP(int(n.y), 0, 255);
|
||||
dst_ptr[2] = CLAMP(int(n.z), 0, 255);
|
||||
}
|
||||
|
||||
dst_ptr += CC;
|
||||
rup_ptr += CC * 2;
|
||||
rdown_ptr += CC * 2;
|
||||
|
@ -1045,11 +1058,11 @@ void Image::shrink_x2() {
|
|||
switch (format) {
|
||||
|
||||
case FORMAT_L8:
|
||||
case FORMAT_R8: _generate_po2_mipmap<1>(r.ptr(), w.ptr(), width, height); break;
|
||||
case FORMAT_LA8: _generate_po2_mipmap<2>(r.ptr(), w.ptr(), width, height); break;
|
||||
case FORMAT_RG8: _generate_po2_mipmap<2>(r.ptr(), w.ptr(), width, height); break;
|
||||
case FORMAT_RGB8: _generate_po2_mipmap<3>(r.ptr(), w.ptr(), width, height); break;
|
||||
case FORMAT_RGBA8: _generate_po2_mipmap<4>(r.ptr(), w.ptr(), width, height); break;
|
||||
case FORMAT_R8: _generate_po2_mipmap<1, false>(r.ptr(), w.ptr(), width, height); break;
|
||||
case FORMAT_LA8: _generate_po2_mipmap<2, false>(r.ptr(), w.ptr(), width, height); break;
|
||||
case FORMAT_RG8: _generate_po2_mipmap<2, false>(r.ptr(), w.ptr(), width, height); break;
|
||||
case FORMAT_RGB8: _generate_po2_mipmap<3, false>(r.ptr(), w.ptr(), width, height); break;
|
||||
case FORMAT_RGBA8: _generate_po2_mipmap<4, false>(r.ptr(), w.ptr(), width, height); break;
|
||||
default: {}
|
||||
}
|
||||
}
|
||||
|
@ -1060,7 +1073,7 @@ void Image::shrink_x2() {
|
|||
}
|
||||
}
|
||||
|
||||
Error Image::generate_mipmaps() {
|
||||
Error Image::generate_mipmaps(bool p_renormalize) {
|
||||
|
||||
if (!_can_modify(format)) {
|
||||
ERR_EXPLAIN("Cannot generate mipmaps in indexed, compressed or custom image formats.");
|
||||
|
@ -1089,11 +1102,22 @@ Error Image::generate_mipmaps() {
|
|||
switch (format) {
|
||||
|
||||
case FORMAT_L8:
|
||||
case FORMAT_R8: _generate_po2_mipmap<1>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
|
||||
case FORMAT_R8: _generate_po2_mipmap<1, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
|
||||
case FORMAT_LA8:
|
||||
case FORMAT_RG8: _generate_po2_mipmap<2>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
|
||||
case FORMAT_RGB8: _generate_po2_mipmap<3>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
|
||||
case FORMAT_RGBA8: _generate_po2_mipmap<4>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
|
||||
case FORMAT_RG8: _generate_po2_mipmap<2, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
|
||||
case FORMAT_RGB8:
|
||||
if (p_renormalize)
|
||||
_generate_po2_mipmap<3, true>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
|
||||
else
|
||||
_generate_po2_mipmap<3, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
|
||||
|
||||
break;
|
||||
case FORMAT_RGBA8:
|
||||
if (p_renormalize)
|
||||
_generate_po2_mipmap<4, true>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
|
||||
else
|
||||
_generate_po2_mipmap<4, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
|
||||
break;
|
||||
default: {}
|
||||
}
|
||||
|
||||
|
@ -2217,7 +2241,7 @@ void Image::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("crop", "width", "height"), &Image::crop);
|
||||
ClassDB::bind_method(D_METHOD("flip_x"), &Image::flip_x);
|
||||
ClassDB::bind_method(D_METHOD("flip_y"), &Image::flip_y);
|
||||
ClassDB::bind_method(D_METHOD("generate_mipmaps"), &Image::generate_mipmaps);
|
||||
ClassDB::bind_method(D_METHOD("generate_mipmaps", "renormalize"), &Image::generate_mipmaps, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("clear_mipmaps"), &Image::clear_mipmaps);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("create", "width", "height", "use_mipmaps", "format"), &Image::_create_empty);
|
||||
|
|
|
@ -217,7 +217,7 @@ public:
|
|||
/**
|
||||
* Generate a mipmap to an image (creates an image 1/4 the size, with averaging of 4->1)
|
||||
*/
|
||||
Error generate_mipmaps();
|
||||
Error generate_mipmaps(bool p_renormalize = false);
|
||||
|
||||
void clear_mipmaps();
|
||||
|
||||
|
|
|
@ -295,7 +295,7 @@ void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String
|
|||
case COMPRESS_VIDEO_RAM: {
|
||||
|
||||
Ref<Image> image = p_image->duplicate();
|
||||
image->generate_mipmaps();
|
||||
image->generate_mipmaps(p_force_normal);
|
||||
|
||||
if (p_force_rgbe && image->get_format() >= Image::FORMAT_R8 && image->get_format() <= Image::FORMAT_RGBE9995) {
|
||||
image->convert(Image::FORMAT_RGBE9995);
|
||||
|
|
Loading…
Reference in New Issue