diff --git a/doc/classes/BakedLightmap.xml b/doc/classes/BakedLightmap.xml
index e73ad41b26..ba5b99687c 100644
--- a/doc/classes/BakedLightmap.xml
+++ b/doc/classes/BakedLightmap.xml
@@ -5,7 +5,6 @@
Baked lightmaps are an alternative workflow for adding indirect (or baked) lighting to a scene. Unlike the [GIProbe] approach, baked lightmaps work fine on low-end PCs and mobile devices as they consume almost no resources in run-time.
- [b]Note:[/b] This node has many known bugs and will be [url=https://godotengine.org/article/godot-40-will-get-new-modernized-lightmapper]rewritten for Godot 4.0[/url]. See [url=https://github.com/godotengine/godot/issues/30929]GitHub issue #30929[/url].
https://docs.godotengine.org/en/3.2/tutorials/3d/baked_lightmaps.html
@@ -63,6 +62,9 @@
The rotation of the baked custom sky.
+
+ Minimum ambient light for all the lightmap texels. This doesn't take into account any occlusion from the scene's geometry, it simply ensures a minimum amount of light on all the lightmap texels. Can be used for artistic control on shadow color.
+
Decides which environment to use during baking.
diff --git a/doc/classes/BakedLightmapData.xml b/doc/classes/BakedLightmapData.xml
index f602b3f0bc..6799054e19 100644
--- a/doc/classes/BakedLightmapData.xml
+++ b/doc/classes/BakedLightmapData.xml
@@ -66,6 +66,10 @@
+ Global energy multiplier for baked and dynamic capture objects.
+
+
+ Controls whether dynamic capture objects receive environment lighting or not.
diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml
index 8aae7d98a4..2f29aebda8 100644
--- a/doc/classes/VisualServer.xml
+++ b/doc/classes/VisualServer.xml
@@ -2323,6 +2323,15 @@
Returns the cell transform for this lightmap capture's octree.
+
+
+
+
+
+
+ Returns [code]true[/code] if capture is in "interior" mode.
+
+
@@ -2345,6 +2354,17 @@
Sets the energy multiplier for this lightmap capture. Equivalent to [member BakedLightmapData.energy].
+
+
+
+
+
+
+
+
+ Sets the "interior" mode for this lightmap capture. Equivalent to [member BakedLightmapData.interior].
+
+
diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h
index 7cd7e96ec0..d3314cf510 100644
--- a/drivers/dummy/rasterizer_dummy.h
+++ b/drivers/dummy/rasterizer_dummy.h
@@ -655,6 +655,8 @@ public:
int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const { return 0; }
void lightmap_capture_set_energy(RID p_capture, float p_energy) {}
float lightmap_capture_get_energy(RID p_capture) const { return 0.0; }
+ void lightmap_capture_set_interior(RID p_capture, bool p_interior) {}
+ bool lightmap_capture_is_interior(RID p_capture) const { return false; }
const PoolVector *lightmap_capture_get_octree_ptr(RID p_capture) const {
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
ERR_FAIL_COND_V(!capture, NULL);
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index 6e856b9e30..eba43e1c0b 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -2598,7 +2598,6 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
if (use_lightmap_capture) { //this is per instance, must be set always if present
glUniform4fv(state.scene_shader.get_uniform_location(SceneShaderGLES2::LIGHTMAP_CAPTURES), 12, (const GLfloat *)e->instance->lightmap_capture_data.ptr());
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHTMAP_CAPTURE_SKY, false);
}
_render_geometry(e);
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index e312ef6e74..19b818c86c 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -4521,6 +4521,10 @@ void RasterizerStorageGLES2::lightmap_capture_set_energy(RID p_capture, float p_
LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
ERR_FAIL_COND(!capture);
capture->energy = p_energy;
+
+ if (!capture->update_list.in_list()) {
+ capture_update_list.add(&capture->update_list);
+ }
}
float RasterizerStorageGLES2::lightmap_capture_get_energy(RID p_capture) const {
@@ -4530,6 +4534,30 @@ float RasterizerStorageGLES2::lightmap_capture_get_energy(RID p_capture) const {
return capture->energy;
}
+void RasterizerStorageGLES2::lightmap_capture_set_interior(RID p_capture, bool p_interior) {
+ LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND(!capture);
+ capture->interior = p_interior;
+
+ if (!capture->update_list.in_list()) {
+ capture_update_list.add(&capture->update_list);
+ }
+}
+
+bool RasterizerStorageGLES2::lightmap_capture_is_interior(RID p_capture) const {
+ const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND_V(!capture, false);
+ return capture->interior;
+}
+
+void RasterizerStorageGLES2::update_dirty_captures() {
+ while (capture_update_list.first()) {
+ LightmapCapture *capture = capture_update_list.first()->self();
+ capture->instance_change_notify(false, true);
+ capture_update_list.remove(capture_update_list.first());
+ }
+}
+
const PoolVector *RasterizerStorageGLES2::lightmap_capture_get_octree_ptr(RID p_capture) const {
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
ERR_FAIL_COND_V(!capture, NULL);
@@ -6361,6 +6389,7 @@ void RasterizerStorageGLES2::update_dirty_resources() {
update_dirty_materials();
update_dirty_skeletons();
update_dirty_multimeshes();
+ update_dirty_captures();
}
RasterizerStorageGLES2::RasterizerStorageGLES2() {
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index 23823026b8..264d0e6584 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -1096,12 +1096,22 @@ public:
Transform cell_xform;
int cell_subdiv;
float energy;
- LightmapCapture() {
+ bool interior;
+
+ SelfList update_list;
+
+ LightmapCapture() :
+ update_list(this) {
energy = 1.0;
cell_subdiv = 1;
+ interior = false;
}
};
+ SelfList::List capture_update_list;
+
+ void update_dirty_captures();
+
mutable RID_Owner lightmap_capture_data_owner;
virtual RID lightmap_capture_create();
@@ -1115,6 +1125,9 @@ public:
virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const;
virtual void lightmap_capture_set_energy(RID p_capture, float p_energy);
virtual float lightmap_capture_get_energy(RID p_capture) const;
+ virtual void lightmap_capture_set_interior(RID p_capture, bool p_interior);
+ virtual bool lightmap_capture_is_interior(RID p_capture) const;
+
virtual const PoolVector *lightmap_capture_get_octree_ptr(RID p_capture) const;
/* PARTICLES */
diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl
index 521d420b16..e4d0620cba 100644
--- a/drivers/gles2/shaders/scene.glsl
+++ b/drivers/gles2/shaders/scene.glsl
@@ -956,8 +956,6 @@ vec4 texture2D_bicubic(sampler2D tex, vec2 uv) {
#ifdef USE_LIGHTMAP_CAPTURE
uniform mediump vec4 lightmap_captures[12];
-uniform bool lightmap_capture_sky;
-
#endif
#ifdef USE_RADIANCE_MAP
@@ -1781,8 +1779,9 @@ FRAGMENT_SHADER_CODE
captured /= sum;
- if (lightmap_capture_sky) {
- ambient_light = mix(ambient_light, captured.rgb, captured.a);
+ // Alpha channel is used to indicate if dynamic objects keep the environment lighting
+ if (lightmap_captures[0].a > 0.5) {
+ ambient_light += captured.rgb;
} else {
ambient_light = captured.rgb;
}
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 01e6631f6e..dac4c47f80 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1941,7 +1941,6 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform
} else if (!e->instance->lightmap_capture_data.empty()) {
glUniform4fv(state.scene_shader.get_uniform_location(SceneShaderGLES3::LIGHTMAP_CAPTURES), 12, (const GLfloat *)e->instance->lightmap_capture_data.ptr());
- state.scene_shader.set_uniform(SceneShaderGLES3::LIGHTMAP_CAPTURE_SKY, false);
} else if (e->instance->lightmap.is_valid()) {
RasterizerStorageGLES3::Texture *lightmap = storage->texture_owner.getornull(e->instance->lightmap);
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index a0aa79f890..f1ca68809a 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -6385,6 +6385,10 @@ void RasterizerStorageGLES3::lightmap_capture_set_energy(RID p_capture, float p_
LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
ERR_FAIL_COND(!capture);
capture->energy = p_energy;
+
+ if (!capture->update_list.in_list()) {
+ capture_update_list.add(&capture->update_list);
+ }
}
float RasterizerStorageGLES3::lightmap_capture_get_energy(RID p_capture) const {
@@ -6394,12 +6398,35 @@ float RasterizerStorageGLES3::lightmap_capture_get_energy(RID p_capture) const {
return capture->energy;
}
+void RasterizerStorageGLES3::lightmap_capture_set_interior(RID p_capture, bool p_interior) {
+ LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND(!capture);
+ capture->interior = p_interior;
+ if (!capture->update_list.in_list()) {
+ capture_update_list.add(&capture->update_list);
+ }
+}
+
+bool RasterizerStorageGLES3::lightmap_capture_is_interior(RID p_capture) const {
+ const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND_V(!capture, false);
+ return capture->interior;
+}
+
const PoolVector *RasterizerStorageGLES3::lightmap_capture_get_octree_ptr(RID p_capture) const {
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
ERR_FAIL_COND_V(!capture, NULL);
return &capture->octree;
}
+void RasterizerStorageGLES3::update_dirty_captures() {
+ while (capture_update_list.first()) {
+ LightmapCapture *capture = capture_update_list.first()->self();
+ capture->instance_change_notify(false, true);
+ capture_update_list.remove(capture_update_list.first());
+ }
+}
+
///////
RID RasterizerStorageGLES3::particles_create() {
@@ -8591,6 +8618,7 @@ void RasterizerStorageGLES3::update_dirty_resources() {
update_dirty_shaders();
update_dirty_materials();
update_particles();
+ update_dirty_captures();
}
RasterizerStorageGLES3::RasterizerStorageGLES3() {
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index db51ead802..77c368e90e 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -1152,6 +1152,8 @@ public:
virtual void lightmap_capture_set_energy(RID p_capture, float p_energy);
virtual float lightmap_capture_get_energy(RID p_capture) const;
+ virtual void lightmap_capture_set_interior(RID p_capture, bool p_interior);
+ virtual bool lightmap_capture_is_interior(RID p_capture) const;
virtual const PoolVector *lightmap_capture_get_octree_ptr(RID p_capture) const;
@@ -1162,12 +1164,22 @@ public:
Transform cell_xform;
int cell_subdiv;
float energy;
- LightmapCapture() {
+ bool interior;
+
+ SelfList update_list;
+
+ LightmapCapture() :
+ update_list(this) {
energy = 1.0;
cell_subdiv = 1;
+ interior = false;
}
};
+ SelfList::List capture_update_list;
+
+ void update_dirty_captures();
+
mutable RID_Owner lightmap_capture_data_owner;
/* PARTICLES */
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 021cf70315..a1d3b3beec 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1548,8 +1548,6 @@ vec4 textureArray_bicubic(sampler2DArray tex, vec3 uv) {
#ifdef USE_LIGHTMAP_CAPTURE
uniform mediump vec4[12] lightmap_captures;
-uniform bool lightmap_capture_sky;
-
#endif
#ifdef USE_GI_PROBES
@@ -1964,8 +1962,9 @@ FRAGMENT_SHADER_CODE
captured /= sum;
- if (lightmap_capture_sky) {
- ambient_light = mix(ambient_light, captured.rgb, captured.a);
+ // Alpha channel is used to indicate if dynamic objects keep the environment lighting
+ if (lightmap_captures[0].a > 0.5) {
+ ambient_light += captured.rgb;
} else {
ambient_light = captured.rgb;
}
diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml
index 8395667d31..3d31406e08 100644
--- a/modules/gridmap/doc_classes/GridMap.xml
+++ b/modules/gridmap/doc_classes/GridMap.xml
@@ -230,6 +230,9 @@
The assigned [MeshLibrary].
+
+ Controls whether this GridMap will be baked in a [BakedLightmap] or not.
+
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 5be5671b90..fa79cfc4a0 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -210,6 +210,14 @@ Ref GridMap::get_mesh_library() const {
return mesh_library;
}
+void GridMap::set_use_in_baked_light(bool p_use_baked_light) {
+ use_in_baked_light = p_use_baked_light;
+}
+
+bool GridMap::get_use_in_baked_light() const {
+ return use_in_baked_light;
+}
+
void GridMap::set_cell_size(const Vector3 &p_size) {
ERR_FAIL_COND(p_size.x < 0.001 || p_size.y < 0.001 || p_size.z < 0.001);
cell_size = p_size;
@@ -864,7 +872,11 @@ void GridMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_baked_meshes"), &GridMap::clear_baked_meshes);
ClassDB::bind_method(D_METHOD("make_baked_meshes", "gen_lightmap_uv", "lightmap_uv_texel_size"), &GridMap::make_baked_meshes, DEFVAL(false), DEFVAL(0.1));
+ ClassDB::bind_method(D_METHOD("set_use_in_baked_light", "use_in_baked_light"), &GridMap::set_use_in_baked_light);
+ ClassDB::bind_method(D_METHOD("get_use_in_baked_light"), &GridMap::get_use_in_baked_light);
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh_library", PROPERTY_HINT_RESOURCE_TYPE, "MeshLibrary"), "set_mesh_library", "get_mesh_library");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_in_baked_light"), "set_use_in_baked_light", "get_use_in_baked_light");
ADD_GROUP("Cell", "cell_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "cell_size"), "set_cell_size", "get_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_octant_size", PROPERTY_HINT_RANGE, "1,1024,1"), "set_octant_size", "get_octant_size");
@@ -1066,6 +1078,10 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe
Array GridMap::get_bake_meshes() {
+ if (!use_in_baked_light) {
+ return Array();
+ }
+
if (!baked_meshes.size()) {
make_baked_meshes(true);
}
@@ -1107,6 +1123,8 @@ GridMap::GridMap() {
navigation = NULL;
set_notify_transform(true);
recreating_octants = false;
+
+ use_in_baked_light = false;
}
GridMap::~GridMap() {
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index a8acb07b28..cc2c583c7f 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -158,6 +158,7 @@ class GridMap : public Spatial {
Vector3::Axis clip_axis;
Ref mesh_library;
+ bool use_in_baked_light;
Map octant_map;
Map cell_map;
@@ -230,6 +231,9 @@ public:
void set_mesh_library(const Ref &p_mesh_library);
Ref get_mesh_library() const;
+ void set_use_in_baked_light(bool p_use_baked_light);
+ bool get_use_in_baked_light() const;
+
void set_cell_size(const Vector3 &p_size);
Vector3 get_cell_size() const;
diff --git a/modules/raycast/lightmap_raycaster.cpp b/modules/raycast/lightmap_raycaster.cpp
index a8d7ce0186..29334b7cb0 100644
--- a/modules/raycast/lightmap_raycaster.cpp
+++ b/modules/raycast/lightmap_raycaster.cpp
@@ -33,6 +33,7 @@
// From Embree.
#include