Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Use Color and Use HDR properties to LightmapGI #50574

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/classes/LightmapGI.xml
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,15 @@
Scales the lightmap texel density of all meshes for the current bake. This is a multiplier that builds upon the existing lightmap texel size defined in each imported 3D scene, along with the per-mesh density multiplier (which is designed to be used when the same mesh is used at different scales). Lower values will result in faster bake times.
For example, doubling [member texel_scale] doubles the lightmap texture resolution for all objects [i]on each axis[/i], so it will [i]quadruple[/i] the texel count.
</member>
<member name="use_color" type="bool" setter="set_use_color" getter="is_using_color" default="true">
Store full color values in the lightmap textures. When disabled, lightmap textures will store a single brightness channel. This can be disabled to reduce file size and memory usage if the scene contains mostly grayscale lights, or if you don't mind losing color information in indirect lighting.
</member>
<member name="use_denoiser" type="bool" setter="set_use_denoiser" getter="is_using_denoiser" default="true">
If [code]true[/code], uses a GPU-based denoising algorithm on the generated lightmap. This eliminates most noise within the generated lightmap at the cost of longer bake times. File sizes are generally not impacted significantly by the use of a denoiser, although lossless compression may do a better job at compressing a denoised image.
</member>
<member name="use_hdr" type="bool" setter="set_use_hdr" getter="is_using_hdr" default="true">
If [code]true[/code], stores the lightmap textures in a high dynamic range format (EXR). If [code]false[/code], stores the lightmap texture in a low dynamic range WebP image. This can be set to [code]false[/code] to reduce file size and memory usage, but light values over 1.0 will be clamped and you may see banding caused by the reduced precision.
</member>
<member name="use_texture_for_bounces" type="bool" setter="set_use_texture_for_bounces" getter="is_using_texture_for_bounces" default="true">
If [code]true[/code], a texture with the lighting information will be generated to speed up the generation of indirect lighting at the cost of some accuracy. The geometry might exhibit extra light leak artifacts when using low resolution lightmaps or UVs that stretch the lightmap significantly across surfaces. Leave [member use_texture_for_bounces] at its default value of [code]true[/code] if unsure.
[b]Note:[/b] [member use_texture_for_bounces] only has an effect if [member bounces] is set to a value greater than or equal to [code]1[/code].
Expand Down
28 changes: 28 additions & 0 deletions doc/classes/LightmapGIData.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,40 @@
Returns the [NodePath] of the baked object at index [param user_idx].
</description>
</method>
<method name="is_using_color" qualifiers="const">
<return type="bool" />
<description>
If [code]true[/code], lightmaps were baked with color enabled. See also [member LightmapGI.use_color].
</description>
</method>
<method name="is_using_hdr" qualifiers="const">
<return type="bool" />
<description>
If [code]true[/code], lightmaps were baked with high dynamic range enabled. See also [member LightmapGI.use_hdr].
</description>
</method>
<method name="is_using_spherical_harmonics" qualifiers="const">
<return type="bool" />
<description>
If [code]true[/code], lightmaps were baked with directional information. See also [member LightmapGI.directional].
</description>
</method>
<method name="set_use_color">
<return type="void" />
<param index="0" name="use_color" type="bool" />
<description>
If [param use_color] is [code]true[/code], tells the engine to treat the lightmap data as if it was baked with color enabled.
[b]Note:[/b] Changing this value on already baked lightmaps will not cause them to be baked again. This means the material appearance will look incorrect until lightmaps are baked again, in which case the value set here is discarded as the entire [LightmapGIData] resource is replaced by the lightmapper.
</description>
</method>
<method name="set_use_hdr">
<return type="void" />
<param index="0" name="use_hdr" type="bool" />
<description>
If [param use_hdr] is [code]true[/code], tells the engine to treat the lightmap data as if it was baked with high dynamic range enabled.
[b]Note:[/b] Changing this value on already baked lightmaps will not cause them to be baked again. This means the material appearance will look incorrect until lightmaps are baked again, in which case the value set here is discarded as the entire [LightmapGIData] resource is replaced by the lightmapper.
</description>
</method>
<method name="set_uses_spherical_harmonics">
<return type="void" />
<param index="0" name="uses_spherical_harmonics" type="bool" />
Expand Down
71 changes: 69 additions & 2 deletions scene/3d/lightmap_gi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,22 @@ LightmapGIData::ShadowmaskMode LightmapGIData::get_shadowmask_mode() const {
return (ShadowmaskMode)RS::get_singleton()->lightmap_get_shadowmask_mode(lightmap);
}

