Blender V5.0
hydra/session.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 NVIDIA Corporation
2 * SPDX-FileCopyrightText: 2022 Blender Foundation
3 *
4 * SPDX-License-Identifier: Apache-2.0 */
5
6#include "hydra/session.h"
7#include "scene/object.h"
8#include "scene/shader.h"
9// Have to include shader.h before background.h so that 'set_shader' uses the correct 'set'
10// overload taking a 'Node *', rather than the one taking a 'bool'
11#include "scene/background.h"
12#include "scene/light.h"
13#include "scene/shader_graph.h"
14#include "scene/shader_nodes.h"
15#include "session/session.h"
16
18
19namespace {
20
21const std::unordered_map<TfToken, PassType, TfToken::HashFunctor> kAovToPass = {
22 {HdAovTokens->color, PASS_COMBINED},
23 {HdAovTokens->depth, PASS_DEPTH},
24 {HdAovTokens->normal, PASS_NORMAL},
25 {HdAovTokens->primId, PASS_OBJECT_ID},
26 {HdAovTokens->instanceId, PASS_AOV_VALUE},
27};
28
29} // namespace
30
31SceneLock::SceneLock(const HdRenderParam *renderParam)
32 : scene(static_cast<const HdCyclesSession *>(renderParam)->session->scene.get()),
33 sceneLock(scene->mutex)
34{
35}
36
37SceneLock::~SceneLock() = default;
38
39HdCyclesSession::HdCyclesSession(Session *session_, const bool keep_nodes)
40 : session(session_), keep_nodes(keep_nodes), _ownCyclesSession(false)
41{
42}
43
45 : session(new Session(params, SceneParams())), keep_nodes(false), _ownCyclesSession(true)
46{
47 Scene *const scene = session->scene.get();
48
49 // Create background with ambient light
50 {
51 unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
52
53 BackgroundNode *bgNode = graph->create_node<BackgroundNode>();
54 bgNode->set_color(one_float3());
55
56 graph->connect(bgNode->output("Background"), graph->output()->input("Surface"));
57
58 scene->default_background->set_graph(std::move(graph));
59 scene->default_background->tag_update(scene);
60 }
61
62 // Wire up object color in default surface material
63 {
64 unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
65
66 ObjectInfoNode *objectNode = graph->create_node<ObjectInfoNode>();
67
68 DiffuseBsdfNode *diffuseNode = graph->create_node<DiffuseBsdfNode>();
69
70 graph->connect(objectNode->output("Color"), diffuseNode->input("Color"));
71 graph->connect(diffuseNode->output("BSDF"), graph->output()->input("Surface"));
72
73 // Create the instanceId AOV output
74 const ustring instanceId(HdAovTokens->instanceId.GetString());
75
76 OutputAOVNode *aovNode = graph->create_node<OutputAOVNode>();
77 aovNode->set_name(instanceId);
78
79 AttributeNode *instanceIdNode = graph->create_node<AttributeNode>();
80 instanceIdNode->set_attribute(instanceId);
81
82 graph->connect(instanceIdNode->output("Fac"), aovNode->input("Value"));
83
84 scene->default_surface->set_graph(std::move(graph));
85 scene->default_surface->tag_update(scene);
86 }
87}
88
90{
91 if (_ownCyclesSession) {
92 delete session;
93 }
94}
95
97{
98 Scene *const scene = session->scene.get();
99
100 // Update background depending on presence of a background light
101 if (scene->light_manager->need_update()) {
102 Light *background_light = nullptr;
103 bool have_lights = false;
104 for (Object *object : scene->objects) {
105 if (!object->get_geometry()->is_light()) {
106 continue;
107 }
108
109 have_lights = true;
110
111 Light *light = static_cast<Light *>(object->get_geometry());
112 if (light->get_light_type() == LIGHT_BACKGROUND) {
113 background_light = light;
114 break;
115 }
116 }
117
118 if (!background_light) {
119 scene->background->set_shader(scene->default_background);
120 scene->background->set_transparent(true);
121
122 /* Set background color depending to non-zero value if there are no
123 * lights in the scene, to match behavior of other renderers. */
124 for (ShaderNode *node : scene->default_background->graph->nodes) {
125 if (node->is_a(BackgroundNode::get_node_type())) {
126 BackgroundNode *bgNode = static_cast<BackgroundNode *>(node);
127 bgNode->set_color((have_lights) ? zero_float3() : make_float3(0.5f));
128 }
129 }
130 }
131 else {
132 scene->background->set_shader(background_light->get_shader());
133 scene->background->set_transparent(false);
134 }
135
136 scene->background->tag_update(scene);
137 }
138}
139
140void HdCyclesSession::SyncAovBindings(const HdRenderPassAovBindingVector &aovBindings)
141{
142 Scene *const scene = session->scene.get();
143
144 // Delete all existing passes
145 const vector<Pass *> &scene_passes = scene->passes;
146 scene->delete_nodes(set<Pass *>(scene_passes.begin(), scene_passes.end()));
147
148 // Update passes with requested AOV bindings
149 _aovBindings = aovBindings;
150 for (const HdRenderPassAovBinding &aovBinding : aovBindings) {
151 const auto cyclesAov = kAovToPass.find(aovBinding.aovName);
152 if (cyclesAov == kAovToPass.end()) {
153 // TODO: Use PASS_AOV_COLOR and PASS_AOV_VALUE for these?
154 TF_WARN("Unknown pass %s", aovBinding.aovName.GetText());
155 continue;
156 }
157
158 const PassType type = cyclesAov->second;
159 const PassMode mode = PassMode::DENOISED;
160
161 Pass *pass = scene->create_node<Pass>();
162 pass->set_type(type);
163 pass->set_mode(mode);
164 pass->set_name(ustring(aovBinding.aovName.GetString()));
165 }
166}
167
168void HdCyclesSession::RemoveAovBinding(HdRenderBuffer *renderBuffer)
169{
170 for (HdRenderPassAovBinding &aovBinding : _aovBindings) {
171 if (renderBuffer == aovBinding.renderBuffer) {
172 aovBinding.renderBuffer = nullptr;
173 break;
174 }
175 }
176
177 if (renderBuffer == _displayAovBinding.renderBuffer) {
178 _displayAovBinding.renderBuffer = nullptr;
179 }
180}
181
KDTree *BLI_kdtree_nd_ new(unsigned int nodes_len_capacity)
Definition kdtree_impl.h:98
struct Scene Scene
return true
void tag_update(Scene *scene)
HdCyclesSession(CCL_NS::Session *session_, const bool keep_nodes)
~HdCyclesSession() override
CCL_NS::Session * session
void RemoveAovBinding(PXR_NS::HdRenderBuffer *renderBuffer)
void SyncAovBindings(const PXR_NS::HdRenderPassAovBindingVector &aovBindings)
Definition pass.h:50
ShaderInput * input(const char *name)
ShaderOutput * output(const char *name)
void set_graph(unique_ptr< ShaderGraph > &&graph)
void tag_update(Scene *scene)
NODE_DECLARE unique_ptr< ShaderGraph > graph
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
ThreadMutex mutex
#define HDCYCLES_NAMESPACE_CLOSE_SCOPE
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
PassType
@ PASS_DEPTH
@ PASS_COMBINED
@ PASS_OBJECT_ID
@ PASS_NORMAL
@ PASS_AOV_VALUE
@ LIGHT_BACKGROUND
ccl_device_inline float3 one_float3()
Definition math_float3.h:26
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:17
const std::unordered_map< TfToken, PassType, TfToken::HashFunctor > kAovToPass
std::shared_ptr< const T > get(const GenericKey &key, FunctionRef< std::unique_ptr< T >()> compute_fn)
PassMode
Definition pass.h:20
@ DENOISED
Definition pass.h:22
Shader * get_shader() const
bool is_a(const NodeType *type)
SceneLock(const PXR_NS::HdRenderParam *renderParam)
unique_ptr< LightManager > light_manager
Definition scene.h:146
Shader * default_surface
Definition scene.h:157
Shader * default_background
Definition scene.h:160
T * create_node(Args &&...)=delete
Background * background
Definition scene.h:129
void delete_nodes(const set< T * > &nodes)
Definition scene.h:227
unique_ptr_vector< Object > objects
Definition scene.h:141
unique_ptr_vector< Pass > passes
Definition scene.h:138