Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle Topological Value Changes #1406

Closed
wants to merge 11 commits into from
41 changes: 41 additions & 0 deletions source/MaterialXGenShader/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,47 @@ bool hasElementAttributes(OutputPtr output, const StringVec& attributes)
return false;
}

bool inputChangeRequiresShaderGen(InputPtr input, const string& target)
jstone-lucasfilm marked this conversation as resolved.
Show resolved Hide resolved
jstone-lucasfilm marked this conversation as resolved.
Show resolved Hide resolved
{
ElementPtr inputParent = input ? input->getParent() : nullptr;
if (inputParent)
{
NodePtr node = inputParent->asA<Node>();
if (node)
{
NodeDefPtr nodeDef = node->getNodeDef(target);
// All conditional nodes are considered to change the topology of the shader graph
if (nodeDef->getNodeGroup() == NodeDef::CONDITIONAL_NODE_GROUP)
{
return true;
}
}

// This is an interface input so find what it's connected to.
NodeGraphPtr nodeGraph = inputParent->asA<NodeGraph>();
if (nodeGraph)
{
const std::string& inputName = input->getName();
for (NodePtr graphNode : nodeGraph->getNodes())
{
for (InputPtr graphNodeInput : graphNode->getActiveInputs())
{
if (graphNodeInput->getInterfaceName() == inputName)
{
NodeDefPtr nodeDef = graphNode->getNodeDef();
// All conditional nodes are considered to change the topology of the shader graph
if (nodeDef->getNodeGroup() == NodeDef::CONDITIONAL_NODE_GROUP)
{
return true;
}
}
}
}
}
}
return false;
}

void findRenderableMaterialNodes(ConstDocumentPtr doc, vector<TypedElementPtr>& elements, bool, std::unordered_set<ElementPtr>&)
{
elements = findRenderableMaterialNodes(doc);
Expand Down
8 changes: 8 additions & 0 deletions source/MaterialXGenShader/Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ MX_GENSHADER_API NodePtr connectsToWorldSpaceNode(OutputPtr output);
/// @param attributes Attributes to test for
MX_GENSHADER_API bool hasElementAttributes(OutputPtr output, const StringVec& attributes);

/// Returns true if a value change on a given input could require a shader compilation as it changes the output shader
/// graph configuration (i.e. is a topological change).
/// The current criteria is:
/// * any input on a conditional node is considered to modify the topology of the output shader graph.
/// @param input Input to test
/// @param target An optional target name which may be used as part of the criteria
MX_GENSHADER_API bool inputChangeRequiresShaderGen(InputPtr input, const string& target = EMPTY_STRING);

//
// These are deprecated wrappers for older versions of the function interfaces in this module.
// Clients using these interfaces should update them to the latest API.
Expand Down
61 changes: 41 additions & 20 deletions source/MaterialXGraphEditor/Graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,7 @@ void Graph::setRenderMaterial(UiNodePtr node)
_currRenderNode = node;
_frameCount = ImGui::GetFrameCount();
_renderer->setMaterialCompilation(true);
_shaderPopup = true;
jstone-lucasfilm marked this conversation as resolved.
Show resolved Hide resolved
}
}
else
Expand All @@ -734,6 +735,7 @@ void Graph::setRenderMaterial(UiNodePtr node)
_currRenderNode = shaderOut[0];
_frameCount = ImGui::GetFrameCount();
_renderer->setMaterialCompilation(true);
_shaderPopup = true;
}
}
}
Expand All @@ -750,6 +752,7 @@ void Graph::setRenderMaterial(UiNodePtr node)
_currRenderNode = outNodes[0];
_frameCount = ImGui::GetFrameCount();
_renderer->setMaterialCompilation(true);
_shaderPopup = true;
}
}
}
Expand Down Expand Up @@ -811,29 +814,24 @@ void Graph::updateMaterials(mx::InputPtr input, mx::ValuePtr value)
{
if (!input)
{
mx::ElementPtr elem = nullptr;
{
elem = _graphDoc->getDescendant(renderablePath);
}
mx::ElementPtr elem = _graphDoc->getDescendant(renderablePath);
mx::TypedElementPtr typedElem = elem ? elem->asA<mx::TypedElement>() : nullptr;
_renderer->updateMaterials(typedElem);
}
else
{
std::string name = input->getNamePath();
// need to use exact interface name in order for input
std::string name = input->getNamePath();
mx::InputPtr interfaceInput = findInput(input, input->getName());
if (interfaceInput)
{
name = interfaceInput->getNamePath();
}
// Note that if there is a topogical change due to
jstone-lucasfilm marked this conversation as resolved.
Show resolved Hide resolved
// this value change or a transparency change, then
// this is not currently caught here.
_renderer->getMaterials()[num]->modifyUniform(name, value);
}
}
}

