Commit current work
Reworked conditions, added uber-shaders, comparison nodes, fixed Discard
This commit is contained in:
163
src/ShaderNode/DataModels/BinOp.hpp
Normal file
163
src/ShaderNode/DataModels/BinOp.hpp
Normal file
@@ -0,0 +1,163 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_BINOP_HPP
|
||||
#define NAZARA_SHADERNODES_BINOP_HPP
|
||||
|
||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||
#include <ShaderNode/DataTypes/FloatData.hpp>
|
||||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
class BinOp : public ShaderNode
|
||||
{
|
||||
public:
|
||||
BinOp(ShaderGraph& graph);
|
||||
~BinOp() = default;
|
||||
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
|
||||
virtual QString GetOperationString() const = 0;
|
||||
|
||||
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;
|
||||
|
||||
QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
|
||||
void setInData(std::shared_ptr<QtNodes::NodeData> value, int index) override;
|
||||
|
||||
QtNodes::NodeValidationState validationState() const override;
|
||||
QString validationMessage() const override;
|
||||
|
||||
private:
|
||||
virtual void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) = 0;
|
||||
|
||||
bool ComputePreview(QPixmap& pixmap) override;
|
||||
void UpdateOutput();
|
||||
|
||||
std::shared_ptr<DataType> m_lhs;
|
||||
std::shared_ptr<DataType> m_rhs;
|
||||
std::shared_ptr<DataType> m_output;
|
||||
};
|
||||
|
||||
|
||||
template<typename DataType>
|
||||
class BinAdd : public BinOp<DataType, Nz::ShaderNodes::BinaryType::Add>
|
||||
{
|
||||
public:
|
||||
using BinOp<DataType, Nz::ShaderNodes::BinaryType::Add>::BinOp;
|
||||
|
||||
void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override;
|
||||
QString GetOperationString() const final;
|
||||
};
|
||||
|
||||
template<typename DataType>
|
||||
class BinMul : public BinOp<DataType, Nz::ShaderNodes::BinaryType::Multiply>
|
||||
{
|
||||
public:
|
||||
using BinOp<DataType, Nz::ShaderNodes::BinaryType::Multiply>::BinOp;
|
||||
|
||||
void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override;
|
||||
QString GetOperationString() const final;
|
||||
};
|
||||
|
||||
template<typename DataType>
|
||||
class BinSub : public BinOp<DataType, Nz::ShaderNodes::BinaryType::Substract>
|
||||
{
|
||||
public:
|
||||
using BinOp<DataType, Nz::ShaderNodes::BinaryType::Substract>::BinOp;
|
||||
|
||||
void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override;
|
||||
QString GetOperationString() const final;
|
||||
};
|
||||
|
||||
template<typename DataType>
|
||||
class BinDiv : public BinOp<DataType, Nz::ShaderNodes::BinaryType::Divide>
|
||||
{
|
||||
public:
|
||||
using BinOp<DataType, Nz::ShaderNodes::BinaryType::Divide>::BinOp;
|
||||
|
||||
void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override;
|
||||
QString GetOperationString() const final;
|
||||
};
|
||||
|
||||
|
||||
class FloatAdd : public BinAdd<FloatData>
|
||||
{
|
||||
public:
|
||||
using BinAdd<FloatData>::BinAdd;
|
||||
|
||||
QString caption() const override { return "Float addition"; }
|
||||
QString name() const override { return "float_add"; }
|
||||
};
|
||||
|
||||
class FloatMul : public BinMul<FloatData>
|
||||
{
|
||||
public:
|
||||
using BinMul<FloatData>::BinMul;
|
||||
|
||||
QString caption() const override { return "Float multiplication"; }
|
||||
QString name() const override { return "float_mul"; }
|
||||
};
|
||||
|
||||
class FloatSub : public BinMul<FloatData>
|
||||
{
|
||||
public:
|
||||
using BinMul<FloatData>::BinMul;
|
||||
|
||||
QString caption() const override { return "Float subtraction"; }
|
||||
QString name() const override { return "float_sub"; }
|
||||
};
|
||||
|
||||
class FloatDiv : public BinDiv<FloatData>
|
||||
{
|
||||
public:
|
||||
using BinDiv<FloatData>::BinDiv;
|
||||
|
||||
QString caption() const override { return "Float division"; }
|
||||
QString name() const override { return "float_div"; }
|
||||
};
|
||||
|
||||
|
||||
class VecAdd : public BinAdd<VecData>
|
||||
{
|
||||
public:
|
||||
using BinAdd<VecData>::BinAdd;
|
||||
|
||||
QString caption() const override { return "Vector addition"; }
|
||||
QString name() const override { return "vec_add"; }
|
||||
};
|
||||
|
||||
class VecMul : public BinMul<VecData>
|
||||
{
|
||||
public:
|
||||
using BinMul<VecData>::BinMul;
|
||||
|
||||
QString caption() const override { return "Vector multiplication"; }
|
||||
QString name() const override { return "vec_mul"; }
|
||||
};
|
||||
|
||||
class VecSub : public BinMul<VecData>
|
||||
{
|
||||
public:
|
||||
using BinMul<VecData>::BinMul;
|
||||
|
||||
QString caption() const override { return "Vector subtraction"; }
|
||||
QString name() const override { return "vec_sub"; }
|
||||
};
|
||||
|
||||
class VecDiv : public BinDiv<VecData>
|
||||
{
|
||||
public:
|
||||
using BinDiv<VecData>::BinDiv;
|
||||
|
||||
QString caption() const override { return "Vector division"; }
|
||||
QString name() const override { return "vec_div"; }
|
||||
};
|
||||
|
||||
#include <ShaderNode/DataModels/BinOp.inl>
|
||||
|
||||
#endif
|
||||
240
src/ShaderNode/DataModels/BinOp.inl
Normal file
240
src/ShaderNode/DataModels/BinOp.inl
Normal file
@@ -0,0 +1,240 @@
|
||||
#include <ShaderNode/DataModels/BinOp.hpp>
|
||||
#include <Nazara/Shader/ShaderBuilder.hpp>
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
BinOp<DataType, Op>::BinOp(ShaderGraph& graph) :
|
||||
ShaderNode(graph)
|
||||
{
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
Nz::ShaderNodes::NodePtr BinOp<DataType, Op>::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(count == 2);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder<Op>;
|
||||
constexpr BuilderType builder;
|
||||
return builder(expressions[0], expressions[1]);
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
QtNodes::NodeDataType BinOp<DataType, Op>::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0 || portIndex == 1);
|
||||
|
||||
return DataType::Type();
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
unsigned int BinOp<DataType, Op>::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return 2;
|
||||
case QtNodes::PortType::Out: return 1;
|
||||
default: break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("invalid port type");
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
std::shared_ptr<QtNodes::NodeData> BinOp<DataType, Op>::outData(QtNodes::PortIndex port)
|
||||
{
|
||||
assert(port == 0);
|
||||
return m_output;
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
QString BinOp<DataType, Op>::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In:
|
||||
{
|
||||
switch (portIndex)
|
||||
{
|
||||
case 0:
|
||||
return "A";
|
||||
|
||||
case 1:
|
||||
return "B";
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case QtNodes::PortType::Out:
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
return "A " + GetOperationString() + " B";
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QString{};
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
bool BinOp<DataType, Op>::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0 || portIndex == 1);
|
||||
return portType == QtNodes::PortType::In || portType == QtNodes::PortType::Out;
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
void BinOp<DataType, Op>::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||
{
|
||||
assert(index == 0 || index == 1);
|
||||
|
||||
std::shared_ptr<DataType> castedValue;
|
||||
if (value && value->type().id == DataType::Type().id)
|
||||
castedValue = std::static_pointer_cast<DataType>(value);
|
||||
|
||||
if (index == 0)
|
||||
m_lhs = std::move(castedValue);
|
||||
else
|
||||
m_rhs = std::move(castedValue);
|
||||
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
QtNodes::NodeValidationState BinOp<DataType, Op>::validationState() const
|
||||
{
|
||||
if (!m_lhs || !m_rhs)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
|
||||
if constexpr (std::is_same_v<DataType, VecData>)
|
||||
{
|
||||
if (m_lhs->componentCount != m_rhs->componentCount)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
}
|
||||
|
||||
return QtNodes::NodeValidationState::Valid;
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
QString BinOp<DataType, Op>::validationMessage() const
|
||||
{
|
||||
if (!m_lhs || !m_rhs)
|
||||
return "Missing operands";
|
||||
|
||||
if constexpr (std::is_same_v<DataType, VecData>)
|
||||
{
|
||||
if (m_lhs->componentCount != m_rhs->componentCount)
|
||||
return "Incompatible components count (left has " + QString::number(m_lhs->componentCount) + ", right has " + QString::number(m_rhs->componentCount) + ")";
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
bool BinOp<DataType, Op>::ComputePreview(QPixmap& pixmap)
|
||||
{
|
||||
if (!m_lhs || !m_rhs)
|
||||
return false;
|
||||
|
||||
pixmap = QPixmap::fromImage(m_output->preview.GenerateImage());
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
void BinOp<DataType, Op>::UpdateOutput()
|
||||
{
|
||||
if (validationState() != QtNodes::NodeValidationState::Valid)
|
||||
{
|
||||
if constexpr (std::is_same_v<DataType, VecData>)
|
||||
m_output = std::make_shared<DataType>(4);
|
||||
else
|
||||
m_output = std::make_shared<DataType>();
|
||||
|
||||
m_output->preview = PreviewValues(1, 1);
|
||||
m_output->preview.Fill(Nz::Vector4f::Zero());
|
||||
return;
|
||||
}
|
||||
|
||||
if constexpr (std::is_same_v<DataType, VecData>)
|
||||
m_output = std::make_shared<DataType>(m_lhs->componentCount);
|
||||
else
|
||||
m_output = std::make_shared<DataType>();
|
||||
|
||||
const PreviewValues& leftPreview = m_lhs->preview;
|
||||
const PreviewValues& rightPreview = m_rhs->preview;
|
||||
std::size_t maxWidth = std::max(leftPreview.GetWidth(), rightPreview.GetWidth());
|
||||
std::size_t maxHeight = std::max(leftPreview.GetHeight(), rightPreview.GetHeight());
|
||||
|
||||
// FIXME: Prevent useless copy
|
||||
PreviewValues leftResized = leftPreview;
|
||||
if (leftResized.GetWidth() != maxWidth || leftResized.GetHeight() != maxHeight)
|
||||
leftResized = leftResized.Resized(maxWidth, maxHeight);
|
||||
|
||||
PreviewValues rightResized = rightPreview;
|
||||
if (rightResized.GetWidth() != maxWidth || rightResized.GetHeight() != maxHeight)
|
||||
rightResized = rightResized.Resized(maxWidth, maxHeight);
|
||||
|
||||
m_output->preview = PreviewValues(maxWidth, maxHeight);
|
||||
ApplyOp(leftResized.GetData(), rightResized.GetData(), m_output->preview.GetData(), maxWidth * maxHeight);
|
||||
|
||||
Q_EMIT dataUpdated(0);
|
||||
|
||||
UpdatePreview();
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
void BinAdd<DataType>::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
output[i] = left[i] + right[i];
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
QString BinAdd<DataType>::GetOperationString() const
|
||||
{
|
||||
return "+";
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
void BinMul<DataType>::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
output[i] = left[i] * right[i];
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
QString BinMul<DataType>::GetOperationString() const
|
||||
{
|
||||
return "*";
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
void BinSub<DataType>::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
output[i] = left[i] - right[i];
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
QString BinSub<DataType>::GetOperationString() const
|
||||
{
|
||||
return "-";
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
void BinDiv<DataType>::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
output[i] = left[i] / right[i];
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
QString BinDiv<DataType>::GetOperationString() const
|
||||
{
|
||||
return "/";
|
||||
}
|
||||
126
src/ShaderNode/DataModels/BoolValue.cpp
Normal file
126
src/ShaderNode/DataModels/BoolValue.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
#include <ShaderNode/DataModels/BoolValue.hpp>
|
||||
#include <ShaderNode/DataTypes/BoolData.hpp>
|
||||
#include <Nazara/Shader/ShaderBuilder.hpp>
|
||||
#include <QtWidgets/QCheckBox>
|
||||
#include <cassert>
|
||||
|
||||
BoolValue::BoolValue(ShaderGraph& graph) :
|
||||
ShaderNode(graph),
|
||||
m_value(true)
|
||||
{
|
||||
UpdatePreview();
|
||||
}
|
||||
|
||||
QString BoolValue::caption() const
|
||||
{
|
||||
static QString caption = "Boolean constant";
|
||||
return caption;
|
||||
}
|
||||
|
||||
QString BoolValue::name() const
|
||||
{
|
||||
static QString name = "bool_constant";
|
||||
return name;
|
||||
}
|
||||
|
||||
QtNodes::NodeDataType BoolValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portType == QtNodes::PortType::Out);
|
||||
assert(portIndex == 0);
|
||||
|
||||
return BoolData::Type();
|
||||
}
|
||||
|
||||
unsigned int BoolValue::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return 0;
|
||||
case QtNodes::PortType::Out: return 1;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Invalid port type");
|
||||
}
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> BoolValue::outData(QtNodes::PortIndex port)
|
||||
{
|
||||
assert(port == 0);
|
||||
|
||||
float c = (m_value) ? 1.f : 0.f;
|
||||
|
||||
auto out = std::make_shared<BoolData>();
|
||||
out->preview(0, 0) = Nz::Vector4f(c, c, c, 1.f);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
QString BoolValue::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
assert(portType == QtNodes::PortType::Out);
|
||||
|
||||
return (m_value) ? "true" : "false";
|
||||
}
|
||||
|
||||
bool BoolValue::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
return portType == QtNodes::PortType::Out;
|
||||
}
|
||||
|
||||
void BoolValue::BuildNodeEdition(QFormLayout* layout)
|
||||
{
|
||||
ShaderNode::BuildNodeEdition(layout);
|
||||
|
||||
QCheckBox* checkbox = new QCheckBox;
|
||||
checkbox->setCheckState((m_value) ? Qt::Checked : Qt::Unchecked);
|
||||
connect(checkbox, &QCheckBox::stateChanged, [=](int newState)
|
||||
{
|
||||
m_value = (newState == Qt::Checked);
|
||||
Q_EMIT dataUpdated(0);
|
||||
|
||||
UpdatePreview();
|
||||
});
|
||||
|
||||
layout->addRow(tr("Value"), checkbox);
|
||||
}
|
||||
|
||||
Nz::ShaderNodes::NodePtr BoolValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(count == 0);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
return Nz::ShaderBuilder::Constant(m_value);
|
||||
}
|
||||
|
||||
bool BoolValue::ComputePreview(QPixmap& pixmap)
|
||||
{
|
||||
pixmap.fill(ToColor());
|
||||
return true;
|
||||
}
|
||||
|
||||
QColor BoolValue::ToColor() const
|
||||
{
|
||||
float value = (m_value) ? 1.f : 0.f;
|
||||
|
||||
return QColor::fromRgbF(value, value, value, value);
|
||||
}
|
||||
|
||||
void BoolValue::restore(const QJsonObject& data)
|
||||
{
|
||||
m_value = float(data["value"].toBool(m_value));
|
||||
|
||||
ShaderNode::restore(data);
|
||||
}
|
||||
|
||||
QJsonObject BoolValue::save() const
|
||||
{
|
||||
QJsonObject data = ShaderNode::save();
|
||||
data["value"] = m_value;
|
||||
|
||||
return data;
|
||||
}
|
||||
47
src/ShaderNode/DataModels/BoolValue.hpp
Normal file
47
src/ShaderNode/DataModels/BoolValue.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_BOOLVALUE_HPP
|
||||
#define NAZARA_SHADERNODES_BOOLVALUE_HPP
|
||||
|
||||
#include <QtGui/QImage>
|
||||
#include <QtWidgets/QDoubleSpinBox>
|
||||
#include <QtWidgets/QFormLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||
#include <ShaderNode/DataTypes/FloatData.hpp>
|
||||
#include <array>
|
||||
|
||||
class BoolValue : public ShaderNode
|
||||
{
|
||||
public:
|
||||
BoolValue(ShaderGraph& graph);
|
||||
~BoolValue() = default;
|
||||
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
void BuildNodeEdition(QFormLayout* layout) override;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
||||
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
|
||||
unsigned int nPorts(QtNodes::PortType portType) const override;
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
||||
|
||||
QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
|
||||
private:
|
||||
bool ComputePreview(QPixmap& pixmap) override;
|
||||
QColor ToColor() const;
|
||||
|
||||
void restore(const QJsonObject& data) override;
|
||||
QJsonObject save() const override;
|
||||
|
||||
bool m_value;
|
||||
};
|
||||
|
||||
#include <ShaderNode/DataModels/BoolValue.inl>
|
||||
|
||||
#endif
|
||||
1
src/ShaderNode/DataModels/BoolValue.inl
Normal file
1
src/ShaderNode/DataModels/BoolValue.inl
Normal file
@@ -0,0 +1 @@
|
||||
#include <ShaderNode/DataModels/BoolValue.hpp>
|
||||
@@ -49,9 +49,10 @@ ShaderNode(graph)
|
||||
UpdatePreview();
|
||||
}
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr BufferField::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const
|
||||
Nz::ShaderNodes::NodePtr BufferField::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(count == 0);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
if (!m_currentBufferIndex)
|
||||
throw std::runtime_error("no buffer");
|
||||
|
||||
@@ -15,10 +15,9 @@ class BufferField : public ShaderNode
|
||||
BufferField(ShaderGraph& graph);
|
||||
~BufferField() = default;
|
||||
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
void BuildNodeEdition(QFormLayout* layout) override;
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override;
|
||||
|
||||
QString caption() const override { return "BufferField"; }
|
||||
QString name() const override { return "BufferField"; }
|
||||
|
||||
|
||||
@@ -17,10 +17,9 @@ class CastVec : public ShaderNode
|
||||
CastVec(ShaderGraph& graph);
|
||||
~CastVec() = default;
|
||||
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const;
|
||||
void BuildNodeEdition(QFormLayout* layout) override;
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
||||
|
||||
@@ -16,6 +16,44 @@ ShaderNode(graph)
|
||||
m_output = std::make_shared<VecData>(ToComponentCount);
|
||||
}
|
||||
|
||||
template<std::size_t ToComponentCount>
|
||||
Nz::ShaderNodes::NodePtr CastVec<ToComponentCount>::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(m_input);
|
||||
assert(count == 1);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
std::size_t fromComponentCount = m_input->componentCount;
|
||||
|
||||
if (ToComponentCount > fromComponentCount)
|
||||
{
|
||||
std::size_t overflowComponentCount = ToComponentCount - fromComponentCount;
|
||||
|
||||
std::array<Nz::ShaderNodes::ExpressionPtr, 4> expr;
|
||||
expr[0] = expressions[0];
|
||||
for (std::size_t i = 0; i < overflowComponentCount; ++i)
|
||||
expr[i + 1] = Nz::ShaderBuilder::Constant(m_overflowComponents[i]);
|
||||
|
||||
constexpr auto ExpressionType = VecExpressionType<ToComponentCount>;
|
||||
|
||||
return Nz::ShaderBuilder::Cast<ExpressionType>(expr.data(), 1 + overflowComponentCount);
|
||||
}
|
||||
else if (ToComponentCount < fromComponentCount)
|
||||
{
|
||||
std::array<Nz::ShaderNodes::SwizzleComponent, ToComponentCount> swizzleComponents;
|
||||
for (std::size_t i = 0; i < ToComponentCount; ++i)
|
||||
swizzleComponents[i] = static_cast<Nz::ShaderNodes::SwizzleComponent>(static_cast<std::size_t>(Nz::ShaderNodes::SwizzleComponent::First) + i);
|
||||
|
||||
return std::apply([&](auto... components)
|
||||
{
|
||||
std::initializer_list<Nz::ShaderNodes::SwizzleComponent> componentList{ components... };
|
||||
return Nz::ShaderBuilder::Swizzle(expressions[0], componentList);
|
||||
}, swizzleComponents);
|
||||
}
|
||||
else
|
||||
return expressions[0]; //< no-op
|
||||
}
|
||||
|
||||
template<std::size_t ToComponentCount>
|
||||
void CastVec<ToComponentCount>::BuildNodeEdition(QFormLayout* layout)
|
||||
{
|
||||
@@ -48,43 +86,6 @@ void CastVec<ToComponentCount>::BuildNodeEdition(QFormLayout* layout)
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t ToComponentCount>
|
||||
Nz::ShaderNodes::ExpressionPtr CastVec<ToComponentCount>::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
|
||||
{
|
||||
assert(m_input);
|
||||
assert(count == 1);
|
||||
|
||||
std::size_t fromComponentCount = m_input->componentCount;
|
||||
|
||||
if (ToComponentCount > fromComponentCount)
|
||||
{
|
||||
std::size_t overflowComponentCount = ToComponentCount - fromComponentCount;
|
||||
|
||||
std::array<Nz::ShaderNodes::ExpressionPtr, 4> expr;
|
||||
expr[0] = expressions[0];
|
||||
for (std::size_t i = 0; i < overflowComponentCount; ++i)
|
||||
expr[i + 1] = Nz::ShaderBuilder::Constant(m_overflowComponents[i]);
|
||||
|
||||
constexpr auto ExpressionType = VecExpressionType<ToComponentCount>;
|
||||
|
||||
return Nz::ShaderBuilder::Cast<ExpressionType>(expr.data(), 1 + overflowComponentCount);
|
||||
}
|
||||
else if (ToComponentCount < fromComponentCount)
|
||||
{
|
||||
std::array<Nz::ShaderNodes::SwizzleComponent, ToComponentCount> swizzleComponents;
|
||||
for (std::size_t i = 0; i < ToComponentCount; ++i)
|
||||
swizzleComponents[i] = static_cast<Nz::ShaderNodes::SwizzleComponent>(static_cast<std::size_t>(Nz::ShaderNodes::SwizzleComponent::First) + i);
|
||||
|
||||
return std::apply([&](auto... components)
|
||||
{
|
||||
std::initializer_list<Nz::ShaderNodes::SwizzleComponent> componentList{ components... };
|
||||
return Nz::ShaderBuilder::Swizzle(expressions[0], componentList);
|
||||
}, swizzleComponents);
|
||||
}
|
||||
else
|
||||
return expressions[0]; //< no-op
|
||||
}
|
||||
|
||||
template<std::size_t ToComponentCount>
|
||||
QString CastVec<ToComponentCount>::caption() const
|
||||
{
|
||||
|
||||
220
src/ShaderNode/DataModels/CompOp.hpp
Normal file
220
src/ShaderNode/DataModels/CompOp.hpp
Normal file
@@ -0,0 +1,220 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_COMPOP_HPP
|
||||
#define NAZARA_SHADERNODES_COMPOP_HPP
|
||||
|
||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||
#include <ShaderNode/DataTypes/BoolData.hpp>
|
||||
#include <ShaderNode/DataTypes/FloatData.hpp>
|
||||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
class CompOp : public ShaderNode
|
||||
{
|
||||
public:
|
||||
CompOp(ShaderGraph& graph);
|
||||
~CompOp() = default;
|
||||
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
|
||||
virtual QString GetOperationString() const = 0;
|
||||
|
||||
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;
|
||||
|
||||
QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
|
||||
void setInData(std::shared_ptr<QtNodes::NodeData> value, int index) override;
|
||||
|
||||
QtNodes::NodeValidationState validationState() const override;
|
||||
QString validationMessage() const override;
|
||||
|
||||
private:
|
||||
virtual void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) = 0;
|
||||
|
||||
bool ComputePreview(QPixmap& pixmap) override;
|
||||
void UpdateOutput();
|
||||
|
||||
std::shared_ptr<BoolData> m_output;
|
||||
std::shared_ptr<DataType> m_lhs;
|
||||
std::shared_ptr<DataType> m_rhs;
|
||||
};
|
||||
|
||||
|
||||
template<typename DataType>
|
||||
class CompEq : public CompOp<DataType, Nz::ShaderNodes::BinaryType::CompEq>
|
||||
{
|
||||
public:
|
||||
using CompOp<DataType, Nz::ShaderNodes::BinaryType::CompEq>::CompOp;
|
||||
|
||||
void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override;
|
||||
QString GetOperationString() const final;
|
||||
};
|
||||
|
||||
template<typename DataType>
|
||||
class CompGe : public CompOp<DataType, Nz::ShaderNodes::BinaryType::CompGe>
|
||||
{
|
||||
public:
|
||||
using CompOp<DataType, Nz::ShaderNodes::BinaryType::CompGe>::CompOp;
|
||||
|
||||
void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override;
|
||||
QString GetOperationString() const final;
|
||||
};
|
||||
|
||||
template<typename DataType>
|
||||
class CompGt : public CompOp<DataType, Nz::ShaderNodes::BinaryType::CompGt>
|
||||
{
|
||||
public:
|
||||
using CompOp<DataType, Nz::ShaderNodes::BinaryType::CompGt>::CompOp;
|
||||
|
||||
void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override;
|
||||
QString GetOperationString() const final;
|
||||
};
|
||||
|
||||
template<typename DataType>
|
||||
class CompLe : public CompOp<DataType, Nz::ShaderNodes::BinaryType::CompLe>
|
||||
{
|
||||
public:
|
||||
using CompOp<DataType, Nz::ShaderNodes::BinaryType::CompLe>::CompOp;
|
||||
|
||||
void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override;
|
||||
QString GetOperationString() const final;
|
||||
};
|
||||
|
||||
template<typename DataType>
|
||||
class CompLt : public CompOp<DataType, Nz::ShaderNodes::BinaryType::CompLt>
|
||||
{
|
||||
public:
|
||||
using CompOp<DataType, Nz::ShaderNodes::BinaryType::CompLt>::CompOp;
|
||||
|
||||
void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override;
|
||||
QString GetOperationString() const final;
|
||||
};
|
||||
|
||||
template<typename DataType>
|
||||
class CompNe : public CompOp<DataType, Nz::ShaderNodes::BinaryType::CompNe>
|
||||
{
|
||||
public:
|
||||
using CompOp<DataType, Nz::ShaderNodes::BinaryType::CompNe>::CompOp;
|
||||
|
||||
void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override;
|
||||
QString GetOperationString() const final;
|
||||
};
|
||||
|
||||
|
||||
class FloatEq : public CompEq<FloatData>
|
||||
{
|
||||
public:
|
||||
using CompEq<FloatData>::CompEq;
|
||||
|
||||
QString caption() const override { return "Float equality"; }
|
||||
QString name() const override { return "float_eq"; }
|
||||
};
|
||||
|
||||
class FloatGe : public CompGe<FloatData>
|
||||
{
|
||||
public:
|
||||
using CompGe<FloatData>::CompGe;
|
||||
|
||||
QString caption() const override { return "Float greater than or equal"; }
|
||||
QString name() const override { return "float_ge"; }
|
||||
};
|
||||
|
||||
class FloatGt : public CompGt<FloatData>
|
||||
{
|
||||
public:
|
||||
using CompGt<FloatData>::CompGt;
|
||||
|
||||
QString caption() const override { return "Float greater than"; }
|
||||
QString name() const override { return "float_gt"; }
|
||||
};
|
||||
|
||||
class FloatLe : public CompLe<FloatData>
|
||||
{
|
||||
public:
|
||||
using CompLe<FloatData>::CompLe;
|
||||
|
||||
QString caption() const override { return "Float less than or equal"; }
|
||||
QString name() const override { return "float_le"; }
|
||||
};
|
||||
|
||||
class FloatLt : public CompLt<FloatData>
|
||||
{
|
||||
public:
|
||||
using CompLt<FloatData>::CompLt;
|
||||
|
||||
QString caption() const override { return "Float less than"; }
|
||||
QString name() const override { return "float_lt"; }
|
||||
};
|
||||
|
||||
class FloatNe : public CompNe<FloatData>
|
||||
{
|
||||
public:
|
||||
using CompNe<FloatData>::CompNe;
|
||||
|
||||
QString caption() const override { return "Float inequality"; }
|
||||
QString name() const override { return "float_ne"; }
|
||||
};
|
||||
|
||||
|
||||
class VecEq : public CompEq<VecData>
|
||||
{
|
||||
public:
|
||||
using CompEq<VecData>::CompEq;
|
||||
|
||||
QString caption() const override { return "Vector equality"; }
|
||||
QString name() const override { return "vec_eq"; }
|
||||
};
|
||||
|
||||
class VecGe : public CompGe<VecData>
|
||||
{
|
||||
public:
|
||||
using CompGe<VecData>::CompGe;
|
||||
|
||||
QString caption() const override { return "Vector greater than or equal"; }
|
||||
QString name() const override { return "vec_ge"; }
|
||||
};
|
||||
|
||||
class VecGt : public CompGt<VecData>
|
||||
{
|
||||
public:
|
||||
using CompGt<VecData>::CompGt;
|
||||
|
||||
QString caption() const override { return "Vector greater than"; }
|
||||
QString name() const override { return "vec_gt"; }
|
||||
};
|
||||
|
||||
class VecLe : public CompLe<VecData>
|
||||
{
|
||||
public:
|
||||
using CompLe<VecData>::CompLe;
|
||||
|
||||
QString caption() const override { return "Vector less than or equal"; }
|
||||
QString name() const override { return "vec_le"; }
|
||||
};
|
||||
|
||||
class VecLt : public CompLt<VecData>
|
||||
{
|
||||
public:
|
||||
using CompLt<VecData>::CompLt;
|
||||
|
||||
QString caption() const override { return "Vector less than"; }
|
||||
QString name() const override { return "vec_lt"; }
|
||||
};
|
||||
|
||||
class VecNe : public CompNe<VecData>
|
||||
{
|
||||
public:
|
||||
using CompNe<VecData>::CompNe;
|
||||
|
||||
QString caption() const override { return "Vector inequality"; }
|
||||
QString name() const override { return "vec_ne"; }
|
||||
};
|
||||
|
||||
#include <ShaderNode/DataModels/CompOp.inl>
|
||||
|
||||
#endif
|
||||
293
src/ShaderNode/DataModels/CompOp.inl
Normal file
293
src/ShaderNode/DataModels/CompOp.inl
Normal file
@@ -0,0 +1,293 @@
|
||||
#include <ShaderNode/DataModels/CompOp.hpp>
|
||||
#include <Nazara/Shader/ShaderBuilder.hpp>
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
CompOp<DataType, Op>::CompOp(ShaderGraph& graph) :
|
||||
ShaderNode(graph)
|
||||
{
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
Nz::ShaderNodes::NodePtr CompOp<DataType, Op>::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(count == 2);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder<Op>;
|
||||
constexpr BuilderType builder;
|
||||
return builder(expressions[0], expressions[1]);
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
QtNodes::NodeDataType CompOp<DataType, Op>::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In:
|
||||
{
|
||||
assert(portIndex == 0 || portIndex == 1);
|
||||
return DataType::Type();
|
||||
}
|
||||
|
||||
case QtNodes::PortType::Out:
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
return BoolData::Type();
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("invalid port type");
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
unsigned int CompOp<DataType, Op>::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return 2;
|
||||
case QtNodes::PortType::Out: return 1;
|
||||
default: break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("invalid port type");
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
std::shared_ptr<QtNodes::NodeData> CompOp<DataType, Op>::outData(QtNodes::PortIndex port)
|
||||
{
|
||||
assert(port == 0);
|
||||
return m_output;
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
QString CompOp<DataType, Op>::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In:
|
||||
{
|
||||
switch (portIndex)
|
||||
{
|
||||
case 0:
|
||||
return "A";
|
||||
|
||||
case 1:
|
||||
return "B";
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case QtNodes::PortType::Out:
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
return "A " + GetOperationString() + " B";
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QString{};
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
bool CompOp<DataType, Op>::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0 || portIndex == 1);
|
||||
return portType == QtNodes::PortType::In || portType == QtNodes::PortType::Out;
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
void CompOp<DataType, Op>::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||
{
|
||||
assert(index == 0 || index == 1);
|
||||
|
||||
std::shared_ptr<DataType> castedValue;
|
||||
if (value && value->type().id == DataType::Type().id)
|
||||
castedValue = std::static_pointer_cast<DataType>(value);
|
||||
|
||||
if (index == 0)
|
||||
m_lhs = std::move(castedValue);
|
||||
else
|
||||
m_rhs = std::move(castedValue);
|
||||
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
QtNodes::NodeValidationState CompOp<DataType, Op>::validationState() const
|
||||
{
|
||||
if (!m_lhs || !m_rhs)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
|
||||
if constexpr (std::is_same_v<DataType, VecData>)
|
||||
{
|
||||
if (m_lhs->componentCount != m_rhs->componentCount)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
}
|
||||
|
||||
return QtNodes::NodeValidationState::Valid;
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
QString CompOp<DataType, Op>::validationMessage() const
|
||||
{
|
||||
if (!m_lhs || !m_rhs)
|
||||
return "Missing operands";
|
||||
|
||||
if constexpr (std::is_same_v<DataType, VecData>)
|
||||
{
|
||||
if (m_lhs->componentCount != m_rhs->componentCount)
|
||||
return "Incompatible components count (left has " + QString::number(m_lhs->componentCount) + ", right has " + QString::number(m_rhs->componentCount) + ")";
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
bool CompOp<DataType, Op>::ComputePreview(QPixmap& pixmap)
|
||||
{
|
||||
if (!m_lhs || !m_rhs)
|
||||
return false;
|
||||
|
||||
pixmap = QPixmap::fromImage(m_output->preview.GenerateImage());
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename DataType, Nz::ShaderNodes::BinaryType Op>
|
||||
void CompOp<DataType, Op>::UpdateOutput()
|
||||
{
|
||||
if (validationState() != QtNodes::NodeValidationState::Valid)
|
||||
{
|
||||
m_output = std::make_shared<BoolData>();
|
||||
m_output->preview = PreviewValues(1, 1);
|
||||
m_output->preview.Fill(Nz::Vector4f::Zero());
|
||||
return;
|
||||
}
|
||||
|
||||
m_output = std::make_shared<BoolData>();
|
||||
|
||||
const PreviewValues& leftPreview = m_lhs->preview;
|
||||
const PreviewValues& rightPreview = m_rhs->preview;
|
||||
std::size_t maxWidth = std::max(leftPreview.GetWidth(), rightPreview.GetWidth());
|
||||
std::size_t maxHeight = std::max(leftPreview.GetHeight(), rightPreview.GetHeight());
|
||||
|
||||
// FIXME: Prevent useless copy
|
||||
PreviewValues leftResized = leftPreview;
|
||||
if (leftResized.GetWidth() != maxWidth || leftResized.GetHeight() != maxHeight)
|
||||
leftResized = leftResized.Resized(maxWidth, maxHeight);
|
||||
|
||||
PreviewValues rightResized = rightPreview;
|
||||
if (rightResized.GetWidth() != maxWidth || rightResized.GetHeight() != maxHeight)
|
||||
rightResized = rightResized.Resized(maxWidth, maxHeight);
|
||||
|
||||
m_output->preview = PreviewValues(maxWidth, maxHeight);
|
||||
ApplyOp(leftResized.GetData(), rightResized.GetData(), m_output->preview.GetData(), maxWidth * maxHeight);
|
||||
|
||||
Q_EMIT dataUpdated(0);
|
||||
|
||||
UpdatePreview();
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
void CompEq<DataType>::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
{
|
||||
float r = (left[i] == right[i]) ? 1.f : 0.f;
|
||||
output[i] = Nz::Vector4f(r, r, r, r);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
QString CompEq<DataType>::GetOperationString() const
|
||||
{
|
||||
return "==";
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
void CompGe<DataType>::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
{
|
||||
float r = (left[i] >= right[i]) ? 1.f : 0.f;
|
||||
output[i] = Nz::Vector4f(r, r, r, r);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
QString CompGe<DataType>::GetOperationString() const
|
||||
{
|
||||
return ">=";
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
void CompGt<DataType>::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
{
|
||||
float r = (left[i] > right[i]) ? 1.f : 0.f;
|
||||
output[i] = Nz::Vector4f(r, r, r, r);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
QString CompGt<DataType>::GetOperationString() const
|
||||
{
|
||||
return ">";
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
void CompLe<DataType>::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
{
|
||||
float r = (left[i] >= right[i]) ? 1.f : 0.f;
|
||||
output[i] = Nz::Vector4f(r, r, r, r);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
QString CompLe<DataType>::GetOperationString() const
|
||||
{
|
||||
return "<=";
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
void CompLt<DataType>::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
{
|
||||
float r = (left[i] > right[i]) ? 1.f : 0.f;
|
||||
output[i] = Nz::Vector4f(r, r, r, r);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
QString CompLt<DataType>::GetOperationString() const
|
||||
{
|
||||
return "<";
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
void CompNe<DataType>::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
{
|
||||
float r = (left[i] != right[i]) ? 1.f : 0.f;
|
||||
output[i] = Nz::Vector4f(r, r, r, r);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
QString CompNe<DataType>::GetOperationString() const
|
||||
{
|
||||
return "!=";
|
||||
}
|
||||
@@ -35,9 +35,10 @@ ShaderNode(graph)
|
||||
UpdatePreview();
|
||||
}
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr ConditionalExpression::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
|
||||
Nz::ShaderNodes::NodePtr ConditionalExpression::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(count == 2);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
if (!m_currentConditionIndex)
|
||||
throw std::runtime_error("no condition");
|
||||
@@ -100,15 +101,48 @@ void ConditionalExpression::BuildNodeEdition(QFormLayout* layout)
|
||||
|
||||
auto ConditionalExpression::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In:
|
||||
{
|
||||
switch (portIndex)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (!m_truePath && !m_falsePath)
|
||||
return VecData::Type();
|
||||
|
||||
return (m_truePath) ? m_truePath->type() : m_falsePath->type();
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
if (!m_truePath && !m_falsePath)
|
||||
return VecData::Type();
|
||||
|
||||
return (m_falsePath) ? m_falsePath->type() : m_truePath->type();
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case QtNodes::PortType::Out:
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
|
||||
if (!m_truePath && !m_falsePath)
|
||||
return VecData::Type();
|
||||
|
||||
return (m_truePath) ? m_truePath->type() : m_falsePath->type();
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return VecData::Type();
|
||||
|
||||
assert(portType == QtNodes::PortType::Out);
|
||||
assert(portIndex == 0);
|
||||
|
||||
if (!m_truePath && !m_falsePath)
|
||||
return VecData::Type();
|
||||
|
||||
return (m_truePath) ? m_truePath->type() : m_falsePath->type();
|
||||
}
|
||||
|
||||
QString ConditionalExpression::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
@@ -120,10 +154,10 @@ QString ConditionalExpression::portCaption(QtNodes::PortType portType, QtNodes::
|
||||
switch (portIndex)
|
||||
{
|
||||
case 0:
|
||||
return "True path";
|
||||
return "True expression";
|
||||
|
||||
case 1:
|
||||
return "False path";
|
||||
return "False expression";
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -189,6 +223,9 @@ QtNodes::NodeValidationState ConditionalExpression::validationState() const
|
||||
|
||||
QString ConditionalExpression::validationMessage() const
|
||||
{
|
||||
if (!m_currentConditionIndex)
|
||||
return "Invalid condition";
|
||||
|
||||
if (!m_truePath || !m_falsePath)
|
||||
return "Missing input";
|
||||
|
||||
|
||||
@@ -15,10 +15,9 @@ class ConditionalExpression : public ShaderNode
|
||||
ConditionalExpression(ShaderGraph& graph);
|
||||
~ConditionalExpression() = default;
|
||||
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
void BuildNodeEdition(QFormLayout* layout) override;
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
||||
|
||||
@@ -36,9 +36,13 @@ unsigned int FloatValue::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
case QtNodes::PortType::In: return 0;
|
||||
case QtNodes::PortType::Out: return 1;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
assert(false);
|
||||
throw std::runtime_error("Invalid port type");
|
||||
}
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> FloatValue::outData(QtNodes::PortIndex port)
|
||||
@@ -51,6 +55,20 @@ std::shared_ptr<QtNodes::NodeData> FloatValue::outData(QtNodes::PortIndex port)
|
||||
return out;
|
||||
}
|
||||
|
||||
QString FloatValue::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
assert(portType == QtNodes::PortType::Out);
|
||||
|
||||
return QString::number(m_value);
|
||||
}
|
||||
|
||||
bool FloatValue::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
return portType == QtNodes::PortType::Out;
|
||||
}
|
||||
|
||||
void FloatValue::BuildNodeEdition(QFormLayout* layout)
|
||||
{
|
||||
ShaderNode::BuildNodeEdition(layout);
|
||||
@@ -71,9 +89,10 @@ void FloatValue::BuildNodeEdition(QFormLayout* layout)
|
||||
layout->addRow(tr("Value"), spinbox);
|
||||
}
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr FloatValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const
|
||||
Nz::ShaderNodes::NodePtr FloatValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(count == 0);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
return Nz::ShaderBuilder::Constant(m_value);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ class FloatValue : public ShaderNode
|
||||
FloatValue(ShaderGraph& graph);
|
||||
~FloatValue() = default;
|
||||
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
void BuildNodeEdition(QFormLayout* layout) override;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
||||
@@ -26,9 +29,8 @@ class FloatValue : public ShaderNode
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
||||
|
||||
void BuildNodeEdition(QFormLayout* layout) override;
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
|
||||
QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
|
||||
private:
|
||||
bool ComputePreview(QPixmap& pixmap) override;
|
||||
|
||||
@@ -109,9 +109,10 @@ void InputValue::BuildNodeEdition(QFormLayout* layout)
|
||||
layout->addRow(tr("Input"), inputSelection);
|
||||
}
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr InputValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const
|
||||
Nz::ShaderNodes::NodePtr InputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(count == 0);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
if (!m_currentInputIndex)
|
||||
throw std::runtime_error("no input");
|
||||
@@ -184,6 +185,35 @@ std::shared_ptr<QtNodes::NodeData> InputValue::outData(QtNodes::PortIndex port)
|
||||
throw std::runtime_error("Unhandled input type");
|
||||
}
|
||||
|
||||
QString InputValue::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
assert(portType == QtNodes::PortType::Out);
|
||||
|
||||
if (!m_currentInputIndex)
|
||||
return QString();
|
||||
|
||||
const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex);
|
||||
return QString::fromStdString(inputEntry.name);
|
||||
}
|
||||
|
||||
bool InputValue::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return false;
|
||||
case QtNodes::PortType::Out: return m_currentInputIndex.has_value();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Invalid port type");
|
||||
}
|
||||
|
||||
QtNodes::NodeValidationState InputValue::validationState() const
|
||||
{
|
||||
if (!m_currentInputIndex)
|
||||
|
||||
@@ -19,7 +19,7 @@ class InputValue : public ShaderNode
|
||||
|
||||
void BuildNodeEdition(QFormLayout* layout) override;
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override;
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
|
||||
QString caption() const override { return "Input"; }
|
||||
QString name() const override { return "Input"; }
|
||||
@@ -30,6 +30,9 @@ class InputValue : public ShaderNode
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
||||
|
||||
QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
|
||||
QtNodes::NodeValidationState validationState() const override;
|
||||
QString validationMessage() const override;
|
||||
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||
#include <ShaderNode/DataTypes/Matrix4Data.hpp>
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
template<Nz::ShaderNodes::BinaryType Op>
|
||||
class Mat4BinOp : public ShaderNode
|
||||
{
|
||||
public:
|
||||
Mat4BinOp(ShaderGraph& graph);
|
||||
~Mat4BinOp() = default;
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const;
|
||||
|
||||
unsigned int nPorts(QtNodes::PortType portType) const override;
|
||||
|
||||
|
||||
@@ -1,51 +1,55 @@
|
||||
#include <ShaderNode/DataModels/Mat4BinOp.hpp>
|
||||
#include <Nazara/Shader/ShaderBuilder.hpp>
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
Mat4BinOp<BinOp>::Mat4BinOp(ShaderGraph& graph) :
|
||||
template<Nz::ShaderNodes::BinaryType Op>
|
||||
Mat4BinOp<Op>::Mat4BinOp(ShaderGraph& graph) :
|
||||
ShaderNode(graph)
|
||||
{
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
Nz::ShaderNodes::ExpressionPtr Mat4BinOp<BinOp>::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
|
||||
template<Nz::ShaderNodes::BinaryType Op>
|
||||
Nz::ShaderNodes::NodePtr Mat4BinOp<Op>::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(count == 2);
|
||||
using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder<BinOp>;
|
||||
assert(outputIndex == 0);
|
||||
|
||||
using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder<Op>;
|
||||
constexpr BuilderType builder;
|
||||
return builder(expressions[0], expressions[1]);
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
QtNodes::NodeDataType Mat4BinOp<BinOp>::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const
|
||||
template<Nz::ShaderNodes::BinaryType Op>
|
||||
QtNodes::NodeDataType Mat4BinOp<Op>::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0 || portIndex == 1);
|
||||
|
||||
return Matrix4Data::Type();
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
unsigned int Mat4BinOp<BinOp>::nPorts(QtNodes::PortType portType) const
|
||||
template<Nz::ShaderNodes::BinaryType Op>
|
||||
unsigned int Mat4BinOp<Op>::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return 2;
|
||||
case QtNodes::PortType::Out: return 1;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
assert(false);
|
||||
throw std::runtime_error("invalid port type");
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
std::shared_ptr<QtNodes::NodeData> Mat4BinOp<BinOp>::outData(QtNodes::PortIndex port)
|
||||
template<Nz::ShaderNodes::BinaryType Op>
|
||||
std::shared_ptr<QtNodes::NodeData> Mat4BinOp<Op>::outData(QtNodes::PortIndex port)
|
||||
{
|
||||
assert(port == 0);
|
||||
return m_output;
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
void Mat4BinOp<BinOp>::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||
template<Nz::ShaderNodes::BinaryType Op>
|
||||
void Mat4BinOp<Op>::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||
{
|
||||
assert(index == 0 || index == 1);
|
||||
|
||||
@@ -64,8 +68,8 @@ void Mat4BinOp<BinOp>::setInData(std::shared_ptr<QtNodes::NodeData> value, int i
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
QtNodes::NodeValidationState Mat4BinOp<BinOp>::validationState() const
|
||||
template<Nz::ShaderNodes::BinaryType Op>
|
||||
QtNodes::NodeValidationState Mat4BinOp<Op>::validationState() const
|
||||
{
|
||||
if (!m_lhs || !m_rhs)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
@@ -73,8 +77,8 @@ QtNodes::NodeValidationState Mat4BinOp<BinOp>::validationState() const
|
||||
return QtNodes::NodeValidationState::Valid;
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
QString Mat4BinOp<BinOp>::validationMessage() const
|
||||
template<Nz::ShaderNodes::BinaryType Op>
|
||||
QString Mat4BinOp<Op>::validationMessage() const
|
||||
{
|
||||
if (!m_lhs || !m_rhs)
|
||||
return "Missing operands";
|
||||
@@ -82,8 +86,8 @@ QString Mat4BinOp<BinOp>::validationMessage() const
|
||||
return QString();
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
bool Mat4BinOp<BinOp>::ComputePreview(QPixmap& pixmap)
|
||||
template<Nz::ShaderNodes::BinaryType Op>
|
||||
bool Mat4BinOp<Op>::ComputePreview(QPixmap& pixmap)
|
||||
{
|
||||
if (!m_lhs || !m_rhs)
|
||||
return false;
|
||||
@@ -94,8 +98,8 @@ bool Mat4BinOp<BinOp>::ComputePreview(QPixmap& pixmap)
|
||||
//return true;
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
void Mat4BinOp<BinOp>::UpdateOutput()
|
||||
template<Nz::ShaderNodes::BinaryType Op>
|
||||
void Mat4BinOp<Op>::UpdateOutput()
|
||||
{
|
||||
if (validationState() != QtNodes::NodeValidationState::Valid)
|
||||
{
|
||||
|
||||
@@ -7,9 +7,11 @@ ShaderNode(graph)
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr Mat4VecMul::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
|
||||
Nz::ShaderNodes::NodePtr Mat4VecMul::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(count == 2);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
using namespace Nz::ShaderNodes;
|
||||
return BinaryOp::Build(BinaryType::Multiply, expressions[0], expressions[1]);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class Mat4VecMul : public ShaderNode
|
||||
Mat4VecMul(ShaderGraph& graph);
|
||||
~Mat4VecMul() = default;
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
||||
@@ -54,12 +54,13 @@ void OutputValue::BuildNodeEdition(QFormLayout* layout)
|
||||
layout->addRow(tr("Output"), outputSelection);
|
||||
}
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr OutputValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
|
||||
Nz::ShaderNodes::NodePtr OutputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
using namespace Nz::ShaderBuilder;
|
||||
using namespace Nz::ShaderNodes;
|
||||
|
||||
assert(count == 1);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
if (!m_currentOutputIndex)
|
||||
throw std::runtime_error("no output");
|
||||
@@ -70,6 +71,11 @@ Nz::ShaderNodes::ExpressionPtr OutputValue::GetExpression(Nz::ShaderNodes::Expre
|
||||
return Nz::ShaderBuilder::Assign(std::move(output), *expressions);
|
||||
}
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> OutputValue::outData(QtNodes::PortIndex /*port*/)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
QtNodes::NodeDataType OutputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portType == QtNodes::PortType::In);
|
||||
@@ -88,14 +94,40 @@ unsigned int OutputValue::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
case QtNodes::PortType::In: return 1;
|
||||
case QtNodes::PortType::Out: return 0;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
assert(false);
|
||||
throw std::runtime_error("invalid port type");
|
||||
}
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> OutputValue::outData(QtNodes::PortIndex /*port*/)
|
||||
QString OutputValue::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
return {};
|
||||
assert(portType == QtNodes::PortType::In);
|
||||
assert(portIndex == 0);
|
||||
|
||||
if (!m_currentOutputIndex)
|
||||
return QString();
|
||||
|
||||
const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex);
|
||||
return QString::fromStdString(outputEntry.name);
|
||||
}
|
||||
|
||||
bool OutputValue::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return m_currentOutputIndex.has_value();
|
||||
case QtNodes::PortType::Out: return false;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Invalid port type");
|
||||
}
|
||||
|
||||
void OutputValue::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||
|
||||
@@ -16,7 +16,7 @@ class OutputValue : public ShaderNode
|
||||
|
||||
void BuildNodeEdition(QFormLayout* layout) override;
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
|
||||
QString caption() const override { return "Output"; }
|
||||
QString name() const override { return "Output"; }
|
||||
@@ -27,6 +27,9 @@ class OutputValue : public ShaderNode
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
||||
|
||||
QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
|
||||
void setInData(std::shared_ptr<QtNodes::NodeData> value, int index) override;
|
||||
|
||||
QtNodes::NodeValidationState validationState() const override;
|
||||
|
||||
@@ -14,12 +14,13 @@ ShaderNode(graph)
|
||||
DisableCustomVariableName();
|
||||
}
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr PositionOutputValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
|
||||
Nz::ShaderNodes::NodePtr PositionOutputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
using namespace Nz::ShaderBuilder;
|
||||
using namespace Nz::ShaderNodes;
|
||||
|
||||
assert(count == 1);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
auto output = Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Builtin(BuiltinEntry::VertexPosition));
|
||||
return Nz::ShaderBuilder::Assign(std::move(output), *expressions);
|
||||
|
||||
@@ -14,7 +14,7 @@ class PositionOutputValue : public ShaderNode
|
||||
public:
|
||||
PositionOutputValue(ShaderGraph& graph);
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
|
||||
QString caption() const override { return "PositionOutputValue"; }
|
||||
QString name() const override { return "PositionOutputValue"; }
|
||||
|
||||
@@ -71,11 +71,12 @@ bool SampleTexture::ComputePreview(QPixmap& pixmap)
|
||||
return true;
|
||||
}
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr SampleTexture::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
|
||||
Nz::ShaderNodes::NodePtr SampleTexture::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(m_texture);
|
||||
assert(m_uv);
|
||||
assert(count == 2);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
return Nz::ShaderBuilder::Sample2D(expressions[0], expressions[1]);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ class SampleTexture : public ShaderNode
|
||||
SampleTexture(ShaderGraph& graph);
|
||||
~SampleTexture() = default;
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override;
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
|
||||
QString caption() const override { return "Sample texture"; }
|
||||
QString name() const override { return "SampleTexture"; }
|
||||
|
||||
@@ -85,6 +85,11 @@ void ShaderNode::EnablePreview(bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
int ShaderNode::GetOutputOrder() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
QWidget* ShaderNode::embeddedWidget()
|
||||
{
|
||||
if (!m_embeddedWidget)
|
||||
|
||||
@@ -18,14 +18,15 @@ class ShaderNode : public QtNodes::NodeDataModel
|
||||
public:
|
||||
ShaderNode(ShaderGraph& graph);
|
||||
|
||||
virtual Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const = 0;
|
||||
virtual void BuildNodeEdition(QFormLayout* layout);
|
||||
|
||||
inline void DisablePreview();
|
||||
void EnablePreview(bool enable = true);
|
||||
|
||||
virtual Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const = 0;
|
||||
inline ShaderGraph& GetGraph();
|
||||
inline const ShaderGraph& GetGraph() const;
|
||||
virtual int GetOutputOrder() const;
|
||||
inline const std::string& GetVariableName() const;
|
||||
|
||||
inline void SetPreviewSize(const Nz::Vector2i& size);
|
||||
|
||||
@@ -110,12 +110,13 @@ void TextureValue::BuildNodeEdition(QFormLayout* layout)
|
||||
layout->addRow(tr("Texture"), textureSelection);
|
||||
}
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr TextureValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const
|
||||
Nz::ShaderNodes::NodePtr TextureValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
if (!m_currentTextureIndex)
|
||||
throw std::runtime_error("invalid texture input");
|
||||
|
||||
assert(count == 0);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
const auto& textureEntry = GetGraph().GetTexture(*m_currentTextureIndex);
|
||||
|
||||
@@ -178,6 +179,32 @@ std::shared_ptr<QtNodes::NodeData> TextureValue::outData(QtNodes::PortIndex port
|
||||
return textureData;
|
||||
}
|
||||
|
||||
QString TextureValue::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portType == QtNodes::PortType::Out);
|
||||
|
||||
if (!m_currentTextureIndex)
|
||||
return QString();
|
||||
|
||||
const auto& textureEntry = GetGraph().GetTexture(*m_currentTextureIndex);
|
||||
return QString::fromStdString(textureEntry.name);
|
||||
}
|
||||
|
||||
bool TextureValue::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return false;
|
||||
case QtNodes::PortType::Out: return m_currentTextureIndex.has_value();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Invalid port type");
|
||||
}
|
||||
|
||||
QtNodes::NodeValidationState TextureValue::validationState() const
|
||||
{
|
||||
if (!m_currentTextureIndex)
|
||||
|
||||
@@ -18,7 +18,7 @@ class TextureValue : public ShaderNode
|
||||
|
||||
void BuildNodeEdition(QFormLayout* layout) override;
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override;
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
|
||||
QString caption() const override { return "Texture"; }
|
||||
QString name() const override { return "Texture"; }
|
||||
@@ -29,6 +29,9 @@ class TextureValue : public ShaderNode
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
||||
|
||||
QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
|
||||
QtNodes::NodeValidationState validationState() const override;
|
||||
QString validationMessage() const override;
|
||||
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
#include <ShaderNode/DataModels/VecBinOp.hpp>
|
||||
|
||||
QString VecAdd::caption() const
|
||||
{
|
||||
static QString caption = "Vector addition";
|
||||
return caption;
|
||||
}
|
||||
|
||||
QString VecAdd::name() const
|
||||
{
|
||||
static QString name = "vec_add";
|
||||
return name;
|
||||
}
|
||||
|
||||
void VecAdd::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
output[i] = left[i] + right[i];
|
||||
}
|
||||
|
||||
QString VecMul::caption() const
|
||||
{
|
||||
static QString caption = "Vector multiplication";
|
||||
return caption;
|
||||
}
|
||||
|
||||
QString VecMul::name() const
|
||||
{
|
||||
static QString name = "vec_mul";
|
||||
return name;
|
||||
}
|
||||
|
||||
void VecMul::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
output[i] = left[i] * right[i];
|
||||
}
|
||||
|
||||
QString VecSub::caption() const
|
||||
{
|
||||
static QString caption = "Vector subtraction";
|
||||
return caption;
|
||||
}
|
||||
|
||||
|
||||
QString VecSub::name() const
|
||||
{
|
||||
static QString name = "vec_sub";
|
||||
return name;
|
||||
}
|
||||
|
||||
void VecSub::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
output[i] = left[i] - right[i];
|
||||
}
|
||||
|
||||
QString VecDiv::caption() const
|
||||
{
|
||||
static QString caption = "Vector divide";
|
||||
return caption;
|
||||
}
|
||||
|
||||
|
||||
QString VecDiv::name() const
|
||||
{
|
||||
static QString name = "vec_div";
|
||||
return name;
|
||||
}
|
||||
|
||||
void VecDiv::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
output[i] = left[i] / right[i];
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_VECBINOP_HPP
|
||||
#define NAZARA_SHADERNODES_VECBINOP_HPP
|
||||
|
||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
class VecBinOp : public ShaderNode
|
||||
{
|
||||
public:
|
||||
VecBinOp(ShaderGraph& graph);
|
||||
~VecBinOp() = default;
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const 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;
|
||||
|
||||
QtNodes::NodeValidationState validationState() const override;
|
||||
QString validationMessage() const override;
|
||||
|
||||
private:
|
||||
virtual void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) = 0;
|
||||
|
||||
bool ComputePreview(QPixmap& pixmap) override;
|
||||
void UpdateOutput();
|
||||
|
||||
std::shared_ptr<VecData> m_lhs;
|
||||
std::shared_ptr<VecData> m_rhs;
|
||||
std::shared_ptr<VecData> m_output;
|
||||
};
|
||||
|
||||
class VecAdd : public VecBinOp<Nz::ShaderNodes::BinaryType::Add>
|
||||
{
|
||||
public:
|
||||
using VecBinOp<Nz::ShaderNodes::BinaryType::Add>::VecBinOp;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
||||
void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override;
|
||||
};
|
||||
|
||||
class VecMul : public VecBinOp<Nz::ShaderNodes::BinaryType::Multiply>
|
||||
{
|
||||
public:
|
||||
using VecBinOp<Nz::ShaderNodes::BinaryType::Multiply>::VecBinOp;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
||||
void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override;
|
||||
};
|
||||
|
||||
class VecSub : public VecBinOp<Nz::ShaderNodes::BinaryType::Substract>
|
||||
{
|
||||
public:
|
||||
using VecBinOp<Nz::ShaderNodes::BinaryType::Substract>::VecBinOp;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
||||
void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override;
|
||||
};
|
||||
|
||||
class VecDiv : public VecBinOp<Nz::ShaderNodes::BinaryType::Divide>
|
||||
{
|
||||
public:
|
||||
using VecBinOp<Nz::ShaderNodes::BinaryType::Divide>::VecBinOp;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
||||
void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override;
|
||||
};
|
||||
|
||||
#include <ShaderNode/DataModels/VecBinOp.inl>
|
||||
|
||||
#endif
|
||||
@@ -1,131 +0,0 @@
|
||||
#include <ShaderNode/DataModels/VecBinOp.hpp>
|
||||
#include <Nazara/Shader/ShaderBuilder.hpp>
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
VecBinOp<BinOp>::VecBinOp(ShaderGraph& graph) :
|
||||
ShaderNode(graph)
|
||||
{
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
Nz::ShaderNodes::ExpressionPtr VecBinOp<BinOp>::GetExpression(Nz::ShaderNodes::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<Nz::ShaderNodes::BinaryType BinOp>
|
||||
QtNodes::NodeDataType VecBinOp<BinOp>::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0 || portIndex == 1);
|
||||
|
||||
return VecData::Type();
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
unsigned int VecBinOp<BinOp>::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return 2;
|
||||
case QtNodes::PortType::Out: return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
std::shared_ptr<QtNodes::NodeData> VecBinOp<BinOp>::outData(QtNodes::PortIndex port)
|
||||
{
|
||||
assert(port == 0);
|
||||
return m_output;
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
void VecBinOp<BinOp>::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||
{
|
||||
assert(index == 0 || index == 1);
|
||||
|
||||
std::shared_ptr<VecData> castedValue;
|
||||
if (value && value->type().id == VecData::Type().id)
|
||||
castedValue = std::static_pointer_cast<VecData>(value);
|
||||
|
||||
if (index == 0)
|
||||
m_lhs = std::move(castedValue);
|
||||
else
|
||||
m_rhs = std::move(castedValue);
|
||||
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
QtNodes::NodeValidationState VecBinOp<BinOp>::validationState() const
|
||||
{
|
||||
if (!m_lhs || !m_rhs)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
|
||||
if (m_lhs->componentCount != m_rhs->componentCount)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
|
||||
return QtNodes::NodeValidationState::Valid;
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
QString VecBinOp<BinOp>::validationMessage() const
|
||||
{
|
||||
if (!m_lhs || !m_rhs)
|
||||
return "Missing operands";
|
||||
|
||||
if (m_lhs->componentCount != m_rhs->componentCount)
|
||||
return "Incompatible components count (left has " + QString::number(m_lhs->componentCount) + ", right has " + QString::number(m_rhs->componentCount) + ")";
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
bool VecBinOp<BinOp>::ComputePreview(QPixmap& pixmap)
|
||||
{
|
||||
if (!m_lhs || !m_rhs)
|
||||
return false;
|
||||
|
||||
pixmap = QPixmap::fromImage(m_output->preview.GenerateImage());
|
||||
return true;
|
||||
}
|
||||
|
||||
template<Nz::ShaderNodes::BinaryType BinOp>
|
||||
void VecBinOp<BinOp>::UpdateOutput()
|
||||
{
|
||||
if (validationState() != QtNodes::NodeValidationState::Valid)
|
||||
{
|
||||
m_output = std::make_shared<VecData>(4);
|
||||
m_output->preview = PreviewValues(1, 1);
|
||||
m_output->preview.Fill(Nz::Vector4f::Zero());
|
||||
return;
|
||||
}
|
||||
|
||||
m_output = std::make_shared<VecData>(m_lhs->componentCount);
|
||||
|
||||
const PreviewValues& leftPreview = m_lhs->preview;
|
||||
const PreviewValues& rightPreview = m_rhs->preview;
|
||||
std::size_t maxWidth = std::max(leftPreview.GetWidth(), rightPreview.GetWidth());
|
||||
std::size_t maxHeight = std::max(leftPreview.GetHeight(), rightPreview.GetHeight());
|
||||
|
||||
// FIXME: Prevent useless copy
|
||||
PreviewValues leftResized = leftPreview;
|
||||
if (leftResized.GetWidth() != maxWidth || leftResized.GetHeight() != maxHeight)
|
||||
leftResized = leftResized.Resized(maxWidth, maxHeight);
|
||||
|
||||
PreviewValues rightResized = rightPreview;
|
||||
if (rightResized.GetWidth() != maxWidth || rightResized.GetHeight() != maxHeight)
|
||||
rightResized = rightResized.Resized(maxWidth, maxHeight);
|
||||
|
||||
m_output->preview = PreviewValues(maxWidth, maxHeight);
|
||||
ApplyOp(leftResized.GetData(), rightResized.GetData(), m_output->preview.GetData(), maxWidth * maxHeight);
|
||||
|
||||
Q_EMIT dataUpdated(0);
|
||||
|
||||
UpdatePreview();
|
||||
}
|
||||
49
src/ShaderNode/DataModels/VecComposition.hpp
Normal file
49
src/ShaderNode/DataModels/VecComposition.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_VECTOR_COMPOSITION_HPP
|
||||
#define NAZARA_SHADERNODES_VECTOR_COMPOSITION_HPP
|
||||
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
class VecComposition : public ShaderNode
|
||||
{
|
||||
public:
|
||||
VecComposition(ShaderGraph& graph);
|
||||
~VecComposition() = default;
|
||||
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
||||
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
unsigned int nPorts(QtNodes::PortType portType) const override;
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
||||
|
||||
void setInData(std::shared_ptr<QtNodes::NodeData> value, int index) override;
|
||||
|
||||
QtNodes::NodeValidationState validationState() const override;
|
||||
QString validationMessage() const override;
|
||||
|
||||
private:
|
||||
bool ComputePreview(QPixmap& pixmap) override;
|
||||
void UpdateOutput();
|
||||
|
||||
std::array<std::shared_ptr<FloatData>, ComponentCount> m_inputs;
|
||||
std::shared_ptr<VecData> m_output;
|
||||
};
|
||||
|
||||
using Vec2Composition = VecComposition<2>;
|
||||
using Vec3Composition = VecComposition<3>;
|
||||
using Vec4Composition = VecComposition<4>;
|
||||
|
||||
#include <ShaderNode/DataModels/VecComposition.inl>
|
||||
|
||||
#endif
|
||||
192
src/ShaderNode/DataModels/VecComposition.inl
Normal file
192
src/ShaderNode/DataModels/VecComposition.inl
Normal file
@@ -0,0 +1,192 @@
|
||||
#include <ShaderNode/DataModels/VecComposition.hpp>
|
||||
#include <Nazara/Shader/ShaderBuilder.hpp>
|
||||
#include <QtWidgets/QDoubleSpinBox>
|
||||
#include <QtWidgets/QFormLayout>
|
||||
#include <stdexcept>
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
VecComposition<ComponentCount>::VecComposition(ShaderGraph& graph) :
|
||||
ShaderNode(graph)
|
||||
{
|
||||
static_assert(ComponentCount <= s_vectorComponents.size());
|
||||
|
||||
m_output = std::make_shared<VecData>(ComponentCount);
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
Nz::ShaderNodes::NodePtr VecComposition<ComponentCount>::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(count == ComponentCount);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
std::array<Nz::ShaderNodes::ExpressionPtr, ComponentCount> expr;
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
expr[i] = expressions[i];
|
||||
|
||||
constexpr auto ExpressionType = VecExpressionType<ComponentCount>;
|
||||
return Nz::ShaderBuilder::Cast<ExpressionType>(expr.data(), expr.size());
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
QString VecComposition<ComponentCount>::caption() const
|
||||
{
|
||||
static QString caption = "Compose Vector" + QString::number(ComponentCount);
|
||||
return caption;
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
QString VecComposition<ComponentCount>::name() const
|
||||
{
|
||||
static QString name = "vec_compose" + QString::number(ComponentCount);
|
||||
return name;
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
QtNodes::NodeDataType VecComposition<ComponentCount>::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In:
|
||||
{
|
||||
assert(portIndex >= 0);
|
||||
assert(portIndex < ComponentCount);
|
||||
return FloatData::Type();
|
||||
}
|
||||
|
||||
case QtNodes::PortType::Out:
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
return VecData::Type();
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Invalid port type");
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
unsigned int VecComposition<ComponentCount>::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return ComponentCount;
|
||||
case QtNodes::PortType::Out: return 1;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Invalid port type");
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
std::shared_ptr<QtNodes::NodeData> VecComposition<ComponentCount>::outData(QtNodes::PortIndex port)
|
||||
{
|
||||
assert(port == 0);
|
||||
|
||||
if (validationState() != QtNodes::NodeValidationState::Valid)
|
||||
return nullptr;
|
||||
|
||||
return m_output;
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
void VecComposition<ComponentCount>::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||
{
|
||||
assert(index >= 0 && index < ComponentCount);
|
||||
|
||||
if (value && value->type().id == FloatData::Type().id)
|
||||
{
|
||||
assert(dynamic_cast<FloatData*>(value.get()) != nullptr);
|
||||
m_inputs[index] = std::static_pointer_cast<FloatData>(value);
|
||||
}
|
||||
else
|
||||
m_inputs[index].reset();
|
||||
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
QtNodes::NodeValidationState VecComposition<ComponentCount>::validationState() const
|
||||
{
|
||||
for (std::size_t i = 0; i < ComponentCount; ++i)
|
||||
{
|
||||
if (!m_inputs[i])
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
}
|
||||
|
||||
return QtNodes::NodeValidationState::Valid;
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
QString VecComposition<ComponentCount>::validationMessage() const
|
||||
{
|
||||
for (std::size_t i = 0; i < ComponentCount; ++i)
|
||||
{
|
||||
if (!m_inputs[i])
|
||||
return "Missing input #" + QString::number(i + 1);
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
bool VecComposition<ComponentCount>::ComputePreview(QPixmap& pixmap)
|
||||
{
|
||||
if (validationState() != QtNodes::NodeValidationState::Valid)
|
||||
return false;
|
||||
|
||||
pixmap = QPixmap::fromImage(m_output->preview.GenerateImage());
|
||||
return true;
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
void VecComposition<ComponentCount>::UpdateOutput()
|
||||
{
|
||||
if (validationState() != QtNodes::NodeValidationState::Valid)
|
||||
{
|
||||
m_output->preview = PreviewValues(1, 1);
|
||||
m_output->preview(0, 0) = Nz::Vector4f::Zero();
|
||||
return;
|
||||
}
|
||||
|
||||
std::array<PreviewValues, ComponentCount> previewResized;
|
||||
std::size_t maxInputWidth = 0;
|
||||
std::size_t maxInputHeight = 0;
|
||||
|
||||
for (std::size_t i = 0; i < ComponentCount; ++i)
|
||||
{
|
||||
// FIXME: Prevent useless copy
|
||||
previewResized[i] = m_inputs[i]->preview;
|
||||
|
||||
maxInputWidth = std::max(maxInputWidth, previewResized[i].GetWidth());
|
||||
maxInputHeight = std::max(maxInputHeight, previewResized[i].GetHeight());
|
||||
}
|
||||
|
||||
PreviewValues& output = m_output->preview;
|
||||
output = PreviewValues(maxInputWidth, maxInputHeight);
|
||||
|
||||
for (std::size_t i = 0; i < ComponentCount; ++i)
|
||||
{
|
||||
if (previewResized[i].GetWidth() != maxInputWidth || previewResized[i].GetHeight() != maxInputHeight)
|
||||
previewResized[i] = previewResized[i].Resized(maxInputWidth, maxInputHeight);
|
||||
}
|
||||
|
||||
for (std::size_t y = 0; y < maxInputHeight; ++y)
|
||||
{
|
||||
for (std::size_t x = 0; x < maxInputWidth; ++x)
|
||||
{
|
||||
Nz::Vector4f color(0.f, 0.f, 0.f, 1.f);
|
||||
for (std::size_t i = 0; i < ComponentCount; ++i)
|
||||
color[i] = previewResized[i](x, y)[0];
|
||||
|
||||
output(x, y) = color;
|
||||
}
|
||||
}
|
||||
|
||||
Q_EMIT dataUpdated(0);
|
||||
|
||||
UpdatePreview();
|
||||
}
|
||||
176
src/ShaderNode/DataModels/VecDecomposition.cpp
Normal file
176
src/ShaderNode/DataModels/VecDecomposition.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
#include <ShaderNode/DataModels/VecDecomposition.hpp>
|
||||
#include <Nazara/Shader/ShaderBuilder.hpp>
|
||||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
#include <ShaderNode/DataTypes/BoolData.hpp>
|
||||
#include <ShaderNode/DataTypes/FloatData.hpp>
|
||||
#include <ShaderNode/DataTypes/Matrix4Data.hpp>
|
||||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QFormLayout>
|
||||
#include <limits>
|
||||
|
||||
VecDecomposition::VecDecomposition(ShaderGraph& graph) :
|
||||
ShaderNode(graph)
|
||||
{
|
||||
DisablePreview();
|
||||
DisableCustomVariableName();
|
||||
}
|
||||
|
||||
Nz::ShaderNodes::NodePtr VecDecomposition::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(count == 1);
|
||||
assert(outputIndex < m_outputs.size());
|
||||
|
||||
using namespace Nz::ShaderBuilder;
|
||||
using namespace Nz::ShaderNodes;
|
||||
|
||||
return Nz::ShaderBuilder::Swizzle(expressions[0], static_cast<SwizzleComponent>(Nz::UnderlyingCast(SwizzleComponent::First) + outputIndex));
|
||||
}
|
||||
|
||||
QString VecDecomposition::caption() const
|
||||
{
|
||||
return "Vector decomposition";
|
||||
}
|
||||
|
||||
QString VecDecomposition::name() const
|
||||
{
|
||||
return "vec_decompose";
|
||||
}
|
||||
|
||||
QtNodes::NodeDataType VecDecomposition::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In:
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
return VecData::Type();
|
||||
}
|
||||
|
||||
case QtNodes::PortType::Out:
|
||||
{
|
||||
assert(portIndex >= 0 && portIndex < m_outputs.size());
|
||||
return FloatData::Type();
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Invalid port type");
|
||||
}
|
||||
|
||||
unsigned int VecDecomposition::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return 1;
|
||||
case QtNodes::PortType::Out: return m_outputs.size();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Invalid port type");
|
||||
}
|
||||
|
||||
QString VecDecomposition::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portType == QtNodes::PortType::Out);
|
||||
assert(portIndex >= 0 && portIndex < s_vectorComponents.size());
|
||||
|
||||
return QString(QChar(s_vectorComponents[portIndex]));
|
||||
}
|
||||
|
||||
bool VecDecomposition::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return false;
|
||||
case QtNodes::PortType::Out: return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Invalid port type");
|
||||
}
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> VecDecomposition::outData(QtNodes::PortIndex port)
|
||||
{
|
||||
if (!m_input)
|
||||
return {};
|
||||
|
||||
return m_outputs[port];
|
||||
}
|
||||
|
||||
void VecDecomposition::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||
{
|
||||
assert(index == 0);
|
||||
|
||||
std::shared_ptr<VecData> castedValue;
|
||||
if (value && value->type().id == VecData::Type().id)
|
||||
castedValue = std::static_pointer_cast<VecData>(value);
|
||||
|
||||
m_input = std::move(castedValue);
|
||||
|
||||
UpdateOutputs();
|
||||
}
|
||||
|
||||
QtNodes::NodeValidationState VecDecomposition::validationState() const
|
||||
{
|
||||
if (!m_input)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
|
||||
return QtNodes::NodeValidationState::Valid;
|
||||
}
|
||||
|
||||
QString VecDecomposition::validationMessage() const
|
||||
{
|
||||
if (!m_input)
|
||||
return "Missing input";
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
void VecDecomposition::UpdateOutputs()
|
||||
{
|
||||
if (validationState() != QtNodes::NodeValidationState::Valid)
|
||||
{
|
||||
auto dummy = std::make_shared<FloatData>();
|
||||
dummy->preview = PreviewValues(1, 1);
|
||||
dummy->preview.Fill(Nz::Vector4f::Zero());
|
||||
|
||||
m_outputs.fill(dummy);
|
||||
return;
|
||||
}
|
||||
|
||||
std::size_t previewWidth = m_input->preview.GetWidth();
|
||||
std::size_t previewHeight = m_input->preview.GetHeight();
|
||||
std::size_t pixelCount = previewWidth * previewHeight;
|
||||
|
||||
for (std::size_t i = 0; i < m_input->componentCount; ++i)
|
||||
{
|
||||
m_outputs[i] = std::make_shared<FloatData>();
|
||||
m_outputs[i]->preview = PreviewValues(previewWidth, previewHeight);
|
||||
|
||||
const Nz::Vector4f* inputData = m_input->preview.GetData();
|
||||
Nz::Vector4f* outputData = m_outputs[i]->preview.GetData();
|
||||
for (std::size_t j = 0; j < pixelCount; ++j)
|
||||
{
|
||||
const Nz::Vector4f& input = *inputData++;
|
||||
|
||||
*outputData++ = Nz::Vector4f(input[i], input[i], input[i], input[i]);
|
||||
}
|
||||
|
||||
Q_EMIT dataUpdated(i);
|
||||
}
|
||||
|
||||
for (std::size_t i = m_input->componentCount; i < m_outputs.size(); ++i)
|
||||
m_outputs[i] = nullptr;
|
||||
|
||||
UpdatePreview();
|
||||
}
|
||||
48
src/ShaderNode/DataModels/VecDecomposition.hpp
Normal file
48
src/ShaderNode/DataModels/VecDecomposition.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_VECTOR_DECOMPOSITION_HPP
|
||||
#define NAZARA_SHADERNODES_VECTOR_DECOMPOSITION_HPP
|
||||
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||
#include <ShaderNode/DataTypes/FloatData.hpp>
|
||||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
#include <array>
|
||||
|
||||
class VecDecomposition : public ShaderNode
|
||||
{
|
||||
public:
|
||||
VecDecomposition(ShaderGraph& graph);
|
||||
~VecDecomposition() = default;
|
||||
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
||||
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
unsigned int nPorts(QtNodes::PortType portType) const override;
|
||||
|
||||
QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
bool portCaptionVisible(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;
|
||||
|
||||
QtNodes::NodeValidationState validationState() const override;
|
||||
QString validationMessage() const override;
|
||||
|
||||
private:
|
||||
void UpdateOutputs();
|
||||
|
||||
std::shared_ptr<VecData> m_input;
|
||||
std::array<std::shared_ptr<FloatData>, 4> m_outputs;
|
||||
};
|
||||
|
||||
#include <ShaderNode/DataModels/VecDecomposition.inl>
|
||||
|
||||
#endif
|
||||
@@ -8,9 +8,11 @@ ShaderNode(graph)
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr VecDot::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
|
||||
Nz::ShaderNodes::NodePtr VecDot::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(count == 2);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
using namespace Nz::ShaderNodes;
|
||||
return IntrinsicCall::Build(IntrinsicType::DotProduct, { expressions[0], expressions[1] });
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class VecDot : public ShaderNode
|
||||
VecDot(ShaderGraph& graph);
|
||||
~VecDot() = default;
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
||||
@@ -7,9 +7,11 @@ ShaderNode(graph)
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr VecFloatMul::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
|
||||
Nz::ShaderNodes::NodePtr VecFloatMul::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(count == 2);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
using namespace Nz::ShaderNodes;
|
||||
return BinaryOp::Build(BinaryType::Multiply, expressions[0], expressions[1]);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class VecFloatMul : public ShaderNode
|
||||
VecFloatMul(ShaderGraph& graph);
|
||||
~VecFloatMul() = default;
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
#include <ShaderNode/DataModels/VecValue.hpp>
|
||||
@@ -18,6 +18,9 @@ class VecValue : public ShaderNode
|
||||
VecValue(ShaderGraph& graph);
|
||||
~VecValue() = default;
|
||||
|
||||
Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override;
|
||||
void BuildNodeEdition(QFormLayout* layout) override;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
||||
@@ -27,9 +30,8 @@ class VecValue : public ShaderNode
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
||||
|
||||
void BuildNodeEdition(QFormLayout* layout) override;
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
|
||||
QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
|
||||
private:
|
||||
bool ComputePreview(QPixmap& pixmap) override;
|
||||
|
||||
@@ -75,6 +75,33 @@ std::shared_ptr<QtNodes::NodeData> VecValue<ComponentCount>::outData(QtNodes::Po
|
||||
return out;
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
QString VecValue<ComponentCount>::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
assert(portType == QtNodes::PortType::Out);
|
||||
|
||||
QString caption = "vec" + QString::number(ComponentCount) + "(";
|
||||
for (std::size_t i = 0; i < ComponentCount; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
caption += ", ";
|
||||
|
||||
caption += QString::number(m_value[i]);
|
||||
}
|
||||
|
||||
caption += ")";
|
||||
|
||||
return caption;
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
bool VecValue<ComponentCount>::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
return portType == QtNodes::PortType::Out;
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
void VecValue<ComponentCount>::BuildNodeEdition(QFormLayout* layout)
|
||||
{
|
||||
@@ -100,9 +127,10 @@ void VecValue<ComponentCount>::BuildNodeEdition(QFormLayout* layout)
|
||||
}
|
||||
|
||||
template<std::size_t ComponentCount>
|
||||
Nz::ShaderNodes::ExpressionPtr VecValue<ComponentCount>::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const
|
||||
Nz::ShaderNodes::NodePtr VecValue<ComponentCount>::BuildNode(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const
|
||||
{
|
||||
assert(count == 0);
|
||||
assert(outputIndex == 0);
|
||||
|
||||
return Nz::ShaderBuilder::Constant(m_value);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
#include <Nazara/Core/StackArray.hpp>
|
||||
#include <ShaderNode/DataModels/BinOp.hpp>
|
||||
#include <ShaderNode/DataModels/BoolValue.hpp>
|
||||
#include <ShaderNode/DataModels/BufferField.hpp>
|
||||
#include <ShaderNode/DataModels/Cast.hpp>
|
||||
#include <ShaderNode/DataModels/CompOp.hpp>
|
||||
#include <ShaderNode/DataModels/ConditionalExpression.hpp>
|
||||
#include <ShaderNode/DataModels/Discard.hpp>
|
||||
#include <ShaderNode/DataModels/FloatValue.hpp>
|
||||
#include <ShaderNode/DataModels/InputValue.hpp>
|
||||
#include <ShaderNode/DataModels/Mat4BinOp.hpp>
|
||||
#include <ShaderNode/DataModels/Mat4VecMul.hpp>
|
||||
#include <ShaderNode/DataModels/OutputValue.hpp>
|
||||
#include <ShaderNode/DataModels/PositionOutputValue.hpp>
|
||||
#include <ShaderNode/DataModels/SampleTexture.hpp>
|
||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||
#include <ShaderNode/DataModels/TextureValue.hpp>
|
||||
#include <ShaderNode/DataModels/Mat4BinOp.hpp>
|
||||
#include <ShaderNode/DataModels/Mat4VecMul.hpp>
|
||||
#include <ShaderNode/DataModels/PositionOutputValue.hpp>
|
||||
#include <ShaderNode/DataModels/VecBinOp.hpp>
|
||||
#include <ShaderNode/DataModels/VecComposition.hpp>
|
||||
#include <ShaderNode/DataModels/VecDecomposition.hpp>
|
||||
#include <ShaderNode/DataModels/VecDot.hpp>
|
||||
#include <ShaderNode/DataModels/VecFloatMul.hpp>
|
||||
#include <ShaderNode/DataModels/VecValue.hpp>
|
||||
@@ -61,27 +65,6 @@ m_type(ShaderType::NotSet)
|
||||
AddInput("UV", PrimitiveType::Float2, InputRole::TexCoord, 0, 0);
|
||||
AddOutput("RenderTarget0", PrimitiveType::Float4, 0);
|
||||
AddTexture("Potato", TextureType::Sampler2D, 1);
|
||||
AddStruct("TestStruct", {
|
||||
{
|
||||
{ "position", PrimitiveType::Float3 },
|
||||
{ "normal", PrimitiveType::Float3 },
|
||||
{ "uv", PrimitiveType::Float2 },
|
||||
{ "inner", 2 }
|
||||
}
|
||||
});
|
||||
AddStruct("InnerStruct", {
|
||||
{
|
||||
{ "a", PrimitiveType::Float3 },
|
||||
}
|
||||
});
|
||||
AddStruct("OuterStruct", {
|
||||
{
|
||||
{ "a", 1 },
|
||||
{ "b", PrimitiveType::Float1 }
|
||||
}
|
||||
});
|
||||
|
||||
AddBuffer("testUBO", BufferType::UniformBufferObject, 0, 0);
|
||||
|
||||
UpdateTexturePreview(0, QImage(R"(C:\Users\Lynix\Pictures\potatavril.png)"));
|
||||
|
||||
@@ -460,23 +443,30 @@ QJsonObject ShaderGraph::Save()
|
||||
Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst()
|
||||
{
|
||||
std::vector<Nz::ShaderNodes::StatementPtr> statements;
|
||||
QHash<QUuid, unsigned int> usageCount;
|
||||
|
||||
std::function<void(QtNodes::Node*)> DetectVariables;
|
||||
DetectVariables = [&](QtNodes::Node* node)
|
||||
using Key = QPair<QUuid, std::size_t>;
|
||||
auto BuildKey = [](QUuid uuid, std::size_t index)
|
||||
{
|
||||
auto it = usageCount.find(node->id());
|
||||
return Key(uuid, index);
|
||||
};
|
||||
|
||||
QHash<Key, unsigned int> usageCount;
|
||||
|
||||
std::function<void(QtNodes::Node*, std::size_t)> DetectVariables;
|
||||
DetectVariables = [&](QtNodes::Node* node, std::size_t outputIndex)
|
||||
{
|
||||
auto it = usageCount.find(BuildKey(node->id(), outputIndex));
|
||||
if (it == usageCount.end())
|
||||
{
|
||||
for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In))
|
||||
{
|
||||
for (const auto& [uuid, conn] : connectionSet)
|
||||
{
|
||||
DetectVariables(conn->getNode(QtNodes::PortType::Out));
|
||||
DetectVariables(conn->getNode(QtNodes::PortType::Out), conn->getPortIndex(QtNodes::PortType::Out));
|
||||
}
|
||||
}
|
||||
|
||||
it = usageCount.insert(node->id(), 0);
|
||||
it = usageCount.insert(BuildKey(node->id(), outputIndex), 0);
|
||||
}
|
||||
|
||||
(*it)++;
|
||||
@@ -488,28 +478,28 @@ Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst()
|
||||
{
|
||||
if (node->nodeDataModel()->nPorts(QtNodes::PortType::Out) == 0)
|
||||
{
|
||||
DetectVariables(node);
|
||||
DetectVariables(node, 0);
|
||||
outputNodes.push_back(node);
|
||||
}
|
||||
});
|
||||
|
||||
QHash<QUuid, Nz::ShaderNodes::ExpressionPtr> variableExpressions;
|
||||
QHash<Key, Nz::ShaderNodes::ExpressionPtr> variableExpressions;
|
||||
|
||||
unsigned int varCount = 0;
|
||||
std::unordered_set<std::string> usedVariableNames;
|
||||
|
||||
std::function<Nz::ShaderNodes::ExpressionPtr(QtNodes::Node*)> HandleNode;
|
||||
HandleNode = [&](QtNodes::Node* node) -> Nz::ShaderNodes::ExpressionPtr
|
||||
std::function<Nz::ShaderNodes::NodePtr(QtNodes::Node*, std::size_t portIndex)> HandleNode;
|
||||
HandleNode = [&](QtNodes::Node* node, std::size_t portIndex) -> Nz::ShaderNodes::NodePtr
|
||||
{
|
||||
ShaderNode* shaderNode = static_cast<ShaderNode*>(node->nodeDataModel());
|
||||
if (shaderNode->validationState() != QtNodes::NodeValidationState::Valid)
|
||||
throw std::runtime_error(shaderNode->validationMessage().toStdString());
|
||||
|
||||
qDebug() << shaderNode->name() << node->id();
|
||||
if (auto it = variableExpressions.find(node->id()); it != variableExpressions.end())
|
||||
if (auto it = variableExpressions.find(BuildKey(node->id(), portIndex)); it != variableExpressions.end())
|
||||
return *it;
|
||||
|
||||
auto it = usageCount.find(node->id());
|
||||
auto it = usageCount.find(BuildKey(node->id(), portIndex));
|
||||
assert(it != usageCount.end());
|
||||
|
||||
std::size_t inputCount = shaderNode->nPorts(QtNodes::PortType::In);
|
||||
@@ -521,16 +511,25 @@ Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst()
|
||||
for (const auto& [uuid, conn] : connectionSet)
|
||||
{
|
||||
assert(i < expressions.size());
|
||||
expressions[i] = HandleNode(conn->getNode(QtNodes::PortType::Out));
|
||||
Nz::ShaderNodes::NodePtr inputNode = HandleNode(conn->getNode(QtNodes::PortType::Out), conn->getPortIndex(QtNodes::PortType::Out));
|
||||
if (inputNode->IsStatement())
|
||||
throw std::runtime_error("unexpected statement");
|
||||
|
||||
expressions[i] = std::static_pointer_cast<Nz::ShaderNodes::Expression>(inputNode);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
auto expression = shaderNode->GetExpression(expressions.data(), expressions.size());
|
||||
auto astNode = shaderNode->BuildNode(expressions.data(), expressions.size(), portIndex);
|
||||
|
||||
const std::string& variableName = shaderNode->GetVariableName();
|
||||
if (*it > 1 || !variableName.empty())
|
||||
{
|
||||
if (astNode->IsStatement())
|
||||
throw std::runtime_error("unexpected statement");
|
||||
|
||||
auto expression = std::static_pointer_cast<Nz::ShaderNodes::Expression>(astNode);
|
||||
|
||||
Nz::ShaderNodes::ExpressionPtr varExpression;
|
||||
if (expression->GetExpressionCategory() == Nz::ShaderNodes::ExpressionCategory::RValue)
|
||||
{
|
||||
@@ -546,23 +545,37 @@ Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst()
|
||||
usedVariableNames.insert(name);
|
||||
|
||||
auto variable = Nz::ShaderBuilder::Local(std::move(name), expression->GetExpressionType());
|
||||
statements.emplace_back(Nz::ShaderBuilder::DeclareVariable(variable, expression));
|
||||
statements.emplace_back(Nz::ShaderBuilder::DeclareVariable(variable, std::move(expression)));
|
||||
|
||||
varExpression = Nz::ShaderBuilder::Identifier(variable);
|
||||
}
|
||||
else
|
||||
varExpression = expression;
|
||||
varExpression = std::move(expression);
|
||||
|
||||
variableExpressions.insert(node->id(), varExpression);
|
||||
variableExpressions.insert(BuildKey(node->id(), portIndex), varExpression);
|
||||
|
||||
return varExpression;
|
||||
}
|
||||
else
|
||||
return expression;
|
||||
return astNode;
|
||||
};
|
||||
|
||||
std::sort(outputNodes.begin(), outputNodes.end(), [](QtNodes::Node* lhs, QtNodes::Node* rhs)
|
||||
{
|
||||
ShaderNode* leftNode = static_cast<ShaderNode*>(lhs->nodeDataModel());
|
||||
ShaderNode* rightNode = static_cast<ShaderNode*>(rhs->nodeDataModel());
|
||||
|
||||
return leftNode->GetOutputOrder() < rightNode->GetOutputOrder();
|
||||
});
|
||||
|
||||
for (QtNodes::Node* node : outputNodes)
|
||||
statements.emplace_back(Nz::ShaderBuilder::ExprStatement(HandleNode(node)));
|
||||
{
|
||||
auto astNode = HandleNode(node, 0);
|
||||
if (!astNode->IsStatement())
|
||||
statements.emplace_back(Nz::ShaderBuilder::ExprStatement(std::static_pointer_cast<Nz::ShaderNodes::Expression>(astNode)));
|
||||
else
|
||||
statements.emplace_back(std::static_pointer_cast<Nz::ShaderNodes::Statement>(astNode));
|
||||
}
|
||||
|
||||
return Nz::ShaderNodes::StatementBlock::Build(std::move(statements));
|
||||
}
|
||||
@@ -738,31 +751,74 @@ Nz::ShaderStageType ShaderGraph::ToShaderStageType(ShaderType type)
|
||||
std::shared_ptr<QtNodes::DataModelRegistry> ShaderGraph::BuildRegistry()
|
||||
{
|
||||
auto registry = std::make_shared<QtNodes::DataModelRegistry>();
|
||||
RegisterShaderNode<BufferField>(*this, registry, "Inputs");
|
||||
|
||||
// Casts
|
||||
RegisterShaderNode<CastToVec2>(*this, registry, "Casts");
|
||||
RegisterShaderNode<CastToVec3>(*this, registry, "Casts");
|
||||
RegisterShaderNode<CastToVec4>(*this, registry, "Casts");
|
||||
RegisterShaderNode<ConditionalExpression>(*this, registry, "Shader");
|
||||
RegisterShaderNode<Discard>(*this, registry, "Outputs");
|
||||
|
||||
// Constants
|
||||
RegisterShaderNode<BoolValue>(*this, registry, "Constants");
|
||||
RegisterShaderNode<FloatValue>(*this, registry, "Constants");
|
||||
RegisterShaderNode<Vec2Value>(*this, registry, "Constants");
|
||||
RegisterShaderNode<Vec3Value>(*this, registry, "Constants");
|
||||
RegisterShaderNode<Vec4Value>(*this, registry, "Constants");
|
||||
|
||||
// Inputs
|
||||
RegisterShaderNode<BufferField>(*this, registry, "Inputs");
|
||||
RegisterShaderNode<InputValue>(*this, registry, "Inputs");
|
||||
RegisterShaderNode<PositionOutputValue>(*this, registry, "Outputs");
|
||||
|
||||
// Outputs
|
||||
RegisterShaderNode<Discard>(*this, registry, "Outputs");
|
||||
RegisterShaderNode<OutputValue>(*this, registry, "Outputs");
|
||||
RegisterShaderNode<SampleTexture>(*this, registry, "Texture");
|
||||
RegisterShaderNode<TextureValue>(*this, registry, "Texture");
|
||||
RegisterShaderNode<PositionOutputValue>(*this, registry, "Outputs");
|
||||
|
||||
// Float comparison
|
||||
RegisterShaderNode<FloatEq>(*this, registry, "Float comparisons");
|
||||
RegisterShaderNode<FloatGe>(*this, registry, "Float comparisons");
|
||||
RegisterShaderNode<FloatGt>(*this, registry, "Float comparisons");
|
||||
RegisterShaderNode<FloatLe>(*this, registry, "Float comparisons");
|
||||
RegisterShaderNode<FloatLt>(*this, registry, "Float comparisons");
|
||||
RegisterShaderNode<FloatNe>(*this, registry, "Float comparisons");
|
||||
|
||||
// Float operations
|
||||
RegisterShaderNode<FloatAdd>(*this, registry, "Float operations");
|
||||
RegisterShaderNode<FloatDiv>(*this, registry, "Float operations");
|
||||
RegisterShaderNode<FloatMul>(*this, registry, "Float operations");
|
||||
RegisterShaderNode<FloatSub>(*this, registry, "Float operations");
|
||||
|
||||
// Matrix operations
|
||||
RegisterShaderNode<Mat4Add>(*this, registry, "Matrix operations");
|
||||
RegisterShaderNode<Mat4Mul>(*this, registry, "Matrix operations");
|
||||
RegisterShaderNode<Mat4Sub>(*this, registry, "Matrix operations");
|
||||
RegisterShaderNode<Mat4VecMul>(*this, registry, "Matrix operations");
|
||||
|
||||
// Shader
|
||||
RegisterShaderNode<ConditionalExpression>(*this, registry, "Shader");
|
||||
|
||||
// Texture
|
||||
RegisterShaderNode<SampleTexture>(*this, registry, "Texture");
|
||||
RegisterShaderNode<TextureValue>(*this, registry, "Texture");
|
||||
|
||||
// Vector comparison
|
||||
RegisterShaderNode<VecEq>(*this, registry, "Vector comparisons");
|
||||
RegisterShaderNode<VecGe>(*this, registry, "Vector comparisons");
|
||||
RegisterShaderNode<VecGt>(*this, registry, "Vector comparisons");
|
||||
RegisterShaderNode<VecLe>(*this, registry, "Vector comparisons");
|
||||
RegisterShaderNode<VecLt>(*this, registry, "Vector comparisons");
|
||||
RegisterShaderNode<VecNe>(*this, registry, "Vector comparisons");
|
||||
|
||||
// Vector operations
|
||||
RegisterShaderNode<VecAdd>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<Vec2Composition>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<Vec3Composition>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<Vec4Composition>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<VecDecomposition>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<VecDiv>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<VecDot>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<VecFloatMul>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<VecMul>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<VecSub>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<Vec2Value>(*this, registry, "Constants");
|
||||
RegisterShaderNode<Vec3Value>(*this, registry, "Constants");
|
||||
RegisterShaderNode<Vec4Value>(*this, registry, "Constants");
|
||||
|
||||
return registry;
|
||||
}
|
||||
|
||||
@@ -112,6 +112,8 @@ void ConditionEditor::RefreshConditions()
|
||||
QStandardItem* checkbox = new QStandardItem(1);
|
||||
checkbox->setCheckable(true);
|
||||
checkbox->setCheckState((conditionEntry.enabled) ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
|
||||
|
||||
|
||||
m_model->setItem(rowIndex, 1, checkbox);
|
||||
|
||||
rowIndex++;
|
||||
}
|
||||
|
||||
@@ -184,10 +184,10 @@ void MainWindow::OnGenerateGLSL()
|
||||
Nz::GlslWriter writer;
|
||||
|
||||
Nz::GlslWriter::States states;
|
||||
for (const auto& condition : m_shaderGraph.GetConditions())
|
||||
for (std::size_t i = 0; i < m_shaderGraph.GetConditionCount(); ++i)
|
||||
{
|
||||
if (condition.enabled)
|
||||
states.enabledConditions.insert(condition.name);
|
||||
if (m_shaderGraph.IsConditionEnabled(i))
|
||||
states.enabledConditions = Nz::SetBit<Nz::UInt64>(states.enabledConditions, i);
|
||||
}
|
||||
|
||||
std::string glsl = writer.Generate(ToShader(), states);
|
||||
|
||||
Reference in New Issue
Block a user