|
|
@@ -97,11 +97,16 @@ Array LightmapGIData::_get_user_data() const {
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-void LightmapGIData::_set_light_textures_data(const Array &p_data) {
|
|
|
- ERR_FAIL_COND(p_data.is_empty());
|
|
|
+void LightmapGIData::set_lightmap_textures(const TypedArray<TextureLayered> &p_data) {
|
|
|
+ light_textures = p_data;
|
|
|
+ if (p_data.is_empty()) {
|
|
|
+ light_texture = Ref<TextureLayered>();
|
|
|
+ _reset_lightmap_textures();
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
if (p_data.size() == 1) {
|
|
|
- set_light_texture(p_data[0]);
|
|
|
+ light_texture = p_data[0];
|
|
|
} else {
|
|
|
Vector<Ref<Image>> images;
|
|
|
for (int i = 0; i < p_data.size(); i++) {
|
|
|
@@ -116,73 +121,13 @@ void LightmapGIData::_set_light_textures_data(const Array &p_data) {
|
|
|
combined_texture.instantiate();
|
|
|
|
|
|
combined_texture->create_from_images(images);
|
|
|
- set_light_texture(combined_texture);
|
|
|
+ light_texture = combined_texture;
|
|
|
}
|
|
|
+ _reset_lightmap_textures();
|
|
|
}
|
|
|
|
|
|
-Array LightmapGIData::_get_light_textures_data() const {
|
|
|
- Array ret;
|
|
|
- if (light_texture.is_null() || light_texture->get_layers() == 0) {
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
- Vector<Ref<Image>> images;
|
|
|
- for (int i = 0; i < light_texture->get_layers(); i++) {
|
|
|
- images.push_back(light_texture->get_layer_data(i));
|
|
|
- }
|
|
|
-
|
|
|
- int slice_count = images.size();
|
|
|
- int slice_width = images[0]->get_width();
|
|
|
- int slice_height = images[0]->get_height();
|
|
|
-
|
|
|
- int slices_per_texture = Image::MAX_HEIGHT / slice_height;
|
|
|
- int texture_count = Math::ceil(slice_count / (float)slices_per_texture);
|
|
|
-
|
|
|
- ret.resize(texture_count);
|
|
|
-
|
|
|
- String base_name = get_path().get_basename();
|
|
|
-
|
|
|
- int last_count = slice_count % slices_per_texture;
|
|
|
- for (int i = 0; i < texture_count; i++) {
|
|
|
- int texture_slice_count = (i == texture_count - 1 && last_count != 0) ? last_count : slices_per_texture;
|
|
|
-
|
|
|
- Ref<Image> texture_image = Image::create_empty(slice_width, slice_height * texture_slice_count, false, images[0]->get_format());
|
|
|
-
|
|
|
- for (int j = 0; j < texture_slice_count; j++) {
|
|
|
- texture_image->blit_rect(images[i * slices_per_texture + j], Rect2i(0, 0, slice_width, slice_height), Point2i(0, slice_height * j));
|
|
|
- }
|
|
|
-
|
|
|
- String texture_path = texture_count > 1 ? base_name + "_" + itos(i) + ".exr" : base_name + ".exr";
|
|
|
-
|
|
|
- Ref<ConfigFile> config;
|
|
|
- config.instantiate();
|
|
|
-
|
|
|
- if (FileAccess::exists(texture_path + ".import")) {
|
|
|
- config->load(texture_path + ".import");
|
|
|
- }
|
|
|
-
|
|
|
- config->set_value("remap", "importer", "2d_array_texture");
|
|
|
- config->set_value("remap", "type", "CompressedTexture2DArray");
|
|
|
- if (!config->has_section_key("params", "compress/mode")) {
|
|
|
- // User may want another compression, so leave it be, but default to VRAM uncompressed.
|
|
|
- config->set_value("params", "compress/mode", 3);
|
|
|
- }
|
|
|
- config->set_value("params", "compress/channel_pack", 1);
|
|
|
- config->set_value("params", "mipmaps/generate", false);
|
|
|
- config->set_value("params", "slices/horizontal", 1);
|
|
|
- config->set_value("params", "slices/vertical", texture_slice_count);
|
|
|
-
|
|
|
- config->save(texture_path + ".import");
|
|
|
-
|
|
|
- Error err = texture_image->save_exr(texture_path, false);
|
|
|
- ERR_FAIL_COND_V(err, ret);
|
|
|
- ResourceLoader::import(texture_path);
|
|
|
- Ref<TextureLayered> t = ResourceLoader::load(texture_path); //if already loaded, it will be updated on refocus?
|
|
|
- ERR_FAIL_COND_V(t.is_null(), ret);
|
|
|
- ret[i] = t;
|
|
|
- }
|
|
|
-
|
|
|
- return ret;
|
|
|
+TypedArray<TextureLayered> LightmapGIData::get_lightmap_textures() const {
|
|
|
+ return light_textures;
|
|
|
}
|
|
|
|
|
|
RID LightmapGIData::get_rid() const {
|
|
|
@@ -193,18 +138,13 @@ void LightmapGIData::clear() {
|
|
|
users.clear();
|
|
|
}
|
|
|
|
|
|
-void LightmapGIData::set_light_texture(const Ref<TextureLayered> &p_light_texture) {
|
|
|
- light_texture = p_light_texture;
|
|
|
+void LightmapGIData::_reset_lightmap_textures() {
|
|
|
RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics);
|
|
|
}
|
|
|
|
|
|
-Ref<TextureLayered> LightmapGIData::get_light_texture() const {
|
|
|
- return light_texture;
|
|
|
-}
|
|
|
-
|
|
|
void LightmapGIData::set_uses_spherical_harmonics(bool p_enable) {
|
|
|
uses_spherical_harmonics = p_enable;
|
|
|
- RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics);
|
|
|
+ _reset_lightmap_textures();
|
|
|
}
|
|
|
|
|
|
bool LightmapGIData::is_using_spherical_harmonics() const {
|
|
|
@@ -282,15 +222,35 @@ Dictionary LightmapGIData::_get_probe_data() const {
|
|
|
return d;
|
|
|
}
|
|
|
|
|
|
+#ifndef DISABLE_DEPRECATED
|
|
|
+void LightmapGIData::set_light_texture(const Ref<TextureLayered> &p_light_texture) {
|
|
|
+ TypedArray<TextureLayered> arr;
|
|
|
+ arr.append(p_light_texture);
|
|
|
+ set_lightmap_textures(arr);
|
|
|
+}
|
|
|
+
|
|
|
+Ref<TextureLayered> LightmapGIData::get_light_texture() const {
|
|
|
+ if (light_textures.is_empty()) {
|
|
|
+ return Ref<TextureLayered>();
|
|
|
+ }
|
|
|
+ return light_textures.get(0);
|
|
|
+}
|
|
|
+
|
|
|
+void LightmapGIData::_set_light_textures_data(const Array &p_data) {
|
|
|
+ set_lightmap_textures(p_data);
|
|
|
+}
|
|
|
+
|
|
|
+Array LightmapGIData::_get_light_textures_data() const {
|
|
|
+ return Array(light_textures);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
void LightmapGIData::_bind_methods() {
|
|
|
ClassDB::bind_method(D_METHOD("_set_user_data", "data"), &LightmapGIData::_set_user_data);
|
|
|
ClassDB::bind_method(D_METHOD("_get_user_data"), &LightmapGIData::_get_user_data);
|
|
|
|
|
|
- ClassDB::bind_method(D_METHOD("set_light_texture", "light_texture"), &LightmapGIData::set_light_texture);
|
|
|
- ClassDB::bind_method(D_METHOD("get_light_texture"), &LightmapGIData::get_light_texture);
|
|
|
-
|
|
|
- ClassDB::bind_method(D_METHOD("_set_light_textures_data", "data"), &LightmapGIData::_set_light_textures_data);
|
|
|
- ClassDB::bind_method(D_METHOD("_get_light_textures_data"), &LightmapGIData::_get_light_textures_data);
|
|
|
+ ClassDB::bind_method(D_METHOD("set_lightmap_textures", "light_textures"), &LightmapGIData::set_lightmap_textures);
|
|
|
+ ClassDB::bind_method(D_METHOD("get_lightmap_textures"), &LightmapGIData::get_lightmap_textures);
|
|
|
|
|
|
ClassDB::bind_method(D_METHOD("set_uses_spherical_harmonics", "uses_spherical_harmonics"), &LightmapGIData::set_uses_spherical_harmonics);
|
|
|
ClassDB::bind_method(D_METHOD("is_using_spherical_harmonics"), &LightmapGIData::is_using_spherical_harmonics);
|
|
|
@@ -303,11 +263,21 @@ void LightmapGIData::_bind_methods() {
|
|
|
ClassDB::bind_method(D_METHOD("_set_probe_data", "data"), &LightmapGIData::_set_probe_data);
|
|
|
ClassDB::bind_method(D_METHOD("_get_probe_data"), &LightmapGIData::_get_probe_data);
|
|
|
|
|
|
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered", PROPERTY_USAGE_EDITOR), "set_light_texture", "get_light_texture"); // property usage default but no save
|
|
|
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "light_textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_light_textures_data", "_get_light_textures_data");
|
|
|
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "lightmap_textures", PROPERTY_HINT_ARRAY_TYPE, "TextureLayered", PROPERTY_USAGE_NO_EDITOR), "set_lightmap_textures", "get_lightmap_textures");
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics");
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data");
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "probe_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_probe_data", "_get_probe_data");
|
|
|
+
|
|
|
+#ifndef DISABLE_DEPRECATED
|
|
|
+ ClassDB::bind_method(D_METHOD("set_light_texture", "light_texture"), &LightmapGIData::set_light_texture);
|
|
|
+ ClassDB::bind_method(D_METHOD("get_light_texture"), &LightmapGIData::get_light_texture);
|
|
|
+
|
|
|
+ ClassDB::bind_method(D_METHOD("_set_light_textures_data", "data"), &LightmapGIData::_set_light_textures_data);
|
|
|
+ ClassDB::bind_method(D_METHOD("_get_light_textures_data"), &LightmapGIData::_get_light_textures_data);
|
|
|
+
|
|
|
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered", PROPERTY_USAGE_EDITOR), "set_light_texture", "get_light_texture");
|
|
|
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "light_textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_light_textures_data", "_get_light_textures_data");
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
LightmapGIData::LightmapGIData() {
|
|
|
@@ -1091,6 +1061,68 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
|
|
|
return BAKE_ERROR_MESHES_INVALID;
|
|
|
}
|
|
|
|
|
|
+ // POSTBAKE: Save Textures.
|
|
|
+
|
|
|
+ TypedArray<TextureLayered> textures;
|
|
|
+ {
|
|
|
+ Vector<Ref<Image>> images;
|
|
|
+ images.resize(lightmapper->get_bake_texture_count());
|
|
|
+ for (int i = 0; i < images.size(); i++) {
|
|
|
+ images.set(i, lightmapper->get_bake_texture(i));
|
|
|
+ }
|
|
|
+
|
|
|
+ int slice_count = images.size();
|
|
|
+ int slice_width = images[0]->get_width();
|
|
|
+ int slice_height = images[0]->get_height();
|
|
|
+
|
|
|
+ int slices_per_texture = Image::MAX_HEIGHT / slice_height;
|
|
|
+ int texture_count = Math::ceil(slice_count / (float)slices_per_texture);
|
|
|
+
|
|
|
+ textures.resize(texture_count);
|
|
|
+
|
|
|
+ String base_path = p_image_data_path.get_basename();
|
|
|
+
|
|
|
+ int last_count = slice_count % slices_per_texture;
|
|
|
+ for (int i = 0; i < texture_count; i++) {
|
|
|
+ int texture_slice_count = (i == texture_count - 1 && last_count != 0) ? last_count : slices_per_texture;
|
|
|
+
|
|
|
+ Ref<Image> texture_image = Image::create_empty(slice_width, slice_height * texture_slice_count, false, images[0]->get_format());
|
|
|
+
|
|
|
+ for (int j = 0; j < texture_slice_count; j++) {
|
|
|
+ texture_image->blit_rect(images[i * slices_per_texture + j], Rect2i(0, 0, slice_width, slice_height), Point2i(0, slice_height * j));
|
|
|
+ }
|
|
|
+
|
|
|
+ String texture_path = texture_count > 1 ? base_path + "_" + itos(i) + ".exr" : base_path + ".exr";
|
|
|
+
|
|
|
+ Ref<ConfigFile> config;
|
|
|
+ config.instantiate();
|
|
|
+
|
|
|
+ if (FileAccess::exists(texture_path + ".import")) {
|
|
|
+ config->load(texture_path + ".import");
|
|
|
+ }
|
|
|
+
|
|
|
+ config->set_value("remap", "importer", "2d_array_texture");
|
|
|
+ config->set_value("remap", "type", "CompressedTexture2DArray");
|
|
|
+ if (!config->has_section_key("params", "compress/mode")) {
|
|
|
+ // User may want another compression, so leave it be, but default to VRAM uncompressed.
|
|
|
+ config->set_value("params", "compress/mode", 3);
|
|
|
+ }
|
|
|
+ config->set_value("params", "compress/channel_pack", 1);
|
|
|
+ config->set_value("params", "mipmaps/generate", false);
|
|
|
+ config->set_value("params", "slices/horizontal", 1);
|
|
|
+ config->set_value("params", "slices/vertical", texture_slice_count);
|
|
|
+
|
|
|
+ config->save(texture_path + ".import");
|
|
|
+
|
|
|
+ Error err = texture_image->save_exr(texture_path, false);
|
|
|
+ ERR_FAIL_COND_V(err, BAKE_ERROR_CANT_CREATE_IMAGE);
|
|
|
+ ResourceLoader::import(texture_path);
|
|
|
+ Ref<TextureLayered> t = ResourceLoader::load(texture_path); // If already loaded, it will be updated on refocus?
|
|
|
+ ERR_FAIL_COND_V(t.is_null(), BAKE_ERROR_CANT_CREATE_IMAGE);
|
|
|
+ textures[i] = t;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/* POSTBAKE: Save Light Data */
|
|
|
|
|
|
Ref<LightmapGIData> gi_data;
|
|
|
@@ -1102,18 +1134,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
|
|
|
gi_data.instantiate();
|
|
|
}
|
|
|
|
|
|
- Ref<Texture2DArray> texture;
|
|
|
- {
|
|
|
- Vector<Ref<Image>> images;
|
|
|
- for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) {
|
|
|
- images.push_back(lightmapper->get_bake_texture(i));
|
|
|
- }
|
|
|
-
|
|
|
- texture.instantiate();
|
|
|
- texture->create_from_images(images);
|
|
|
- }
|
|
|
-
|
|
|
- gi_data->set_light_texture(texture);
|
|
|
+ gi_data->set_lightmap_textures(textures);
|
|
|
gi_data->set_uses_spherical_harmonics(directional);
|
|
|
|
|
|
for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) {
|