Blender V4.3
io/usd/hydra/world.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 "world.hh"
6#include "usd_private.hh"
7
8#include <pxr/base/gf/rotation.h>
9#include <pxr/base/gf/vec2f.h>
10#include <pxr/base/vt/array.h>
11#include <pxr/imaging/hd/light.h>
12#include <pxr/imaging/hd/renderDelegate.h>
13#include <pxr/imaging/hd/tokens.h>
14#include <pxr/usd/usdLux/tokens.h>
15
16#include "DNA_node_types.h"
17#include "DNA_scene_types.h"
18
19#include "BLI_math_rotation.h"
20#include "BLI_path_utils.hh"
21
22#include "BKE_node.hh"
23#include "BKE_node_runtime.hh"
24#include "BKE_studiolight.h"
25
26#include "NOD_shader.h"
27
29#include "image.hh"
30
31/* TODO: add custom `tftoken` "transparency"? */
32
33/* NOTE: opacity and blur aren't supported by USD */
34
35namespace blender::io::hydra {
36
37WorldData::WorldData(HydraSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id)
38 : LightData(scene_delegate, nullptr, prim_id)
39{
40 prim_type_ = pxr::HdPrimTypeTokens->domeLight;
41}
42
44{
45 data_.clear();
46
47 float intensity = 1.0f;
48 float exposure = 1.0f;
49 pxr::GfVec3f color(1.0f, 1.0f, 1.0f);
50 pxr::SdfAssetPath texture_file;
51
53 const World *world = scene_delegate_->scene->world;
54 ID_LOG(1, "%s", world->id.name);
55
56 exposure = world->exposure;
57 if (world->use_nodes) {
58 /* TODO: Create nodes parsing system */
59
60 bNode *output_node = ntreeShaderOutputNode(world->nodetree, SHD_OUTPUT_ALL);
61 if (!output_node) {
62 return;
63 }
64 const Span<bNodeSocket *> input_sockets = output_node->input_sockets();
65 bNodeSocket *input_socket = nullptr;
66
67 for (auto socket : input_sockets) {
68 if (STREQ(socket->name, "Surface")) {
69 input_socket = socket;
70 break;
71 }
72 }
73 if (!input_socket) {
74 return;
75 }
76 if (input_socket->directly_linked_links().is_empty()) {
77 return;
78 }
79 bNodeLink const *link = input_socket->directly_linked_links()[0];
80
81 bNode *input_node = link->fromnode;
82 if (input_node->type != SH_NODE_BACKGROUND) {
83 return;
84 }
85
86 const bNodeSocket &color_input = input_node->input_by_identifier("Color");
87 const bNodeSocket &strength_input = input_node->input_by_identifier("Strength");
88
89 float const *strength = strength_input.default_value_typed<float>();
90 float const *input_color = color_input.default_value_typed<float>();
91 intensity = strength[1];
92 color = pxr::GfVec3f(input_color[0], input_color[1], input_color[2]);
93
94 if (!color_input.directly_linked_links().is_empty()) {
95 bNode *color_input_node = color_input.directly_linked_links()[0]->fromnode;
96 if (ELEM(color_input_node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) {
97 NodeTexImage *tex = static_cast<NodeTexImage *>(color_input_node->storage);
98 Image *image = (Image *)color_input_node->id;
99 if (image) {
100 std::string image_path = cache_or_get_image_file(
102 if (!image_path.empty()) {
103 texture_file = pxr::SdfAssetPath(image_path, image_path);
104 }
105 }
106 }
107 }
108 }
109 else {
110 intensity = 1.0f;
111 color = pxr::GfVec3f(world->horr, world->horg, world->horb);
112 }
113
114 if (texture_file.GetAssetPath().empty()) {
115 float fill_color[4] = {color[0], color[1], color[2], 1.0f};
116 std::string image_path = blender::io::usd::cache_image_color(fill_color);
117 texture_file = pxr::SdfAssetPath(image_path, image_path);
118 }
119 }
120 else {
121 ID_LOG(1, "studiolight: %s", scene_delegate_->shading_settings.studiolight_name.c_str());
122
126 if (sl != nullptr && sl->flag & STUDIOLIGHT_TYPE_WORLD) {
127 texture_file = pxr::SdfAssetPath(sl->filepath, sl->filepath);
128 /* coefficient to follow Cycles result */
130 }
131 }
132
133 data_[pxr::UsdLuxTokens->orientToStageUpAxis] = true;
134 data_[pxr::HdLightTokens->intensity] = intensity;
135 data_[pxr::HdLightTokens->exposure] = exposure;
136 data_[pxr::HdLightTokens->color] = color;
137 data_[pxr::HdLightTokens->textureFile] = texture_file;
138
140}
141
143{
144 ID_LOG(1, "");
145
148 {
149 init();
150 if (data_.empty()) {
151 remove();
152 return;
153 }
154 insert();
155 scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(prim_id,
156 pxr::HdLight::AllDirty);
157 }
158 else {
159 remove();
160 }
161}
162
164{
165 transform = pxr::GfMatrix4d().SetRotate(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), 90.0)) *
166 pxr::GfMatrix4d().SetRotate(pxr::GfRotation(pxr::GfVec3d(0.0, 0.0, 1.0), 90.0));
168 transform *= pxr::GfMatrix4d().SetRotate(
169 pxr::GfRotation(pxr::GfVec3d(0.0, 0.0, -1.0),
171 }
172}
173
174} // namespace blender::io::hydra
#define SH_NODE_TEX_IMAGE
Definition BKE_node.hh:930
#define SH_NODE_TEX_ENVIRONMENT
Definition BKE_node.hh:940
@ STUDIOLIGHT_TYPE_WORLD
struct StudioLight * BKE_studiolight_find(const char *name, int flag)
#define STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE
#define RAD2DEGF(_rad)
#define ELEM(...)
#define STREQ(a, b)
@ SHD_OUTPUT_ALL
struct bNode * ntreeShaderOutputNode(struct bNodeTree *ntree, int target)
pxr::SdfPath prim_id
Definition id.hh:36
HydraSceneDelegate * scene_delegate_
Definition id.hh:39
std::map< pxr::TfToken, pxr::VtValue > data_
Definition light.hh:23
WorldData(HydraSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id)
#define ID_LOG(level, msg,...)
Definition id.hh:53
std::string cache_or_get_image_file(Main *bmain, Scene *scene, Image *image, ImageUser *iuser)
std::string cache_image_color(const float color[4])
struct World * world
char filepath[FILE_MAX]
struct ImageUser iuser
struct ID * id
void * storage
int16_t type