13 #include <pxr/imaging/hd/sceneDelegate.h>
19 ((cyclesSurface,
"cycles:surface"))
20 ((cyclesDisplacement,
"cycles:displacement"))
21 ((cyclesVolume,
"cycles:volume"))
24 (UsdPrimvarReader_float)
26 (UsdPrimvarReader_float3)
27 (UsdPrimvarReader_float4)
28 (UsdPrimvarReader_int)
45 using ParamMap = std::unordered_map<TfToken, ustring, TfToken::HashFunctor>;
49 : _nodeType(
nodeType), _paramMap(
std::move(paramMap))
60 VtValue *value =
nullptr)
const
65 if (inputConnection) {
66 if (name == CyclesMaterialTokens->a) {
69 if (name == CyclesMaterialTokens->rgb) {
73 if (name == CyclesMaterialTokens->r || name == CyclesMaterialTokens->g ||
74 name == CyclesMaterialTokens->b) {
78 if (name == CyclesMaterialTokens->result) {
96 const auto it = _paramMap.find(name);
97 return it != _paramMap.end() ? it->second.string() : name.GetString();
101 const ustring _nodeType;
111 VtValue *value)
const override
115 if (name == CyclesMaterialTokens->wrapS || name == CyclesMaterialTokens->wrapT) {
116 std::string valueString = VtValue::Cast<std::string>(*value).Get<std::string>();
119 if (valueString ==
"repeat") {
120 *value = VtValue(CyclesMaterialTokens->periodic);
137 {TfToken(
"diffuseColor"), ustring(
"base_color")},
138 {TfToken(
"emissiveColor"), ustring(
"emission")},
139 {TfToken(
"specularColor"), ustring(
"specular")},
140 {TfToken(
"clearcoatRoughness"), ustring(
"clearcoat_roughness")},
141 {TfToken(
"opacity"), ustring(
"alpha")},
149 {CyclesMaterialTokens->st, ustring(
"vector")},
150 {CyclesMaterialTokens->wrapS, ustring(
"extension")},
151 {CyclesMaterialTokens->wrapT, ustring(
"extension")},
152 {TfToken(
"file"), ustring(
"filename")},
153 {TfToken(
"sourceColorSpace"), ustring(
"colorspace")},
156 {{TfToken(
"varname"), ustring(
"attribute")}}};
161 if (usdNodeType == CyclesMaterialTokens->UsdPreviewSurface) {
164 if (usdNodeType == CyclesMaterialTokens->UsdUVTexture) {
167 if (usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_float ||
168 usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_float2 ||
169 usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_float3 ||
170 usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_float4 ||
171 usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_int) {
172 return &UsdPrimvarReader;
182 TfStaticData<UsdToCycles> sUsdToCyles;
196 return DirtyBits::DirtyResource | DirtyBits::DirtyParams;
200 HdRenderParam *renderParam,
201 HdDirtyBits *dirtyBits)
203 if (*dirtyBits == DirtyBits::Clean) {
207 Initialize(renderParam);
211 const bool dirtyParams = (*dirtyBits & DirtyBits::DirtyParams);
212 const bool dirtyResource = (*dirtyBits & DirtyBits::DirtyResource);
215 const SdfPath &
id = GetId();
217 if (dirtyResource || dirtyParams) {
218 value = sceneDelegate->GetMaterialResource(
id);
221 const HdMaterialNetwork2 *network =
nullptr;
222 std::unique_ptr<HdMaterialNetwork2> networkConverted;
223 if (value.IsHolding<HdMaterialNetwork2>()) {
224 network = &value.UncheckedGet<HdMaterialNetwork2>();
226 else if (value.IsHolding<HdMaterialNetworkMap>()) {
227 const auto &networkOld = value.UncheckedGet<HdMaterialNetworkMap>();
230 if (!_nodes.empty() && !dirtyResource) {
231 for (
const auto &networkEntry : networkOld.map) {
232 UpdateParameters(networkEntry.second);
234 _shader->tag_modified();
237 networkConverted = std::make_unique<HdMaterialNetwork2>();
238 HdMaterialNetwork2ConvertFromHdMaterialNetworkMap(networkOld, networkConverted.get());
239 network = networkConverted.get();
243 TF_RUNTIME_ERROR(
"Could not get a HdMaterialNetwork2.");
247 if (!_nodes.empty() && !dirtyResource) {
248 UpdateParameters(*network);
249 _shader->tag_modified();
252 PopulateShaderGraph(*network);
258 if (_shader->is_modified()) {
259 _shader->tag_update(
lock.scene);
262 *dirtyBits = DirtyBits::Clean;
265 void HdCyclesMaterial::UpdateParameters(NodeDesc &nodeDesc,
267 const SdfPath &nodePath)
270 VtValue value = param.second;
274 const std::string inputName = inputMapping ?
276 param.first.GetString();
288 TF_WARN(
"Could not find parameter '%s' on node '%s' ('%s')",
289 param.first.GetText(),
291 nodeDesc.node->name.c_str());
299 void HdCyclesMaterial::UpdateParameters(
const HdMaterialNetwork &network)
301 for (
const HdMaterialNode &nodeEntry : network.nodes) {
302 const SdfPath &nodePath = nodeEntry.path;
304 const auto nodeIt = _nodes.find(nodePath);
305 if (nodeIt == _nodes.end()) {
306 TF_RUNTIME_ERROR(
"Could not update parameters on missing node '%s'", nodePath.GetText());
310 UpdateParameters(nodeIt->second, nodeEntry.parameters, nodePath);
314 void HdCyclesMaterial::UpdateParameters(
const HdMaterialNetwork2 &network)
316 for (
const auto &nodeEntry : network.nodes) {
317 const SdfPath &nodePath = nodeEntry.first;
319 const auto nodeIt = _nodes.find(nodePath);
320 if (nodeIt == _nodes.end()) {
321 TF_RUNTIME_ERROR(
"Could not update parameters on missing node '%s'", nodePath.GetText());
325 UpdateParameters(nodeIt->second, nodeEntry.second.parameters, nodePath);
329 void HdCyclesMaterial::UpdateConnections(NodeDesc &nodeDesc,
330 const HdMaterialNode2 &matNode,
331 const SdfPath &nodePath,
334 for (
const auto &connection : matNode.inputConnections) {
335 const TfToken &dstSocketName = connection.first;
338 const std::string inputName = inputMapping ?
340 dstSocketName.GetString();
352 TF_WARN(
"Ignoring connection on '%s.%s', input '%s' was not found",
354 dstSocketName.GetText(),
355 dstSocketName.GetText());
360 const auto &connectedNodes = connection.second;
361 if (connectedNodes.empty()) {
367 if (connectedNodes.size() > 1) {
369 "Ignoring multiple connections to '%s.%s'", nodePath.GetText(), dstSocketName.GetText());
372 const SdfPath &upstreamNodePath = connectedNodes.front().upstreamNode;
373 const TfToken &upstreamOutputName = connectedNodes.front().upstreamOutputName;
375 const auto srcNodeIt = _nodes.find(upstreamNodePath);
376 if (srcNodeIt == _nodes.end()) {
377 TF_WARN(
"Ignoring connection from '%s.%s' to '%s.%s', node '%s' was not found",
378 upstreamNodePath.GetText(),
379 upstreamOutputName.GetText(),
381 dstSocketName.GetText(),
382 upstreamNodePath.GetText());
387 const std::string outputName = outputMapping ?
389 upstreamOutputName.GetString();
400 TF_WARN(
"Ignoring connection from '%s.%s' to '%s.%s', output '%s' was not found",
401 upstreamNodePath.GetText(),
402 upstreamOutputName.GetText(),
404 dstSocketName.GetText(),
405 upstreamOutputName.GetText());
413 void HdCyclesMaterial::PopulateShaderGraph(
const HdMaterialNetwork2 &networkMap)
420 for (
const auto &nodeEntry : networkMap.nodes) {
421 NodeDesc nodeDesc = {};
422 const SdfPath &nodePath = nodeEntry.first;
424 const auto nodeIt = _nodes.find(nodePath);
426 if (nodeIt != _nodes.end()) {
427 nodeDesc = nodeIt->second;
431 const std::string &nodeTypeId = nodeEntry.second.nodeTypeId.GetString();
433 ustring cyclesType(nodeTypeId);
435 if (nodeTypeId.rfind(
"cycles", 0) == 0) {
436 cyclesType = nodeTypeId.substr(7);
437 nodeDesc.mapping = sUsdToCyles->findCycles(cyclesType);
441 nodeDesc.mapping = sUsdToCyles->findUsd(nodeEntry.second.nodeTypeId);
442 if (nodeDesc.mapping) {
443 cyclesType = nodeDesc.mapping->nodeType();
449 nodeDesc.node =
static_cast<ShaderNode *
>(nodeType->create(nodeType));
452 graph->add(nodeDesc.node);
454 _nodes.emplace(nodePath, nodeDesc);
457 TF_RUNTIME_ERROR(
"Could not create node '%s'", nodePath.GetText());
462 UpdateParameters(nodeDesc, nodeEntry.second.parameters, nodePath);
467 for (
const auto &nodeEntry : networkMap.nodes) {
468 const SdfPath &nodePath = nodeEntry.first;
470 const auto nodeIt = _nodes.find(nodePath);
471 if (nodeIt == _nodes.end()) {
472 TF_RUNTIME_ERROR(
"Could not find node '%s' to connect", nodePath.GetText());
476 UpdateConnections(nodeIt->second, nodeEntry.second, nodePath,
graph);
480 for (
const auto &terminalEntry : networkMap.terminals) {
481 const TfToken &terminalName = terminalEntry.first;
482 const HdMaterialConnection2 &connection = terminalEntry.second;
484 const auto nodeIt = _nodes.find(connection.upstreamNode);
485 if (nodeIt == _nodes.end()) {
486 TF_RUNTIME_ERROR(
"Could not find terminal node '%s'", connection.upstreamNode.GetText());
492 const char *inputName =
nullptr;
493 const char *outputName =
nullptr;
494 if (terminalName == HdMaterialTerminalTokens->surface ||
495 terminalName == CyclesMaterialTokens->cyclesSurface) {
496 inputName =
"Surface";
498 if (
node->type->name ==
"add_closure" ||
node->type->name ==
"mix_closure") {
499 outputName =
"Closure";
501 else if (
node->type->name ==
"emission") {
502 outputName =
"Emission";
508 else if (terminalName == HdMaterialTerminalTokens->displacement ||
509 terminalName == CyclesMaterialTokens->cyclesDisplacement) {
510 inputName = outputName =
"Displacement";
512 else if (terminalName == HdMaterialTerminalTokens->volume ||
513 terminalName == CyclesMaterialTokens->cyclesVolume) {
514 inputName = outputName =
"Volume";
517 if (!connection.upstreamOutputName.IsEmpty()) {
518 outputName = connection.upstreamOutputName.GetText();
523 TF_RUNTIME_ERROR(
"Could not find terminal input '%s.%s'",
524 connection.upstreamNode.GetText(),
525 inputName ? inputName :
"<null>");
531 TF_RUNTIME_ERROR(
"Could not find terminal output '%s.%s'",
532 connection.upstreamNode.GetText(),
533 outputName ? outputName :
"<null>");
542 const ustring instanceId(HdAovTokens->instanceId.GetString());
545 aovNode->set_name(instanceId);
549 instanceIdNode->set_attribute(instanceId);
550 graph->add(instanceIdNode);
555 _shader->set_graph(
graph);
565 const bool keep_nodes =
static_cast<const HdCyclesSession *
>(renderParam)->keep_nodes;
570 lock.scene->delete_node(_shader);
575 void HdCyclesMaterial::Initialize(HdRenderParam *renderParam)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override
void Finalize(PXR_NS::HdRenderParam *renderParam) override
HdCyclesMaterial(const PXR_NS::SdfPath &sprimId)
~HdCyclesMaterial() override
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate, PXR_NS::HdRenderParam *renderParam, PXR_NS::HdDirtyBits *dirtyBits) override
void connect(ShaderOutput *from, ShaderInput *to)
ShaderInput * input(const char *name)
ShaderOutput * output(const char *name)
virtual std::string parameterName(const TfToken &name, const ShaderInput *inputConnection, VtValue *value=nullptr) const
UsdToCyclesMapping(const char *nodeType, ParamMap paramMap)
std::string parameterName(const TfToken &name, const ShaderInput *inputConnection, VtValue *value) const override
#define HDCYCLES_NAMESPACE_CLOSE_SCOPE
ccl_global KernelShaderEvalInput ccl_global float * output
ccl_global KernelShaderEvalInput * input
double parameters[NUM_PARAMETERS]
HDCYCLES_NAMESPACE_OPEN_SCOPE TF_DEFINE_PRIVATE_TOKENS(CyclesMaterialTokens,((cyclesSurface, "cycles:surface"))((cyclesDisplacement, "cycles:displacement"))((cyclesVolume, "cycles:volume"))(UsdPreviewSurface)(UsdUVTexture)(UsdPrimvarReader_float)(UsdPrimvarReader_float2)(UsdPrimvarReader_float3)(UsdPrimvarReader_float4)(UsdPrimvarReader_int)(UsdTransform2d)(a)(rgb)(r)(g)(b)(result)(st)(wrapS)(wrapT)(periodic))
static const pxr::TfToken st("st", pxr::TfToken::Immortal)
static const pxr::TfToken UsdPreviewSurface("UsdPreviewSurface", pxr::TfToken::Immortal)
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
static const pxr::TfToken UsdUVTexture("UsdUVTexture", pxr::TfToken::Immortal)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static const pxr::TfToken g("g", pxr::TfToken::Immortal)
static const pxr::TfToken rgb("rgb", pxr::TfToken::Immortal)
static const pxr::TfToken UsdPrimvarReader_float2("UsdPrimvarReader_float2", pxr::TfToken::Immortal)
void SetNodeValue(Node *node, const SocketType &socket, const VtValue &value)
bool string_iequals(const string &a, const string &b)
static const NodeType * find(ustring name)
void set_owner(const NodeOwner *owner_)