Blender V5.0
io/usd/hydra/light.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "light.hh"
6
7#include <pxr/imaging/hd/light.h>
8#include <pxr/imaging/hd/tokens.h>
9#include <pxr/usd/usdLux/tokens.h>
10
11#include "DNA_light_types.h"
12
14
15#include "BLI_math_rotation.h"
16
18
19namespace blender::io::hydra {
20
22 const Object *object,
23 pxr::SdfPath const &prim_id)
24 : ObjectData(scene_delegate, object, prim_id)
25{
26}
27
29{
30 ID_LOGN("");
31
32 const Light *light = (const Light *)((const Object *)id)->data;
33 data_.clear();
34
35 switch (light->type) {
36 case LA_AREA: {
37 switch (light->area_shape) {
38 case LA_AREA_SQUARE:
39 data_[pxr::HdLightTokens->width] = light->area_size;
40 data_[pxr::HdLightTokens->height] = light->area_size;
41 break;
42 case LA_AREA_RECT:
43 data_[pxr::HdLightTokens->width] = light->area_size;
44 data_[pxr::HdLightTokens->height] = light->area_sizey;
45 break;
46 case LA_AREA_DISK:
47 data_[pxr::HdLightTokens->radius] = light->area_size / 2.0f;
48 break;
49 case LA_AREA_ELLIPSE:
50 /* An ellipse light deteriorates into a disk light. */
51 data_[pxr::HdLightTokens->radius] = (light->area_size + light->area_sizey) / 4.0f;
52 break;
53 }
54 break;
55 }
56 case LA_LOCAL:
57 case LA_SPOT: {
58 data_[pxr::HdLightTokens->radius] = light->radius;
59 if (light->radius == 0.0f) {
60 data_[pxr::UsdLuxTokens->treatAsPoint] = true;
61 }
62
63 if (light->type == LA_SPOT) {
64 data_[pxr::UsdLuxTokens->inputsShapingConeAngle] = RAD2DEGF(light->spotsize * 0.5f);
65 data_[pxr::UsdLuxTokens->inputsShapingConeSoftness] = light->spotblend;
66 }
67 break;
68 }
69 case LA_SUN: {
70 data_[pxr::HdLightTokens->angle] = RAD2DEGF(light->sun_angle * 0.5f);
71 break;
72 }
73 default: {
75 break;
76 }
77 }
78
79 float intensity;
80 if (light->type == LA_SUN) {
81 /* Unclear why, but approximately matches Karma. */
82 intensity = light->energy / 4.0f;
83 }
84 else {
85 /* Convert from radiant flux to intensity. */
86 intensity = light->energy / M_PI;
87 }
88
89 pxr::GfVec3f color(light->r, light->g, light->b);
90 data_[pxr::HdLightTokens->color] = color; /* We multiply the Temperature by 1. */
91 data_[pxr::HdLightTokens->enableColorTemperature] = (light->mode & LA_USE_TEMPERATURE) != 0;
92 data_[pxr::HdLightTokens->colorTemperature] = light->temperature;
93
94 data_[pxr::HdLightTokens->intensity] = intensity;
95 data_[pxr::HdLightTokens->exposure] = light->exposure;
96 data_[pxr::HdLightTokens->diffuse] = light->diff_fac;
97 data_[pxr::HdLightTokens->specular] = light->spec_fac;
98 data_[pxr::HdLightTokens->normalize] = (light->mode & LA_UNNORMALIZED) == 0;
99
100 prim_type_ = prim_type(light);
101
103}
104
106{
107 ID_LOGN("");
108 scene_delegate_->GetRenderIndex().InsertSprim(prim_type_, scene_delegate_, prim_id);
109}
110
112{
113 ID_LOG("");
114 scene_delegate_->GetRenderIndex().RemoveSprim(prim_type_, prim_id);
115}
116
118{
119 const Object *object = (const Object *)id;
120 const Light *light = (const Light *)object->data;
121 pxr::HdDirtyBits bits = pxr::HdLight::Clean;
122 if (id->recalc & ID_RECALC_GEOMETRY || light->id.recalc & ID_RECALC_GEOMETRY) {
123 if (prim_type(light) != prim_type_) {
124 remove();
125 init();
126 insert();
127 return;
128 }
129 init();
130 bits = pxr::HdLight::AllDirty;
131 }
132 else if (id->recalc & ID_RECALC_TRANSFORM) {
134 bits = pxr::HdLight::DirtyTransform;
135 }
136 if (bits != pxr::HdChangeTracker::Clean) {
137 scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(prim_id, bits);
138 ID_LOGN("");
139 }
140}
141
142pxr::VtValue LightData::get_data(pxr::TfToken const &key) const
143{
144 ID_LOGN("%s", key.GetText());
145 auto it = data_.find(key);
146 if (it != data_.end()) {
147 return pxr::VtValue(it->second);
148 }
149
150 return pxr::VtValue();
151}
152
153pxr::TfToken LightData::prim_type(const Light *light)
154{
155 switch (light->type) {
156 case LA_AREA:
157 switch (light->area_shape) {
158 case LA_AREA_SQUARE:
159 case LA_AREA_RECT:
160 return pxr::HdPrimTypeTokens->rectLight;
161
162 case LA_AREA_DISK:
163 case LA_AREA_ELLIPSE:
164 return pxr::HdPrimTypeTokens->diskLight;
165
166 default:
167 return pxr::HdPrimTypeTokens->rectLight;
168 }
169 break;
170
171 case LA_LOCAL:
172 case LA_SPOT:
173 return pxr::HdPrimTypeTokens->sphereLight;
174
175 case LA_SUN:
176 return pxr::HdPrimTypeTokens->distantLight;
177
178 default:
180 }
181 return pxr::TfToken();
182}
183
184} // namespace blender::io::hydra
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define RAD2DEGF(_rad)
#define M_PI
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1054
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ LA_AREA
@ LA_LOCAL
@ LA_SPOT
@ LA_SUN
@ LA_USE_TEMPERATURE
@ LA_UNNORMALIZED
@ LA_AREA_ELLIPSE
@ LA_AREA_SQUARE
@ LA_AREA_RECT
@ LA_AREA_DISK
pxr::SdfPath prim_id
Definition id.hh:36
HydraSceneDelegate * scene_delegate_
Definition id.hh:39
pxr::TfToken prim_type(const Light *light)
LightData(HydraSceneDelegate *scene_delegate, const Object *object, pxr::SdfPath const &prim_id)
std::map< pxr::TfToken, pxr::VtValue > data_
Definition light.hh:23
pxr::VtValue get_data(pxr::TfToken const &key) const override
ObjectData(HydraSceneDelegate *scene_delegate, const Object *object, pxr::SdfPath const &prim_id)
#define ID_LOGN(msg,...)
Definition id.hh:55
#define ID_LOG(msg,...)
Definition id.hh:53
unsigned int recalc
Definition DNA_ID.h:445
float sun_angle
float energy
float temperature
float spec_fac
float area_sizey
short area_shape
float spotblend
float spotsize
float exposure
float radius
float area_size
short type
float diff_fac