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