GLTF: dupe images during serialization to prevent segfaults
This commit is contained in:
@@ -2053,10 +2053,18 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> p_state) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
static inline Ref<Image> _duplicate_and_decompress_image(const Ref<Image> &p_image) {
|
||||
Ref<Image> img = p_image->duplicate();
|
||||
if (img->is_compressed()) {
|
||||
img->decompress();
|
||||
}
|
||||
return img;
|
||||
}
|
||||
|
||||
Dictionary GLTFDocument::_serialize_image(Ref<GLTFState> p_state, Ref<Image> p_image, const String &p_image_format, float p_lossy_quality, Ref<GLTFDocumentExtension> p_image_save_extension) {
|
||||
Dictionary image_dict;
|
||||
if (p_image->is_compressed()) {
|
||||
p_image->decompress();
|
||||
p_image = _duplicate_and_decompress_image(p_image);
|
||||
ERR_FAIL_COND_V_MSG(p_image->is_compressed(), image_dict, "glTF: Image was compressed, but could not be decompressed.");
|
||||
}
|
||||
|
||||
@@ -2707,10 +2715,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
|
||||
if (has_ao) {
|
||||
height = ao_texture->get_height();
|
||||
width = ao_texture->get_width();
|
||||
ao_image = ao_texture->get_image();
|
||||
if (ao_image->is_compressed()) {
|
||||
ao_image->decompress();
|
||||
}
|
||||
ao_image = _duplicate_and_decompress_image(ao_texture->get_image());
|
||||
if (!ao_texture->get_path().is_empty()) {
|
||||
common_paths.insert(ao_texture->get_path());
|
||||
}
|
||||
@@ -2719,10 +2724,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
|
||||
if (has_roughness) {
|
||||
height = roughness_texture->get_height();
|
||||
width = roughness_texture->get_width();
|
||||
roughness_image = roughness_texture->get_image();
|
||||
if (roughness_image->is_compressed()) {
|
||||
roughness_image->decompress();
|
||||
}
|
||||
roughness_image = _duplicate_and_decompress_image(roughness_texture->get_image());
|
||||
if (!roughness_texture->get_path().is_empty()) {
|
||||
common_paths.insert(roughness_texture->get_path());
|
||||
}
|
||||
@@ -2731,10 +2733,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
|
||||
if (has_metalness) {
|
||||
height = metallic_texture->get_height();
|
||||
width = metallic_texture->get_width();
|
||||
metallness_image = metallic_texture->get_image();
|
||||
if (metallness_image->is_compressed()) {
|
||||
metallness_image->decompress();
|
||||
}
|
||||
metallness_image = _duplicate_and_decompress_image(metallic_texture->get_image());
|
||||
if (!metallic_texture->get_path().is_empty()) {
|
||||
common_paths.insert(metallic_texture->get_path());
|
||||
}
|
||||
@@ -2805,9 +2804,6 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
|
||||
has_ao = true;
|
||||
has_roughness = true;
|
||||
has_metalness = true;
|
||||
Ref<Image> orm_image = original_orm_tex->get_image();
|
||||
orm_image->decompress();
|
||||
orm_image->convert(Image::FORMAT_RGBA8);
|
||||
|
||||
_set_material_texture_name(original_orm_tex, original_orm_tex->get_path(), mat_name, "_orm");
|
||||
orm_texture_index = _set_texture(p_state, original_orm_tex, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
|
||||
@@ -2839,26 +2835,23 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
|
||||
String path;
|
||||
{
|
||||
Ref<Texture2D> normal_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_NORMAL);
|
||||
if (normal_texture.is_valid()) {
|
||||
if (normal_texture.is_valid() && normal_texture->get_image().is_valid()) {
|
||||
path = normal_texture->get_path();
|
||||
// Code for uncompressing RG normal maps
|
||||
Ref<Image> img = normal_texture->get_image();
|
||||
if (img.is_valid()) {
|
||||
img->decompress();
|
||||
img->convert(Image::FORMAT_RGBA8);
|
||||
for (int32_t y = 0; y < img->get_height(); y++) {
|
||||
for (int32_t x = 0; x < img->get_width(); x++) {
|
||||
Color c = img->get_pixel(x, y);
|
||||
Vector2 red_green = Vector2(c.r, c.g);
|
||||
red_green = red_green * Vector2(2.0f, 2.0f) - Vector2(1.0f, 1.0f);
|
||||
float blue = 1.0f - red_green.dot(red_green);
|
||||
blue = MAX(0.0f, blue);
|
||||
c.b = Math::sqrt(blue);
|
||||
img->set_pixel(x, y, c);
|
||||
}
|
||||
Ref<Image> img = _duplicate_and_decompress_image(normal_texture->get_image());
|
||||
img->convert(Image::FORMAT_RGBA8);
|
||||
for (int32_t y = 0; y < img->get_height(); y++) {
|
||||
for (int32_t x = 0; x < img->get_width(); x++) {
|
||||
Color c = img->get_pixel(x, y);
|
||||
Vector2 red_green = Vector2(c.r, c.g);
|
||||
red_green = red_green * Vector2(2.0f, 2.0f) - Vector2(1.0f, 1.0f);
|
||||
float blue = 1.0f - red_green.dot(red_green);
|
||||
blue = MAX(0.0f, blue);
|
||||
c.b = Math::sqrt(blue);
|
||||
img->set_pixel(x, y, c);
|
||||
}
|
||||
tex->set_image(img);
|
||||
}
|
||||
tex->set_image(img);
|
||||
}
|
||||
}
|
||||
GLTFTextureIndex gltf_texture_index = -1;
|
||||
|
||||
Reference in New Issue
Block a user