USD: improve light units conversion #109795
|
@ -94,6 +94,15 @@ void HdCyclesLight::Sync(HdSceneDelegate *sceneDelegate,
|
|||
strength *= value.Get<float>();
|
||||
}
|
||||
|
||||
if (_lightType == HdPrimTypeTokens->distantLight) {
|
||||
/* Unclear why, but approximately matches Karma. */
|
||||
strength *= 4.0f;
|
||||
}
|
||||
else {
|
||||
/* Convert from intensity to radiant flux. */
|
||||
strength *= M_PI;
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->normalize);
|
||||
_light->set_normalize(value.IsHolding<bool>() && value.UncheckedGet<bool>());
|
||||
|
||||
|
@ -133,9 +142,15 @@ void HdCyclesLight::Sync(HdSceneDelegate *sceneDelegate,
|
|||
}
|
||||
}
|
||||
else if (_lightType == HdPrimTypeTokens->sphereLight) {
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->radius);
|
||||
if (!value.IsEmpty()) {
|
||||
_light->set_size(value.Get<float>());
|
||||
value = sceneDelegate->GetLightParamValue(id, TfToken("treatAsPoint"));
|
||||
if (!value.IsEmpty() && value.Get<bool>()) {
|
||||
_light->set_size(0.0f);
|
||||
}
|
||||
else {
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->radius);
|
||||
if (!value.IsEmpty()) {
|
||||
_light->set_size(value.Get<float>());
|
||||
}
|
||||
}
|
||||
|
||||
bool shaping = false;
|
||||
|
|
|
@ -44,7 +44,7 @@ ccl_device_inline bool point_light_sample(const ccl_global KernelLight *klight,
|
|||
|
||||
ls->P = P + ls->D * ls->t;
|
||||
|
||||
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
|
||||
ls->eval_fac = M_1_PI_F * klight->spot.invarea;
|
||||
if (r_sq == 0) {
|
||||
/* Use intensity instead of radiance for point light. */
|
||||
ls->eval_fac /= sqr(ls->t);
|
||||
|
@ -100,7 +100,7 @@ ccl_device_forceinline void point_light_mnee_sample_update(const ccl_global Kern
|
|||
ls->Ng = normalize(ls->P - klight->co);
|
||||
}
|
||||
else {
|
||||
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
|
||||
ls->eval_fac = M_1_PI_F * klight->spot.invarea;
|
||||
|
||||
ls->Ng = -ls->D;
|
||||
|
||||
|
@ -136,7 +136,7 @@ ccl_device_inline bool point_light_sample_from_intersection(
|
|||
const uint32_t path_flag,
|
||||
ccl_private LightSample *ccl_restrict ls)
|
||||
{
|
||||
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
|
||||
ls->eval_fac = M_1_PI_F * klight->spot.invarea;
|
||||
|
||||
const float radius = klight->spot.radius;
|
||||
|
||||
|
|
|
@ -1152,9 +1152,13 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
|
|||
float3 axis_v = normalize_len(extentv, &len_v);
|
||||
float area = len_u * len_v;
|
||||
if (light->ellipse) {
|
||||
area *= -M_PI_4_F;
|
||||
area *= M_PI_4_F;
|
||||
}
|
||||
float invarea = (area != 0.0f) ? 1.0f / area : 1.0f;
|
||||
if (light->ellipse) {
|
||||
/* Negative inverse area indicates ellipse. */
|
||||
invarea = -invarea;
|
||||
}
|
||||
float3 dir = light->dir;
|
||||
|
||||
dir = safe_normalize(dir);
|
||||
|
@ -1217,8 +1221,9 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
|
|||
/* TODO: `invarea` was used for disk sampling, with the current solid angle sampling this
|
||||
* becomes unnecessary. We could store `eval_fac` instead, but currently it shares the same
|
||||
* #KernelSpotLight type with #LIGHT_SPOT, so keep it know until refactor for spot light. */
|
||||
float invarea = (light->normalize && radius > 0.0f) ? 1.0f / (M_PI_F * radius * radius) :
|
||||
1.0f;
|
||||
float invarea = (radius == 0.0f) ? 1.0f / 4.0f :
|
||||
(light->normalize) ? 1.0f / (4.0f * M_PI_F * radius * radius) :
|
||||
1.0f;
|
||||
|
||||
if (light->use_mis && radius > 0.0f)
|
||||
shader_id |= SHADER_USE_MIS;
|
||||
|
@ -1277,9 +1282,13 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
|
|||
float3 axis_v = normalize_len(extentv, &len_v);
|
||||
float area = len_u * len_v;
|
||||
if (light->ellipse) {
|
||||
area *= -M_PI_4_F;
|
||||
area *= M_PI_4_F;
|
||||
}
|
||||
float invarea = (light->normalize && area != 0.0f) ? 1.0f / area : 1.0f;
|
||||
if (light->ellipse) {
|
||||
/* Negative inverse area indicates ellipse. */
|
||||
invarea = -invarea;
|
||||
}
|
||||
float3 dir = light->dir;
|
||||
|
||||
const float half_spread = 0.5f * light->spread;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include "usd_reader_light.h"
|
||||
|
||||
#include "BLI_math_rotation.h"
|
||||
|
||||
#include "BKE_light.h"
|
||||
#include "BKE_object.h"
|
||||
|
||||
|
@ -80,7 +82,15 @@ void USDLightReader::read_object_data(Main *bmain, const double motionSampleTime
|
|||
if (pxr::UsdAttribute intensity_attr = light_api.GetIntensityAttr()) {
|
||||
float intensity = 0.0f;
|
||||
if (intensity_attr.Get(&intensity, motionSampleTime)) {
|
||||
blight->energy = intensity * this->import_params_.light_intensity_scale;
|
||||
if (blight->type == LA_SUN) {
|
||||
/* Unclear why, but approximately matches Karma. */
|
||||
blight->energy = intensity * 4.0f;
|
||||
}
|
||||
else {
|
||||
/* Convert from intensity to radiant flux. */
|
||||
blight->energy = intensity * M_PI;
|
||||
}
|
||||
blight->energy *= this->import_params_.light_intensity_scale;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,22 +175,6 @@ void USDLightReader::read_object_data(Main *bmain, const double motionSampleTime
|
|||
}
|
||||
break;
|
||||
case LA_LOCAL:
|
||||
if (prim_.IsA<pxr::UsdLuxSphereLight>()) {
|
||||
|
||||
pxr::UsdLuxSphereLight sphere_light(prim_);
|
||||
|
||||
if (!sphere_light) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (pxr::UsdAttribute radius_attr = sphere_light.GetRadiusAttr()) {
|
||||
float radius = 0.0f;
|
||||
if (radius_attr.Get(&radius, motionSampleTime)) {
|
||||
blight->radius = radius;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LA_SPOT:
|
||||
if (prim_.IsA<pxr::UsdLuxSphereLight>()) {
|
||||
|
||||
|
@ -190,28 +184,32 @@ void USDLightReader::read_object_data(Main *bmain, const double motionSampleTime
|
|||
break;
|
||||
}
|
||||
|
||||
if (pxr::UsdAttribute radius_attr = sphere_light.GetRadiusAttr()) {
|
||||
pxr::UsdAttribute treatAsPoint_attr = sphere_light.GetTreatAsPointAttr();
|
||||
bool treatAsPoint;
|
||||
if (treatAsPoint_attr && treatAsPoint_attr.Get(&treatAsPoint, motionSampleTime) &&
|
||||
treatAsPoint) {
|
||||
blight->radius = 0.0f;
|
||||
}
|
||||
else if (pxr::UsdAttribute radius_attr = sphere_light.GetRadiusAttr()) {
|
||||
float radius = 0.0f;
|
||||
if (radius_attr.Get(&radius, motionSampleTime)) {
|
||||
blight->radius = radius;
|
||||
}
|
||||
}
|
||||
|
||||
if (!shaping_api) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (pxr::UsdAttribute cone_angle_attr = shaping_api.GetShapingConeAngleAttr()) {
|
||||
float cone_angle = 0.0f;
|
||||
if (cone_angle_attr.Get(&cone_angle, motionSampleTime)) {
|
||||
blight->spotsize = cone_angle * (float(M_PI) / 180.0f) * 2.0f;
|
||||
if (blight->type == LA_SPOT && shaping_api) {
|
||||
if (pxr::UsdAttribute cone_angle_attr = shaping_api.GetShapingConeAngleAttr()) {
|
||||
float cone_angle = 0.0f;
|
||||
if (cone_angle_attr.Get(&cone_angle, motionSampleTime)) {
|
||||
blight->spotsize = DEG2RADF(cone_angle) * 2.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pxr::UsdAttribute cone_softness_attr = shaping_api.GetShapingConeSoftnessAttr()) {
|
||||
float cone_softness = 0.0f;
|
||||
if (cone_softness_attr.Get(&cone_softness, motionSampleTime)) {
|
||||
blight->spotblend = cone_softness;
|
||||
if (pxr::UsdAttribute cone_softness_attr = shaping_api.GetShapingConeSoftnessAttr()) {
|
||||
float cone_softness = 0.0f;
|
||||
if (cone_softness_attr.Get(&cone_softness, motionSampleTime)) {
|
||||
blight->spotblend = cone_softness;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,11 @@
|
|||
#include <pxr/usd/usdLux/diskLight.h>
|
||||
#include <pxr/usd/usdLux/distantLight.h>
|
||||
#include <pxr/usd/usdLux/rectLight.h>
|
||||
#include <pxr/usd/usdLux/shapingAPI.h>
|
||||
#include <pxr/usd/usdLux/sphereLight.h>
|
||||
|
||||
#include "BLI_assert.h"
|
||||
#include "BLI_math_rotation.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_light_types.h"
|
||||
|
@ -22,7 +24,7 @@ USDLightWriter::USDLightWriter(const USDExporterContext &ctx) : USDAbstractWrite
|
|||
bool USDLightWriter::is_supported(const HierarchyContext *context) const
|
||||
{
|
||||
Light *light = static_cast<Light *>(context->object->data);
|
||||
return ELEM(light->type, LA_AREA, LA_LOCAL, LA_SUN);
|
||||
return ELEM(light->type, LA_AREA, LA_LOCAL, LA_SUN, LA_SPOT);
|
||||
}
|
||||
|
||||
void USDLightWriter::do_write(HierarchyContext &context)
|
||||
|
@ -77,9 +79,22 @@ void USDLightWriter::do_write(HierarchyContext &context)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case LA_LOCAL: {
|
||||
case LA_LOCAL:
|
||||
case LA_SPOT: {
|
||||
pxr::UsdLuxSphereLight sphere_light = pxr::UsdLuxSphereLight::Define(stage, usd_path);
|
||||
sphere_light.CreateRadiusAttr().Set(light->radius, timecode);
|
||||
if (light->radius == 0.0f) {
|
||||
sphere_light.CreateTreatAsPointAttr().Set(true, timecode);
|
||||
}
|
||||
|
||||
if (light->type == LA_SPOT) {
|
||||
pxr::UsdLuxShapingAPI shaping_api = pxr::UsdLuxShapingAPI::Apply(sphere_light.GetPrim());
|
||||
if (shaping_api) {
|
||||
shaping_api.CreateShapingConeAngleAttr().Set(RAD2DEGF(light->spotsize) / 2.0f, timecode);
|
||||
shaping_api.CreateShapingConeSoftnessAttr().Set(light->spotblend, timecode);
|
||||
}
|
||||
}
|
||||
|
||||
#if PXR_VERSION >= 2111
|
||||
usd_light_api = sphere_light.LightAPI();
|
||||
#else
|
||||
|
@ -101,21 +116,20 @@ void USDLightWriter::do_write(HierarchyContext &context)
|
|||
BLI_assert_msg(0, "is_supported() returned true for unsupported light type");
|
||||
}
|
||||
|
||||
/* Scale factor to get to somewhat-similar illumination. Since the USDViewer had similar
|
||||
* over-exposure as Blender Internal with the same values, this code applies the reverse of the
|
||||
* versioning code in light_emission_unify(). */
|
||||
float usd_intensity;
|
||||
if (light->type == LA_SUN) {
|
||||
/* Untested, as the Hydra GL viewport of USDViewer doesn't support distant lights. */
|
||||
usd_intensity = light->energy;
|
||||
/* Unclear why, but approximately matches Karma. */
|
||||
usd_intensity = light->energy / 4.0f;
|
||||
}
|
||||
else {
|
||||
usd_intensity = light->energy / 100.0f;
|
||||
/* Convert from radiant flux to intensity. */
|
||||
usd_intensity = light->energy / M_PI;
|
||||
}
|
||||
usd_light_api.CreateIntensityAttr().Set(usd_intensity, timecode);
|
||||
|
||||
usd_light_api.CreateIntensityAttr().Set(usd_intensity, timecode);
|
||||
usd_light_api.CreateColorAttr().Set(pxr::GfVec3f(light->r, light->g, light->b), timecode);
|
||||
usd_light_api.CreateSpecularAttr().Set(light->spec_fac, timecode);
|
||||
usd_light_api.CreateNormalizeAttr().Set(true, timecode);
|
||||
}
|
||||
|
||||
} // namespace blender::io::usd
|
||||
|
|
Loading…
Reference in New Issue