Add option to renormalize mipmaps when generating them for normalmaps.

Reduces some aliasing.
This commit is contained in:
Juan Linietsky 2018-04-29 21:51:37 -03:00
parent dc7ed4b547
commit 6244b9e2e1
3 changed files with 38 additions and 14 deletions

View file

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

View file

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

View file

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