Lights: Add exposure property

Similar to other renderers, this adds an exposure property to multiply
the light power by 2^exposure. This can be more convenient to control
a wide range of values.

This is supported in Cycles, EEVEE, Hydra, USD, COLLADA and FBX.

Pull Request: https://projects.blender.org/blender/blender/pulls/134528
This commit is contained in:
Eqkoss / T1NT1N
2025-02-13 21:21:02 +01:00
committed by Brecht Van Lommel
parent a47954fbf2
commit 7e0dad0580
14 changed files with 32 additions and 9 deletions

View File

@@ -1536,6 +1536,7 @@ class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel):
col.prop(light, "color")
col.prop(light, "energy")
col.prop(light, "exposure")
layout.separator()

View File

@@ -75,7 +75,8 @@ void BlenderSync::sync_light(BObjectInfo &b_ob_info, Light *light)
}
/* strength */
const float3 strength = get_float3(b_light.color()) * BL::PointLight(b_light).energy();
const float3 strength = get_float3(b_light.color()) *
(BL::PointLight(b_light).energy() * exp2f(b_light.exposure()));
light->set_strength(strength);
/* shadow */

View File

@@ -170,6 +170,7 @@ class STORM_HYDRA_LIGHT_PT_light(Panel):
main_col.prop(light, "color")
main_col.prop(light, "energy")
main_col.prop(light, "exposure")
main_col.separator()
if light.type == 'POINT':

View File

@@ -204,6 +204,7 @@ def fbx_template_def_light(scene, settings, override_defaults=None, nbr_users=0)
b"CastLight": (True, "p_bool", False),
b"Color": ((1.0, 1.0, 1.0), "p_color", True),
b"Intensity": (100.0, "p_number", True), # Times 100 compared to Blender values...
b"Exposure" : (0.0, "p_number", True ),
b"DecayType": (2, "p_enum", False), # Quadratic.
b"DecayStart": (30.0 * gscale, "p_double", False),
b"CastShadows": (True, "p_bool", False),
@@ -601,12 +602,14 @@ def fbx_data_light_elements(root, lamp, scene_data):
elem_data_single_int32(light, b"GeometryVersion", FBX_GEOMETRY_VERSION) # Sic...
intensity = lamp.energy * 100.0 * pow(2.0, lamp.exposure)
tmpl = elem_props_template_init(scene_data.templates, b"Light")
props = elem_properties(light)
elem_props_template_set(tmpl, props, "p_enum", b"LightType", FBX_LIGHT_TYPES[lamp.type])
elem_props_template_set(tmpl, props, "p_bool", b"CastLight", do_light)
elem_props_template_set(tmpl, props, "p_color", b"Color", lamp.color)
elem_props_template_set(tmpl, props, "p_number", b"Intensity", lamp.energy * 100.0)
elem_props_template_set(tmpl, props, "p_number", b"Intensity", intensity)
elem_props_template_set(tmpl, props, "p_enum", b"DecayType", FBX_LIGHT_DECAY_TYPES['INVERSE_SQUARE'])
elem_props_template_set(tmpl, props, "p_double", b"DecayStart", 25.0 * gscale) # 25 is old Blender default
elem_props_template_set(tmpl, props, "p_bool", b"CastShadows", do_shadow)

View File

@@ -2236,6 +2236,7 @@ def blen_read_light(fbx_tmpl, fbx_obj, settings):
# TODO, cycles nodes???
lamp.color = elem_props_get_color_rgb(fbx_props, b'Color', (1.0, 1.0, 1.0))
lamp.energy = elem_props_get_number(fbx_props, b'Intensity', 100.0) / 100.0
lamp.exposure = elem_props_get_number(fbx_props, b'Exposure', 0.0)
lamp.use_shadow = elem_props_get_bool(fbx_props, b'CastShadow', True)
if hasattr(lamp, "cycles"):
lamp.cycles.cast_shadow = lamp.use_shadow

