ShaderNode: Add automatic variables
This commit is contained in:
parent
09e08255fb
commit
d96bc9db6e
|
|
@ -40,6 +40,12 @@ namespace Nz
|
|||
VertexPosition, // gl_Position
|
||||
};
|
||||
|
||||
enum class ExpressionCategory
|
||||
{
|
||||
LValue,
|
||||
RValue
|
||||
};
|
||||
|
||||
enum class ExpressionType
|
||||
{
|
||||
Boolean, // bool
|
||||
|
|
@ -104,6 +110,7 @@ namespace Nz
|
|||
class NAZARA_RENDERER_API Expression : public Node
|
||||
{
|
||||
public:
|
||||
virtual ExpressionCategory GetExpressionCategory() const;
|
||||
virtual ExpressionType GetExpressionType() const = 0;
|
||||
};
|
||||
|
||||
|
|
@ -152,6 +159,7 @@ namespace Nz
|
|||
public:
|
||||
inline Variable(VariableType varKind, ExpressionType varType);
|
||||
|
||||
ExpressionCategory GetExpressionCategory() const override;
|
||||
ExpressionType GetExpressionType() const override;
|
||||
|
||||
ExpressionType type;
|
||||
|
|
@ -191,14 +199,14 @@ namespace Nz
|
|||
class NAZARA_RENDERER_API AssignOp : public Expression
|
||||
{
|
||||
public:
|
||||
inline AssignOp(AssignType Op, VariablePtr Var, ExpressionPtr Right);
|
||||
inline AssignOp(AssignType Op, ExpressionPtr Left, ExpressionPtr Right);
|
||||
|
||||
ExpressionType GetExpressionType() const override;
|
||||
void Register(ShaderWriter& visitor) override;
|
||||
void Visit(ShaderWriter& visitor) override;
|
||||
|
||||
AssignType op;
|
||||
VariablePtr variable;
|
||||
ExpressionPtr left;
|
||||
ExpressionPtr right;
|
||||
};
|
||||
|
||||
|
|
@ -277,6 +285,7 @@ namespace Nz
|
|||
public:
|
||||
inline SwizzleOp(ExpressionPtr expressionPtr, std::initializer_list<SwizzleComponent> swizzleComponents);
|
||||
|
||||
ExpressionCategory GetExpressionCategory() const override;
|
||||
ExpressionType GetExpressionType() const override;
|
||||
void Register(ShaderWriter& visitor) override;
|
||||
void Visit(ShaderWriter& visitor) override;
|
||||
|
|
|
|||
|
|
@ -82,11 +82,14 @@ namespace Nz
|
|||
{
|
||||
}
|
||||
|
||||
inline AssignOp::AssignOp(AssignType Op, VariablePtr Var, ExpressionPtr Right) :
|
||||
inline AssignOp::AssignOp(AssignType Op, ExpressionPtr Left, ExpressionPtr Right) :
|
||||
op(Op),
|
||||
variable(std::move(Var)),
|
||||
left(std::move(Left)),
|
||||
right(std::move(Right))
|
||||
{
|
||||
if (left->GetExpressionCategory() != ExpressionCategory::LValue)
|
||||
//TODO: AstParseError
|
||||
throw std::runtime_error("Assignation is only possible with lvalues");
|
||||
}
|
||||
|
||||
inline BinaryOp::BinaryOp(BinaryType Op, ExpressionPtr Left, ExpressionPtr Right) :
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Nz { namespace ShaderBuilder
|
|||
{
|
||||
constexpr AssignOpBuilder() {}
|
||||
|
||||
std::shared_ptr<ShaderAst::AssignOp> operator()(const ShaderAst::VariablePtr& left, const ShaderAst::ExpressionPtr& right) const;
|
||||
std::shared_ptr<ShaderAst::AssignOp> operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const;
|
||||
};
|
||||
|
||||
template<ShaderAst::BinaryType op>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Nz { namespace ShaderBuilder
|
|||
}
|
||||
|
||||
template<ShaderAst::AssignType op>
|
||||
std::shared_ptr<ShaderAst::AssignOp> AssignOpBuilder<op>::operator()(const ShaderAst::VariablePtr& left, const ShaderAst::ExpressionPtr& right) const
|
||||
std::shared_ptr<ShaderAst::AssignOp> AssignOpBuilder<op>::operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const
|
||||
{
|
||||
return std::make_shared<ShaderAst::AssignOp>(op, left, right);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ namespace Nz
|
|||
|
||||
void GlslWriter::Write(const ShaderAst::AssignOp& node)
|
||||
{
|
||||
Write(node.variable);
|
||||
Write(node.left);
|
||||
|
||||
switch (node.op)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,6 +8,11 @@
|
|||
|
||||
namespace Nz::ShaderAst
|
||||
{
|
||||
ExpressionCategory Expression::GetExpressionCategory() const
|
||||
{
|
||||
return ExpressionCategory::RValue;
|
||||
}
|
||||
|
||||
void ExpressionStatement::Register(ShaderWriter& visitor)
|
||||
{
|
||||
expression->Register(visitor);
|
||||
|
|
@ -43,6 +48,10 @@ namespace Nz::ShaderAst
|
|||
visitor.Write(*this);
|
||||
}
|
||||
|
||||
ExpressionCategory Variable::GetExpressionCategory() const
|
||||
{
|
||||
return ExpressionCategory::LValue;
|
||||
}
|
||||
|
||||
ExpressionType Variable::GetExpressionType() const
|
||||
{
|
||||
|
|
@ -60,7 +69,7 @@ namespace Nz::ShaderAst
|
|||
}
|
||||
|
||||
|
||||
void BuiltinVariable::Register(ShaderWriter& visitor)
|
||||
void BuiltinVariable::Register(ShaderWriter& /*visitor*/)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -72,12 +81,12 @@ namespace Nz::ShaderAst
|
|||
|
||||
ExpressionType AssignOp::GetExpressionType() const
|
||||
{
|
||||
return variable->GetExpressionType();
|
||||
return left->GetExpressionType();
|
||||
}
|
||||
|
||||
void AssignOp::Register(ShaderWriter& visitor)
|
||||
{
|
||||
variable->Register(visitor);
|
||||
left->Register(visitor);
|
||||
right->Register(visitor);
|
||||
}
|
||||
|
||||
|
|
@ -102,6 +111,7 @@ namespace Nz::ShaderAst
|
|||
|
||||
case ShaderAst::BinaryType::Equality:
|
||||
exprType = ExpressionType::Boolean;
|
||||
break;
|
||||
}
|
||||
|
||||
NazaraAssert(exprType != ShaderAst::ExpressionType::Void, "Unhandled builtin");
|
||||
|
|
@ -178,7 +188,12 @@ namespace Nz::ShaderAst
|
|||
}
|
||||
|
||||
|
||||
ExpressionType ShaderAst::SwizzleOp::GetExpressionType() const
|
||||
ExpressionCategory SwizzleOp::GetExpressionCategory() const
|
||||
{
|
||||
return ExpressionCategory::LValue;
|
||||
}
|
||||
|
||||
ExpressionType SwizzleOp::GetExpressionType() const
|
||||
{
|
||||
return static_cast<ExpressionType>(UnderlyingCast(GetComponentType(expression->GetExpressionType())) + componentCount - 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,13 @@ ShaderNode(graph)
|
|||
UpdatePreview();
|
||||
});
|
||||
|
||||
if (graph.GetInputCount() > 0)
|
||||
{
|
||||
auto& firstInput = graph.GetInput(0);
|
||||
m_currentInputIndex = 0;
|
||||
m_currentInputText = firstInput.name;
|
||||
}
|
||||
|
||||
UpdatePreview();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,15 @@ ShaderNode(graph)
|
|||
if (m_currentTextureIndex == textureIndex)
|
||||
UpdatePreview();
|
||||
});
|
||||
|
||||
if (graph.GetTextureCount() > 0)
|
||||
{
|
||||
auto& firstInput = graph.GetTexture(0);
|
||||
m_currentTextureIndex = 0;
|
||||
m_currentTextureText = firstInput.name;
|
||||
}
|
||||
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
unsigned int SampleTexture::nPorts(QtNodes::PortType portType) const
|
||||
|
|
|
|||
|
|
@ -40,13 +40,28 @@ m_flowScene(BuildRegistry())
|
|||
OnSelectedNodeUpdate(this, nullptr);
|
||||
});
|
||||
|
||||
auto& node1 = m_flowScene.createNode(std::make_unique<Vec4Value>(*this));
|
||||
node1.nodeGraphicsObject().setPos(200, 200);
|
||||
// Test
|
||||
AddInput("UV", InputType::Float2, InputRole::TexCoord, 0);
|
||||
AddTexture("Potato", TextureType::Sampler2D);
|
||||
|
||||
auto& node2 = m_flowScene.createNode(std::make_unique<FragmentOutput>(*this));
|
||||
node2.nodeGraphicsObject().setPos(500, 300);
|
||||
UpdateTexturePreview(0, QImage(R"(C:\Users\Lynix\Pictures\potatavril.png)"));
|
||||
|
||||
auto& node1 = m_flowScene.createNode(std::make_unique<InputValue>(*this));
|
||||
node1.nodeGraphicsObject().setPos(0, 200);
|
||||
|
||||
auto& node2 = m_flowScene.createNode(std::make_unique<SampleTexture>(*this));
|
||||
node2.nodeGraphicsObject().setPos(200, 200);
|
||||
|
||||
auto& node3 = m_flowScene.createNode(std::make_unique<Vec4Mul>(*this));
|
||||
node3.nodeGraphicsObject().setPos(400, 200);
|
||||
|
||||
auto& node4 = m_flowScene.createNode(std::make_unique<FragmentOutput>(*this));
|
||||
node4.nodeGraphicsObject().setPos(600, 300);
|
||||
|
||||
m_flowScene.createConnection(node2, 0, node1, 0);
|
||||
m_flowScene.createConnection(node3, 0, node2, 0);
|
||||
m_flowScene.createConnection(node3, 1, node2, 0);
|
||||
m_flowScene.createConnection(node4, 0, node3, 0);
|
||||
}
|
||||
|
||||
ShaderGraph::~ShaderGraph()
|
||||
|
|
@ -83,13 +98,51 @@ std::size_t ShaderGraph::AddTexture(std::string name, TextureType type)
|
|||
Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
|
||||
{
|
||||
std::vector<Nz::ShaderAst::StatementPtr> statements;
|
||||
QHash<QUuid, unsigned int> usageCount;
|
||||
|
||||
unsigned int varCount = 0;
|
||||
|
||||
std::function<void(QtNodes::Node*)> DetectVariables;
|
||||
DetectVariables = [&](QtNodes::Node* node)
|
||||
{
|
||||
ShaderNode* shaderNode = static_cast<ShaderNode*>(node->nodeDataModel());
|
||||
|
||||
qDebug() << shaderNode->name() << node->id();
|
||||
auto it = usageCount.find(node->id());
|
||||
if (it == usageCount.end())
|
||||
it = usageCount.insert(node->id(), 0);
|
||||
|
||||
(*it)++;
|
||||
|
||||
for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In))
|
||||
{
|
||||
for (const auto& [uuid, conn] : connectionSet)
|
||||
{
|
||||
DetectVariables(conn->getNode(QtNodes::PortType::Out));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
m_flowScene.iterateOverNodes([&](QtNodes::Node* node)
|
||||
{
|
||||
if (node->nodeDataModel()->nPorts(QtNodes::PortType::Out) == 0)
|
||||
DetectVariables(node);
|
||||
});
|
||||
|
||||
QHash<QUuid, Nz::ShaderAst::ExpressionPtr> variableExpressions;
|
||||
|
||||
std::function<Nz::ShaderAst::ExpressionPtr(QtNodes::Node*)> HandleNode;
|
||||
HandleNode = [&](QtNodes::Node* node) -> Nz::ShaderAst::ExpressionPtr
|
||||
{
|
||||
ShaderNode* shaderNode = static_cast<ShaderNode*>(node->nodeDataModel());
|
||||
|
||||
qDebug() << shaderNode->name();
|
||||
qDebug() << shaderNode->name() << node->id();
|
||||
if (auto it = variableExpressions.find(node->id()); it != variableExpressions.end())
|
||||
return *it;
|
||||
|
||||
auto it = usageCount.find(node->id());
|
||||
assert(it != usageCount.end());
|
||||
|
||||
std::size_t inputCount = shaderNode->nPorts(QtNodes::PortType::In);
|
||||
Nz::StackArray<Nz::ShaderAst::ExpressionPtr> expressions = NazaraStackArray(Nz::ShaderAst::ExpressionPtr, inputCount);
|
||||
std::size_t i = 0;
|
||||
|
|
@ -104,7 +157,25 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
|
|||
}
|
||||
}
|
||||
|
||||
return shaderNode->GetExpression(expressions.data(), expressions.size());
|
||||
auto expression = shaderNode->GetExpression(expressions.data(), expressions.size());
|
||||
|
||||
if (*it > 1)
|
||||
{
|
||||
Nz::ShaderAst::ExpressionPtr varExpression;
|
||||
if (expression->GetExpressionCategory() == Nz::ShaderAst::ExpressionCategory::RValue)
|
||||
{
|
||||
varExpression = Nz::ShaderBuilder::Variable("var" + std::to_string(varCount++), expression->GetExpressionType());
|
||||
statements.emplace_back(Nz::ShaderBuilder::ExprStatement(Nz::ShaderBuilder::Assign(varExpression, expression)));
|
||||
}
|
||||
else
|
||||
varExpression = expression;
|
||||
|
||||
variableExpressions.insert(node->id(), varExpression);
|
||||
|
||||
return varExpression;
|
||||
}
|
||||
else
|
||||
return expression;
|
||||
};
|
||||
|
||||
m_flowScene.iterateOverNodes([&](QtNodes::Node* node)
|
||||
|
|
|
|||
|
|
@ -26,10 +26,12 @@ class ShaderGraph
|
|||
std::size_t AddTexture(std::string name, TextureType type);
|
||||
|
||||
inline const InputEntry& GetInput(std::size_t inputIndex) const;
|
||||
inline std::size_t GetInputCount() const;
|
||||
inline const std::vector<InputEntry>& GetInputs() const;
|
||||
inline const PreviewModel& GetPreviewModel() const;
|
||||
inline QtNodes::FlowScene& GetScene();
|
||||
inline const TextureEntry& GetTexture(std::size_t textureIndex) const;
|
||||
inline std::size_t GetTextureCount() const;
|
||||
inline const std::vector<TextureEntry>& GetTextures() const;
|
||||
|
||||
Nz::ShaderAst::StatementPtr ToAst();
|
||||
|
|
|
|||
|
|
@ -6,6 +6,11 @@ inline auto ShaderGraph::GetInput(std::size_t inputIndex) const -> const InputEn
|
|||
return m_inputs[inputIndex];
|
||||
}
|
||||
|
||||
inline std::size_t ShaderGraph::GetInputCount() const
|
||||
{
|
||||
return m_inputs.size();
|
||||
}
|
||||
|
||||
inline auto ShaderGraph::GetInputs() const -> const std::vector<InputEntry>&
|
||||
{
|
||||
return m_inputs;
|
||||
|
|
@ -27,6 +32,11 @@ inline auto ShaderGraph::GetTexture(std::size_t textureIndex) const -> const Tex
|
|||
return m_textures[textureIndex];
|
||||
}
|
||||
|
||||
inline std::size_t ShaderGraph::GetTextureCount() const
|
||||
{
|
||||
return m_textures.size();
|
||||
}
|
||||
|
||||
inline auto ShaderGraph::GetTextures() const -> const std::vector<TextureEntry>&
|
||||
{
|
||||
return m_textures;
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ int main(int argc, char* argv[])
|
|||
QApplication app(argc, argv);
|
||||
|
||||
ShaderGraph shaderGraph;
|
||||
shaderGraph.AddInput("UV", InputType::Float2, InputRole::TexCoord, 0);
|
||||
shaderGraph.AddTexture("Potato", TextureType::Sampler2D);
|
||||
|
||||
MainWindow mainWindow(shaderGraph);
|
||||
mainWindow.resize(1280, 720);
|
||||
|
|
|
|||
Loading…
Reference in New Issue