diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml index 4878599dbd5..038240f4abe 100644 --- a/doc/classes/Light3D.xml +++ b/doc/classes/Light3D.xml @@ -64,7 +64,7 @@ [b]Note:[/b] Meshes' global illumination mode will also affect the global illumination rendering. See [member GeometryInstance3D.gi_mode]. - The light's color. An [i]overbright[/i] color can be used to achieve a result equivalent to increasing the light's [member light_energy]. + The light's color in the nonlinear sRGB color space. An [i]overbright[/i] color can be used to achieve a result equivalent to increasing the light's [member light_energy]. The light will affect objects in the selected layers. diff --git a/modules/gltf/doc_classes/GLTFLight.xml b/modules/gltf/doc_classes/GLTFLight.xml index e07d24a1446..c4a9d2641c4 100644 --- a/modules/gltf/doc_classes/GLTFLight.xml +++ b/modules/gltf/doc_classes/GLTFLight.xml @@ -53,7 +53,8 @@ - The [Color] of the light. Defaults to white. A black color causes the light to have no effect. + The [Color] of the light in linear space. Defaults to white. A black color causes the light to have no effect. + This value is linear to match glTF, but will be converted to nonlinear sRGB when creating a Godot [Light3D] node upon import, or converted to linear when exporting a Godot [Light3D] to glTF. The inner angle of the cone in a spotlight. Must be less than or equal to the outer cone angle. diff --git a/modules/gltf/extensions/gltf_light.cpp b/modules/gltf/extensions/gltf_light.cpp index 41680baf757..15c760bbb8b 100644 --- a/modules/gltf/extensions/gltf_light.cpp +++ b/modules/gltf/extensions/gltf_light.cpp @@ -130,7 +130,7 @@ Ref GLTFLight::from_node(const Light3D *p_light) { Ref l; l.instantiate(); ERR_FAIL_NULL_V_MSG(p_light, l, "Tried to create a GLTFLight from a Light3D node, but the given node was null."); - l->color = p_light->get_color(); + l->color = p_light->get_color().srgb_to_linear(); if (cast_to(p_light)) { l->light_type = "directional"; const DirectionalLight3D *light = cast_to(p_light); @@ -156,33 +156,33 @@ Ref GLTFLight::from_node(const Light3D *p_light) { } Light3D *GLTFLight::to_node() const { + Light3D *light = nullptr; if (light_type == "directional") { - DirectionalLight3D *light = memnew(DirectionalLight3D); - light->set_param(Light3D::PARAM_ENERGY, intensity); - light->set_color(color); - return light; - } - if (light_type == "point") { - OmniLight3D *light = memnew(OmniLight3D); - light->set_param(OmniLight3D::PARAM_ENERGY, intensity); - light->set_param(OmniLight3D::PARAM_RANGE, CLAMP(range, 0, 4096)); - light->set_color(color); - return light; - } - if (light_type == "spot") { - SpotLight3D *light = memnew(SpotLight3D); - light->set_param(SpotLight3D::PARAM_ENERGY, intensity); - light->set_param(SpotLight3D::PARAM_RANGE, CLAMP(range, 0, 4096)); - light->set_param(SpotLight3D::PARAM_SPOT_ANGLE, Math::rad_to_deg(outer_cone_angle)); - light->set_color(color); + DirectionalLight3D *dir_light = memnew(DirectionalLight3D); + dir_light->set_param(Light3D::PARAM_ENERGY, intensity); + light = dir_light; + } else if (light_type == "point") { + OmniLight3D *omni_light = memnew(OmniLight3D); + omni_light->set_param(OmniLight3D::PARAM_ENERGY, intensity); + omni_light->set_param(OmniLight3D::PARAM_RANGE, CLAMP(range, 0, 4096)); + light = omni_light; + } else if (light_type == "spot") { + SpotLight3D *spot_light = memnew(SpotLight3D); + spot_light->set_param(SpotLight3D::PARAM_ENERGY, intensity); + spot_light->set_param(SpotLight3D::PARAM_RANGE, CLAMP(range, 0, 4096)); + spot_light->set_param(SpotLight3D::PARAM_SPOT_ANGLE, Math::rad_to_deg(outer_cone_angle)); // Line of best fit derived from guessing, see https://www.desmos.com/calculator/biiflubp8b // The points in desmos are not exact, except for (1, infinity). float angle_ratio = inner_cone_angle / outer_cone_angle; float angle_attenuation = 0.2 / (1 - angle_ratio) - 0.1; - light->set_param(SpotLight3D::PARAM_SPOT_ATTENUATION, angle_attenuation); - return light; + spot_light->set_param(SpotLight3D::PARAM_SPOT_ATTENUATION, angle_attenuation); + light = spot_light; + } else { + ERR_PRINT("Failed to create a Light3D node from GLTFLight, unknown light type '" + light_type + "'."); + return nullptr; } - return memnew(Light3D); + light->set_color(color.linear_to_srgb()); + return light; } Ref GLTFLight::from_dictionary(const Dictionary p_dictionary) { @@ -195,7 +195,7 @@ Ref GLTFLight::from_dictionary(const Dictionary p_dictionary) { if (p_dictionary.has("color")) { const Array &arr = p_dictionary["color"]; if (arr.size() == 3) { - light->color = Color(arr[0], arr[1], arr[2]).linear_to_srgb(); + light->color = Color(arr[0], arr[1], arr[2]); } else { ERR_PRINT("Error parsing glTF light: The color must have exactly 3 numbers."); }