Blender V5.0
usd_writer_light.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2019 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4#include "usd_writer_light.hh"
7
8#include <pxr/usd/usdLux/diskLight.h>
9#include <pxr/usd/usdLux/distantLight.h>
10#include <pxr/usd/usdLux/rectLight.h>
11#include <pxr/usd/usdLux/shapingAPI.h>
12#include <pxr/usd/usdLux/sphereLight.h>
13
14#include "BLI_assert.h"
15#include "BLI_math_rotation.h"
16
17#include "DNA_light_types.h"
18
19namespace blender::io::usd {
20
22
23bool USDLightWriter::is_supported(const HierarchyContext * /*context*/) const
24{
25 return true;
26}
27
29{
30 pxr::UsdStageRefPtr stage = usd_export_context_.stage;
31 const pxr::SdfPath &usd_path = usd_export_context_.usd_path;
32 pxr::UsdTimeCode time = get_export_time_code();
33
34 const Light *light = static_cast<const Light *>(context.object->data);
35 pxr::UsdLuxLightAPI usd_light_api;
36
37 switch (light->type) {
38 case LA_AREA: {
39 switch (light->area_shape) {
40 case LA_AREA_RECT: {
41 pxr::UsdLuxRectLight rect_light = pxr::UsdLuxRectLight::Define(stage, usd_path);
42 set_attribute(rect_light.CreateWidthAttr(pxr::VtValue(), true),
43 light->area_size,
44 time,
46 set_attribute(rect_light.CreateHeightAttr(pxr::VtValue(), true),
47 light->area_sizey,
48 time,
50 usd_light_api = rect_light.LightAPI();
51 break;
52 }
53 case LA_AREA_SQUARE: {
54 pxr::UsdLuxRectLight rect_light = pxr::UsdLuxRectLight::Define(stage, usd_path);
55 set_attribute(rect_light.CreateWidthAttr(pxr::VtValue(), true),
56 light->area_size,
57 time,
59 set_attribute(rect_light.CreateHeightAttr(pxr::VtValue(), true),
60 light->area_size,
61 time,
63 usd_light_api = rect_light.LightAPI();
64 break;
65 }
66 case LA_AREA_DISK: {
67 pxr::UsdLuxDiskLight disk_light = pxr::UsdLuxDiskLight::Define(stage, usd_path);
68 set_attribute(disk_light.CreateRadiusAttr(pxr::VtValue(), true),
69 light->area_size / 2.0f,
70 time,
72 usd_light_api = disk_light.LightAPI();
73 break;
74 }
75 case LA_AREA_ELLIPSE: {
76 /* An ellipse light deteriorates into a disk light. */
77 pxr::UsdLuxDiskLight disk_light = pxr::UsdLuxDiskLight::Define(stage, usd_path);
78 set_attribute(disk_light.CreateRadiusAttr(pxr::VtValue(), true),
79 (light->area_size + light->area_sizey) / 4.0f,
80 time,
82 usd_light_api = disk_light.LightAPI();
83 break;
84 }
85 }
86 break;
87 }
88 case LA_LOCAL:
89 case LA_SPOT: {
90 pxr::UsdLuxSphereLight sphere_light = pxr::UsdLuxSphereLight::Define(stage, usd_path);
91 set_attribute(sphere_light.CreateRadiusAttr(pxr::VtValue(), true),
92 light->radius,
93 time,
95 set_attribute(sphere_light.CreateTreatAsPointAttr(pxr::VtValue(), true),
96 light->radius == 0.0f,
97 time,
99
100 if (light->type == LA_SPOT) {
101 pxr::UsdLuxShapingAPI shaping_api = pxr::UsdLuxShapingAPI::Apply(sphere_light.GetPrim());
102 if (shaping_api) {
103 set_attribute(shaping_api.CreateShapingConeAngleAttr(pxr::VtValue(), true),
104 RAD2DEGF(light->spotsize) / 2.0f,
105 time,
107 set_attribute(shaping_api.CreateShapingConeSoftnessAttr(pxr::VtValue(), true),
108 light->spotblend,
109 time,
111 }
112 }
113
114 usd_light_api = sphere_light.LightAPI();
115 break;
116 }
117 case LA_SUN: {
118 pxr::UsdLuxDistantLight distant_light = pxr::UsdLuxDistantLight::Define(stage, usd_path);
119 set_attribute(distant_light.CreateAngleAttr(pxr::VtValue(), true),
120 RAD2DEGF(light->sun_angle / 2.0f),
121 time,
123 usd_light_api = distant_light.LightAPI();
124 break;
125 }
126 default:
128 break;
129 }
130
131 float intensity;
132 if (light->type == LA_SUN) {
133 /* Unclear why, but approximately matches Karma. */
134 intensity = light->energy / 4.0f;
135 }
136 else {
137 /* Convert from radiant flux to intensity. */
138 intensity = light->energy / M_PI;
139 }
140
142 usd_light_api.CreateIntensityAttr(pxr::VtValue(), true), intensity, time, usd_value_writer_);
143 set_attribute(usd_light_api.CreateExposureAttr(pxr::VtValue(), true),
144 light->exposure,
145 time,
147
148 set_attribute(usd_light_api.CreateColorAttr(pxr::VtValue(), true),
149 pxr::GfVec3f(light->r, light->g, light->b),
150 time,
152 set_attribute(usd_light_api.CreateEnableColorTemperatureAttr(
153 pxr::VtValue(), (light->mode & LA_USE_TEMPERATURE) != 0),
154 true,
155 time,
157 set_attribute(usd_light_api.CreateColorTemperatureAttr(pxr::VtValue(), true),
158 light->temperature,
159 time,
161
162 set_attribute(usd_light_api.CreateDiffuseAttr(pxr::VtValue(), true),
163 light->diff_fac,
164 time,
166 set_attribute(usd_light_api.CreateSpecularAttr(pxr::VtValue(), true),
167 light->spec_fac,
168 time,
170 set_attribute(usd_light_api.CreateNormalizeAttr(pxr::VtValue(), true),
171 (light->mode & LA_UNNORMALIZED) == 0,
172 time,
174
175 pxr::UsdPrim prim = usd_light_api.GetPrim();
176 write_id_properties(prim, light->id, time);
177
178 /* Only a subset of light types are "boundable". */
179 if (auto boundable = pxr::UsdGeomBoundable(prim)) {
180 this->author_extent(boundable, time);
181 }
182}
183
184} // namespace blender::io::usd
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define RAD2DEGF(_rad)
#define M_PI
@ 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
void author_extent(const pxr::UsdGeomBoundable &boundable, const pxr::UsdTimeCode time)
const pxr::SdfPath & usd_path() const
pxr::UsdTimeCode get_export_time_code() const
pxr::UsdUtilsSparseValueWriter usd_value_writer_
USDAbstractWriter(const USDExporterContext &usd_export_context)
void write_id_properties(const pxr::UsdPrim &prim, const ID &id, pxr::UsdTimeCode=pxr::UsdTimeCode::Default()) const
const USDExporterContext usd_export_context_
bool is_supported(const HierarchyContext *context) const override
USDLightWriter(const USDExporterContext &ctx)
void do_write(HierarchyContext &context) override
void set_attribute(const pxr::UsdAttribute &attr, const USDT value, pxr::UsdTimeCode time, pxr::UsdUtilsSparseValueWriter &value_writer)
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