@@ -98,15 +98,15 @@ Array LightmapGIData::_get_user_data() const {
9898}
9999
100100void LightmapGIData::set_lightmap_textures (const TypedArray<TextureLayered> &p_data) {
101- light_textures = p_data;
101+ storage_light_textures = p_data;
102102 if (p_data.is_empty ()) {
103- light_texture = Ref<TextureLayered>();
103+ combined_light_texture = Ref<TextureLayered>();
104104 _reset_lightmap_textures ();
105105 return ;
106106 }
107107
108108 if (p_data.size () == 1 ) {
109- light_texture = p_data[0 ];
109+ combined_light_texture = p_data[0 ];
110110 } else {
111111 Vector<Ref<Image>> images;
112112 for (int i = 0 ; i < p_data.size (); i++) {
@@ -121,13 +121,13 @@ void LightmapGIData::set_lightmap_textures(const TypedArray<TextureLayered> &p_d
121121 combined_texture.instantiate ();
122122
123123 combined_texture->create_from_images (images);
124- light_texture = combined_texture;
124+ combined_light_texture = combined_texture;
125125 }
126126 _reset_lightmap_textures ();
127127}
128128
129129TypedArray<TextureLayered> LightmapGIData::get_lightmap_textures () const {
130- return light_textures ;
130+ return storage_light_textures ;
131131}
132132
133133RID LightmapGIData::get_rid () const {
@@ -139,7 +139,7 @@ void LightmapGIData::clear() {
139139}
140140
141141void LightmapGIData::_reset_lightmap_textures () {
142- RS::get_singleton ()->lightmap_set_textures (lightmap, light_texture .is_valid () ? light_texture ->get_rid () : RID (), uses_spherical_harmonics);
142+ RS::get_singleton ()->lightmap_set_textures (lightmap, combined_light_texture .is_valid () ? combined_light_texture ->get_rid () : RID (), uses_spherical_harmonics);
143143}
144144
145145void LightmapGIData::set_uses_spherical_harmonics (bool p_enable) {
@@ -238,18 +238,18 @@ void LightmapGIData::set_light_texture(const Ref<TextureLayered> &p_light_textur
238238}
239239
240240Ref<TextureLayered> LightmapGIData::get_light_texture () const {
241- if (light_textures .is_empty ()) {
241+ if (storage_light_textures .is_empty ()) {
242242 return Ref<TextureLayered>();
243243 }
244- return light_textures .get (0 );
244+ return storage_light_textures .get (0 );
245245}
246246
247247void LightmapGIData::_set_light_textures_data (const Array &p_data) {
248248 set_lightmap_textures (p_data);
249249}
250250
251251Array LightmapGIData::_get_light_textures_data () const {
252- return Array (light_textures );
252+ return Array (storage_light_textures );
253253}
254254#endif
255255
@@ -274,7 +274,7 @@ void LightmapGIData::_bind_methods() {
274274 ClassDB::bind_method (D_METHOD (" _set_probe_data" , " data" ), &LightmapGIData::_set_probe_data);
275275 ClassDB::bind_method (D_METHOD (" _get_probe_data" ), &LightmapGIData::_get_probe_data);
276276
277- ADD_PROPERTY (PropertyInfo (Variant::ARRAY, " lightmap_textures" , PROPERTY_HINT_ARRAY_TYPE, " TextureLayered" , PROPERTY_USAGE_NO_EDITOR ), " set_lightmap_textures" , " get_lightmap_textures" );
277+ ADD_PROPERTY (PropertyInfo (Variant::ARRAY, " lightmap_textures" , PROPERTY_HINT_ARRAY_TYPE, " TextureLayered" , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY ), " set_lightmap_textures" , " get_lightmap_textures" );
278278 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" );
279279 ADD_PROPERTY (PropertyInfo (Variant::ARRAY, " user_data" , PROPERTY_HINT_NONE, " " , PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), " _set_user_data" , " _get_user_data" );
280280 ADD_PROPERTY (PropertyInfo (Variant::DICTIONARY, " probe_data" , PROPERTY_HINT_NONE, " " , PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), " _set_probe_data" , " _get_probe_data" );
@@ -287,8 +287,8 @@ void LightmapGIData::_bind_methods() {
287287 ClassDB::bind_method (D_METHOD (" _set_light_textures_data" , " data" ), &LightmapGIData::_set_light_textures_data);
288288 ClassDB::bind_method (D_METHOD (" _get_light_textures_data" ), &LightmapGIData::_get_light_textures_data);
289289
290- ADD_PROPERTY (PropertyInfo (Variant::OBJECT, " light_texture" , PROPERTY_HINT_RESOURCE_TYPE, " TextureLayered" , PROPERTY_USAGE_EDITOR ), " set_light_texture" , " get_light_texture" );
291- 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" );
290+ ADD_PROPERTY (PropertyInfo (Variant::OBJECT, " light_texture" , PROPERTY_HINT_RESOURCE_TYPE, " TextureLayered" , PROPERTY_USAGE_NONE ), " set_light_texture" , " get_light_texture" );
291+ ADD_PROPERTY (PropertyInfo (Variant::ARRAY, " light_textures" , PROPERTY_HINT_NONE, " " , PROPERTY_USAGE_INTERNAL), " _set_light_textures_data" , " _get_light_textures_data" );
292292#endif
293293}
294294
@@ -740,6 +740,74 @@ void LightmapGI::_gen_new_positions_from_octree(const GenProbesOctree *p_cell, f
740740 }
741741}
742742
743+ LightmapGI::BakeError LightmapGI::_save_and_reimport_atlas_textures (const Ref<Lightmapper> p_lightmapper, const String &p_base_name, TypedArray<TextureLayered> &r_textures, bool p_compress) const {
744+ Vector<Ref<Image>> images;
745+ images.resize (p_lightmapper->get_bake_texture_count ());
746+
747+ for (int i = 0 ; i < images.size (); i++) {
748+ images.set (i, p_lightmapper->get_bake_texture (i));
749+ }
750+
751+ const int slice_count = images.size ();
752+ const int slice_width = images[0 ]->get_width ();
753+ const int slice_height = images[0 ]->get_height ();
754+
755+ const int slices_per_texture = Image::MAX_HEIGHT / slice_height;
756+ const int texture_count = Math::ceil (slice_count / (float )slices_per_texture);
757+ const int last_count = slice_count % slices_per_texture;
758+
759+ r_textures.resize (texture_count);
760+
761+ for (int i = 0 ; i < texture_count; i++) {
762+ const int texture_slice_count = (i == texture_count - 1 && last_count != 0 ) ? last_count : slices_per_texture;
763+
764+ Ref<Image> texture_image = Image::create_empty (slice_width, slice_height * texture_slice_count, false , images[0 ]->get_format ());
765+
766+ for (int j = 0 ; j < texture_slice_count; j++) {
767+ texture_image->blit_rect (images[i * slices_per_texture + j], Rect2i (0 , 0 , slice_width, slice_height), Point2i (0 , slice_height * j));
768+ }
769+
770+ const String atlas_path = (texture_count > 1 ? p_base_name + " _" + itos (i) : p_base_name) + " .exr" ;
771+ const String config_path = atlas_path + " .import" ;
772+
773+ Ref<ConfigFile> config;
774+ config.instantiate ();
775+
776+ // Load an import configuration if present.
777+ if (FileAccess::exists (config_path)) {
778+ config->load (config_path);
779+ }
780+
781+ config->set_value (" remap" , " importer" , " 2d_array_texture" );
782+ config->set_value (" remap" , " type" , " CompressedTexture2DArray" );
783+ if (!config->has_section_key (" params" , " compress/mode" )) {
784+ // Do not override an existing compression mode.
785+ config->set_value (" params" , " compress/mode" , p_compress ? 2 : 3 );
786+ }
787+ config->set_value (" params" , " compress/channel_pack" , 1 );
788+ config->set_value (" params" , " mipmaps/generate" , false );
789+ config->set_value (" params" , " slices/horizontal" , 1 );
790+ config->set_value (" params" , " slices/vertical" , texture_slice_count);
791+
792+ config->save (config_path);
793+
794+ // Save the file.
795+ Error save_err = texture_image->save_exr (atlas_path, false );
796+
797+ ERR_FAIL_COND_V (save_err, LightmapGI::BAKE_ERROR_CANT_CREATE_IMAGE);
798+
799+ // Reimport the file.
800+ ResourceLoader::import (atlas_path);
801+ Ref<TextureLayered> t = ResourceLoader::load (atlas_path); // If already loaded, it will be updated on refocus?
802+ ERR_FAIL_COND_V (t.is_null (), LightmapGI::BAKE_ERROR_CANT_CREATE_IMAGE);
803+
804+ // Store the atlas in the array.
805+ r_textures[i] = t;
806+ }
807+
808+ return LightmapGI::BAKE_ERROR_OK;
809+ }
810+
743811LightmapGI::BakeError LightmapGI::bake (Node *p_from_node, String p_image_data_path, Lightmapper::BakeStepFunc p_bake_step, void *p_bake_userdata) {
744812 if (p_image_data_path.is_empty ()) {
745813 if (get_light_data ().is_null ()) {
@@ -1127,80 +1195,30 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
11271195
11281196 // POSTBAKE: Save Textures.
11291197
1130- TypedArray<TextureLayered> textures;
1131- {
1132- Vector<Ref<Image>> images;
1133- images.resize (lightmapper->get_bake_texture_count ());
1134- for (int i = 0 ; i < images.size (); i++) {
1135- images.set (i, lightmapper->get_bake_texture (i));
1136- }
1137-
1138- int slice_count = images.size ();
1139- int slice_width = images[0 ]->get_width ();
1140- int slice_height = images[0 ]->get_height ();
1141-
1142- int slices_per_texture = Image::MAX_HEIGHT / slice_height;
1143- int texture_count = Math::ceil (slice_count / (float )slices_per_texture);
1144-
1145- textures.resize (texture_count);
1146-
1147- String base_path = p_image_data_path.get_basename ();
1148-
1149- int last_count = slice_count % slices_per_texture;
1150- for (int i = 0 ; i < texture_count; i++) {
1151- int texture_slice_count = (i == texture_count - 1 && last_count != 0 ) ? last_count : slices_per_texture;
1152-
1153- Ref<Image> texture_image = Image::create_empty (slice_width, slice_height * texture_slice_count, false , images[0 ]->get_format ());
1154-
1155- for (int j = 0 ; j < texture_slice_count; j++) {
1156- texture_image->blit_rect (images[i * slices_per_texture + j], Rect2i (0 , 0 , slice_width, slice_height), Point2i (0 , slice_height * j));
1157- }
1158-
1159- String texture_path = texture_count > 1 ? base_path + " _" + itos (i) + " .exr" : base_path + " .exr" ;
1198+ TypedArray<TextureLayered> lightmap_textures;
11601199
1161- Ref<ConfigFile> config;
1162- config.instantiate ();
1200+ const String texture_filename = p_image_data_path.get_basename ();
11631201
1164- if ( FileAccess::exists (texture_path + " .import " )) {
1165- config-> load (texture_path + " .import " );
1166- }
1202+ // Save the lightmap atlases.
1203+ BakeError save_err = _save_and_reimport_atlas_textures (lightmapper, texture_filename, lightmap_textures, false );
1204+ ERR_FAIL_COND_V (save_err != BAKE_ERROR_OK, save_err);
11671205
1168- config->set_value (" remap" , " importer" , " 2d_array_texture" );
1169- config->set_value (" remap" , " type" , " CompressedTexture2DArray" );
1170- if (!config->has_section_key (" params" , " compress/mode" )) {
1171- // User may want another compression, so leave it be, but default to VRAM uncompressed.
1172- config->set_value (" params" , " compress/mode" , 3 );
1173- }
1174- config->set_value (" params" , " compress/channel_pack" , 1 );
1175- config->set_value (" params" , " mipmaps/generate" , false );
1176- config->set_value (" params" , " slices/horizontal" , 1 );
1177- config->set_value (" params" , " slices/vertical" , texture_slice_count);
1178-
1179- config->save (texture_path + " .import" );
1180-
1181- Error err = texture_image->save_exr (texture_path, false );
1182- ERR_FAIL_COND_V (err, BAKE_ERROR_CANT_CREATE_IMAGE);
1183- ResourceLoader::import (texture_path);
1184- Ref<TextureLayered> t = ResourceLoader::load (texture_path); // If already loaded, it will be updated on refocus?
1185- ERR_FAIL_COND_V (t.is_null (), BAKE_ERROR_CANT_CREATE_IMAGE);
1186- textures[i] = t;
1187- }
1188- }
1189-
1190- /* POSTBAKE: Save Light Data */
1206+ // POSTBAKE: Save Light Data.
11911207
11921208 Ref<LightmapGIData> gi_data;
1209+
11931210 if (get_light_data ().is_valid ()) {
11941211 gi_data = get_light_data ();
1195- set_light_data (Ref<LightmapGIData>()); // clear
1212+ set_light_data (Ref<LightmapGIData>()); // Clear.
11961213 gi_data->clear ();
1214+
11971215 } else {
11981216 gi_data.instantiate ();
11991217 }
12001218
1201- gi_data->set_lightmap_textures (textures);
1202- gi_data->_set_uses_packed_directional (directional); // New SH lightmaps are packed automatically.
1219+ gi_data->set_lightmap_textures (lightmap_textures);
12031220 gi_data->set_uses_spherical_harmonics (directional);
1221+ gi_data->_set_uses_packed_directional (directional); // New SH lightmaps are packed automatically.
12041222
12051223 for (int i = 0 ; i < lightmapper->get_bake_mesh_count (); i++) {
12061224 Dictionary d = lightmapper->get_bake_mesh_userdata (i);
0 commit comments