// set the value of the selected node constants in the node property editor
void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIProperties& uiProperties)
{
Expand All @@ -843,6 +841,8 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
mx::ValuePtr minVal = uiProperties.uiMin;
mx::ValuePtr maxVal = uiProperties.uiMax;

bool updateMaterialRequired = false;

// if input is a float set the float slider Ui to the value
if (input->getType() == "float")
{
Expand All @@ -861,7 +861,7 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
{
addNodeInput(_currUiNode, input);
input->setValue(temp, input->getType());
updateMaterials(input, input->getValue());
updateMaterialRequired = true;
}
}
}
Expand All @@ -880,7 +880,7 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
{
addNodeInput(_currUiNode, input);
input->setValue(temp, input->getType());
updateMaterials(input, input->getValue());
updateMaterialRequired = true;
}
}
}
Expand All @@ -904,7 +904,7 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
{
addNodeInput(_currUiNode, input);
input->setValue(temp, input->getType());
updateMaterials(input, input->getValue());
updateMaterialRequired = true;
}
}
}
Expand All @@ -928,7 +928,7 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
{
addNodeInput(_currUiNode, input);
input->setValue(temp, input->getType());
updateMaterials(input, input->getValue());
updateMaterialRequired = true;
}
}
}
Expand All @@ -947,7 +947,7 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
{
addNodeInput(_currUiNode, input);
input->setValue(temp, input->getType());
updateMaterials(input, input->getValue());
updateMaterialRequired = true;
}
}
}
Expand All @@ -966,7 +966,7 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
{
addNodeInput(_currUiNode, input);
input->setValue(temp, input->getType());
updateMaterials(input, input->getValue());
updateMaterialRequired = true;
}
}
}
Expand All @@ -985,7 +985,7 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
{
addNodeInput(_currUiNode, input);
input->setValue(temp, input->getType());
updateMaterials(input, input->getValue());
updateMaterialRequired = true;
}
}
}
Expand All @@ -1001,7 +1001,7 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
{
addNodeInput(_currUiNode, input);
input->setValue(temp, input->getType());
updateMaterials();
updateMaterialRequired = true;
}
}
}
Expand Down Expand Up @@ -1046,7 +1046,7 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
addNodeInput(_currUiNode, input);
input->setValueString(temp);
input->setValue(temp, input->getType());
updateMaterials();
updateMaterialRequired = true;
}
}
}
Expand All @@ -1062,12 +1062,27 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
{
addNodeInput(_currUiNode, input);
input->setValue(temp, input->getType());
updateMaterials(input, input->getValue());
updateMaterialRequired = true;
}
}
}

ImGui::PopItemWidth();

if (updateMaterialRequired)
{
if (!_renderer->getMaterialCompilation() && mx::inputChangeRequiresShaderGen(input))
{
_frameCount = ImGui::GetFrameCount();
jstone-lucasfilm marked this conversation as resolved.
Show resolved Hide resolved
_renderer->setMaterialCompilation(true);
_shaderPopup = false;
}
else
{
updateMaterials(input, input->getValue());
jstone-lucasfilm marked this conversation as resolved.
Show resolved Hide resolved
}
}

}
// build the initial graph of a loaded mtlx document including shader, material and nodegraph node
void Graph::setUiNodeInfo(UiNodePtr node, const std::string& type, const std::string& category)
Expand Down Expand Up @@ -3584,6 +3599,9 @@ void Graph::readOnlyPopup()
// compiling shaders message
void Graph::shaderPopup()
{
if (!_shaderPopup)
return;

if (_renderer->getMaterialCompilation())
{
ImGui::SetNextWindowPos(ImVec2((float) _renderer->getViewWidth() - 135, (float) _renderer->getViewHeight() + 5));
Expand Down Expand Up @@ -4016,8 +4034,11 @@ void Graph::drawGraph(ImVec2 mousePos)
shaderPopup();
if (ImGui::GetFrameCount() == (_frameCount + 2))
{
updateMaterials();
_renderer->setMaterialCompilation(false);
if (_renderer->getMaterialCompilation())
{
updateMaterials();
_renderer->setMaterialCompilation(false);
}
}

ed::Suspend();
Expand Down
1 change: 1 addition & 0 deletions source/PyMaterialX/PyMaterialXGenShader/PyUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ void bindPyUtil(py::module& mod)
mod.def("getUdimScaleAndOffset", &mx::getUdimScaleAndOffset);
mod.def("connectsToWorldSpaceNode", &mx::connectsToWorldSpaceNode);
mod.def("hasElementAttributes", &mx::hasElementAttributes);
mod.def("inputChangeRequiresShaderGen", &mx::inputChangeRequiresShaderGen);
}