View File

@@ -91,6 +91,7 @@ class DATA_PT_EEVEE_light(DataButtonsPanel, Panel):
col = layout.column()
col.prop(light, "color")
col.prop(light, "energy")
col.prop(light, "exposure")
layout.separator()

View File

@@ -128,7 +128,7 @@ static void light_blend_write(BlendWriter *writer, ID *id, const void *id_addres
Light *la = (Light *)id;
/* Forward compatibility for energy. */
la->energy_deprecated = la->energy;
la->energy_deprecated = la->energy * exp2f(la->exposure);
if (la->type == LA_AREA) {
la->energy_deprecated /= M_PI_4;
}

View File

@@ -68,7 +68,7 @@ void Light::sync(ShadowModule &shadows,
shadow_discard_safe(shadows);
}
this->color = float3(&la->r) * la->energy;
this->color = float3(&la->r) * (la->energy * exp2f(la->exposure));
float3 scale;
object_to_world.view<3, 3>() = normalize_and_get_size(object_to_world.view<3, 3>(), scale);

View File

@@ -46,7 +46,8 @@ void LightsExporter::operator()(Object *ob)
Light *la = (Light *)ob->data;
std::string la_id(get_light_id(ob));
std::string la_name(id_name(la));
COLLADASW::Color col(la->r * la->energy, la->g * la->energy, la->b * la->energy);
const float energy = la->energy * exp2f(la->exposure);
COLLADASW::Color col(la->r * energy, la->g * energy, la->b * energy);
/* sun */
if (la->type == LA_SUN) {

View File

@@ -85,7 +85,7 @@ void LightData::init()
}
data_[pxr::HdLightTokens->intensity] = intensity;
data_[pxr::HdLightTokens->exposure] = 0.0f;
data_[pxr::HdLightTokens->exposure] = light->exposure;
data_[pxr::HdLightTokens->color] = pxr::GfVec3f(light->r, light->g, light->b);
data_[pxr::HdLightTokens->diffuse] = light->diff_fac;
data_[pxr::HdLightTokens->specular] = light->spec_fac;

View File

@@ -161,7 +161,7 @@ void USDLightReader::read_object_data(Main *bmain, const double motionSampleTime
if (pxr::UsdAttribute exposure_attr = light_api.GetExposureAttr()) {
float exposure = 0.0f;
if (exposure_attr.Get(&exposure, motionSampleTime)) {
blight->energy *= pow(2.0f, exposure);
blight->exposure = exposure;
}
}

View File

@@ -142,8 +142,10 @@ void USDLightWriter::do_write(HierarchyContext &context)
intensity,
timecode,
usd_value_writer_);
set_attribute(
usd_light_api.CreateExposureAttr(pxr::VtValue(), true), 0.0f, timecode, usd_value_writer_);
set_attribute(usd_light_api.CreateExposureAttr(pxr::VtValue(), true),
light->exposure,
timecode,
usd_value_writer_);
set_attribute(usd_light_api.CreateColorAttr(pxr::VtValue(), true),
pxr::GfVec3f(light->r, light->g, light->b),
timecode,

View File

@@ -37,6 +37,8 @@ typedef struct Light {
/* Color and energy. */
float r, g, b;
float energy;
float exposure;
float _pad3;
/* Point light. */
float radius;

View File

@@ -163,6 +163,16 @@ static void rna_def_light(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, nullptr, "mode", LA_SHADOW);
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "exposure", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_default(prop, 0.0f);
RNA_def_property_range(prop, -20.0f, 20.0f);
RNA_def_property_ui_range(prop, -20.0f, 20.0f, 0.01f, 2);
RNA_def_property_ui_text(
prop,
"Exposure",
"Scales the power of the light exponentially, multiplying the intensity by 2^exposure");
RNA_def_property_update(prop, 0, "rna_Light_update");
/* nodes */
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, nullptr, "nodetree");