This is an intermediate steps towards making lights actual geometry. Light is now a subclass of Geometry, which simplifies some code. The geometry is not added to the BVH yet, which would be the next step and improve light intersection performance with many lights. This makes object attributes work on lights. Co-authored-by: Lukas Stockner <lukas@lukasstockner.de> Pull Request: https://projects.blender.org/blender/blender/pulls/134846
183 lines
5.5 KiB
C++
183 lines
5.5 KiB
C++
/* SPDX-FileCopyrightText: 2022 NVIDIA Corporation
|
|
* SPDX-FileCopyrightText: 2022 Blender Foundation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 */
|
|
|
|
#include "hydra/session.h"
|
|
#include "scene/object.h"
|
|
#include "scene/shader.h"
|
|
// Have to include shader.h before background.h so that 'set_shader' uses the correct 'set'
|
|
// overload taking a 'Node *', rather than the one taking a 'bool'
|
|
#include "scene/background.h"
|
|
#include "scene/light.h"
|
|
#include "scene/shader_graph.h"
|
|
#include "scene/shader_nodes.h"
|
|
#include "session/session.h"
|
|
|
|
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
|
|
|
namespace {
|
|
|
|
const std::unordered_map<TfToken, PassType, TfToken::HashFunctor> kAovToPass = {
|
|
{HdAovTokens->color, PASS_COMBINED},
|
|
{HdAovTokens->depth, PASS_DEPTH},
|
|
{HdAovTokens->normal, PASS_NORMAL},
|
|
{HdAovTokens->primId, PASS_OBJECT_ID},
|
|
{HdAovTokens->instanceId, PASS_AOV_VALUE},
|
|
};
|
|
|
|
} // namespace
|
|
|
|
SceneLock::SceneLock(const HdRenderParam *renderParam)
|
|
: scene(static_cast<const HdCyclesSession *>(renderParam)->session->scene.get()),
|
|
sceneLock(scene->mutex)
|
|
{
|
|
}
|
|
|
|
SceneLock::~SceneLock() = default;
|
|
|
|
HdCyclesSession::HdCyclesSession(Session *session_, const bool keep_nodes)
|
|
: session(session_), keep_nodes(keep_nodes), _ownCyclesSession(false)
|
|
{
|
|
}
|
|
|
|
HdCyclesSession::HdCyclesSession(const SessionParams ¶ms)
|
|
: session(new Session(params, SceneParams())), keep_nodes(false), _ownCyclesSession(true)
|
|
{
|
|
Scene *const scene = session->scene.get();
|
|
|
|
// Create background with ambient light
|
|
{
|
|
unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
|
|
|
|
BackgroundNode *bgNode = graph->create_node<BackgroundNode>();
|
|
bgNode->set_color(one_float3());
|
|
|
|
graph->connect(bgNode->output("Background"), graph->output()->input("Surface"));
|
|
|
|
scene->default_background->set_graph(std::move(graph));
|
|
scene->default_background->tag_update(scene);
|
|
}
|
|
|
|
// Wire up object color in default surface material
|
|
{
|
|
unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
|
|
|
|
ObjectInfoNode *objectNode = graph->create_node<ObjectInfoNode>();
|
|
|
|
DiffuseBsdfNode *diffuseNode = graph->create_node<DiffuseBsdfNode>();
|
|
|
|
graph->connect(objectNode->output("Color"), diffuseNode->input("Color"));
|
|
graph->connect(diffuseNode->output("BSDF"), graph->output()->input("Surface"));
|
|
|
|
// Create the instanceId AOV output
|
|
const ustring instanceId(HdAovTokens->instanceId.GetString());
|
|
|
|
OutputAOVNode *aovNode = graph->create_node<OutputAOVNode>();
|
|
aovNode->set_name(instanceId);
|
|
|
|
AttributeNode *instanceIdNode = graph->create_node<AttributeNode>();
|
|
instanceIdNode->set_attribute(instanceId);
|
|
|
|
graph->connect(instanceIdNode->output("Fac"), aovNode->input("Value"));
|
|
|
|
scene->default_surface->set_graph(std::move(graph));
|
|
scene->default_surface->tag_update(scene);
|
|
}
|
|
}
|
|
|
|
HdCyclesSession::~HdCyclesSession()
|
|
{
|
|
if (_ownCyclesSession) {
|
|
delete session;
|
|
}
|
|
}
|
|
|
|
void HdCyclesSession::UpdateScene()
|
|
{
|
|
Scene *const scene = session->scene.get();
|
|
|
|
// Update background depending on presence of a background light
|
|
if (scene->light_manager->need_update()) {
|
|
Light *background_light = nullptr;
|
|
bool have_lights = false;
|
|
for (Object *object : scene->objects) {
|
|
if (!object->get_geometry()->is_light()) {
|
|
continue;
|
|
}
|
|
|
|
have_lights = true;
|
|
|
|
Light *light = static_cast<Light *>(object->get_geometry());
|
|
if (light->get_light_type() == LIGHT_BACKGROUND) {
|
|
background_light = light;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!background_light) {
|
|
scene->background->set_shader(scene->default_background);
|
|
scene->background->set_transparent(true);
|
|
|
|
/* Set background color depending to non-zero value if there are no
|
|
* lights in the scene, to match behavior of other renderers. */
|
|
for (ShaderNode *node : scene->default_background->graph->nodes) {
|
|
if (node->is_a(BackgroundNode::get_node_type())) {
|
|
BackgroundNode *bgNode = static_cast<BackgroundNode *>(node);
|
|
bgNode->set_color((have_lights) ? zero_float3() : make_float3(0.5f));
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
scene->background->set_shader(background_light->get_shader());
|
|
scene->background->set_transparent(false);
|
|
}
|
|
|
|
scene->background->tag_update(scene);
|
|
}
|
|
}
|
|
|
|
void HdCyclesSession::SyncAovBindings(const HdRenderPassAovBindingVector &aovBindings)
|
|
{
|
|
Scene *const scene = session->scene.get();
|
|
|
|
// Delete all existing passes
|
|
const vector<Pass *> &scene_passes = scene->passes;
|
|
scene->delete_nodes(set<Pass *>(scene_passes.begin(), scene_passes.end()));
|
|
|
|
// Update passes with requested AOV bindings
|
|
_aovBindings = aovBindings;
|
|
for (const HdRenderPassAovBinding &aovBinding : aovBindings) {
|
|
const auto cyclesAov = kAovToPass.find(aovBinding.aovName);
|
|
if (cyclesAov == kAovToPass.end()) {
|
|
// TODO: Use PASS_AOV_COLOR and PASS_AOV_VALUE for these?
|
|
TF_WARN("Unknown pass %s", aovBinding.aovName.GetText());
|
|
continue;
|
|
}
|
|
|
|
const PassType type = cyclesAov->second;
|
|
const PassMode mode = PassMode::DENOISED;
|
|
|
|
Pass *pass = scene->create_node<Pass>();
|
|
pass->set_type(type);
|
|
pass->set_mode(mode);
|
|
pass->set_name(ustring(aovBinding.aovName.GetString()));
|
|
}
|
|
}
|
|
|
|
void HdCyclesSession::RemoveAovBinding(HdRenderBuffer *renderBuffer)
|
|
{
|
|
for (HdRenderPassAovBinding &aovBinding : _aovBindings) {
|
|
if (renderBuffer == aovBinding.renderBuffer) {
|
|
aovBinding.renderBuffer = nullptr;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (renderBuffer == _displayAovBinding.renderBuffer) {
|
|
_displayAovBinding.renderBuffer = nullptr;
|
|
}
|
|
}
|
|
|
|
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|