Lights: Add temperature property
Similar to other renderers, this adds a temperature property to set the light color using blackbody emission. This can be more convenient than using nodes, and can improve interop with other software. This is supported in Cycles, EEVEE, Hydra, USD, COLLADA and FBX. Pull Request: https://projects.blender.org/blender/blender/pulls/134303
This commit is contained in:
parent
7e0dad0580
commit
a12bce039f
@ -1533,8 +1533,30 @@ class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel):
|
||||
layout.row().prop(light, "type")
|
||||
|
||||
col = layout.column()
|
||||
heading = col.column(align=True, heading="Temperature")
|
||||
row = heading.column(align=True).row(align=True)
|
||||
row.prop(light, "use_temperature", text="")
|
||||
# Don't show color preview for now, it is grayed out so the color
|
||||
# is not accurate. Would not a change in the UI code to allow
|
||||
# non-editable colors to be displayed as is.
|
||||
if False: # light.use_temperature:
|
||||
sub = row.split(factor=0.7, align=True)
|
||||
sub.active = light.use_temperature
|
||||
sub.prop(light, "temperature", text="")
|
||||
sub.prop(light, "temperature_color", text="")
|
||||
else:
|
||||
sub = row.row()
|
||||
sub.active = light.use_temperature
|
||||
sub.prop(light, "temperature", text="")
|
||||
|
||||
col.prop(light, "color")
|
||||
if light.use_temperature:
|
||||
col.prop(light, "color", text="Tint")
|
||||
else:
|
||||
col.prop(light, "color", text="Color")
|
||||
|
||||
layout.separator()
|
||||
|
||||
col = layout.column()
|
||||
col.prop(light, "energy")
|
||||
col.prop(light, "exposure")
|
||||
|
||||
@ -1556,6 +1578,7 @@ class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel):
|
||||
sub.prop(light, "size", text="Size X")
|
||||
sub.prop(light, "size_y", text="Y")
|
||||
|
||||
|
||||
class CYCLES_LIGHT_PT_settings(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Settings"
|
||||
bl_context = "data"
|
||||
|
@ -4,6 +4,10 @@
|
||||
|
||||
#include "scene/light.h"
|
||||
|
||||
#include "DNA_light_types.h"
|
||||
|
||||
#include "IMB_colormanagement.hh"
|
||||
|
||||
#include "blender/sync.h"
|
||||
#include "blender/util.h"
|
||||
#include "scene/object.h"
|
||||
@ -74,9 +78,14 @@ void BlenderSync::sync_light(BObjectInfo &b_ob_info, Light *light)
|
||||
}
|
||||
}
|
||||
|
||||
/* strength */
|
||||
const float3 strength = get_float3(b_light.color()) *
|
||||
(BL::PointLight(b_light).energy() * exp2f(b_light.exposure()));
|
||||
/* Color and strength. */
|
||||
float3 light_color = get_float3(b_light.color());
|
||||
if (b_light.use_temperature()) {
|
||||
light_color *= get_float3(b_light.temperature_color());
|
||||
}
|
||||
|
||||
const float3 strength = light_color * BL::PointLight(b_light).energy() *
|
||||
exp2f(b_light.exposure());
|
||||
light->set_strength(strength);
|
||||
|
||||
/* shadow */
|
||||
|
@ -167,8 +167,19 @@ class STORM_HYDRA_LIGHT_PT_light(Panel):
|
||||
layout.use_property_decorate = False
|
||||
|
||||
main_col = layout.column()
|
||||
heading = main_col.column(align=True, heading="Temperature")
|
||||
row = heading.column(align=True).row(align=True)
|
||||
row.prop(light, "use_temperature", text="")
|
||||
sub = row.row()
|
||||
sub.active = light.use_temperature
|
||||
sub.prop(light, "temperature", text="")
|
||||
|
||||
main_col.prop(light, "color")
|
||||
if light.use_temperature:
|
||||
main_col.prop(light, "color", text="Tint")
|
||||
else:
|
||||
main_col.prop(light, "color", text="Color")
|
||||
|
||||
main_col = layout.column()
|
||||
main_col.prop(light, "energy")
|
||||
main_col.prop(light, "exposure")
|
||||
main_col.separator()
|
||||
|
@ -603,12 +603,18 @@ 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)
|
||||
color = lamp.color
|
||||
if lamp.use_temperature:
|
||||
temperature_color = lamp.temperature_color
|
||||
color[0] *= temperature_color[0]
|
||||
color[1] *= temperature_color[1]
|
||||
color[2] *= temperature_color[2]
|
||||
|
||||
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_color", b"Color", color)
|
||||
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
|
||||
|
@ -89,7 +89,30 @@ class DATA_PT_EEVEE_light(DataButtonsPanel, Panel):
|
||||
layout.row().prop(light, "type")
|
||||
|
||||
col = layout.column()
|
||||
col.prop(light, "color")
|
||||
heading = col.column(align=True, heading="Temperature")
|
||||
row = heading.column(align=True).row(align=True)
|
||||
row.prop(light, "use_temperature", text="")
|
||||
# Don't show color preview for now, it is grayed out so the color
|
||||
# is not accurate. Would not a change in the UI code to allow
|
||||
# non-editable colors to be displayed as is.
|
||||
if False: # light.use_temperature:
|
||||
sub = row.split(factor=0.7, align=True)
|
||||
sub.active = light.use_temperature
|
||||
sub.prop(light, "temperature", text="")
|
||||
sub.prop(light, "temperature_color", text="")
|
||||
else:
|
||||
sub = row.row()
|
||||
sub.active = light.use_temperature
|
||||
sub.prop(light, "temperature", text="")
|
||||
|
||||
if light.use_temperature:
|
||||
col.prop(light, "color", text="Tint")
|
||||
else:
|
||||
col.prop(light, "color", text="Color")
|
||||
|
||||
layout.separator()
|
||||
|
||||
col = layout.column()
|
||||
col.prop(light, "energy")
|
||||
col.prop(light, "exposure")
|
||||
|
||||
|
@ -10,11 +10,15 @@
|
||||
*/
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
struct Depsgraph;
|
||||
struct Light;
|
||||
struct Main;
|
||||
|
||||
struct Light *BKE_light_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT;
|
||||
Light *BKE_light_add(Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
void BKE_light_eval(struct Depsgraph *depsgraph, struct Light *la);
|
||||
void BKE_light_eval(Depsgraph *depsgraph, Light *la);
|
||||
|
||||
float BKE_light_power(const Light &light);
|
||||
blender::float3 BKE_light_color(const Light &light);
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
|
||||
#include "IMB_colormanagement.hh"
|
||||
|
||||
#include "BLO_read_write.hh"
|
||||
|
||||
static void light_init_data(ID *id)
|
||||
@ -199,3 +201,21 @@ void BKE_light_eval(Depsgraph *depsgraph, Light *la)
|
||||
{
|
||||
DEG_debug_print_eval(depsgraph, __func__, la->id.name, la);
|
||||
}
|
||||
|
||||
float BKE_light_power(const Light &light)
|
||||
{
|
||||
return light.energy * exp2f(light.exposure);
|
||||
}
|
||||
|
||||
blender::float3 BKE_light_color(const Light &light)
|
||||
{
|
||||
blender::float3 color(&light.r);
|
||||
|
||||
if (light.mode & LA_USE_TEMPERATURE) {
|
||||
float temperature_color[4];
|
||||
IMB_colormanagement_blackbody_temperature_to_rgb(temperature_color, light.temperature);
|
||||
color *= blender::float3(temperature_color);
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_defaults.h"
|
||||
#include "DNA_light_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_sequence_types.h"
|
||||
|
||||
@ -5557,6 +5558,14 @@ void blo_do_versions_450(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 405, 76)) {
|
||||
LISTBASE_FOREACH (Light *, light, &bmain->lights) {
|
||||
if (light->temperature == 0.0f) {
|
||||
light->temperature = 6500.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Always run this versioning (keep at the bottom of the function). Meshes are written with the
|
||||
* legacy format which always needs to be converted to the new format on file load. To be moved
|
||||
* to a subversion check in 5.0. */
|
||||
|
@ -14,11 +14,11 @@
|
||||
|
||||
#include "eevee_light.hh"
|
||||
|
||||
#include "BLI_math_rotation.h"
|
||||
|
||||
#include "DNA_defaults.h"
|
||||
#include "DNA_sdna_type_ids.hh"
|
||||
|
||||
#include "BKE_light.h"
|
||||
|
||||
namespace blender::eevee {
|
||||
|
||||
/* Convert by putting the least significant bits in the first component. */
|
||||
@ -68,7 +68,7 @@ void Light::sync(ShadowModule &shadows,
|
||||
shadow_discard_safe(shadows);
|
||||
}
|
||||
|
||||
this->color = float3(&la->r) * (la->energy * exp2f(la->exposure));
|
||||
this->color = BKE_light_power(*la) * BKE_light_color(*la);
|
||||
|
||||
float3 scale;
|
||||
object_to_world.view<3, 3>() = normalize_and_get_size(object_to_world.view<3, 3>(), scale);
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "LightExporter.h"
|
||||
#include "collada_internal.h"
|
||||
|
||||
#include "BKE_light.h"
|
||||
|
||||
template<class Functor>
|
||||
void forEachLightObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
|
||||
{
|
||||
@ -46,8 +48,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));
|
||||
const float energy = la->energy * exp2f(la->exposure);
|
||||
COLLADASW::Color col(la->r * energy, la->g * energy, la->b * energy);
|
||||
const blender::float3 color = BKE_light_power(*la) * BKE_light_color(*la);
|
||||
COLLADASW::Color col(color[0], color[1], color[2]);
|
||||
|
||||
/* sun */
|
||||
if (la->type == LA_SUN) {
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include "DNA_light_types.h"
|
||||
|
||||
#include "IMB_colormanagement.hh"
|
||||
|
||||
#include "BLI_math_rotation.h"
|
||||
|
||||
#include "hydra_scene_delegate.hh"
|
||||
@ -84,9 +86,13 @@ void LightData::init()
|
||||
intensity = light->energy / M_PI;
|
||||
}
|
||||
|
||||
pxr::GfVec3f color(light->r, light->g, light->b);
|
||||
data_[pxr::HdLightTokens->color] = color; // We multiply the Temperature by 1
|
||||
data_[pxr::HdLightTokens->enableColorTemperature] = (light->mode & LA_USE_TEMPERATURE) != 0;
|
||||
data_[pxr::HdLightTokens->colorTemperature] = light->temperature;
|
||||
|
||||
data_[pxr::HdLightTokens->intensity] = intensity;
|
||||
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;
|
||||
data_[pxr::HdLightTokens->normalize] = true;
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "BKE_light.h"
|
||||
#include "BKE_object.hh"
|
||||
|
||||
#include "IMB_colormanagement.hh"
|
||||
|
||||
#include "DNA_light_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
@ -175,6 +177,23 @@ void USDLightReader::read_object_data(Main *bmain, const double motionSampleTime
|
||||
}
|
||||
}
|
||||
|
||||
/* Temperature */
|
||||
if (pxr::UsdAttribute enable_temperature_attr = light_api.GetEnableColorTemperatureAttr()) {
|
||||
bool enable_temperature = false;
|
||||
if (enable_temperature_attr.Get(&enable_temperature, motionSampleTime)) {
|
||||
if (enable_temperature) {
|
||||
blight->mode |= LA_USE_TEMPERATURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pxr::UsdAttribute color_temperature_attr = light_api.GetColorTemperatureAttr()) {
|
||||
float color_temperature = 6500.0f;
|
||||
if (color_temperature_attr.Get(&color_temperature, motionSampleTime)) {
|
||||
blight->temperature = color_temperature;
|
||||
}
|
||||
}
|
||||
|
||||
/* Diffuse and Specular. */
|
||||
if (pxr::UsdAttribute diff_attr = light_api.GetDiffuseAttr()) {
|
||||
float diff_fac = 1.0f;
|
||||
@ -200,11 +219,6 @@ void USDLightReader::read_object_data(Main *bmain, const double motionSampleTime
|
||||
blight->energy *= light_surface_area;
|
||||
}
|
||||
|
||||
/* TODO:
|
||||
* bool GetEnableColorTemperatureAttr
|
||||
* float GetColorTemperatureAttr
|
||||
*/
|
||||
|
||||
USDXformReader::read_object_data(bmain, motionSampleTime);
|
||||
}
|
||||
|
||||
|
@ -146,10 +146,21 @@ void USDLightWriter::do_write(HierarchyContext &context)
|
||||
light->exposure,
|
||||
timecode,
|
||||
usd_value_writer_);
|
||||
|
||||
set_attribute(usd_light_api.CreateColorAttr(pxr::VtValue(), true),
|
||||
pxr::GfVec3f(light->r, light->g, light->b),
|
||||
timecode,
|
||||
usd_value_writer_);
|
||||
set_attribute(usd_light_api.CreateEnableColorTemperatureAttr(
|
||||
pxr::VtValue(), (light->mode & LA_USE_TEMPERATURE) != 0),
|
||||
true,
|
||||
timecode,
|
||||
usd_value_writer_);
|
||||
set_attribute(usd_light_api.CreateColorTemperatureAttr(pxr::VtValue(), true),
|
||||
light->temperature,
|
||||
timecode,
|
||||
usd_value_writer_);
|
||||
|
||||
set_attribute(usd_light_api.CreateDiffuseAttr(pxr::VtValue(), true),
|
||||
light->diff_fac,
|
||||
timecode,
|
||||
|
@ -19,6 +19,7 @@
|
||||
.r = 1.0f, \
|
||||
.g = 1.0f, \
|
||||
.b = 1.0f, \
|
||||
.temperature = 6500.0f, \
|
||||
.energy = 10.0f, \
|
||||
.energy_deprecated = 10.0f, \
|
||||
.spotsize = DEG2RADF(45.0f), \
|
||||
|
@ -34,11 +34,11 @@ typedef struct Light {
|
||||
short type, flag;
|
||||
int mode;
|
||||
|
||||
/* Color and energy. */
|
||||
/* Color, temperature and energy. */
|
||||
float r, g, b;
|
||||
float temperature;
|
||||
float energy;
|
||||
float exposure;
|
||||
float _pad3;
|
||||
|
||||
/* Point light. */
|
||||
float radius;
|
||||
@ -144,6 +144,7 @@ enum {
|
||||
/** Use absolute resolution clamping instead of relative. */
|
||||
LA_SHAD_RES_ABSOLUTE = 1 << 22,
|
||||
LA_SHADOW_JITTER = 1 << 23,
|
||||
LA_USE_TEMPERATURE = 1 << 24,
|
||||
};
|
||||
|
||||
/** #Light::falloff_type */
|
||||
|
@ -1714,7 +1714,7 @@ void RNA_def_property_ui_range(
|
||||
DefRNA.error = true;
|
||||
}
|
||||
|
||||
if (step < 0 || step > 100) {
|
||||
if (step < 0 || step > 1000) {
|
||||
CLOG_ERROR(&LOG, "\"%s.%s\", step outside range.", srna->identifier, prop->identifier);
|
||||
DefRNA.error = true;
|
||||
}
|
||||
|
@ -14,10 +14,13 @@
|
||||
|
||||
#include "RNA_define.hh"
|
||||
#include "RNA_enum_types.hh"
|
||||
#include "RNA_types.hh"
|
||||
#include "rna_internal.hh"
|
||||
|
||||
#include "DNA_light_types.h"
|
||||
|
||||
#include "IMB_colormanagement.hh"
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
# include "MEM_guardedalloc.h"
|
||||
@ -77,6 +80,18 @@ static void rna_Light_use_nodes_update(bContext *C, PointerRNA *ptr)
|
||||
rna_Light_update(CTX_data_main(C), CTX_data_scene(C), ptr);
|
||||
}
|
||||
|
||||
static void rna_Light_temperature_color_get(PointerRNA *ptr, float *color)
|
||||
{
|
||||
Light *la = (Light *)ptr->data;
|
||||
|
||||
float rgb[4];
|
||||
IMB_colormanagement_blackbody_temperature_to_rgb(rgb, la->temperature);
|
||||
|
||||
color[0] = rgb[0];
|
||||
color[1] = rgb[1];
|
||||
color[2] = rgb[2];
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* NOTE(@dingto): Don't define icons here,
|
||||
@ -109,6 +124,13 @@ static void rna_def_light(BlenderRNA *brna)
|
||||
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_LIGHT);
|
||||
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_temperature", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "mode", LA_USE_TEMPERATURE);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Use Temperature", "Use blackbody temperature to define a natural light color");
|
||||
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_LIGHT);
|
||||
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
|
||||
|
||||
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "r");
|
||||
RNA_def_property_array(prop, 3);
|
||||
@ -116,6 +138,20 @@ static void rna_def_light(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Color", "Light color");
|
||||
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
|
||||
|
||||
prop = RNA_def_property(srna, "temperature", PROP_FLOAT, PROP_TEMPERATURE);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "temperature");
|
||||
RNA_def_property_range(prop, 800.0f, 20000.0f);
|
||||
RNA_def_property_ui_range(prop, 800.0f, 20000.0f, 400.0f, 1);
|
||||
RNA_def_property_ui_text(prop, "Temperature", "Light color temperature in Kelvin");
|
||||
RNA_def_property_update(prop, 0, "rna_Light_update");
|
||||
|
||||
prop = RNA_def_property(srna, "temperature_color", PROP_FLOAT, PROP_COLOR);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_float_funcs(prop, "rna_Light_temperature_color_get", nullptr, nullptr);
|
||||
RNA_def_property_ui_text(prop, "Temperature Color", "Color from Temperature");
|
||||
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
|
||||
|
||||
prop = RNA_def_property(srna, "specular_factor", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "spec_fac");
|
||||
RNA_def_property_range(prop, 0.0f, FLT_MAX);
|
||||
@ -211,7 +247,7 @@ static void rna_def_light_energy(StructRNA *srna, const short light_type)
|
||||
/* Lights with a location have radiometric ppower in Watts,
|
||||
* which is sensitive to scene unit scale. */
|
||||
prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 5);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 3);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Power",
|
||||
@ -225,7 +261,7 @@ static void rna_def_light_energy(StructRNA *srna, const short light_type)
|
||||
/* Lights with a location have radiometric power in Watts,
|
||||
* which is sensitive to scene unit scale. */
|
||||
prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 5);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 3);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Power",
|
||||
"Light energy emitted over the entire area of the light in all "
|
||||
|
Loading…
x
Reference in New Issue
Block a user