void LightmapGIData::set_use_hdr(bool p_enable) {
use_hdr = p_enable;
}

bool LightmapGIData::is_using_hdr() const {
return use_hdr;
}

void LightmapGIData::set_use_color(bool p_enable) {
use_color = p_enable;
}

bool LightmapGIData::is_using_color() const {
return use_color;
}

void LightmapGIData::set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree, float p_baked_exposure) {
if (p_points.size()) {
int pc = p_points.size();
Expand Down Expand Up @@ -330,6 +346,12 @@ void LightmapGIData::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_uses_packed_directional", "_uses_packed_directional"), &LightmapGIData::_set_uses_packed_directional);
ClassDB::bind_method(D_METHOD("_is_using_packed_directional"), &LightmapGIData::_is_using_packed_directional);

ClassDB::bind_method(D_METHOD("set_use_hdr", "use_hdr"), &LightmapGIData::set_use_hdr);
ClassDB::bind_method(D_METHOD("is_using_hdr"), &LightmapGIData::is_using_hdr);

ClassDB::bind_method(D_METHOD("set_use_color", "use_color"), &LightmapGIData::set_use_color);
ClassDB::bind_method(D_METHOD("is_using_color"), &LightmapGIData::is_using_color);

ClassDB::bind_method(D_METHOD("add_user", "path", "uv_scale", "slice_index", "sub_instance"), &LightmapGIData::add_user);
ClassDB::bind_method(D_METHOD("get_user_count"), &LightmapGIData::get_user_count);
ClassDB::bind_method(D_METHOD("get_user_path", "user_idx"), &LightmapGIData::get_user_path);
Expand All @@ -341,6 +363,8 @@ void LightmapGIData::_bind_methods() {
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");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "shadowmask_textures", PROPERTY_HINT_ARRAY_TYPE, "TextureLayered", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY), "set_shadowmask_textures", "get_shadowmask_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::BOOL, "use_hdr", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_use_hdr", "is_using_hdr");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_color", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_use_color", "is_using_color");
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");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "_uses_packed_directional", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_uses_packed_directional", "_is_using_packed_directional");
Expand Down Expand Up @@ -834,7 +858,10 @@ LightmapGI::BakeError LightmapGI::_save_and_reimport_atlas_textures(const Ref<Li
texture_image->blit_rect(images[i * slices_per_texture + j], Rect2i(0, 0, slice_width, slice_height), Point2i(0, slice_height * j));
}

const String atlas_path = (texture_count > 1 ? p_base_name + "_" + itos(i) : p_base_name) + (p_is_shadowmask ? ".png" : ".exr");
// Use OpenEXR for HDR lightmaps (required, as WebP does not support the required format).
// Use (lossless) WebP for LDR lightmaps.
const String non_shadowmask_extension = use_hdr ? ".exr" : ".webp";
const String atlas_path = (texture_count > 1 ? p_base_name + "_" + itos(i) : p_base_name) + (p_is_shadowmask ? ".png" : non_shadowmask_extension);
const String config_path = atlas_path + ".import";

Ref<ConfigFile> config;
Expand Down Expand Up @@ -867,7 +894,21 @@ LightmapGI::BakeError LightmapGI::_save_and_reimport_atlas_textures(const Ref<Li
if (p_is_shadowmask) {
save_err = texture_image->save_png(atlas_path);
} else {
save_err = texture_image->save_exr(atlas_path, false);
if (!use_color) {
// Convert to grayscale to reduce file size.
if (use_hdr) {
texture_image->convert(Image::FORMAT_RH);
} else {
// Convert to low dynamic range to further reduce file size.
texture_image->convert(Image::FORMAT_L8);
}
}

if (use_hdr) {
save_err = texture_image->save_exr(atlas_path, !use_color);
} else {
save_err = texture_image->save_webp(atlas_path, false);
}
}

ERR_FAIL_COND_V(save_err, LightmapGI::BAKE_ERROR_CANT_CREATE_IMAGE);
Expand Down Expand Up @@ -1320,6 +1361,8 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa

gi_data->set_uses_spherical_harmonics(directional);
gi_data->_set_uses_packed_directional(directional); // New SH lightmaps are packed automatically.
gi_data->set_use_hdr(use_hdr);
gi_data->set_use_color(use_color);

for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) {
Dictionary d = lightmapper->get_bake_mesh_userdata(i);
Expand Down Expand Up @@ -1601,6 +1644,22 @@ int LightmapGI::get_denoiser_range() const {
return denoiser_range;
}

void LightmapGI::set_use_hdr(bool p_enable) {
use_hdr = p_enable;
}

bool LightmapGI::is_using_hdr() const {
return use_hdr;
}

void LightmapGI::set_use_color(bool p_enable) {
use_color = p_enable;
}

bool LightmapGI::is_using_color() const {
return use_color;
}

void LightmapGI::set_directional(bool p_enable) {
directional = p_enable;
}
Expand Down Expand Up @@ -1848,6 +1907,12 @@ void LightmapGI::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_denoiser_range", "denoiser_range"), &LightmapGI::set_denoiser_range);
ClassDB::bind_method(D_METHOD("get_denoiser_range"), &LightmapGI::get_denoiser_range);

ClassDB::bind_method(D_METHOD("set_use_hdr", "use_denoiser"), &LightmapGI::set_use_hdr);
ClassDB::bind_method(D_METHOD("is_using_hdr"), &LightmapGI::is_using_hdr);

ClassDB::bind_method(D_METHOD("set_use_color", "use_denoiser"), &LightmapGI::set_use_color);
ClassDB::bind_method(D_METHOD("is_using_color"), &LightmapGI::is_using_color);

ClassDB::bind_method(D_METHOD("set_interior", "enable"), &LightmapGI::set_interior);
ClassDB::bind_method(D_METHOD("is_interior"), &LightmapGI::is_interior);

Expand Down Expand Up @@ -1878,6 +1943,8 @@ void LightmapGI::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_denoiser"), "set_use_denoiser", "is_using_denoiser");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "denoiser_strength", PROPERTY_HINT_RANGE, "0.001,0.2,0.001,or_greater"), "set_denoiser_strength", "get_denoiser_strength");
ADD_PROPERTY(PropertyInfo(Variant::INT, "denoiser_range", PROPERTY_HINT_RANGE, "1,20"), "set_denoiser_range", "get_denoiser_range");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hdr"), "set_use_hdr", "is_using_hdr");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_color"), "set_use_color", "is_using_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.00001,0.1,0.00001,or_greater"), "set_bias", "get_bias");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "texel_scale", PROPERTY_HINT_RANGE, "0.01,100.0,0.01"), "set_texel_scale", "get_texel_scale");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_texture_size", PROPERTY_HINT_RANGE, "2048,16384,1"), "set_max_texture_size", "get_max_texture_size");
Expand Down
17 changes: 17 additions & 0 deletions scene/3d/lightmap_gi.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class LightmapGIData : public Resource {
bool interior = false;

bool _uses_packed_directional = false;
// Mirrors LightmapGI properties (set before each bake). Required to save images correctly.
bool use_hdr = true;
bool use_color = true;

RID lightmap;
AABB bounds;
Expand Down Expand Up @@ -116,6 +119,12 @@ class LightmapGIData : public Resource {
void update_shadowmask_mode(ShadowmaskMode p_mode);
ShadowmaskMode get_shadowmask_mode() const;

void set_use_hdr(bool p_enable);
bool is_using_hdr() const;

void set_use_color(bool p_enable);
bool is_using_color() const;

bool is_interior() const;
float get_baked_exposure() const;

Expand Down Expand Up @@ -189,6 +198,8 @@ class LightmapGI : public VisualInstance3D {
int denoiser_range = 10;
int bounces = 3;
float bounce_indirect_energy = 1.0;
bool use_hdr = true;
bool use_color = true;
float bias = 0.0005;
float texel_scale = 1.0;
int max_texture_size = 16384;
Expand Down Expand Up @@ -295,6 +306,12 @@ class LightmapGI : public VisualInstance3D {
void set_denoiser_range(int p_denoiser_range);
int get_denoiser_range() const;

void set_use_hdr(bool p_enable);
bool is_using_hdr() const;

void set_use_color(bool p_enable);
bool is_using_color() const;

void set_directional(bool p_enable);
bool is_directional() const;

Expand Down