Skip to content

Commit

Permalink
reintroduce tracking of closure evaluation based on classification of…
Browse files Browse the repository at this point in the history
… BSDF.

Note : moved handling of "scatter_mode" input to the shader code - making it data driven again.
  • Loading branch information
ld-kerley committed Feb 1, 2025
1 parent 4bd70e7 commit 8d8c8e2
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 52 deletions.
13 changes: 13 additions & 0 deletions libraries/pbrlib/genglsl/mx_dielectric_bsdf.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

void mx_dielectric_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, float weight, vec3 tint, float ior, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf)
{
if (scatter_mode == 1) // BSDF_T (skip reflection - transmission only)
{
return;
}

if (weight < M_FLOAT_EPS)
{
return;
Expand Down Expand Up @@ -38,6 +43,9 @@ void mx_dielectric_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, floa

void mx_dielectric_bsdf_transmission(vec3 V, float weight, vec3 tint, float ior, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf)
{
// Note: If scatter_mode is BSDF_R (reflection only) we must still keep evaluating both reflection/transmission
// since reflection needs to attenuate the transmission amount in HW shaders when layering is used.

if (weight < M_FLOAT_EPS)
{
return;
Expand Down Expand Up @@ -66,6 +74,11 @@ void mx_dielectric_bsdf_transmission(vec3 V, float weight, vec3 tint, float ior,

void mx_dielectric_bsdf_indirect(vec3 V, float weight, vec3 tint, float ior, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf)
{
if (scatter_mode == 1) // BSDF_T (skip reflection - transmission only)
{
return;
}

if (weight < M_FLOAT_EPS)
{
return;
Expand Down
13 changes: 13 additions & 0 deletions libraries/pbrlib/genglsl/mx_generalized_schlick_bsdf.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

void mx_generalized_schlick_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, float weight, vec3 color0, vec3 color82, vec3 color90, float exponent, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf)
{
if (scatter_mode == 1) // BSDF_T (skip reflection - transmission only)
{
return;
}

if (weight < M_FLOAT_EPS)
{
return;
Expand Down Expand Up @@ -40,6 +45,9 @@ void mx_generalized_schlick_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlus

void mx_generalized_schlick_bsdf_transmission(vec3 V, float weight, vec3 color0, vec3 color82, vec3 color90, float exponent, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf)
{
// Note: If scatter_mode is BSDF_R (reflection only) we must still keep evaluating both reflection/transmission
// since reflection needs to attenuate the transmission amount in HW shaders when layering is used.

if (weight < M_FLOAT_EPS)
{
return;
Expand Down Expand Up @@ -72,6 +80,11 @@ void mx_generalized_schlick_bsdf_transmission(vec3 V, float weight, vec3 color0,

void mx_generalized_schlick_bsdf_indirect(vec3 V, float weight, vec3 color0, vec3 color82, vec3 color90, float exponent, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf)
{
if (scatter_mode == 1) // BSDF_T (skip reflection - transmission only)
{
return;
}

if (weight < M_FLOAT_EPS)
{
return;
Expand Down
62 changes: 46 additions & 16 deletions source/MaterialXGenGlsl/Nodes/SurfaceNodeGlsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,7 @@ void SurfaceNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& conte
const string outTransparency = output->getVariable() + ".transparency";

const ShaderInput* bsdfInput = node.getInput("bsdf");
const ShaderNode* bsdf = bsdfInput->getConnectedSibling();
if (bsdf)
if (const ShaderNode* bsdf = bsdfInput->getConnectedSibling())
{
shadergen.emitLineBegin(stage);
shadergen.emitString("float surfaceOpacity = ", stage);
Expand Down Expand Up @@ -144,9 +143,18 @@ void SurfaceNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& conte
shadergen.emitComment("Add environment contribution", stage);
shadergen.emitScopeBegin(stage);

// indirect lighting
context.pushClosureContext(&_callClosure); // indirect
shadergen.emitLine("ClosureData closureData = ClosureData(" + std::to_string(HwShaderGenerator::ClosureContextType::INDIRECT)+", L, V, N, P, occlusion)", stage);
shadergen.emitFunctionCall(*bsdf, context, stage);
if (bsdf->hasClassification(ShaderNode::Classification::BSDF_R)) {
shadergen.emitLine("ClosureData closureData = ClosureData(CLOSURE_TYPE_INDIRECT, L, V, N, P, occlusion)", stage);
shadergen.emitFunctionCall(*bsdf, context, stage);
}
else
{
shadergen.emitLineBegin(stage);
shadergen.emitOutput(bsdf->getOutput(), true, true, context, stage);
shadergen.emitLineEnd(stage);
}
context.popClosureContext();

shadergen.emitLineBreak(stage);
Expand All @@ -159,15 +167,22 @@ void SurfaceNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& conte
// Handle surface emission.
//
const ShaderInput* edfInput = node.getInput("edf");
const ShaderNode* edf = edfInput->getConnectedSibling();
if (edf)
if (const ShaderNode* edf = edfInput->getConnectedSibling())
{
shadergen.emitComment("Add surface emission", stage);
shadergen.emitScopeBegin(stage);

context.pushClosureContext(&_callClosure);
shadergen.emitLine("ClosureData closureData = ClosureData(" + std::to_string(HwShaderGenerator::ClosureContextType::EMISSION)+", L, V, N, P, occlusion)", stage);
shadergen.emitFunctionCall(*edf, context, stage);
context.pushClosureContext(&_callClosure); // emission
if (edf->hasClassification(ShaderNode::Classification::EDF)) {
shadergen.emitLine("ClosureData closureData = ClosureData(CLOSURE_TYPE_EMISSION, L, V, N, P, occlusion)", stage);
shadergen.emitFunctionCall(*edf, context, stage);
}
else
{
shadergen.emitLineBegin(stage);
shadergen.emitOutput(edf->getOutput(), true, true, context, stage);
shadergen.emitLineEnd(stage);
}
context.popClosureContext();

shadergen.emitLine(outColor + " += " + edf->getOutput()->getVariable(), stage);
Expand All @@ -178,13 +193,21 @@ void SurfaceNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& conte
//
// Handle surface transmission and opacity.
//
if (bsdf)
if (const ShaderNode* bsdf = bsdfInput->getConnectedSibling())
{
shadergen.emitComment("Calculate the BSDF transmission for viewing direction", stage);
shadergen.emitScopeBegin(stage);
context.pushClosureContext(&_callClosure); // transmission
shadergen.emitLine("ClosureData closureData = ClosureData(" + std::to_string(HwShaderGenerator::ClosureContextType::TRANSMISSION)+", L, V, N, P, occlusion)", stage);
shadergen.emitFunctionCall(*bsdf, context, stage);
if (bsdf->hasClassification(ShaderNode::Classification::BSDF_T) || bsdf->hasClassification(ShaderNode::Classification::VDF)) {
shadergen.emitLine("ClosureData closureData = ClosureData(CLOSURE_TYPE_TRANSMISSION, L, V, N, P, occlusion)", stage);
shadergen.emitFunctionCall(*bsdf, context, stage);
}
else
{
shadergen.emitLineBegin(stage);
shadergen.emitOutput(bsdf->getOutput(), true, true, context, stage);
shadergen.emitLineEnd(stage);
}

if (context.getOptions().hwTransmissionRenderMethod == TRANSMISSION_REFRACTION)
{
shadergen.emitLine(outColor + " += " + bsdf->getOutput()->getVariable() + ".response", stage);
Expand All @@ -193,7 +216,6 @@ void SurfaceNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& conte
{
shadergen.emitLine(outTransparency + " += " + bsdf->getOutput()->getVariable() + ".response", stage);
}
shadergen.emitScopeEnd(stage);
context.popClosureContext();

shadergen.emitLineBreak(stage);
Expand Down Expand Up @@ -236,8 +258,16 @@ void SurfaceNodeGlsl::emitLightLoop(const ShaderNode& node, GenContext& context,

shadergen.emitComment("Calculate the BSDF response for this light source", stage);
context.pushClosureContext(&_callClosure); // reflection
shadergen.emitLine("ClosureData closureData = ClosureData(" + std::to_string(HwShaderGenerator::ClosureContextType::REFLECTION)+", L, V, N, P, occlusion)", stage);
shadergen.emitFunctionCall(*bsdf, context, stage);
if (bsdf->hasClassification(ShaderNode::Classification::BSDF_R)) {
shadergen.emitLine("ClosureData closureData = ClosureData(CLOSURE_TYPE_REFLECTION, L, V, N, P, occlusion)", stage);
shadergen.emitFunctionCall(*bsdf, context, stage);
}
else
{
shadergen.emitLineBegin(stage);
shadergen.emitOutput(bsdf->getOutput(), true, true, context, stage);
shadergen.emitLineEnd(stage);
}
context.popClosureContext();

shadergen.emitLineBreak(stage);
Expand Down
64 changes: 46 additions & 18 deletions source/MaterialXGenMsl/Nodes/SurfaceNodeMsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,7 @@ void SurfaceNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& contex
const string outTransparency = output->getVariable() + ".transparency";

const ShaderInput* bsdfInput = node.getInput("bsdf");
const ShaderNode* bsdf = bsdfInput->getConnectedSibling();
if (bsdf)
if (const ShaderNode* bsdf = bsdfInput->getConnectedSibling())
{
shadergen.emitLineBegin(stage);
shadergen.emitString("float surfaceOpacity = ", stage);
Expand Down Expand Up @@ -146,9 +145,17 @@ void SurfaceNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& contex
shadergen.emitScopeBegin(stage);

// indirect lighting
context.pushClosureContext(&_callClosure);
shadergen.emitLine("ClosureData closureData = {" + std::to_string(HwShaderGenerator::ClosureContextType::INDIRECT)+", L, V, N, P, occlusion}", stage);
shadergen.emitFunctionCall(*bsdf, context, stage);
context.pushClosureContext(&_callClosure); // indirect
if (bsdf->hasClassification(ShaderNode::Classification::BSDF_R)) {
shadergen.emitLine("ClosureData closureData = {CLOSURE_TYPE_INDIRECT, L, V, N, P, occlusion}", stage);
shadergen.emitFunctionCall(*bsdf, context, stage);
}
else
{
shadergen.emitLineBegin(stage);
shadergen.emitOutput(bsdf->getOutput(), true, true, context, stage);
shadergen.emitLineEnd(stage);
}
context.popClosureContext();

shadergen.emitLineBreak(stage);
Expand All @@ -161,15 +168,22 @@ void SurfaceNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& contex
// Handle surface emission.
//
const ShaderInput* edfInput = node.getInput("edf");
const ShaderNode* edf = edfInput->getConnectedSibling();
if (edf)
if (const ShaderNode* edf = edfInput->getConnectedSibling())
{
shadergen.emitComment("Add surface emission", stage);
shadergen.emitScopeBegin(stage);

context.pushClosureContext(&_callClosure);
shadergen.emitLine("ClosureData closureData = {" + std::to_string(HwShaderGenerator::ClosureContextType::EMISSION)+", L, V, N, P, occlusion}", stage);
shadergen.emitFunctionCall(*edf, context, stage);
context.pushClosureContext(&_callClosure); // emission
if (edf->hasClassification(ShaderNode::Classification::EDF)) {
shadergen.emitLine("ClosureData closureData = {CLOSURE_TYPE_EMISSION, L, V, N, P, occlusion}", stage);
shadergen.emitFunctionCall(*edf, context, stage);
}
else
{
shadergen.emitLineBegin(stage);
shadergen.emitOutput(edf->getOutput(), true, true, context, stage);
shadergen.emitLineEnd(stage);
}
context.popClosureContext();

shadergen.emitLine(outColor + " += " + edf->getOutput()->getVariable(), stage);
Expand All @@ -180,14 +194,21 @@ void SurfaceNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& contex
//
// Handle surface transmission and opacity.
//
if (bsdf)
if (const ShaderNode* bsdf = bsdfInput->getConnectedSibling())
{
shadergen.emitComment("Calculate the BSDF transmission for viewing direction", stage);
shadergen.emitScopeBegin(stage);
context.pushClosureContext(&_callClosure);
shadergen.emitLine("ClosureData closureData = {" + std::to_string(HwShaderGenerator::ClosureContextType::TRANSMISSION)+", L, V, N, P, occlusion}", stage);
context.pushClosureContext(&_callClosure); // transmission
if (bsdf->hasClassification(ShaderNode::Classification::BSDF_T)) {
shadergen.emitLine("ClosureData closureData = {CLOSURE_TYPE_TRANSMISSION, L, V, N, P, occlusion}", stage);
shadergen.emitFunctionCall(*bsdf, context, stage);
}
else
{
shadergen.emitLineBegin(stage);
shadergen.emitOutput(bsdf->getOutput(), true, true, context, stage);
shadergen.emitLineEnd(stage);
}

shadergen.emitFunctionCall(*bsdf, context, stage);
if (context.getOptions().hwTransmissionRenderMethod == TRANSMISSION_REFRACTION)
{
shadergen.emitLine(outColor + " += " + bsdf->getOutput()->getVariable() + ".response", stage);
Expand All @@ -196,7 +217,6 @@ void SurfaceNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& contex
{
shadergen.emitLine(outTransparency + " += " + bsdf->getOutput()->getVariable() + ".response", stage);
}
shadergen.emitScopeEnd(stage);
context.popClosureContext();

shadergen.emitLineBreak(stage);
Expand Down Expand Up @@ -239,8 +259,16 @@ void SurfaceNodeMsl::emitLightLoop(const ShaderNode& node, GenContext& context,

shadergen.emitComment("Calculate the BSDF response for this light source", stage);
context.pushClosureContext(&_callClosure); // reflection
shadergen.emitLine("ClosureData closureData = {" + std::to_string(HwShaderGenerator::ClosureContextType::REFLECTION)+", L, V, N, P, occlusion}", stage);
shadergen.emitFunctionCall(*bsdf, context, stage);
if (bsdf->hasClassification(ShaderNode::Classification::BSDF_R)) {
shadergen.emitLine("ClosureData closureData = {CLOSURE_TYPE_REFLECTION, L, V, N, P, occlusion}", stage);
shadergen.emitFunctionCall(*bsdf, context, stage);
}
else
{
shadergen.emitLineBegin(stage);
shadergen.emitOutput(bsdf->getOutput(), true, true, context, stage);
shadergen.emitLineEnd(stage);
}
context.popClosureContext();

shadergen.emitLineBreak(stage);
Expand Down
17 changes: 0 additions & 17 deletions source/MaterialXGenShader/ShaderNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ const string ShaderNode::CONSTANT = "constant";
const string ShaderNode::DOT = "dot";
const string ShaderNode::IMAGE = "image";
const string ShaderNode::SURFACESHADER = "surfaceshader";
const string ShaderNode::SCATTER_MODE = "scatter_mode";
const string ShaderNode::BSDF_R = "R";
const string ShaderNode::BSDF_T = "T";
const string ShaderNode::TEXTURE2D_GROUPNAME = "texture2d";
Expand Down Expand Up @@ -407,22 +406,6 @@ void ShaderNode::initialize(const Node& node, const NodeDef& nodeDef, GenContext
input->setPath(nodePath + NAME_PATH_SEPARATOR + nodeInput->getName());
}
}

// For BSDF nodes see if there is a scatter_mode input,
// and update the classification accordingly.
if (hasClassification(Classification::BSDF))
{
const InputPtr scatterModeInput = node.getInput(SCATTER_MODE);
const string& scatterMode = scatterModeInput ? scatterModeInput->getValueString() : EMPTY_STRING;
// If scatter mode is only T, set classification to only transmission.
// Note: For only R we must still keep classification at default value (both reflection/transmission)
// since reflection needs to attenuate the transmission amount in HW shaders when layering is used.
if (scatterMode == BSDF_T)
{
_classification |= Classification::BSDF_T;
_classification &= ~Classification::BSDF_R;
}
}
}

void ShaderNode::createMetadata(const NodeDef& nodeDef, GenContext& context)
Expand Down
1 change: 0 additions & 1 deletion source/MaterialXGenShader/ShaderNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,6 @@ class MX_GENSHADER_API ShaderNode
static const string DOT;
static const string IMAGE;
static const string SURFACESHADER;
static const string SCATTER_MODE;
static const string BSDF_R;
static const string BSDF_T;
static const string TRANSFORM_POINT;
Expand Down

0 comments on commit 8d8c8e2

Please sign in to comment.