mirror of
https://github.com/godotengine/godot.git
synced 2024-11-10 06:03:09 +00:00
BPTC support
This commit is contained in:
parent
0e6551d8e2
commit
35f6ba5c5d
@ -135,6 +135,12 @@ Comment: CA certificates
|
||||
Copyright: Mozilla Contributors
|
||||
License: MPL-2.0
|
||||
|
||||
Files: ./thirdparty/cvtt/
|
||||
Comment: Convection Texture Tools Stand-Alone Kernels
|
||||
Copyright: 2018, Eric Lasota
|
||||
2018, Microsoft Corp.
|
||||
License: MIT
|
||||
|
||||
Files: ./thirdparty/enet/
|
||||
Comment: ENet
|
||||
Copyright: 2002-2016, Lee Salzman
|
||||
|
@ -253,6 +253,21 @@ Color Color::hex64(uint64_t p_hex) {
|
||||
return Color(r, g, b, a);
|
||||
}
|
||||
|
||||
Color Color::from_rgbe9995(uint32_t p_rgbe) {
|
||||
|
||||
float r = p_rgbe & 0x1ff;
|
||||
float g = (p_rgbe >> 9) & 0x1ff;
|
||||
float b = (p_rgbe >> 18) & 0x1ff;
|
||||
float e = (p_rgbe >> 27);
|
||||
float m = Math::pow(2, e - 15.0 - 9.0);
|
||||
|
||||
float rd = r * m;
|
||||
float gd = g * m;
|
||||
float bd = b * m;
|
||||
|
||||
return Color(rd, gd, bd, 1.0f);
|
||||
}
|
||||
|
||||
static float _parse_col(const String &p_str, int p_ofs) {
|
||||
|
||||
int ig = 0;
|
||||
|
@ -195,6 +195,7 @@ struct Color {
|
||||
static Color named(const String &p_name);
|
||||
String to_html(bool p_alpha = true) const;
|
||||
Color from_hsv(float p_h, float p_s, float p_v, float p_a);
|
||||
static Color from_rgbe9995(uint32_t p_color);
|
||||
|
||||
_FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys
|
||||
operator String() const;
|
||||
|
190
core/image.cpp
190
core/image.cpp
@ -1029,8 +1029,10 @@ bool Image::_can_modify(Format p_format) const {
|
||||
return p_format <= FORMAT_RGBE9995;
|
||||
}
|
||||
|
||||
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) {
|
||||
template <class Component, int CC, bool renormalize,
|
||||
void (*average_func)(Component &, const Component &, const Component &, const Component &, const Component &),
|
||||
void (*renormalize_func)(Component *)>
|
||||
static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint32_t p_width, uint32_t p_height) {
|
||||
|
||||
//fast power of 2 mipmap generation
|
||||
uint32_t dst_w = p_width >> 1;
|
||||
@ -1038,34 +1040,19 @@ static void _generate_po2_mipmap(const uint8_t *p_src, uint8_t *p_dst, uint32_t
|
||||
|
||||
for (uint32_t i = 0; i < dst_h; i++) {
|
||||
|
||||
const uint8_t *rup_ptr = &p_src[i * 2 * p_width * CC];
|
||||
const uint8_t *rdown_ptr = rup_ptr + p_width * CC;
|
||||
uint8_t *dst_ptr = &p_dst[i * dst_w * CC];
|
||||
const Component *rup_ptr = &p_src[i * 2 * p_width * CC];
|
||||
const Component *rdown_ptr = rup_ptr + p_width * CC;
|
||||
Component *dst_ptr = &p_dst[i * dst_w * CC];
|
||||
uint32_t count = dst_w;
|
||||
|
||||
while (count--) {
|
||||
|
||||
for (int j = 0; j < CC; j++) {
|
||||
|
||||
uint16_t val = 0;
|
||||
val += rup_ptr[j];
|
||||
val += rup_ptr[j + CC];
|
||||
val += rdown_ptr[j];
|
||||
val += rdown_ptr[j + CC];
|
||||
dst_ptr[j] = val >> 2;
|
||||
average_func(dst_ptr[j], rup_ptr[j], rup_ptr[j + CC], rdown_ptr[j], rdown_ptr[j + CC]);
|
||||
}
|
||||
|
||||
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);
|
||||
renormalize_func(dst_ptr);
|
||||
}
|
||||
|
||||
dst_ptr += CC;
|
||||
@ -1150,11 +1137,23 @@ void Image::shrink_x2() {
|
||||
switch (format) {
|
||||
|
||||
case FORMAT_L8:
|
||||
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;
|
||||
case FORMAT_R8: _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break;
|
||||
case FORMAT_LA8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break;
|
||||
case FORMAT_RG8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break;
|
||||
case FORMAT_RGB8: _generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break;
|
||||
case FORMAT_RGBA8: _generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break;
|
||||
|
||||
case FORMAT_RF: _generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r.ptr()), reinterpret_cast<float *>(w.ptr()), width, height); break;
|
||||
case FORMAT_RGF: _generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r.ptr()), reinterpret_cast<float *>(w.ptr()), width, height); break;
|
||||
case FORMAT_RGBF: _generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r.ptr()), reinterpret_cast<float *>(w.ptr()), width, height); break;
|
||||
case FORMAT_RGBAF: _generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r.ptr()), reinterpret_cast<float *>(w.ptr()), width, height); break;
|
||||
|
||||
case FORMAT_RH: _generate_po2_mipmap<uint16_t, 1, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r.ptr()), reinterpret_cast<uint16_t *>(w.ptr()), width, height); break;
|
||||
case FORMAT_RGH: _generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r.ptr()), reinterpret_cast<uint16_t *>(w.ptr()), width, height); break;
|
||||
case FORMAT_RGBH: _generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r.ptr()), reinterpret_cast<uint16_t *>(w.ptr()), width, height); break;
|
||||
case FORMAT_RGBAH: _generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r.ptr()), reinterpret_cast<uint16_t *>(w.ptr()), width, height); break;
|
||||
|
||||
case FORMAT_RGBE9995: _generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(r.ptr()), reinterpret_cast<uint32_t *>(w.ptr()), width, height); break;
|
||||
default: {}
|
||||
}
|
||||
}
|
||||
@ -1224,21 +1223,68 @@ Error Image::generate_mipmaps(bool p_renormalize) {
|
||||
switch (format) {
|
||||
|
||||
case FORMAT_L8:
|
||||
case FORMAT_R8: _generate_po2_mipmap<1, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
|
||||
case FORMAT_R8: _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
|
||||
case FORMAT_LA8:
|
||||
case FORMAT_RG8: _generate_po2_mipmap<2, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
|
||||
case FORMAT_RG8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(&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);
|
||||
_generate_po2_mipmap<uint8_t, 3, true, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
|
||||
else
|
||||
_generate_po2_mipmap<3, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
|
||||
_generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(&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);
|
||||
_generate_po2_mipmap<uint8_t, 4, true, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
|
||||
else
|
||||
_generate_po2_mipmap<4, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
|
||||
_generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
|
||||
break;
|
||||
case FORMAT_RF:
|
||||
_generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
|
||||
break;
|
||||
case FORMAT_RGF:
|
||||
_generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
|
||||
break;
|
||||
case FORMAT_RGBF:
|
||||
if (p_renormalize)
|
||||
_generate_po2_mipmap<float, 3, true, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
|
||||
else
|
||||
_generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
|
||||
|
||||
break;
|
||||
case FORMAT_RGBAF:
|
||||
if (p_renormalize)
|
||||
_generate_po2_mipmap<float, 4, true, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
|
||||
else
|
||||
_generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
|
||||
|
||||
break;
|
||||
case FORMAT_RH:
|
||||
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
|
||||
break;
|
||||
case FORMAT_RGH:
|
||||
_generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
|
||||
break;
|
||||
case FORMAT_RGBH:
|
||||
if (p_renormalize)
|
||||
_generate_po2_mipmap<uint16_t, 3, true, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
|
||||
else
|
||||
_generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
|
||||
|
||||
break;
|
||||
case FORMAT_RGBAH:
|
||||
if (p_renormalize)
|
||||
_generate_po2_mipmap<uint16_t, 4, true, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
|
||||
else
|
||||
_generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
|
||||
|
||||
break;
|
||||
case FORMAT_RGBE9995:
|
||||
if (p_renormalize)
|
||||
_generate_po2_mipmap<uint32_t, 1, true, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(&wp[prev_ofs]), reinterpret_cast<uint32_t *>(&wp[ofs]), prev_w, prev_h);
|
||||
else
|
||||
_generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(&wp[prev_ofs]), reinterpret_cast<uint32_t *>(&wp[ofs]), prev_w, prev_h);
|
||||
|
||||
break;
|
||||
default: {}
|
||||
}
|
||||
@ -1617,8 +1663,10 @@ bool Image::is_compressed() const {
|
||||
|
||||
Error Image::decompress() {
|
||||
|
||||
if (format >= FORMAT_DXT1 && format <= FORMAT_BPTC_RGBFU && _image_decompress_bc)
|
||||
if (format >= FORMAT_DXT1 && format <= FORMAT_RGTC_RG && _image_decompress_bc)
|
||||
_image_decompress_bc(this);
|
||||
else if (format >= FORMAT_BPTC_RGBA && format <= FORMAT_BPTC_RGBFU && _image_decompress_bptc)
|
||||
_image_decompress_bptc(this);
|
||||
else if (format >= FORMAT_PVRTC2 && format <= FORMAT_PVRTC4A && _image_decompress_pvrtc)
|
||||
_image_decompress_pvrtc(this);
|
||||
else if (format == FORMAT_ETC && _image_decompress_etc1)
|
||||
@ -1659,6 +1707,11 @@ Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_loss
|
||||
ERR_FAIL_COND_V(!_image_compress_etc2_func, ERR_UNAVAILABLE);
|
||||
_image_compress_etc2_func(this, p_lossy_quality, p_source);
|
||||
} break;
|
||||
case COMPRESS_BPTC: {
|
||||
|
||||
ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE);
|
||||
_image_compress_bptc_func(this, p_lossy_quality, p_source);
|
||||
} break;
|
||||
}
|
||||
|
||||
return OK;
|
||||
@ -1996,12 +2049,14 @@ ImageMemLoadFunc Image::_jpg_mem_loader_func = NULL;
|
||||
ImageMemLoadFunc Image::_webp_mem_loader_func = NULL;
|
||||
|
||||
void (*Image::_image_compress_bc_func)(Image *, Image::CompressSource) = NULL;
|
||||
void (*Image::_image_compress_bptc_func)(Image *, float, Image::CompressSource) = NULL;
|
||||
void (*Image::_image_compress_pvrtc2_func)(Image *) = NULL;
|
||||
void (*Image::_image_compress_pvrtc4_func)(Image *) = NULL;
|
||||
void (*Image::_image_compress_etc1_func)(Image *, float) = NULL;
|
||||
void (*Image::_image_compress_etc2_func)(Image *, float, Image::CompressSource) = NULL;
|
||||
void (*Image::_image_decompress_pvrtc)(Image *) = NULL;
|
||||
void (*Image::_image_decompress_bc)(Image *) = NULL;
|
||||
void (*Image::_image_decompress_bptc)(Image *) = NULL;
|
||||
void (*Image::_image_decompress_etc1)(Image *) = NULL;
|
||||
void (*Image::_image_decompress_etc2)(Image *) = NULL;
|
||||
|
||||
@ -2185,18 +2240,7 @@ Color Image::get_pixel(int p_x, int p_y) const {
|
||||
return Color(Math::half_to_float(r), Math::half_to_float(g), Math::half_to_float(b), Math::half_to_float(a));
|
||||
} break;
|
||||
case FORMAT_RGBE9995: {
|
||||
uint32_t rgbe = ((uint32_t *)ptr)[ofs];
|
||||
float r = rgbe & 0x1ff;
|
||||
float g = (rgbe >> 9) & 0x1ff;
|
||||
float b = (rgbe >> 18) & 0x1ff;
|
||||
float e = (rgbe >> 27);
|
||||
float m = Math::pow(2, e - 15.0 - 9.0);
|
||||
;
|
||||
float rd = r * m;
|
||||
float gd = g * m;
|
||||
float bd = b * m;
|
||||
|
||||
return Color(rd, gd, bd, 1.0);
|
||||
return Color::from_rgbe9995(((uint32_t *)ptr)[ofs]);
|
||||
|
||||
} break;
|
||||
default: {
|
||||
@ -2530,6 +2574,11 @@ void Image::set_compress_bc_func(void (*p_compress_func)(Image *, CompressSource
|
||||
_image_compress_bc_func = p_compress_func;
|
||||
}
|
||||
|
||||
void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, float, CompressSource)) {
|
||||
|
||||
_image_compress_bptc_func = p_compress_func;
|
||||
}
|
||||
|
||||
void Image::normalmap_to_xy() {
|
||||
|
||||
convert(Image::FORMAT_RGBA8);
|
||||
@ -2783,6 +2832,55 @@ Error Image::_load_from_buffer(const PoolVector<uint8_t> &p_array, ImageMemLoadF
|
||||
return OK;
|
||||
}
|
||||
|
||||
void Image::average_4_uint8(uint8_t &p_out, const uint8_t &p_a, const uint8_t &p_b, const uint8_t &p_c, const uint8_t &p_d) {
|
||||
p_out = static_cast<uint8_t>((p_a + p_b + p_c + p_d + 2) >> 2);
|
||||
}
|
||||
|
||||
void Image::average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d) {
|
||||
p_out = (p_a + p_b + p_c + p_d) * 0.25f;
|
||||
}
|
||||
|
||||
void Image::average_4_half(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
|
||||
p_out = Math::make_half_float((Math::half_to_float(p_a) + Math::half_to_float(p_b) + Math::half_to_float(p_c) + Math::half_to_float(p_d)) * 0.25f);
|
||||
}
|
||||
|
||||
void Image::average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint32_t &p_b, const uint32_t &p_c, const uint32_t &p_d) {
|
||||
p_out = ((Color::from_rgbe9995(p_a) + Color::from_rgbe9995(p_b) + Color::from_rgbe9995(p_c) + Color::from_rgbe9995(p_d)) * 0.25f).to_rgbe9995();
|
||||
}
|
||||
|
||||
void Image::renormalize_uint8(uint8_t *p_rgb) {
|
||||
Vector3 n(p_rgb[0] / 255.0, p_rgb[1] / 255.0, p_rgb[2] / 255.0);
|
||||
n *= 2.0;
|
||||
n -= Vector3(1, 1, 1);
|
||||
n.normalize();
|
||||
n += Vector3(1, 1, 1);
|
||||
n *= 0.5;
|
||||
n *= 255;
|
||||
p_rgb[0] = CLAMP(int(n.x), 0, 255);
|
||||
p_rgb[1] = CLAMP(int(n.y), 0, 255);
|
||||
p_rgb[2] = CLAMP(int(n.z), 0, 255);
|
||||
}
|
||||
|
||||
void Image::renormalize_float(float *p_rgb) {
|
||||
Vector3 n(p_rgb[0], p_rgb[1], p_rgb[2]);
|
||||
n.normalize();
|
||||
p_rgb[0] = n.x;
|
||||
p_rgb[1] = n.y;
|
||||
p_rgb[2] = n.z;
|
||||
}
|
||||
|
||||
void Image::renormalize_half(uint16_t *p_rgb) {
|
||||
Vector3 n(Math::half_to_float(p_rgb[0]), Math::half_to_float(p_rgb[1]), Math::half_to_float(p_rgb[2]));
|
||||
n.normalize();
|
||||
p_rgb[0] = Math::make_half_float(n.x);
|
||||
p_rgb[1] = Math::make_half_float(n.y);
|
||||
p_rgb[2] = Math::make_half_float(n.z);
|
||||
}
|
||||
|
||||
void Image::renormalize_rgbe9995(uint32_t *p_rgb) {
|
||||
// Never used
|
||||
}
|
||||
|
||||
Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {
|
||||
|
||||
width = 0;
|
||||
|
13
core/image.h
13
core/image.h
@ -127,6 +127,7 @@ public:
|
||||
static ImageMemLoadFunc _webp_mem_loader_func;
|
||||
|
||||
static void (*_image_compress_bc_func)(Image *, CompressSource p_source);
|
||||
static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, CompressSource p_source);
|
||||
static void (*_image_compress_pvrtc2_func)(Image *);
|
||||
static void (*_image_compress_pvrtc4_func)(Image *);
|
||||
static void (*_image_compress_etc1_func)(Image *, float);
|
||||
@ -134,6 +135,7 @@ public:
|
||||
|
||||
static void (*_image_decompress_pvrtc)(Image *);
|
||||
static void (*_image_decompress_bc)(Image *);
|
||||
static void (*_image_decompress_bptc)(Image *);
|
||||
static void (*_image_decompress_etc1)(Image *);
|
||||
static void (*_image_decompress_etc2)(Image *);
|
||||
|
||||
@ -182,6 +184,15 @@ private:
|
||||
|
||||
Error _load_from_buffer(const PoolVector<uint8_t> &p_array, ImageMemLoadFunc p_loader);
|
||||
|
||||
static void average_4_uint8(uint8_t &p_out, const uint8_t &p_a, const uint8_t &p_b, const uint8_t &p_c, const uint8_t &p_d);
|
||||
static void average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d);
|
||||
static void average_4_half(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
|
||||
static void average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint32_t &p_b, const uint32_t &p_c, const uint32_t &p_d);
|
||||
static void renormalize_uint8(uint8_t *p_rgb);
|
||||
static void renormalize_float(float *p_rgb);
|
||||
static void renormalize_half(uint16_t *p_rgb);
|
||||
static void renormalize_rgbe9995(uint32_t *p_rgb);
|
||||
|
||||
public:
|
||||
int get_width() const; ///< Get image width
|
||||
int get_height() const; ///< Get image height
|
||||
@ -282,6 +293,7 @@ public:
|
||||
COMPRESS_PVRTC4,
|
||||
COMPRESS_ETC,
|
||||
COMPRESS_ETC2,
|
||||
COMPRESS_BPTC
|
||||
};
|
||||
|
||||
Error compress(CompressMode p_mode = COMPRESS_S3TC, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7);
|
||||
@ -305,6 +317,7 @@ public:
|
||||
Ref<Image> get_rect(const Rect2 &p_area) const;
|
||||
|
||||
static void set_compress_bc_func(void (*p_compress_func)(Image *, CompressSource));
|
||||
static void set_compress_bptc_func(void (*p_compress_func)(Image *, float, CompressSource));
|
||||
static String get_format_name(Format p_format);
|
||||
|
||||
Error load_png_from_buffer(const PoolVector<uint8_t> &p_array);
|
||||
|
@ -78,7 +78,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
|
||||
if (assign != String()) {
|
||||
if (!path_found && assign.begins_with("path.") && r_path_and_type.path == String()) {
|
||||
String feature = assign.get_slicec('.', 1);
|
||||
if (OS::get_singleton()->has_feature(feature)) {
|
||||
if (feature == "fallback" || OS::get_singleton()->has_feature(feature)) {
|
||||
r_path_and_type.path = value;
|
||||
path_found = true; //first match must have priority
|
||||
}
|
||||
|
@ -61,11 +61,12 @@ void RasterizerStorageGLES2::bind_quad_array() const {
|
||||
glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
|
||||
}
|
||||
|
||||
Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed) {
|
||||
Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed) const {
|
||||
|
||||
r_gl_format = 0;
|
||||
Ref<Image> image = p_image;
|
||||
r_compressed = false;
|
||||
r_real_format = p_format;
|
||||
|
||||
bool need_decompress = false;
|
||||
|
||||
@ -317,6 +318,7 @@ Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_internal_format = GL_RGBA;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_real_format = Image::FORMAT_RGBA8;
|
||||
|
||||
return image;
|
||||
}
|
||||
@ -384,7 +386,8 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
|
||||
} break;
|
||||
}
|
||||
|
||||
_get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, format, internal_format, type, compressed);
|
||||
Image::Format real_format;
|
||||
_get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, format, internal_format, type, compressed);
|
||||
|
||||
texture->alloc_width = texture->width;
|
||||
texture->alloc_height = texture->height;
|
||||
@ -426,7 +429,8 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
|
||||
texture->images.write[p_layer] = p_image;
|
||||
}
|
||||
|
||||
Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, format, internal_format, type, compressed);
|
||||
Image::Format real_format;
|
||||
Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed);
|
||||
|
||||
if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) {
|
||||
|
||||
@ -570,11 +574,19 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer)
|
||||
if (texture->type == VS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && p_layer >= 0 && !texture->images[p_layer].is_null()) {
|
||||
return texture->images[p_layer];
|
||||
}
|
||||
|
||||
#ifdef GLES_OVER_GL
|
||||
|
||||
Image::Format real_format;
|
||||
GLenum gl_format;
|
||||
GLenum gl_internal_format;
|
||||
GLenum gl_type;
|
||||
bool compressed;
|
||||
_get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed);
|
||||
|
||||
PoolVector<uint8_t> data;
|
||||
|
||||
int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->format, texture->mipmaps > 1 ? -1 : 0);
|
||||
int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1 ? -1 : 0);
|
||||
|
||||
data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
|
||||
PoolVector<uint8_t>::Write wb = data.write();
|
||||
@ -591,7 +603,7 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer)
|
||||
|
||||
int ofs = 0;
|
||||
if (i > 0) {
|
||||
ofs = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->format, i - 1);
|
||||
ofs = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, i - 1);
|
||||
}
|
||||
|
||||
if (texture->compressed) {
|
||||
@ -607,7 +619,7 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer)
|
||||
|
||||
data.resize(data_size);
|
||||
|
||||
Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1 ? true : false, texture->format, data));
|
||||
Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1 ? true : false, real_format, data));
|
||||
|
||||
return Ref<Image>(img);
|
||||
#else
|
||||
|
@ -325,7 +325,7 @@ public:
|
||||
|
||||
mutable RID_Owner<Texture> texture_owner;
|
||||
|
||||
Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed);
|
||||
Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed) const;
|
||||
|
||||
virtual RID texture_create();
|
||||
virtual void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VS::TextureType p_type, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT);
|
||||
|
@ -118,10 +118,11 @@ void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat,
|
||||
|
||||
GLuint RasterizerStorageGLES3::system_fbo = 0;
|
||||
|
||||
Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &srgb) {
|
||||
Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &srgb) const {
|
||||
|
||||
r_compressed = false;
|
||||
r_gl_format = 0;
|
||||
r_real_format = p_format;
|
||||
Ref<Image> image = p_image;
|
||||
srgb = false;
|
||||
|
||||
@ -565,6 +566,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
|
||||
r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_compressed = false;
|
||||
r_real_format = Image::FORMAT_RGBA8;
|
||||
srgb = true;
|
||||
|
||||
return image;
|
||||
@ -638,7 +640,8 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_
|
||||
} break;
|
||||
}
|
||||
|
||||
_get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, format, internal_format, type, compressed, srgb);
|
||||
Image::Format real_format;
|
||||
_get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, format, internal_format, type, compressed, srgb);
|
||||
|
||||
texture->alloc_width = texture->width;
|
||||
texture->alloc_height = texture->height;
|
||||
@ -710,7 +713,8 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
|
||||
texture->images.write[p_layer] = p_image;
|
||||
}
|
||||
|
||||
Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, format, internal_format, type, compressed, srgb);
|
||||
Image::Format real_format;
|
||||
Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb);
|
||||
|
||||
if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) {
|
||||
|
||||
@ -941,7 +945,8 @@ void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<I
|
||||
p_sub_img = p_image->get_rect(Rect2(src_x, src_y, src_w, src_h));
|
||||
}
|
||||
|
||||
Ref<Image> img = _get_gl_image_and_format(p_sub_img, p_sub_img->get_format(), texture->flags, format, internal_format, type, compressed, srgb);
|
||||
Image::Format real_format;
|
||||
Ref<Image> img = _get_gl_image_and_format(p_sub_img, p_sub_img->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb);
|
||||
|
||||
GLenum blit_target;
|
||||
|
||||
@ -1014,9 +1019,17 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
|
||||
|
||||
#ifdef GLES_OVER_GL
|
||||
|
||||
Image::Format real_format;
|
||||
GLenum gl_format;
|
||||
GLenum gl_internal_format;
|
||||
GLenum gl_type;
|
||||
bool compressed;
|
||||
bool srgb;
|
||||
_get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb);
|
||||
|
||||
PoolVector<uint8_t> data;
|
||||
|
||||
int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->format, texture->mipmaps > 1 ? -1 : 0);
|
||||
int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1 ? -1 : 0);
|
||||
|
||||
data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
|
||||
PoolVector<uint8_t>::Write wb = data.write();
|
||||
@ -1033,7 +1046,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
|
||||
|
||||
int ofs = 0;
|
||||
if (i > 0) {
|
||||
ofs = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->format, i - 1);
|
||||
ofs = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, i - 1);
|
||||
}
|
||||
|
||||
if (texture->compressed) {
|
||||
@ -1069,7 +1082,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
|
||||
(a | a << 2 | a << 4 | a << 6) << 24;
|
||||
}
|
||||
} else {
|
||||
img_format = texture->format;
|
||||
img_format = real_format;
|
||||
}
|
||||
|
||||
wb = PoolVector<uint8_t>::Write();
|
||||
@ -7368,6 +7381,9 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
|
||||
|
||||
bool RasterizerStorageGLES3::has_os_feature(const String &p_feature) const {
|
||||
|
||||
if (p_feature == "bptc")
|
||||
return config.bptc_supported;
|
||||
|
||||
if (p_feature == "s3tc")
|
||||
return config.s3tc_supported;
|
||||
|
||||
|
@ -340,7 +340,7 @@ public:
|
||||
|
||||
mutable RID_Owner<Texture> texture_owner;
|
||||
|
||||
Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &srgb);
|
||||
Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &srgb) const;
|
||||
|
||||
virtual RID texture_create();
|
||||
virtual void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VS::TextureType p_type, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT);
|
||||
|
@ -661,6 +661,21 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
|
||||
List<String> remaps;
|
||||
config->get_section_keys("remap", &remaps);
|
||||
|
||||
Set<String> remap_features;
|
||||
|
||||
for (List<String>::Element *F = remaps.front(); F; F = F->next()) {
|
||||
|
||||
String remap = F->get();
|
||||
String feature = remap.get_slice(".", 1);
|
||||
if (feature == "fallback" || features.has(feature)) {
|
||||
remap_features.insert(feature);
|
||||
}
|
||||
}
|
||||
|
||||
if (remap_features.size() > 1) {
|
||||
this->resolve_platform_feature_priorities(p_preset, remap_features);
|
||||
}
|
||||
|
||||
for (List<String>::Element *F = remaps.front(); F; F = F->next()) {
|
||||
|
||||
String remap = F->get();
|
||||
@ -670,7 +685,8 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
|
||||
p_func(p_udata, remapped_path, array, idx, total);
|
||||
} else if (remap.begins_with("path.")) {
|
||||
String feature = remap.get_slice(".", 1);
|
||||
if (features.has(feature)) {
|
||||
|
||||
if (remap_features.has(feature)) {
|
||||
String remapped_path = config->get_value("remap", remap);
|
||||
Vector<uint8_t> array = FileAccess::get_file_as_array(remapped_path);
|
||||
p_func(p_udata, remapped_path, array, idx, total);
|
||||
@ -1249,9 +1265,11 @@ void EditorExportPlatformPC::get_preset_features(const Ref<EditorExportPreset> &
|
||||
|
||||
void EditorExportPlatformPC::get_export_options(List<ExportOption> *r_options) {
|
||||
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/bptc"), false));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), true));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), false));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/no_bptc_fallbacks"), true));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "binary_format/64_bits"), true));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE), ""));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE), ""));
|
||||
@ -1434,6 +1452,16 @@ void EditorExportPlatformPC::get_platform_features(List<String> *r_features) {
|
||||
}
|
||||
}
|
||||
|
||||
void EditorExportPlatformPC::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) {
|
||||
|
||||
if (p_features.has("bptc")) {
|
||||
if (p_preset->has("texture_format/no_bptc_fallbacks")) {
|
||||
p_features.erase("s3tc");
|
||||
p_features.erase("fallback");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int EditorExportPlatformPC::get_chmod_flags() const {
|
||||
|
||||
return chmod_flags;
|
||||
|
@ -246,6 +246,7 @@ public:
|
||||
virtual Error export_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
|
||||
virtual Error export_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
|
||||
virtual void get_platform_features(List<String> *r_features) = 0;
|
||||
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) = 0;
|
||||
|
||||
EditorExportPlatform();
|
||||
};
|
||||
@ -403,6 +404,7 @@ public:
|
||||
|
||||
void add_platform_feature(const String &p_feature);
|
||||
virtual void get_platform_features(List<String> *r_features);
|
||||
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features);
|
||||
|
||||
int get_chmod_flags() const;
|
||||
void set_chmod_flags(int p_flags);
|
||||
|
@ -163,6 +163,7 @@ void ResourceImporterLayeredTexture::_save_tex(const Vector<Ref<Image> > &p_imag
|
||||
Error ResourceImporterLayeredTexture::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files) {
|
||||
|
||||
int compress_mode = p_options["compress/mode"];
|
||||
int no_bptc_if_rgb = p_options["compress/no_bptc_if_rgb"];
|
||||
int repeat = p_options["flags/repeat"];
|
||||
bool filter = p_options["flags/filter"];
|
||||
bool mipmaps = p_options["flags/mipmaps"];
|
||||
@ -226,6 +227,26 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const
|
||||
//Android, GLES 2.x
|
||||
|
||||
bool ok_on_pc = false;
|
||||
bool encode_bptc = false;
|
||||
|
||||
if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_bptc")) {
|
||||
|
||||
encode_bptc = true;
|
||||
|
||||
if (no_bptc_if_rgb) {
|
||||
Image::DetectChannels channels = image->get_detected_channels();
|
||||
if (channels != Image::DETECTED_LA && channels != Image::DETECTED_RGBA) {
|
||||
encode_bptc = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (encode_bptc) {
|
||||
|
||||
_save_tex(slices, p_save_path + ".bptc." + extension, compress_mode, Image::COMPRESS_BPTC, mipmaps, tex_flags);
|
||||
r_platform_variants->push_back("bptc");
|
||||
ok_on_pc = true;
|
||||
}
|
||||
|
||||
if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_s3tc")) {
|
||||
|
||||
|
@ -188,7 +188,8 @@ void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options,
|
||||
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Lossless,Lossy,Video RAM,Uncompressed", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), p_preset == PRESET_3D ? 2 : 0));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "compress/lossy_quality", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.7));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/hdr_mode", PROPERTY_HINT_ENUM, "Compress,Force RGBE"), 0));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress/no_bptc_if_rgb"), false));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/hdr_mode", PROPERTY_HINT_ENUM, "LDR Fallback,Force RGBE,RGBE Fallback"), 0));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/normal_map", PROPERTY_HINT_ENUM, "Detect,Enable,Disabled"), 0));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "flags/repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirrored"), p_preset == PRESET_3D ? 1 : 0));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "flags/filter"), p_preset == PRESET_2D_PIXEL ? false : true));
|
||||
@ -347,6 +348,7 @@ void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String
|
||||
Error ResourceImporterTexture::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files) {
|
||||
|
||||
int compress_mode = p_options["compress/mode"];
|
||||
int no_bptc_if_rgb = p_options["compress/no_bptc_if_rgb"];
|
||||
float lossy = p_options["compress/lossy_quality"];
|
||||
int repeat = p_options["flags/repeat"];
|
||||
bool filter = p_options["flags/filter"];
|
||||
@ -359,6 +361,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
|
||||
bool stream = p_options["stream"];
|
||||
int size_limit = p_options["size_limit"];
|
||||
bool force_rgbe = int(p_options["compress/hdr_mode"]) == 1;
|
||||
bool rgbe_fallback = int(p_options["compress/hdr_mode"]) == 2;
|
||||
bool hdr_as_srgb = p_options["process/HDR_as_SRGB"];
|
||||
int normal = p_options["compress/normal_map"];
|
||||
float scale = p_options["svg/scale"];
|
||||
@ -434,31 +437,59 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
|
||||
//Android, GLES 2.x
|
||||
|
||||
bool ok_on_pc = false;
|
||||
bool encode_bptc = false;
|
||||
bool is_hdr = (image->get_format() >= Image::FORMAT_RF && image->get_format() <= Image::FORMAT_RGBE9995);
|
||||
bool no_ldr_compression = (is_hdr && rgbe_fallback);
|
||||
|
||||
if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_s3tc")) {
|
||||
if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_bptc")) {
|
||||
|
||||
encode_bptc = true;
|
||||
|
||||
if (no_bptc_if_rgb && !is_hdr) {
|
||||
Image::DetectChannels channels = image->get_detected_channels();
|
||||
if (channels != Image::DETECTED_LA && channels != Image::DETECTED_RGBA) {
|
||||
encode_bptc = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (encode_bptc) {
|
||||
|
||||
_save_stex(image, p_save_path + ".bptc.stex", compress_mode, lossy, Image::COMPRESS_BPTC, mipmaps, tex_flags, stream, detect_3d, detect_srgb, force_rgbe, detect_normal, force_normal);
|
||||
r_platform_variants->push_back("bptc");
|
||||
ok_on_pc = true;
|
||||
}
|
||||
|
||||
if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_s3tc") && !no_ldr_compression) {
|
||||
|
||||
_save_stex(image, p_save_path + ".s3tc.stex", compress_mode, lossy, Image::COMPRESS_S3TC, mipmaps, tex_flags, stream, detect_3d, detect_srgb, force_rgbe, detect_normal, force_normal);
|
||||
r_platform_variants->push_back("s3tc");
|
||||
ok_on_pc = true;
|
||||
}
|
||||
|
||||
if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc2")) {
|
||||
if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc2") && !no_ldr_compression) {
|
||||
|
||||
_save_stex(image, p_save_path + ".etc2.stex", compress_mode, lossy, Image::COMPRESS_ETC2, mipmaps, tex_flags, stream, detect_3d, detect_srgb, force_rgbe, detect_normal, force_normal);
|
||||
r_platform_variants->push_back("etc2");
|
||||
}
|
||||
|
||||
if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc")) {
|
||||
if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc") && !no_ldr_compression) {
|
||||
_save_stex(image, p_save_path + ".etc.stex", compress_mode, lossy, Image::COMPRESS_ETC, mipmaps, tex_flags, stream, detect_3d, detect_srgb, force_rgbe, detect_normal, force_normal);
|
||||
r_platform_variants->push_back("etc");
|
||||
}
|
||||
|
||||
if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_pvrtc")) {
|
||||
if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_pvrtc") && !no_ldr_compression) {
|
||||
|
||||
_save_stex(image, p_save_path + ".pvrtc.stex", compress_mode, lossy, Image::COMPRESS_PVRTC4, mipmaps, tex_flags, stream, detect_3d, detect_srgb, force_rgbe, detect_normal, force_normal);
|
||||
r_platform_variants->push_back("pvrtc");
|
||||
}
|
||||
|
||||
if (is_hdr && rgbe_fallback) {
|
||||
_save_stex(image, p_save_path + ".fallback.stex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, tex_flags, stream, detect_3d, detect_srgb, true, detect_normal, force_normal);
|
||||
r_platform_variants->push_back("fallback");
|
||||
ok_on_pc = true;
|
||||
}
|
||||
|
||||
if (!ok_on_pc) {
|
||||
EditorNode::add_io_error("Warning, no suitable PC VRAM compression enabled in Project Settings. This texture will not display correcly on PC.");
|
||||
}
|
||||
|
@ -1007,6 +1007,7 @@ void ProjectSettingsEditor::_copy_to_platform_about_to_show() {
|
||||
|
||||
Set<String> presets;
|
||||
|
||||
presets.insert("bptc");
|
||||
presets.insert("s3tc");
|
||||
presets.insert("etc");
|
||||
presets.insert("etc2");
|
||||
|
21
modules/cvtt/SCsub
Normal file
21
modules/cvtt/SCsub
Normal file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import('env')
|
||||
Import('env_modules')
|
||||
|
||||
env_cvtt = env_modules.Clone()
|
||||
|
||||
# Thirdparty source files
|
||||
if env['builtin_squish']:
|
||||
thirdparty_dir = "#thirdparty/cvtt/"
|
||||
thirdparty_sources = [
|
||||
"ConvectionKernels.cpp"
|
||||
]
|
||||
|
||||
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
|
||||
|
||||
env_cvtt.add_source_files(env.modules_sources, thirdparty_sources)
|
||||
env_cvtt.Append(CPPPATH=[thirdparty_dir])
|
||||
|
||||
# Godot source files
|
||||
env_cvtt.add_source_files(env.modules_sources, "*.cpp")
|
5
modules/cvtt/config.py
Normal file
5
modules/cvtt/config.py
Normal file
@ -0,0 +1,5 @@
|
||||
def can_build(env, platform):
|
||||
return env['tools']
|
||||
|
||||
def configure(env):
|
||||
pass
|
300
modules/cvtt/image_compress_cvtt.cpp
Normal file
300
modules/cvtt/image_compress_cvtt.cpp
Normal file
@ -0,0 +1,300 @@
|
||||
/*************************************************************************/
|
||||
/* image_compress_cvtt.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "image_compress_cvtt.h"
|
||||
|
||||
#include "print_string.h"
|
||||
|
||||
#include <ConvectionKernels.h>
|
||||
|
||||
void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::CompressSource p_source) {
|
||||
|
||||
if (p_image->get_format() >= Image::FORMAT_BPTC_RGBA)
|
||||
return; //do not compress, already compressed
|
||||
|
||||
int w = p_image->get_width();
|
||||
int h = p_image->get_height();
|
||||
|
||||
bool is_ldr = (p_image->get_format() <= Image::FORMAT_RGBA8);
|
||||
bool is_hdr = (p_image->get_format() == Image::FORMAT_RGBH);
|
||||
|
||||
if (!is_ldr && !is_hdr) {
|
||||
return; // Not a usable source format
|
||||
}
|
||||
|
||||
cvtt::Options options;
|
||||
uint32_t flags = cvtt::Flags::Fastest;
|
||||
|
||||
if (p_lossy_quality > 0.85)
|
||||
flags = cvtt::Flags::Ultra;
|
||||
else if (p_lossy_quality > 0.75)
|
||||
flags = cvtt::Flags::Better;
|
||||
else if (p_lossy_quality > 0.55)
|
||||
flags = cvtt::Flags::Default;
|
||||
else if (p_lossy_quality > 0.35)
|
||||
flags = cvtt::Flags::Fast;
|
||||
else if (p_lossy_quality > 0.15)
|
||||
flags = cvtt::Flags::Faster;
|
||||
|
||||
flags |= cvtt::Flags::BC7_RespectPunchThrough;
|
||||
|
||||
if (p_source == Image::COMPRESS_SOURCE_NORMAL) {
|
||||
flags |= cvtt::Flags::Uniform;
|
||||
}
|
||||
|
||||
Image::Format target_format = Image::FORMAT_BPTC_RGBA;
|
||||
|
||||
bool is_signed = false;
|
||||
if (is_hdr) {
|
||||
PoolVector<uint8_t>::Read rb = p_image->get_data().read();
|
||||
|
||||
const uint16_t *source_data = reinterpret_cast<const uint16_t *>(&rb[0]);
|
||||
int pixel_element_count = w * h * 3;
|
||||
for (int i = 0; i < pixel_element_count; i++) {
|
||||
if ((source_data[i] & 0x8000) != 0 && (source_data[i] & 0x7fff) != 0) {
|
||||
is_signed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
target_format = is_signed ? Image::FORMAT_BPTC_RGBF : Image::FORMAT_BPTC_RGBFU;
|
||||
} else {
|
||||
p_image->convert(Image::FORMAT_RGBA8); //still uses RGBA to convert
|
||||
}
|
||||
|
||||
PoolVector<uint8_t>::Read rb = p_image->get_data().read();
|
||||
|
||||
PoolVector<uint8_t> data;
|
||||
int target_size = Image::get_image_data_size(w, h, target_format, p_image->has_mipmaps());
|
||||
int mm_count = p_image->has_mipmaps() ? Image::get_image_required_mipmaps(w, h, target_format) : 0;
|
||||
data.resize(target_size);
|
||||
int shift = Image::get_format_pixel_rshift(target_format);
|
||||
|
||||
PoolVector<uint8_t>::Write wb = data.write();
|
||||
|
||||
int dst_ofs = 0;
|
||||
|
||||
for (int i = 0; i <= mm_count; i++) {
|
||||
|
||||
int bw = w % 4 != 0 ? w + (4 - w % 4) : w;
|
||||
int bh = h % 4 != 0 ? h + (4 - h % 4) : h;
|
||||
|
||||
int src_ofs = p_image->get_mipmap_offset(i);
|
||||
|
||||
const uint8_t *in_bytes = &rb[src_ofs];
|
||||
uint8_t *out_bytes = &wb[dst_ofs];
|
||||
|
||||
cvtt::PixelBlockU8 input_blocks_ldr[cvtt::NumParallelBlocks];
|
||||
cvtt::PixelBlockF16 input_blocks_hdr[cvtt::NumParallelBlocks];
|
||||
|
||||
int bytes_per_pixel = is_hdr ? 6 : 4;
|
||||
|
||||
for (int y_start = 0; y_start < h; y_start += 4) {
|
||||
int y_end = y_start + 4;
|
||||
|
||||
for (int x_start = 0; x_start < w; x_start += 4 * cvtt::NumParallelBlocks) {
|
||||
int x_end = x_start + 4 * cvtt::NumParallelBlocks;
|
||||
|
||||
for (int y = y_start; y < y_end; y++) {
|
||||
int first_input_element = (y - y_start) * 4;
|
||||
const uint8_t *row_start;
|
||||
if (y >= h) {
|
||||
row_start = in_bytes + (h - 1) * (w * bytes_per_pixel);
|
||||
} else {
|
||||
row_start = in_bytes + y * (w * bytes_per_pixel);
|
||||
}
|
||||
|
||||
for (int x = x_start; x < x_end; x++) {
|
||||
const uint8_t *pixel_start;
|
||||
if (x >= w) {
|
||||
pixel_start = row_start + (w - 1) * bytes_per_pixel;
|
||||
} else {
|
||||
pixel_start = row_start + x * bytes_per_pixel;
|
||||
}
|
||||
|
||||
int block_index = (x - x_start) / 4;
|
||||
int block_element = (x - x_start) % 4 + first_input_element;
|
||||
if (is_hdr) {
|
||||
memcpy(input_blocks_hdr[block_index].m_pixels[block_element], pixel_start, bytes_per_pixel);
|
||||
input_blocks_hdr[block_index].m_pixels[block_element][3] = 0x3c00; // 1.0 (unused)
|
||||
} else {
|
||||
memcpy(input_blocks_ldr[block_index].m_pixels[block_element], pixel_start, bytes_per_pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t output_blocks[16 * cvtt::NumParallelBlocks];
|
||||
|
||||
if (is_hdr) {
|
||||
if (is_signed) {
|
||||
cvtt::Kernels::EncodeBC6HS(output_blocks, input_blocks_hdr, options);
|
||||
} else {
|
||||
cvtt::Kernels::EncodeBC6HU(output_blocks, input_blocks_hdr, options);
|
||||
}
|
||||
} else {
|
||||
cvtt::Kernels::EncodeBC7(output_blocks, input_blocks_ldr, options);
|
||||
}
|
||||
|
||||
int num_real_blocks = ((w - x_start) + 3) / 4;
|
||||
if (num_real_blocks > cvtt::NumParallelBlocks) {
|
||||
num_real_blocks = cvtt::NumParallelBlocks;
|
||||
}
|
||||
|
||||
memcpy(out_bytes, output_blocks, 16 * num_real_blocks);
|
||||
out_bytes += 16 * num_real_blocks;
|
||||
}
|
||||
}
|
||||
|
||||
dst_ofs += (MAX(4, bw) * MAX(4, bh)) >> shift;
|
||||
w >>= 1;
|
||||
h >>= 1;
|
||||
}
|
||||
|
||||
rb = PoolVector<uint8_t>::Read();
|
||||
wb = PoolVector<uint8_t>::Write();
|
||||
|
||||
p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
|
||||
}
|
||||
|
||||
void image_decompress_cvtt(Image *p_image) {
|
||||
|
||||
Image::Format target_format;
|
||||
bool is_signed = false;
|
||||
bool is_hdr = false;
|
||||
|
||||
Image::Format input_format = p_image->get_format();
|
||||
|
||||
switch (input_format) {
|
||||
case Image::FORMAT_BPTC_RGBA:
|
||||
target_format = Image::FORMAT_RGBA8;
|
||||
break;
|
||||
case Image::FORMAT_BPTC_RGBF:
|
||||
case Image::FORMAT_BPTC_RGBFU:
|
||||
target_format = Image::FORMAT_RGBH;
|
||||
is_signed = (input_format == Image::FORMAT_BPTC_RGBF);
|
||||
is_hdr = true;
|
||||
break;
|
||||
default:
|
||||
return; // Invalid input format
|
||||
};
|
||||
|
||||
int w = p_image->get_width();
|
||||
int h = p_image->get_height();
|
||||
|
||||
PoolVector<uint8_t>::Read rb = p_image->get_data().read();
|
||||
|
||||
PoolVector<uint8_t> data;
|
||||
int target_size = Image::get_image_data_size(w, h, target_format, p_image->has_mipmaps());
|
||||
int mm_count = p_image->get_mipmap_count();
|
||||
data.resize(target_size);
|
||||
int shift = Image::get_format_pixel_rshift(target_format);
|
||||
|
||||
PoolVector<uint8_t>::Write wb = data.write();
|
||||
|
||||
int bytes_per_pixel = is_hdr ? 6 : 4;
|
||||
|
||||
int dst_ofs = 0;
|
||||
|
||||
for (int i = 0; i <= mm_count; i++) {
|
||||
|
||||
int src_ofs = p_image->get_mipmap_offset(i);
|
||||
|
||||
const uint8_t *in_bytes = &rb[src_ofs];
|
||||
uint8_t *out_bytes = &wb[dst_ofs];
|
||||
|
||||
cvtt::PixelBlockU8 output_blocks_ldr[cvtt::NumParallelBlocks];
|
||||
cvtt::PixelBlockF16 output_blocks_hdr[cvtt::NumParallelBlocks];
|
||||
|
||||
for (int y_start = 0; y_start < h; y_start += 4) {
|
||||
int y_end = y_start + 4;
|
||||
|
||||
for (int x_start = 0; x_start < w; x_start += 4 * cvtt::NumParallelBlocks) {
|
||||
int x_end = x_start + 4 * cvtt::NumParallelBlocks;
|
||||
|
||||
uint8_t input_blocks[16 * cvtt::NumParallelBlocks];
|
||||
memset(input_blocks, 0, sizeof(input_blocks));
|
||||
|
||||
int num_real_blocks = ((w - x_start) + 3) / 4;
|
||||
if (num_real_blocks > cvtt::NumParallelBlocks) {
|
||||
num_real_blocks = cvtt::NumParallelBlocks;
|
||||
}
|
||||
|
||||
memcpy(input_blocks, in_bytes, 16 * num_real_blocks);
|
||||
in_bytes += 16 * num_real_blocks;
|
||||
|
||||
if (is_hdr) {
|
||||
if (is_signed) {
|
||||
cvtt::Kernels::DecodeBC6HS(output_blocks_hdr, input_blocks);
|
||||
} else {
|
||||
cvtt::Kernels::DecodeBC6HU(output_blocks_hdr, input_blocks);
|
||||
}
|
||||
} else {
|
||||
cvtt::Kernels::DecodeBC7(output_blocks_ldr, input_blocks);
|
||||
}
|
||||
|
||||
for (int y = y_start; y < y_end; y++) {
|
||||
int first_input_element = (y - y_start) * 4;
|
||||
uint8_t *row_start;
|
||||
if (y >= h) {
|
||||
row_start = out_bytes + (h - 1) * (w * bytes_per_pixel);
|
||||
} else {
|
||||
row_start = out_bytes + y * (w * bytes_per_pixel);
|
||||
}
|
||||
|
||||
for (int x = x_start; x < x_end; x++) {
|
||||
uint8_t *pixel_start;
|
||||
if (x >= w) {
|
||||
pixel_start = row_start + (w - 1) * bytes_per_pixel;
|
||||
} else {
|
||||
pixel_start = row_start + x * bytes_per_pixel;
|
||||
}
|
||||
|
||||
int block_index = (x - x_start) / 4;
|
||||
int block_element = (x - x_start) % 4 + first_input_element;
|
||||
if (is_hdr) {
|
||||
memcpy(pixel_start, output_blocks_hdr[block_index].m_pixels[block_element], bytes_per_pixel);
|
||||
} else {
|
||||
memcpy(pixel_start, output_blocks_ldr[block_index].m_pixels[block_element], bytes_per_pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dst_ofs += w * h * bytes_per_pixel;
|
||||
w >>= 1;
|
||||
h >>= 1;
|
||||
}
|
||||
|
||||
rb = PoolVector<uint8_t>::Read();
|
||||
wb = PoolVector<uint8_t>::Write();
|
||||
|
||||
p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
|
||||
}
|
39
modules/cvtt/image_compress_cvtt.h
Normal file
39
modules/cvtt/image_compress_cvtt.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*************************************************************************/
|
||||
/* image_compress_cvtt.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef IMAGE_COMPRESS_CVTT_H
|
||||
#define IMAGE_COMPRESS_CVTT_H
|
||||
|
||||
#include "image.h"
|
||||
|
||||
void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::CompressSource p_source);
|
||||
void image_decompress_cvtt(Image *p_image);
|
||||
|
||||
#endif // IMAGE_COMPRESS_CVTT_H
|
45
modules/cvtt/register_types.cpp
Normal file
45
modules/cvtt/register_types.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*************************************************************************/
|
||||
/* register_types.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "register_types.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
#include "image_compress_cvtt.h"
|
||||
|
||||
void register_cvtt_types() {
|
||||
|
||||
Image::set_compress_bptc_func(image_compress_cvtt);
|
||||
Image::_image_decompress_bptc = image_decompress_cvtt;
|
||||
}
|
||||
|
||||
void unregister_cvtt_types() {}
|
||||
|
||||
#endif
|
34
modules/cvtt/register_types.h
Normal file
34
modules/cvtt/register_types.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*************************************************************************/
|
||||
/* register_types.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
void register_cvtt_types();
|
||||
void unregister_cvtt_types();
|
||||
#endif
|
@ -1860,6 +1860,9 @@ public:
|
||||
r_features->push_back("Android");
|
||||
}
|
||||
|
||||
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) {
|
||||
}
|
||||
|
||||
EditorExportAndroid() {
|
||||
|
||||
Ref<Image> img = memnew(Image(_android_logo));
|
||||
|
@ -119,6 +119,9 @@ public:
|
||||
r_features->push_back("iOS");
|
||||
}
|
||||
|
||||
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) {
|
||||
}
|
||||
|
||||
EditorExportPlatformIOS();
|
||||
~EditorExportPlatformIOS();
|
||||
};
|
||||
|
@ -74,6 +74,9 @@ public:
|
||||
r_features->push_back(get_os_name());
|
||||
}
|
||||
|
||||
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) {
|
||||
}
|
||||
|
||||
EditorExportPlatformJavaScript();
|
||||
};
|
||||
|
||||
|
@ -86,6 +86,9 @@ public:
|
||||
r_features->push_back("OSX");
|
||||
}
|
||||
|
||||
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) {
|
||||
}
|
||||
|
||||
EditorExportPlatformOSX();
|
||||
~EditorExportPlatformOSX();
|
||||
};
|
||||
|
@ -1454,6 +1454,9 @@ public:
|
||||
r_features->push_back("UWP");
|
||||
}
|
||||
|
||||
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) {
|
||||
}
|
||||
|
||||
EditorExportUWP() {
|
||||
Ref<Image> img = memnew(Image(_uwp_logo));
|
||||
logo.instance();
|
||||
|
@ -2805,7 +2805,7 @@ int OS_Windows::get_power_percent_left() {
|
||||
|
||||
bool OS_Windows::_check_internal_feature_support(const String &p_feature) {
|
||||
|
||||
return p_feature == "pc" || p_feature == "s3tc";
|
||||
return p_feature == "pc" || p_feature == "s3tc" || p_feature == "bptc";
|
||||
}
|
||||
|
||||
void OS_Windows::disable_crash_handler() {
|
||||
|
@ -2344,7 +2344,7 @@ Error OS_X11::shell_open(String p_uri) {
|
||||
|
||||
bool OS_X11::_check_internal_feature_support(const String &p_feature) {
|
||||
|
||||
return p_feature == "pc" || p_feature == "s3tc";
|
||||
return p_feature == "pc" || p_feature == "s3tc" || p_feature == "bptc";
|
||||
}
|
||||
|
||||
String OS_X11::get_config_path() const {
|
||||
|
@ -2361,6 +2361,7 @@ VisualServer::VisualServer() {
|
||||
//ERR_FAIL_COND(singleton);
|
||||
singleton = this;
|
||||
|
||||
GLOBAL_DEF("rendering/vram_compression/import_bptc", false);
|
||||
GLOBAL_DEF("rendering/vram_compression/import_s3tc", true);
|
||||
GLOBAL_DEF("rendering/vram_compression/import_etc", false);
|
||||
GLOBAL_DEF("rendering/vram_compression/import_etc2", true);
|
||||
|
11
thirdparty/README.md
vendored
11
thirdparty/README.md
vendored
@ -40,6 +40,17 @@ File extracted from a recent Fedora install:
|
||||
as it's generated on the user's system.)
|
||||
|
||||
|
||||
## cvtt
|
||||
|
||||
- Upstream: https://github.com/elasota/cvtt
|
||||
- Version: 1.0.0-beta4
|
||||
- License: MIT
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
||||
- all .cpp, .h, and .txt files in ConvectionKernels/
|
||||
|
||||
|
||||
## enet
|
||||
|
||||
- Upstream: http://enet.bespin.org
|
||||
|
7576
thirdparty/cvtt/ConvectionKernels.cpp
vendored
Normal file
7576
thirdparty/cvtt/ConvectionKernels.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
145
thirdparty/cvtt/ConvectionKernels.h
vendored
Normal file
145
thirdparty/cvtt/ConvectionKernels.h
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
Convection Texture Tools
|
||||
Copyright (c) 2018 Eric Lasota
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject
|
||||
to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef __CVTT_CONVECTION_KERNELS__
|
||||
#define __CVTT_CONVECTION_KERNELS__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace cvtt
|
||||
{
|
||||
namespace Flags
|
||||
{
|
||||
// Enable partitioned modes in BC7 encoding (slower, better quality)
|
||||
const uint32_t BC7_EnablePartitioning = 0x001;
|
||||
|
||||
// Enable 3-partition modes in BC7 encoding (slower, better quality, requires BC7_EnablePartitioning)
|
||||
const uint32_t BC7_Enable3Subsets = 0x002;
|
||||
|
||||
// Enable dual-plane modes in BC7 encoding (slower, better quality)
|
||||
const uint32_t BC7_EnableDualPlane = 0x004;
|
||||
|
||||
// Use fast indexing in BC7 encoding (about 2x faster, slightly worse quality)
|
||||
const uint32_t BC7_FastIndexing = 0x008;
|
||||
|
||||
// Try precomputed single-color lookups where applicable (slightly slower, small quality increase on specific blocks)
|
||||
const uint32_t BC7_TrySingleColor = 0x010;
|
||||
|
||||
// Don't allow non-zero or non-max alpha values in blocks that only contain one or the other
|
||||
const uint32_t BC7_RespectPunchThrough = 0x020;
|
||||
|
||||
// Use fast indexing in HDR formats (faster, worse quality)
|
||||
const uint32_t BC6H_FastIndexing = 0x040;
|
||||
|
||||
// Exhaustive search RGB orderings when encoding BC1-BC3 (much slower, better quality)
|
||||
const uint32_t S3TC_Exhaustive = 0x080;
|
||||
|
||||
// Penalize distant endpoints, improving quality on inaccurate GPU decoders
|
||||
const uint32_t S3TC_Paranoid = 0x100;
|
||||
|
||||
// Uniform color channel importance
|
||||
const uint32_t Uniform = 0x200;
|
||||
|
||||
// Misc useful default flag combinations
|
||||
const uint32_t Fastest = (BC6H_FastIndexing | S3TC_Paranoid);
|
||||
const uint32_t Faster = (BC7_EnableDualPlane | BC6H_FastIndexing | S3TC_Paranoid);
|
||||
const uint32_t Fast = (BC7_EnablePartitioning | BC7_EnableDualPlane | BC7_FastIndexing | S3TC_Paranoid);
|
||||
const uint32_t Default = (BC7_EnablePartitioning | BC7_EnableDualPlane | BC7_Enable3Subsets | BC7_FastIndexing | S3TC_Paranoid);
|
||||
const uint32_t Better = (BC7_EnablePartitioning | BC7_EnableDualPlane | BC7_Enable3Subsets | S3TC_Paranoid | S3TC_Exhaustive);
|
||||
const uint32_t Ultra = (BC7_EnablePartitioning | BC7_EnableDualPlane | BC7_Enable3Subsets | BC7_TrySingleColor | S3TC_Paranoid | S3TC_Exhaustive);
|
||||
}
|
||||
|
||||
const unsigned int NumParallelBlocks = 8;
|
||||
|
||||
struct Options
|
||||
{
|
||||
uint32_t flags; // Bitmask of cvtt::Flags values
|
||||
float threshold; // Alpha test threshold for BC1
|
||||
float redWeight; // Red channel importance
|
||||
float greenWeight; // Green channel importance
|
||||
float blueWeight; // Blue channel importance
|
||||
float alphaWeight; // Alpha channel importance
|
||||
|
||||
int refineRoundsBC7; // Number of refine rounds for BC7
|
||||
int refineRoundsBC6H; // Number of refine rounds for BC6H (max 3)
|
||||
int refineRoundsIIC; // Number of refine rounds for independent interpolated channels (BC3 alpha, BC4, BC5)
|
||||
int refineRoundsS3TC; // Number of refine rounds for S3TC RGB
|
||||
|
||||
int seedPoints; // Number of seed points (min 1, max 4)
|
||||
|
||||
Options()
|
||||
: flags(Flags::Default)
|
||||
, threshold(0.5f)
|
||||
, redWeight(0.2125f / 0.7154f)
|
||||
, greenWeight(1.0f)
|
||||
, blueWeight(0.0721f / 0.7154f)
|
||||
, alphaWeight(1.0f)
|
||||
, refineRoundsBC7(2)
|
||||
, refineRoundsBC6H(3)
|
||||
, refineRoundsIIC(8)
|
||||
, refineRoundsS3TC(2)
|
||||
, seedPoints(4)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// RGBA input block for unsigned 8-bit formats
|
||||
struct PixelBlockU8
|
||||
{
|
||||
uint8_t m_pixels[16][4];
|
||||
};
|
||||
|
||||
// RGBA input block for signed 8-bit formats
|
||||
struct PixelBlockS8
|
||||
{
|
||||
int8_t m_pixels[16][4];
|
||||
};
|
||||
|
||||
// RGBA input block for half-precision float formats (bit-cast to int16_t)
|
||||
struct PixelBlockF16
|
||||
{
|
||||
int16_t m_pixels[16][4];
|
||||
};
|
||||
|
||||
namespace Kernels
|
||||
{
|
||||
// NOTE: All functions accept and output NumParallelBlocks blocks at once
|
||||
void EncodeBC1(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options);
|
||||
void EncodeBC2(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options);
|
||||
void EncodeBC3(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options);
|
||||
void EncodeBC4U(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options);
|
||||
void EncodeBC4S(uint8_t *pBC, const PixelBlockS8 *pBlocks, const Options &options);
|
||||
void EncodeBC5U(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options);
|
||||
void EncodeBC5S(uint8_t *pBC, const PixelBlockS8 *pBlocks, const Options &options);
|
||||
void EncodeBC6HU(uint8_t *pBC, const PixelBlockF16 *pBlocks, const Options &options);
|
||||
void EncodeBC6HS(uint8_t *pBC, const PixelBlockF16 *pBlocks, const Options &options);
|
||||
void EncodeBC7(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options);
|
||||
|
||||
void DecodeBC6HU(PixelBlockF16 *pBlocks, const uint8_t *pBC);
|
||||
void DecodeBC6HS(PixelBlockF16 *pBlocks, const uint8_t *pBC);
|
||||
void DecodeBC7(PixelBlockU8 *pBlocks, const uint8_t *pBC);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
1940
thirdparty/cvtt/ConvectionKernels_BC7_SingleColor.h
vendored
Normal file
1940
thirdparty/cvtt/ConvectionKernels_BC7_SingleColor.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
45
thirdparty/cvtt/LICENSE.txt
vendored
Normal file
45
thirdparty/cvtt/LICENSE.txt
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
Convection Texture Tools Stand-Alone Kernels
|
||||
|
||||
Copyright (c) 2018 Eric Lasota
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject
|
||||
to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
**************************************************************************
|
||||
|
||||
Based on DirectX Texture Library
|
||||
|
||||
Copyright (c) 2018 Microsoft Corp
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies
|
||||
or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
Loading…
Reference in New Issue
Block a user