Update ShaderNode

This commit is contained in:
Lynix 2020-05-19 20:06:32 +02:00
parent e23eb74802
commit effaa9b88f
17 changed files with 646 additions and 84 deletions

View File

@ -10,6 +10,8 @@
class FragmentOutput : public ShaderNode class FragmentOutput : public ShaderNode
{ {
public: public:
inline FragmentOutput(ShaderGraph& graph);
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override; Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
QString caption() const override { return "Fragment shader output"; } QString caption() const override { return "Fragment shader output"; }

View File

@ -1 +1,6 @@
#include <DataModels/FragmentOutput.hpp> #include <DataModels/FragmentOutput.hpp>
inline FragmentOutput::FragmentOutput(ShaderGraph& graph) :
ShaderNode(graph)
{
}

View File

@ -0,0 +1,106 @@
#include <ShaderGraph.hpp>
#include <DataModels/SampleTexture.hpp>
#include <DataModels/VecValue.hpp>
#include <Nazara/Renderer/ShaderBuilder.hpp>
SampleTexture::SampleTexture(ShaderGraph& graph) :
ShaderNode(graph)
{
m_layout = new QVBoxLayout;
m_textureSelection = new QComboBox;
m_textureSelection->setStyleSheet("background-color: rgba(255,255,255,255)");
m_layout->addWidget(m_textureSelection);
m_pixmap = QPixmap(64, 64);
m_pixmap.fill();
m_pixmapLabel = new QLabel;
m_pixmapLabel->setPixmap(m_pixmap);
m_layout->addWidget(m_pixmapLabel);
m_widget = new QWidget;
m_widget->setStyleSheet("background-color: rgba(0,0,0,0)");
m_widget->setLayout(m_layout);
m_onTextureListUpdate.Connect(GetGraph().OnTextureListUpdate, [&](ShaderGraph*) { UpdateTextureList(); });
UpdateTextureList();
}
QWidget* SampleTexture::embeddedWidget()
{
return m_widget;
}
unsigned int SampleTexture::nPorts(QtNodes::PortType portType) const
{
switch (portType)
{
case QtNodes::PortType::In: return 1;
case QtNodes::PortType::Out: return 1;
}
return 0;
}
void SampleTexture::UpdatePreview()
{
ComputePreview(m_pixmap);
m_pixmapLabel->setPixmap(m_pixmap);
}
void SampleTexture::UpdateTextureList()
{
QString currentTexture = m_textureSelection->currentText();
m_textureSelection->clear();
for (const auto& textureEntry : GetGraph().GetTextures())
m_textureSelection->addItem(QString::fromStdString(textureEntry.name));
m_textureSelection->setCurrentText(currentTexture);
}
void SampleTexture::ComputePreview(QPixmap& pixmap) const
{
pixmap.fill();
}
Nz::ShaderAst::ExpressionPtr SampleTexture::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
{
assert(count == 1);
auto sampler = Nz::ShaderBuilder::Uniform("Texture0", Nz::ShaderAst::ExpressionType::Sampler2D);
return Nz::ShaderBuilder::Sample2D(sampler, expressions[0]);
}
auto SampleTexture::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType
{
switch (portType)
{
case QtNodes::PortType::In:
{
assert(portIndex == 0);
return Vec2Data::Type();
}
case QtNodes::PortType::Out:
{
assert(portIndex == 0);
return Vec4Data::Type();
}
default:
assert(false);
throw std::runtime_error("Invalid PortType");
}
}
std::shared_ptr<QtNodes::NodeData> SampleTexture::outData(QtNodes::PortIndex port)
{
assert(port == 0);
return std::make_shared<Vec4Data>(Nz::Vector4f::Zero());
}

View File

@ -0,0 +1,47 @@
#pragma once
#ifndef NAZARA_SHADERNODES_SAMPLETEXTURE_HPP
#define NAZARA_SHADERNODES_SAMPLETEXTURE_HPP
#include <QtWidgets/QComboBox>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QLabel>
#include <ShaderGraph.hpp>
#include <DataModels/ShaderNode.hpp>
#include <array>
class SampleTexture : public ShaderNode
{
public:
SampleTexture(ShaderGraph& graph);
~SampleTexture() = default;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override;
QString caption() const override { return "Sample texture"; }
QString name() const override { return "SampleTexture"; }
QWidget* embeddedWidget() override;
unsigned int nPorts(QtNodes::PortType portType) const override;
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
protected:
void UpdatePreview();
void UpdateTextureList();
void ComputePreview(QPixmap& pixmap) const;
NazaraSlot(ShaderGraph, OnTextureListUpdate, m_onTextureListUpdate);
QComboBox* m_textureSelection;
QLabel* m_pixmapLabel;
QPixmap m_pixmap;
QWidget* m_widget;
QVBoxLayout* m_layout;
};
#include <DataModels/SampleTexture.inl>
#endif

View File

@ -0,0 +1,2 @@
#include <DataModels/SampleTexture.hpp>
#include <array>

View File

@ -6,10 +6,21 @@
#include <Nazara/Renderer/ShaderAst.hpp> #include <Nazara/Renderer/ShaderAst.hpp>
#include <nodes/NodeDataModel> #include <nodes/NodeDataModel>
class ShaderGraph;
class ShaderNode : public QtNodes::NodeDataModel class ShaderNode : public QtNodes::NodeDataModel
{ {
public: public:
inline ShaderNode(ShaderGraph& graph);
virtual Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const = 0; virtual Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const = 0;
inline ShaderGraph& GetGraph();
inline const ShaderGraph& GetGraph() const;
void setInData(std::shared_ptr<QtNodes::NodeData>, int) override {};
private:
ShaderGraph& m_graph;
}; };
#include <DataModels/ShaderNode.inl> #include <DataModels/ShaderNode.inl>

View File

@ -1 +1,16 @@
#include <DataModels/ShaderNode.hpp> #include <DataModels/ShaderNode.hpp>
inline ShaderNode::ShaderNode(ShaderGraph& graph) :
m_graph(graph)
{
}
inline ShaderGraph& ShaderNode::GetGraph()
{
return m_graph;
}
inline const ShaderGraph& ShaderNode::GetGraph() const
{
return m_graph;
}

View File

@ -0,0 +1 @@
#include <DataModels/VecBinOp.hpp>

View File

@ -0,0 +1,60 @@
#pragma once
#ifndef NAZARA_SHADERNODES_VECBINOP_HPP
#define NAZARA_SHADERNODES_VECBINOP_HPP
#include <DataModels/ShaderNode.hpp>
#include <DataModels/VecValue.hpp>
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
class VecBinOp : public ShaderNode
{
public:
VecBinOp(ShaderGraph& graph);
~VecBinOp() = default;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
QWidget* embeddedWidget() override;
unsigned int nPorts(QtNodes::PortType portType) const override;
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
void setInData(std::shared_ptr<QtNodes::NodeData> value, int index) override;
private:
void UpdatePreview();
using InternalType = typename Data::InternalType;
InternalType GetValue() const;
QLabel* m_pixmapLabel;
QPixmap m_preview;
std::shared_ptr<Vec4Data> m_lhs;
std::shared_ptr<Vec4Data> m_rhs;
};
class Vec4Add : public VecBinOp<Vec4Data, Nz::ShaderAst::BinaryType::Add>
{
public:
using VecBinOp::VecBinOp;
QString caption() const override { return "Vec4 addition"; }
QString name() const override { return "Vec4Add"; }
};
class Vec4Mul : public VecBinOp<Vec4Data, Nz::ShaderAst::BinaryType::Multiply>
{
public:
using VecBinOp::VecBinOp;
QString caption() const override { return "Vec4 multiplication"; }
QString name() const override { return "Vec4Mul"; }
};
#include <DataModels/VecBinOp.inl>
#endif

View File

@ -0,0 +1,93 @@
#include <DataModels/VecBinOp.hpp>
#include <Nazara/Renderer/ShaderBuilder.hpp>
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
VecBinOp<Data, BinOp>::VecBinOp(ShaderGraph& graph) :
ShaderNode(graph)
{
m_preview = QPixmap(64, 64);
m_pixmapLabel = new QLabel;
m_pixmapLabel->setPixmap(m_preview);
}
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
Nz::ShaderAst::ExpressionPtr VecBinOp<Data, BinOp>::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
{
assert(count == 2);
using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder<BinOp>;
constexpr BuilderType builder;
return builder(expressions[0], expressions[1]);
}
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
QWidget* VecBinOp<Data, BinOp>::embeddedWidget()
{
return m_pixmapLabel;
}
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
QtNodes::NodeDataType VecBinOp<Data, BinOp>::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const
{
assert(portIndex == 0 || portIndex == 1);
return Data::Type();
}
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
unsigned int VecBinOp<Data, BinOp>::nPorts(QtNodes::PortType portType) const
{
switch (portType)
{
case QtNodes::PortType::In: return 2;
case QtNodes::PortType::Out: return 1;
}
return 0;
}
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
std::shared_ptr<QtNodes::NodeData> VecBinOp<Data, BinOp>::outData(QtNodes::PortIndex port)
{
assert(port == 0);
return std::make_shared<Data>(GetValue());
}
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
void VecBinOp<Data, BinOp>::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
{
std::shared_ptr<Data> castedValue;
if (value)
{
assert(dynamic_cast<Data*>(value.get()) != nullptr);
assert(index == 0 || index == 1);
castedValue = std::static_pointer_cast<Data>(value);
}
if (index == 0)
m_lhs = std::move(castedValue);
else
m_rhs = std::move(castedValue);
UpdatePreview();
Q_EMIT dataUpdated(0);
}
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
void VecBinOp<Data, BinOp>::UpdatePreview()
{
InternalType value = GetValue();
m_preview.fill(QColor::fromRgbF(value.x, value.y, value.z, value.w));
m_pixmapLabel->setPixmap(m_preview);
}
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
auto VecBinOp<Data, BinOp>::GetValue() const -> InternalType
{
if (!m_lhs || !m_rhs)
return InternalType::Zero();
return m_lhs->value * m_rhs->value;
}

View File

@ -1,6 +1,55 @@
#include <DataModels/VecValue.hpp> #include <DataModels/VecValue.hpp>
#include <Nazara/Renderer/ShaderBuilder.hpp> #include <Nazara/Renderer/ShaderBuilder.hpp>
Vec2Value::Vec2Value(ShaderGraph& graph) :
VecValue(graph)
{
UpdatePreview();
}
Nz::ShaderAst::ExpressionPtr Vec2Value::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
{
assert(count == 0);
return Nz::ShaderBuilder::Constant(GetValue());
}
auto Vec2Value::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType
{
assert(portType == QtNodes::PortType::Out);
assert(portIndex == 0);
return Vec2Data::Type();
}
std::shared_ptr<QtNodes::NodeData> Vec2Value::outData(QtNodes::PortIndex port)
{
assert(port == 0);
return std::make_shared<Vec2Data>(GetValue());
}
void Vec2Value::ComputePreview(QPixmap& pixmap) const
{
Nz::Vector4f value = GetValue();
pixmap.fill(QColor::fromRgbF(value.x, value.y, value.z, value.w));
}
Nz::Vector2f Vec2Value::GetValue() const
{
float x = float(m_values[0]->value());
float y = float(m_values[1]->value());
return Nz::Vector2f(x, y);
}
Vec4Value::Vec4Value(ShaderGraph& graph) :
VecValue(graph)
{
UpdatePreview();
}
Nz::ShaderAst::ExpressionPtr Vec4Value::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const Nz::ShaderAst::ExpressionPtr Vec4Value::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
{ {
assert(count == 0); assert(count == 0);
@ -23,6 +72,12 @@ std::shared_ptr<QtNodes::NodeData> Vec4Value::outData(QtNodes::PortIndex port)
return std::make_shared<Vec4Data>(GetValue()); return std::make_shared<Vec4Data>(GetValue());
} }
void Vec4Value::ComputePreview(QPixmap& pixmap) const
{
Nz::Vector4f value = GetValue();
pixmap.fill(QColor::fromRgbF(value.x, value.y, value.z, value.w));
}
Nz::Vector4f Vec4Value::GetValue() const Nz::Vector4f Vec4Value::GetValue() const
{ {
float x = float(m_values[0]->value()); float x = float(m_values[0]->value());

View File

@ -5,6 +5,7 @@
#include <QtWidgets/QDoubleSpinBox> #include <QtWidgets/QDoubleSpinBox>
#include <QtWidgets/QFormLayout> #include <QtWidgets/QFormLayout>
#include <QtWidgets/QLabel>
#include <DataModels/ShaderNode.hpp> #include <DataModels/ShaderNode.hpp>
#include <array> #include <array>
@ -12,22 +13,50 @@ template<std::size_t N>
class VecValue : public ShaderNode class VecValue : public ShaderNode
{ {
public: public:
VecValue(); VecValue(ShaderGraph& graph);
~VecValue() = default; ~VecValue() = default;
QWidget* embeddedWidget() override; QWidget* embeddedWidget() override;
unsigned int nPorts(QtNodes::PortType portType) const override; unsigned int nPorts(QtNodes::PortType portType) const override;
protected: protected:
void UpdatePreview();
virtual void ComputePreview(QPixmap& pixmap) const = 0;
QLabel* m_pixmapLabel;
QPixmap m_pixmap;
QWidget* m_widget; QWidget* m_widget;
QFormLayout* m_layout; QFormLayout* m_layout;
std::array<QDoubleSpinBox*, N> m_values; std::array<QDoubleSpinBox*, N> m_values;
}; };
class Vec2Data : public QtNodes::NodeData
{
public:
using InternalType = Nz::Vector2f;
inline Vec2Data(const InternalType& vec);
QtNodes::NodeDataType type() const override
{
return Type();
}
static QtNodes::NodeDataType Type()
{
return { "vec2", "Vec2" };
}
InternalType value;
};
class Vec4Data : public QtNodes::NodeData class Vec4Data : public QtNodes::NodeData
{ {
public: public:
inline Vec4Data(const Nz::Vector4f& vec); using InternalType = Nz::Vector4f;
inline Vec4Data(const InternalType& vec);
QtNodes::NodeDataType type() const override QtNodes::NodeDataType type() const override
{ {
@ -39,25 +68,46 @@ class Vec4Data : public QtNodes::NodeData
return { "vec4", "Vec4" }; return { "vec4", "Vec4" };
} }
Nz::Vector4f value; InternalType value;
};
class Vec2Value : public VecValue<2>
{
public:
Vec2Value(ShaderGraph& graph);
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
QString caption() const override { return "Vec2 value"; }
QString name() const override { return "Vec2Value"; }
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
private:
void ComputePreview(QPixmap& pixmap) const override;
Nz::Vector2f GetValue() const;
}; };
class Vec4Value : public VecValue<4> class Vec4Value : public VecValue<4>
{ {
public: public:
Vec4Value(ShaderGraph& graph);
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override; Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
QString caption() const override { return "Vec4 value"; } QString caption() const override { return "Vec4 value"; }
bool captionVisible() const override { return true; }
QString name() const override { return "Vec4Value"; } QString name() const override { return "Vec4Value"; }
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override; std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
void setInData(std::shared_ptr<QtNodes::NodeData>, int) override {};
private: private:
void ComputePreview(QPixmap& pixmap) const override;
Nz::Vector4f GetValue() const; Nz::Vector4f GetValue() const;
}; };

View File

@ -2,7 +2,8 @@
#include <array> #include <array>
template<std::size_t N> template<std::size_t N>
VecValue<N>::VecValue() VecValue<N>::VecValue(ShaderGraph& graph) :
ShaderNode(graph)
{ {
constexpr std::array<char, 4> componentName = { 'X', 'Y', 'Z', 'W' }; constexpr std::array<char, 4> componentName = { 'X', 'Y', 'Z', 'W' };
static_assert(N <= componentName.size()); static_assert(N <= componentName.size());
@ -11,10 +12,27 @@ VecValue<N>::VecValue()
for (std::size_t i = 0; i < N; ++i) for (std::size_t i = 0; i < N; ++i)
{ {
m_values[i] = new QDoubleSpinBox; m_values[i] = new QDoubleSpinBox;
m_values[i]->setDecimals(6);
m_values[i]->setValue(1.0);
m_values[i]->setStyleSheet("background-color: rgba(255,255,255,255)"); m_values[i]->setStyleSheet("background-color: rgba(255,255,255,255)");
connect(m_values[i], qOverload<double>(&QDoubleSpinBox::valueChanged), [this](double)
{
UpdatePreview();
Q_EMIT dataUpdated(0);
});
m_layout->addRow(QString::fromUtf8(&componentName[i], 1), m_values[i]); m_layout->addRow(QString::fromUtf8(&componentName[i], 1), m_values[i]);
} }
m_pixmap = QPixmap(64, 64);
m_pixmap.fill();
m_pixmapLabel = new QLabel;
m_pixmapLabel->setPixmap(m_pixmap);
m_layout->addWidget(m_pixmapLabel);
m_widget = new QWidget; m_widget = new QWidget;
m_widget->setStyleSheet("background-color: rgba(0,0,0,0)"); m_widget->setStyleSheet("background-color: rgba(0,0,0,0)");
m_widget->setLayout(m_layout); m_widget->setLayout(m_layout);
@ -38,7 +56,19 @@ unsigned int VecValue<N>::nPorts(QtNodes::PortType portType) const
return 0; return 0;
} }
Vec4Data::Vec4Data(const Nz::Vector4f& vec) : template<std::size_t N>
void VecValue<N>::UpdatePreview()
{
ComputePreview(m_pixmap);
m_pixmapLabel->setPixmap(m_pixmap);
}
Vec2Data::Vec2Data(const InternalType& vec) :
value(vec)
{
}
Vec4Data::Vec4Data(const InternalType& vec) :
value(vec) value(vec)
{ {
} }

View File

@ -0,0 +1,95 @@
#include <ShaderGraph.hpp>
#include <Nazara/Core/StackArray.hpp>
#include <DataModels/FragmentOutput.hpp>
#include <DataModels/SampleTexture.hpp>
#include <DataModels/ShaderNode.hpp>
#include <DataModels/VecBinOp.hpp>
#include <DataModels/VecValue.hpp>
#include <QtCore/QDebug>
#include <nodes/Node>
#include <nodes/NodeData>
#include <nodes/NodeGeometry>
#include <nodes/FlowScene>
#include <nodes/FlowView>
#include <nodes/DataModelRegistry>
namespace
{
template<typename T>
void RegisterShaderNode(ShaderGraph& graph, std::shared_ptr<QtNodes::DataModelRegistry> registry)
{
auto creator = [&] { return std::make_unique<T>(graph); };
registry->registerModel<T>(std::move(creator));
}
}
ShaderGraph::ShaderGraph() :
m_flowScene(BuildRegistry())
{
auto& node1 = m_flowScene.createNode(std::make_unique<Vec4Value>(*this));
node1.nodeGraphicsObject().setPos(200, 200);
auto& node2 = m_flowScene.createNode(std::make_unique<FragmentOutput>(*this));
node2.nodeGraphicsObject().setPos(500, 300);
m_flowScene.createConnection(node2, 0, node1, 0);
}
void ShaderGraph::AddTexture(std::string name, Nz::ShaderAst::ExpressionType type)
{
auto& textureEntry = m_textures.emplace_back();
textureEntry.name = std::move(name);
textureEntry.type = type;
OnTextureListUpdate(this);
}
Nz::ShaderAst::StatementPtr ShaderGraph::Generate()
{
std::vector<Nz::ShaderAst::StatementPtr> statements;
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();
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;
for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In))
{
for (const auto& [uuid, conn] : connectionSet)
{
assert(i < expressions.size());
expressions[i] = HandleNode(conn->getNode(QtNodes::PortType::Out));
i++;
}
}
return shaderNode->GetExpression(expressions.data(), expressions.size());
};
m_flowScene.iterateOverNodes([&](QtNodes::Node* node)
{
if (node->nodeDataModel()->nPorts(QtNodes::PortType::Out) == 0)
{
statements.emplace_back(Nz::ShaderBuilder::ExprStatement(HandleNode(node)));
}
});
return std::make_shared<Nz::ShaderAst::StatementBlock>(std::move(statements));
}
std::shared_ptr<QtNodes::DataModelRegistry> ShaderGraph::BuildRegistry()
{
auto registry = std::make_shared<QtNodes::DataModelRegistry>();
RegisterShaderNode<FragmentOutput>(*this, registry);
RegisterShaderNode<SampleTexture>(*this, registry);
RegisterShaderNode<Vec4Mul>(*this, registry);
RegisterShaderNode<Vec2Value>(*this, registry);
RegisterShaderNode<Vec4Value>(*this, registry);
return registry;
}

View File

@ -0,0 +1,45 @@
#pragma once
#ifndef NAZARA_SHADERNODES_SHADERGRAPH_HPP
#define NAZARA_SHADERNODES_SHADERGRAPH_HPP
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <nodes/FlowScene>
#include <nodes/FlowView>
#include <string>
#include <vector>
class ShaderGraph
{
public:
struct TextureEntry;
ShaderGraph();
~ShaderGraph() = default;
void AddTexture(std::string name, Nz::ShaderAst::ExpressionType type);
Nz::ShaderAst::StatementPtr Generate();
inline QtNodes::FlowScene& GetScene();
inline const std::vector<TextureEntry>& GetTextures();
NazaraSignal(OnTextureListUpdate, ShaderGraph*);
struct TextureEntry
{
std::string name;
Nz::ShaderAst::ExpressionType type;
};
private:
std::shared_ptr<QtNodes::DataModelRegistry> BuildRegistry();
QtNodes::FlowScene m_flowScene;
std::vector<TextureEntry> m_textures;
};
#include <ShaderGraph.inl>
#endif

View File

@ -0,0 +1,11 @@
#include <ShaderGraph.hpp>
inline QtNodes::FlowScene& ShaderGraph::GetScene()
{
return m_flowScene;
}
inline auto ShaderGraph::GetTextures() -> const std::vector<TextureEntry>&
{
return m_textures;
}

View File

@ -1,10 +1,6 @@
#include <Nazara/Core/StackArray.hpp>
#include <Nazara/Renderer/ShaderAst.hpp> #include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderBuilder.hpp> #include <Nazara/Renderer/ShaderBuilder.hpp>
#include <Nazara/Renderer/GlslWriter.hpp> #include <Nazara/Renderer/GlslWriter.hpp>
#include <DataModels/FragmentOutput.hpp>
#include <DataModels/ShaderNode.hpp>
#include <DataModels/VecValue.hpp>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
#include <QtWidgets/QMenuBar> #include <QtWidgets/QMenuBar>
@ -17,103 +13,41 @@
#include <nodes/FlowScene> #include <nodes/FlowScene>
#include <nodes/FlowView> #include <nodes/FlowView>
#include <nodes/DataModelRegistry> #include <nodes/DataModelRegistry>
#include <ShaderGraph.hpp>
#include <iostream> #include <iostream>
std::shared_ptr<QtNodes::DataModelRegistry> registerDataModels() void GenerateGLSL(ShaderGraph& graph)
{ {
auto ret = std::make_shared<QtNodes::DataModelRegistry>();
ret->registerModel<FragmentOutput>();
ret->registerModel<Vec4Value>();
return ret;
}
void GenerateGLSL(QtNodes::FlowScene* scene)
{
/*using namespace ShaderBuilder;
using ShaderAst::BuiltinEntry;
using ShaderAst::ExpressionType;
// Fragment shader
{
auto rt0 = Output("RenderTarget0", ExpressionType::Float4);
auto color = Uniform("Color", ExpressionType::Float4);
fragmentShader = writer.Generate(ExprStatement(Assign(rt0, color)));
}*/
Nz::GlslWriter writer; Nz::GlslWriter writer;
std::vector<Nz::ShaderAst::StatementPtr> statements; Nz::String glsl = writer.Generate(graph.Generate());
std::function<Nz::ShaderAst::ExpressionPtr(QtNodes::Node*)> HandleNode; std::cout << glsl << std::endl;
HandleNode = [&](QtNodes::Node* node) -> Nz::ShaderAst::ExpressionPtr
{
ShaderNode* shaderNode = static_cast<ShaderNode*>(node->nodeDataModel());
qDebug() << shaderNode->name();
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;
for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In))
{
for (const auto& [uuid, conn] : connectionSet)
{
assert(i < expressions.size());
expressions[i] = HandleNode(conn->getNode(QtNodes::PortType::Out));
i++;
}
}
return shaderNode->GetExpression(expressions.data(), expressions.size());
};
scene->iterateOverNodes([&](QtNodes::Node* node)
{
if (node->nodeDataModel()->nPorts(QtNodes::PortType::Out) == 0)
{
statements.emplace_back(Nz::ShaderBuilder::ExprStatement(HandleNode(node)));
//qDebug() << node->nodeDataModel()->name();
}
});
Nz::String glsl = writer.Generate(std::make_shared<Nz::ShaderAst::StatementBlock>(std::move(statements)));
QTextEdit* output = new QTextEdit; QTextEdit* output = new QTextEdit;
output->setReadOnly(true);
output->setText(QString::fromUtf8(glsl.GetConstBuffer(), glsl.GetSize())); output->setText(QString::fromUtf8(glsl.GetConstBuffer(), glsl.GetSize()));
output->setAttribute(Qt::WA_DeleteOnClose, true); output->setAttribute(Qt::WA_DeleteOnClose, true);
output->setWindowTitle("GLSL Output"); output->setWindowTitle("GLSL Output");
output->show(); output->show();
std::cout << glsl << std::endl;
}
void SetupTestScene(QtNodes::FlowScene* scene)
{
auto& node1 = scene->createNode(std::make_unique<Vec4Value>());
node1.nodeGraphicsObject().setPos(200, 200);
auto& node2 = scene->createNode(std::make_unique<FragmentOutput>());
node2.nodeGraphicsObject().setPos(500, 300);
scene->createConnection(node2, 0, node1, 0);
} }
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
QApplication app(argc, argv); QApplication app(argc, argv);
ShaderGraph shaderGraph;
shaderGraph.AddTexture("TextureMachin", Nz::ShaderAst::ExpressionType::Sampler2D);
QWidget mainWindow; QWidget mainWindow;
QVBoxLayout* layout = new QVBoxLayout; QVBoxLayout* layout = new QVBoxLayout;
layout->setContentsMargins(0, 0, 0, 0); layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0); layout->setSpacing(0);
QtNodes::FlowScene* scene = new QtNodes::FlowScene(registerDataModels()); QtNodes::FlowScene* scene = &shaderGraph.GetScene();
SetupTestScene(scene);
QMenuBar* menuBar = new QMenuBar; QMenuBar* menuBar = new QMenuBar;
QAction* glslCode = menuBar->addAction("To GLSL"); QAction* glslCode = menuBar->addAction("To GLSL");
QObject::connect(glslCode, &QAction::triggered, [&](bool) { GenerateGLSL(scene); }); QObject::connect(glslCode, &QAction::triggered, [&](bool) { GenerateGLSL(shaderGraph); });
layout->addWidget(new QtNodes::FlowView(scene)); layout->addWidget(new QtNodes::FlowView(scene));
layout->addWidget(menuBar); layout->addWidget(menuBar);