ShaderNode: Add custom output support
This commit is contained in:
@@ -1,62 +0,0 @@
|
||||
#include <ShaderNode/DataModels/FragmentOutput.hpp>
|
||||
#include <Nazara/Renderer/ShaderBuilder.hpp>
|
||||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
|
||||
Nz::ShaderAst::ExpressionPtr FragmentOutput::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
|
||||
{
|
||||
using namespace Nz::ShaderAst;
|
||||
using namespace Nz::ShaderBuilder;
|
||||
|
||||
assert(count == 1);
|
||||
|
||||
auto output = Nz::ShaderBuilder::Output("RenderTarget0", ExpressionType::Float4);
|
||||
|
||||
return Nz::ShaderBuilder::Assign(output, *expressions);
|
||||
}
|
||||
|
||||
QtNodes::NodeDataType FragmentOutput::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portType == QtNodes::PortType::In);
|
||||
assert(portIndex == 0);
|
||||
|
||||
return Vec4Data::Type();
|
||||
}
|
||||
|
||||
unsigned int FragmentOutput::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return 1;
|
||||
case QtNodes::PortType::Out: return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> FragmentOutput::outData(QtNodes::PortIndex /*port*/)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void FragmentOutput::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||
{
|
||||
assert(index == 0);
|
||||
if (value)
|
||||
{
|
||||
assert(dynamic_cast<Vec4Data*>(value.get()) != nullptr);
|
||||
m_input = std::static_pointer_cast<Vec4Data>(value);
|
||||
}
|
||||
else
|
||||
m_input.reset();
|
||||
|
||||
UpdatePreview();
|
||||
}
|
||||
|
||||
bool FragmentOutput::ComputePreview(QPixmap& pixmap)
|
||||
{
|
||||
if (!m_input)
|
||||
return false;
|
||||
|
||||
pixmap = QPixmap::fromImage(m_input->preview);
|
||||
return true;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#include <ShaderNode/DataModels/FragmentOutput.hpp>
|
||||
|
||||
inline FragmentOutput::FragmentOutput(ShaderGraph& graph) :
|
||||
ShaderNode(graph)
|
||||
{
|
||||
SetPreviewSize({ 128, 128 });
|
||||
DisableCustomVariableName();
|
||||
EnablePreview(true);
|
||||
}
|
||||
@@ -101,11 +101,11 @@ Nz::ShaderAst::ExpressionPtr InputValue::GetExpression(Nz::ShaderAst::Expression
|
||||
{
|
||||
switch (inputEntry.type)
|
||||
{
|
||||
case InputType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
|
||||
case InputType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
|
||||
case InputType::Float2: return Nz::ShaderAst::ExpressionType::Float2;
|
||||
case InputType::Float3: return Nz::ShaderAst::ExpressionType::Float3;
|
||||
case InputType::Float4: return Nz::ShaderAst::ExpressionType::Float4;
|
||||
case InOutType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
|
||||
case InOutType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
|
||||
case InOutType::Float2: return Nz::ShaderAst::ExpressionType::Float2;
|
||||
case InOutType::Float3: return Nz::ShaderAst::ExpressionType::Float3;
|
||||
case InOutType::Float4: return Nz::ShaderAst::ExpressionType::Float4;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
@@ -117,20 +117,20 @@ Nz::ShaderAst::ExpressionPtr InputValue::GetExpression(Nz::ShaderAst::Expression
|
||||
|
||||
auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType
|
||||
{
|
||||
if (!m_currentInputIndex)
|
||||
return Vec4Data::Type();
|
||||
|
||||
assert(portType == QtNodes::PortType::Out);
|
||||
assert(portIndex == 0);
|
||||
|
||||
if (!m_currentInputIndex)
|
||||
return Vec4Data::Type();
|
||||
|
||||
const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex);
|
||||
switch (inputEntry.type)
|
||||
{
|
||||
//case InputType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
|
||||
//case InputType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
|
||||
case InputType::Float2: return Vec2Data::Type();
|
||||
case InputType::Float3: return Vec3Data::Type();
|
||||
case InputType::Float4: return Vec4Data::Type();
|
||||
case InOutType::Float2: return Vec2Data::Type();
|
||||
case InOutType::Float3: return Vec3Data::Type();
|
||||
case InOutType::Float4: return Vec4Data::Type();
|
||||
}
|
||||
|
||||
assert(false);
|
||||
|
||||
160
src/ShaderNode/DataModels/OutputValue.cpp
Normal file
160
src/ShaderNode/DataModels/OutputValue.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
#include <ShaderNode/DataModels/OutputValue.hpp>
|
||||
#include <Nazara/Renderer/ShaderBuilder.hpp>
|
||||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QFormLayout>
|
||||
|
||||
OutputValue::OutputValue(ShaderGraph& graph) :
|
||||
ShaderNode(graph)
|
||||
{
|
||||
m_onOutputListUpdateSlot.Connect(GetGraph().OnOutputListUpdate, [&](ShaderGraph*) { OnOutputListUpdate(); });
|
||||
m_onOutputUpdateSlot.Connect(GetGraph().OnOutputUpdate, [&](ShaderGraph*, std::size_t inputIndex)
|
||||
{
|
||||
if (m_currentOutputIndex == inputIndex)
|
||||
UpdatePreview();
|
||||
});
|
||||
|
||||
if (graph.GetOutputCount() > 0)
|
||||
{
|
||||
auto& firstOutput = graph.GetOutput(0);
|
||||
m_currentOutputIndex = 0;
|
||||
m_currentOutputText = firstOutput.name;
|
||||
}
|
||||
|
||||
EnablePreview();
|
||||
SetPreviewSize({ 128, 128 });
|
||||
DisableCustomVariableName();
|
||||
}
|
||||
|
||||
void OutputValue::BuildNodeEdition(QFormLayout* layout)
|
||||
{
|
||||
ShaderNode::BuildNodeEdition(layout);
|
||||
|
||||
QComboBox* outputSelection = new QComboBox;
|
||||
|
||||
connect(outputSelection, qOverload<int>(&QComboBox::currentIndexChanged), [&](int index)
|
||||
{
|
||||
if (index >= 0)
|
||||
m_currentOutputIndex = static_cast<std::size_t>(index);
|
||||
else
|
||||
m_currentOutputIndex.reset();
|
||||
|
||||
UpdatePreview();
|
||||
});
|
||||
|
||||
for (const auto& outputEntry : GetGraph().GetOutputs())
|
||||
outputSelection->addItem(QString::fromStdString(outputEntry.name));
|
||||
|
||||
layout->addRow(tr("Output"), outputSelection);
|
||||
}
|
||||
|
||||
Nz::ShaderAst::ExpressionPtr OutputValue::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
|
||||
{
|
||||
using namespace Nz::ShaderAst;
|
||||
using namespace Nz::ShaderBuilder;
|
||||
|
||||
assert(count == 1);
|
||||
|
||||
if (!m_currentOutputIndex)
|
||||
throw std::runtime_error("no output");
|
||||
|
||||
const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex);
|
||||
|
||||
Nz::ShaderAst::ExpressionType expression = [&]
|
||||
{
|
||||
switch (outputEntry.type)
|
||||
{
|
||||
case InOutType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
|
||||
case InOutType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
|
||||
case InOutType::Float2: return Nz::ShaderAst::ExpressionType::Float2;
|
||||
case InOutType::Float3: return Nz::ShaderAst::ExpressionType::Float3;
|
||||
case InOutType::Float4: return Nz::ShaderAst::ExpressionType::Float4;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Unhandled output type");
|
||||
}();
|
||||
|
||||
auto output = Nz::ShaderBuilder::Output(outputEntry.name, expression);
|
||||
|
||||
return Nz::ShaderBuilder::Assign(std::move(output), *expressions);
|
||||
}
|
||||
|
||||
QtNodes::NodeDataType OutputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portType == QtNodes::PortType::In);
|
||||
assert(portIndex == 0);
|
||||
|
||||
if (!m_currentOutputIndex)
|
||||
return Vec4Data::Type();
|
||||
|
||||
const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex);
|
||||
switch (outputEntry.type)
|
||||
{
|
||||
//case InOutType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
|
||||
//case InOutType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
|
||||
case InOutType::Float2: return Vec2Data::Type();
|
||||
case InOutType::Float3: return Vec3Data::Type();
|
||||
case InOutType::Float4: return Vec4Data::Type();
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Unhandled output type");
|
||||
}
|
||||
|
||||
unsigned int OutputValue::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return 1;
|
||||
case QtNodes::PortType::Out: return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> OutputValue::outData(QtNodes::PortIndex /*port*/)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void OutputValue::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||
{
|
||||
assert(index == 0);
|
||||
if (value)
|
||||
{
|
||||
assert(dynamic_cast<Vec4Data*>(value.get()) != nullptr);
|
||||
m_input = std::static_pointer_cast<Vec4Data>(value);
|
||||
}
|
||||
else
|
||||
m_input.reset();
|
||||
|
||||
UpdatePreview();
|
||||
}
|
||||
|
||||
bool OutputValue::ComputePreview(QPixmap& pixmap)
|
||||
{
|
||||
if (!m_input)
|
||||
return false;
|
||||
|
||||
pixmap = QPixmap::fromImage(m_input->preview);
|
||||
return true;
|
||||
}
|
||||
|
||||
void OutputValue::OnOutputListUpdate()
|
||||
{
|
||||
m_currentOutputIndex.reset();
|
||||
|
||||
std::size_t inputIndex = 0;
|
||||
for (const auto& inputEntry : GetGraph().GetOutputs())
|
||||
{
|
||||
if (inputEntry.name == m_currentOutputText)
|
||||
{
|
||||
m_currentOutputIndex = inputIndex;
|
||||
break;
|
||||
}
|
||||
|
||||
inputIndex++;
|
||||
}
|
||||
}
|
||||
@@ -3,20 +3,23 @@
|
||||
#ifndef NAZARA_SHADERNODES_FRAGMENTOUTPUT_HPP
|
||||
#define NAZARA_SHADERNODES_FRAGMENTOUTPUT_HPP
|
||||
|
||||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
#include <QtWidgets/QDoubleSpinBox>
|
||||
#include <QtWidgets/QFormLayout>
|
||||
|
||||
class FragmentOutput : public ShaderNode
|
||||
class QFormLayout;
|
||||
|
||||
class OutputValue : public ShaderNode
|
||||
{
|
||||
public:
|
||||
inline FragmentOutput(ShaderGraph& graph);
|
||||
OutputValue(ShaderGraph& graph);
|
||||
|
||||
void BuildNodeEdition(QFormLayout* layout) override;
|
||||
|
||||
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
|
||||
|
||||
QString caption() const override { return "Fragment shader output"; }
|
||||
QString name() const override { return "FragmentShaderOutput"; }
|
||||
QString caption() const override { return "Output"; }
|
||||
QString name() const override { return "Output"; }
|
||||
|
||||
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
|
||||
@@ -28,10 +31,16 @@ class FragmentOutput : public ShaderNode
|
||||
|
||||
private:
|
||||
bool ComputePreview(QPixmap& pixmap) override;
|
||||
void OnOutputListUpdate();
|
||||
|
||||
std::shared_ptr<Vec4Data> m_input;
|
||||
NazaraSlot(ShaderGraph, OnOutputListUpdate, m_onOutputListUpdateSlot);
|
||||
NazaraSlot(ShaderGraph, OnOutputUpdate, m_onOutputUpdateSlot);
|
||||
|
||||
std::optional<std::size_t> m_currentOutputIndex;
|
||||
std::shared_ptr<VecData> m_input;
|
||||
std::string m_currentOutputText;
|
||||
};
|
||||
|
||||
#include <ShaderNode/DataModels/FragmentOutput.inl>
|
||||
#include <ShaderNode/DataModels/OutputValue.inl>
|
||||
|
||||
#endif
|
||||
1
src/ShaderNode/DataModels/OutputValue.inl
Normal file
1
src/ShaderNode/DataModels/OutputValue.inl
Normal file
@@ -0,0 +1 @@
|
||||
#include <ShaderNode/DataModels/OutputValue.hpp>
|
||||
@@ -20,7 +20,8 @@ class ShaderNode : public QtNodes::NodeDataModel
|
||||
|
||||
virtual void BuildNodeEdition(QFormLayout* layout);
|
||||
|
||||
void EnablePreview(bool enable);
|
||||
inline void DisablePreview();
|
||||
void EnablePreview(bool enable = true);
|
||||
|
||||
virtual Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const = 0;
|
||||
inline ShaderGraph& GetGraph();
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||
|
||||
inline void ShaderNode::DisablePreview()
|
||||
{
|
||||
return EnablePreview(false);
|
||||
}
|
||||
|
||||
inline ShaderGraph& ShaderNode::GetGraph()
|
||||
{
|
||||
return m_graph;
|
||||
|
||||
Reference in New Issue
Block a user