From 5a350ee76b69e1c6f88b2028ead32f4ea2d4d55a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 22 Jul 2020 14:46:44 +0200 Subject: [PATCH] ShaderNode: Add Mat4x4 type and nodes --- src/ShaderNode/DataModels/BufferField.cpp | 18 +-- src/ShaderNode/DataModels/InputValue.cpp | 80 +++++----- src/ShaderNode/DataModels/Mat4BinOp.cpp | 37 +++++ src/ShaderNode/DataModels/Mat4BinOp.hpp | 67 ++++++++ src/ShaderNode/DataModels/Mat4BinOp.inl | 131 +++++++++++++++ src/ShaderNode/DataModels/Mat4VecMul.cpp | 186 ++++++++++++++++++++++ src/ShaderNode/DataModels/Mat4VecMul.hpp | 43 +++++ src/ShaderNode/DataModels/Mat4VecMul.inl | 1 + src/ShaderNode/DataModels/OutputValue.cpp | 131 ++++++++++----- src/ShaderNode/DataModels/OutputValue.hpp | 6 +- src/ShaderNode/DataTypes/Matrix4Data.cpp | 1 + src/ShaderNode/DataTypes/Matrix4Data.hpp | 19 +++ src/ShaderNode/DataTypes/Matrix4Data.inl | 11 ++ src/ShaderNode/Enums.cpp | 2 + src/ShaderNode/Enums.hpp | 3 +- src/ShaderNode/ShaderGraph.cpp | 35 ++++ src/ShaderNode/ShaderGraph.hpp | 1 + 17 files changed, 668 insertions(+), 104 deletions(-) create mode 100644 src/ShaderNode/DataModels/Mat4BinOp.cpp create mode 100644 src/ShaderNode/DataModels/Mat4BinOp.hpp create mode 100644 src/ShaderNode/DataModels/Mat4BinOp.inl create mode 100644 src/ShaderNode/DataModels/Mat4VecMul.cpp create mode 100644 src/ShaderNode/DataModels/Mat4VecMul.hpp create mode 100644 src/ShaderNode/DataModels/Mat4VecMul.inl create mode 100644 src/ShaderNode/DataTypes/Matrix4Data.cpp create mode 100644 src/ShaderNode/DataTypes/Matrix4Data.hpp create mode 100644 src/ShaderNode/DataTypes/Matrix4Data.inl diff --git a/src/ShaderNode/DataModels/BufferField.cpp b/src/ShaderNode/DataModels/BufferField.cpp index a8399509c..480d53c2c 100644 --- a/src/ShaderNode/DataModels/BufferField.cpp +++ b/src/ShaderNode/DataModels/BufferField.cpp @@ -173,22 +173,7 @@ auto BufferField::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIn const auto& member = RetrieveNestedMember(); assert(std::holds_alternative(member.type)); - switch (std::get(member.type)) - { - case PrimitiveType::Bool: - return BoolData::Type(); - - case PrimitiveType::Float1: - return FloatData::Type(); - - case PrimitiveType::Float2: - case PrimitiveType::Float3: - case PrimitiveType::Float4: - return VecData::Type(); - } - - assert(false); - throw std::runtime_error("Unhandled primitive type"); + return ShaderGraph::ToNodeDataType(std::get(member.type)); } QString BufferField::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const @@ -260,6 +245,7 @@ std::shared_ptr BufferField::outData(QtNodes::PortIndex port) case PrimitiveType::Float2: return std::make_shared(2); case PrimitiveType::Float3: return std::make_shared(3); case PrimitiveType::Float4: return std::make_shared(4); + case PrimitiveType::Mat4x4: return std::make_shared(); } assert(false); diff --git a/src/ShaderNode/DataModels/InputValue.cpp b/src/ShaderNode/DataModels/InputValue.cpp index 1b33a8c9b..c2c6f6b01 100644 --- a/src/ShaderNode/DataModels/InputValue.cpp +++ b/src/ShaderNode/DataModels/InputValue.cpp @@ -1,6 +1,8 @@ #include #include +#include #include +#include #include #include #include @@ -115,23 +117,7 @@ Nz::ShaderNodes::ExpressionPtr InputValue::GetExpression(Nz::ShaderNodes::Expres throw std::runtime_error("no input"); const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex); - - Nz::ShaderNodes::BasicType expression = [&] - { - switch (inputEntry.type) - { - case PrimitiveType::Bool: return Nz::ShaderNodes::BasicType::Boolean; - case PrimitiveType::Float1: return Nz::ShaderNodes::BasicType::Float1; - case PrimitiveType::Float2: return Nz::ShaderNodes::BasicType::Float2; - case PrimitiveType::Float3: return Nz::ShaderNodes::BasicType::Float3; - case PrimitiveType::Float4: return Nz::ShaderNodes::BasicType::Float4; - } - - assert(false); - throw std::runtime_error("Unhandled input type"); - }(); - - return Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Input(inputEntry.name, expression)); + return Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Input(inputEntry.name, ShaderGraph::ToShaderExpressionType(inputEntry.type))); } auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType @@ -143,20 +129,7 @@ auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portInd return VecData::Type(); const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex); - switch (inputEntry.type) - { - //case InputType::Bool: return Nz::ShaderNodes::BasicType::Boolean; - case PrimitiveType::Float1: - return FloatData::Type(); - - case PrimitiveType::Float2: - case PrimitiveType::Float3: - case PrimitiveType::Float4: - return VecData::Type(); - } - - assert(false); - throw std::runtime_error("Unhandled input type"); + return ShaderGraph::ToNodeDataType(inputEntry.type); } std::shared_ptr InputValue::outData(QtNodes::PortIndex port) @@ -170,20 +143,45 @@ std::shared_ptr InputValue::outData(QtNodes::PortIndex port) const auto& inputEntry = graph.GetInput(*m_currentInputIndex); const auto& preview = graph.GetPreviewModel(); - if (inputEntry.type == PrimitiveType::Float1) + switch (inputEntry.type) { - auto fData = std::make_shared(); - fData->preview = preview.GetPreview(inputEntry.role, inputEntry.roleIndex); + case PrimitiveType::Bool: + { + auto bData = std::make_shared(); + bData->preview = preview.GetPreview(inputEntry.role, inputEntry.roleIndex); - return fData; - } - else - { - auto vecData = std::make_shared(GetComponentCount(inputEntry.type)); - vecData->preview = preview.GetPreview(inputEntry.role, inputEntry.roleIndex); + return bData; + } - return vecData; + case PrimitiveType::Float1: + { + auto fData = std::make_shared(); + fData->preview = preview.GetPreview(inputEntry.role, inputEntry.roleIndex); + + return fData; + } + + case PrimitiveType::Float2: + case PrimitiveType::Float3: + case PrimitiveType::Float4: + { + auto vecData = std::make_shared(GetComponentCount(inputEntry.type)); + vecData->preview = preview.GetPreview(inputEntry.role, inputEntry.roleIndex); + + return vecData; + } + + case PrimitiveType::Mat4x4: + { + auto matData = std::make_shared(); + //TODO: Handle preview + + return matData; + } } + + assert(false); + throw std::runtime_error("Unhandled input type"); } QtNodes::NodeValidationState InputValue::validationState() const diff --git a/src/ShaderNode/DataModels/Mat4BinOp.cpp b/src/ShaderNode/DataModels/Mat4BinOp.cpp new file mode 100644 index 000000000..4376b2995 --- /dev/null +++ b/src/ShaderNode/DataModels/Mat4BinOp.cpp @@ -0,0 +1,37 @@ +#include + +QString Mat4Add::caption() const +{ + static QString caption = "Matrix4 addition"; + return caption; +} + +QString Mat4Add::name() const +{ + static QString name = "mat4_add"; + return name; +} + +QString Mat4Mul::caption() const +{ + static QString caption = "Matrix4 multiplication"; + return caption; +} + +QString Mat4Mul::name() const +{ + static QString name = "mat4_mul"; + return name; +} + +QString Mat4Sub::caption() const +{ + static QString caption = "Matrix4 subtraction"; + return caption; +} + +QString Mat4Sub::name() const +{ + static QString name = "mat4_sub"; + return name; +} diff --git a/src/ShaderNode/DataModels/Mat4BinOp.hpp b/src/ShaderNode/DataModels/Mat4BinOp.hpp new file mode 100644 index 000000000..c90549bdd --- /dev/null +++ b/src/ShaderNode/DataModels/Mat4BinOp.hpp @@ -0,0 +1,67 @@ +#pragma once + +#ifndef NAZARA_SHADERNODES_MAT4BINOP_HPP +#define NAZARA_SHADERNODES_MAT4BINOP_HPP + +#include +#include + +template +class Mat4BinOp : public ShaderNode +{ + public: + Mat4BinOp(ShaderGraph& graph); + ~Mat4BinOp() = 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 outData(QtNodes::PortIndex port) override; + + void setInData(std::shared_ptr value, int index) override; + + QtNodes::NodeValidationState validationState() const override; + QString validationMessage() const override; + + private: + bool ComputePreview(QPixmap& pixmap) override; + void UpdateOutput(); + + std::shared_ptr m_lhs; + std::shared_ptr m_rhs; + std::shared_ptr m_output; +}; + +class Mat4Add : public Mat4BinOp +{ + public: + using Mat4BinOp::Mat4BinOp; + + QString caption() const override; + QString name() const override; +}; + +class Mat4Mul : public Mat4BinOp +{ + public: + using Mat4BinOp::Mat4BinOp; + + QString caption() const override; + QString name() const override; +}; + +class Mat4Sub : public Mat4BinOp +{ + public: + using Mat4BinOp::Mat4BinOp; + + QString caption() const override; + QString name() const override; +}; + +#include + +#endif diff --git a/src/ShaderNode/DataModels/Mat4BinOp.inl b/src/ShaderNode/DataModels/Mat4BinOp.inl new file mode 100644 index 000000000..684a6ec79 --- /dev/null +++ b/src/ShaderNode/DataModels/Mat4BinOp.inl @@ -0,0 +1,131 @@ +#include +#include + +template +Mat4BinOp::Mat4BinOp(ShaderGraph& graph) : +ShaderNode(graph) +{ + UpdateOutput(); +} + +template +Nz::ShaderNodes::ExpressionPtr Mat4BinOp::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const +{ + assert(count == 2); + using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder; + constexpr BuilderType builder; + return builder(expressions[0], expressions[1]); +} + +template +QtNodes::NodeDataType Mat4BinOp::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const +{ + assert(portIndex == 0 || portIndex == 1); + + return Matrix4Data::Type(); +} + +template +unsigned int Mat4BinOp::nPorts(QtNodes::PortType portType) const +{ + switch (portType) + { + case QtNodes::PortType::In: return 2; + case QtNodes::PortType::Out: return 1; + } + + return 0; +} + +template +std::shared_ptr Mat4BinOp::outData(QtNodes::PortIndex port) +{ + assert(port == 0); + return m_output; +} + +template +void Mat4BinOp::setInData(std::shared_ptr value, int index) +{ + assert(index == 0 || index == 1); + + std::shared_ptr castedValue; + if (value) + { + assert(dynamic_cast(value.get()) != nullptr); + + castedValue = std::static_pointer_cast(value); + } + + if (index == 0) + m_lhs = std::move(castedValue); + else + m_rhs = std::move(castedValue); + + UpdateOutput(); +} + +template +QtNodes::NodeValidationState Mat4BinOp::validationState() const +{ + if (!m_lhs || !m_rhs) + return QtNodes::NodeValidationState::Error; + + return QtNodes::NodeValidationState::Valid; +} + +template +QString Mat4BinOp::validationMessage() const +{ + if (!m_lhs || !m_rhs) + return "Missing operands"; + + return QString(); +} + +template +bool Mat4BinOp::ComputePreview(QPixmap& pixmap) +{ + if (!m_lhs || !m_rhs) + return false; + + return false; + + //pixmap = QPixmap::fromImage(m_output->preview.GenerateImage()); + //return true; +} + +template +void Mat4BinOp::UpdateOutput() +{ + if (validationState() != QtNodes::NodeValidationState::Valid) + { + m_output = std::make_shared(); + return; + } + + m_output = std::make_shared(); + + /*m_output = std::make_shared(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(); +} diff --git a/src/ShaderNode/DataModels/Mat4VecMul.cpp b/src/ShaderNode/DataModels/Mat4VecMul.cpp new file mode 100644 index 000000000..2e530e496 --- /dev/null +++ b/src/ShaderNode/DataModels/Mat4VecMul.cpp @@ -0,0 +1,186 @@ +#include +#include + +Mat4VecMul::Mat4VecMul(ShaderGraph& graph) : +ShaderNode(graph) +{ + UpdateOutput(); +} + +Nz::ShaderNodes::ExpressionPtr Mat4VecMul::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const +{ + assert(count == 2); + using namespace Nz::ShaderNodes; + return BinaryOp::Build(BinaryType::Multiply, expressions[0], expressions[1]); +} + +QString Mat4VecMul::caption() const +{ + static QString caption = "Mat4/Vec multiplication"; + return caption; +} + +QString Mat4VecMul::name() const +{ + static QString name = "mat4vec_mul"; + return name; +} + +QtNodes::NodeDataType Mat4VecMul::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + switch (portType) + { + case QtNodes::PortType::In: + { + assert(portIndex == 0 || portIndex == 1); + switch (portIndex) + { + case 0: return Matrix4Data::Type(); + case 1: return VecData::Type(); + } + } + + case QtNodes::PortType::Out: + { + assert(portIndex == 0); + return VecData::Type(); + } + } + + assert(false); + throw std::runtime_error("Invalid port type"); +} + +unsigned int Mat4VecMul::nPorts(QtNodes::PortType portType) const +{ + switch (portType) + { + case QtNodes::PortType::In: return 2; + case QtNodes::PortType::Out: return 1; + } + + assert(false); + throw std::runtime_error("Invalid port type"); +} + +std::shared_ptr Mat4VecMul::outData(QtNodes::PortIndex port) +{ + assert(port == 0); + return m_output; +} + +void Mat4VecMul::setInData(std::shared_ptr value, int index) +{ + assert(index == 0 || index == 1); + + switch (index) + { + case 0: + { + if (value) + { + assert(dynamic_cast(value.get()) != nullptr); + m_lhs = std::static_pointer_cast(value); + } + else + m_lhs.reset(); + + break; + } + + case 1: + { + if (value) + { + assert(dynamic_cast(value.get()) != nullptr); + m_rhs = std::static_pointer_cast(value); + } + else + m_rhs.reset(); + + break; + } + + default: + assert(false); + throw std::runtime_error("Invalid PortType"); + } + + UpdateOutput(); +} + +QtNodes::NodeValidationState Mat4VecMul::validationState() const +{ + if (!m_lhs || !m_rhs) + return QtNodes::NodeValidationState::Error; + + if (m_rhs->componentCount != 4) + return QtNodes::NodeValidationState::Error; + + return QtNodes::NodeValidationState::Valid; +} + +QString Mat4VecMul::validationMessage() const +{ + if (!m_lhs || !m_rhs) + return "Missing operands"; + + if (m_rhs->componentCount != 4) + return QString("Expected vector with 4 components, got ") + QString::number(m_rhs->componentCount); + + return QString(); +} + +bool Mat4VecMul::ComputePreview(QPixmap& pixmap) +{ + if (validationState() != QtNodes::NodeValidationState::Valid) + return false; + + pixmap = QPixmap::fromImage(m_output->preview.GenerateImage()); + return true; +} + +void Mat4VecMul::UpdateOutput() +{ + if (validationState() != QtNodes::NodeValidationState::Valid) + { + m_output = std::make_shared(4); + m_output->preview = PreviewValues(1, 1); + m_output->preview.Fill(Nz::Vector4f::Zero()); + return; + } + + m_output = std::make_shared(4); + m_output->preview = PreviewValues(1, 1); + m_output->preview.Fill(Nz::Vector4f::Zero()); + + /*m_output = std::make_shared(m_rhs->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); + + const Nz::Vector4f* left = leftResized.GetData(); + const Nz::Vector4f* right = rightPreview.GetData(); + Nz::Vector4f* output = m_output->preview.GetData(); + + std::size_t pixelCount = maxWidth * maxHeight; + for (std::size_t i = 0; i < pixelCount; ++i) + output[i] = left[i] * right[i]; + + Q_EMIT dataUpdated(0); + + UpdatePreview();*/ +} diff --git a/src/ShaderNode/DataModels/Mat4VecMul.hpp b/src/ShaderNode/DataModels/Mat4VecMul.hpp new file mode 100644 index 000000000..608439fcb --- /dev/null +++ b/src/ShaderNode/DataModels/Mat4VecMul.hpp @@ -0,0 +1,43 @@ +#pragma once + +#ifndef NAZARA_SHADERNODES_MAT4VECMUL_HPP +#define NAZARA_SHADERNODES_MAT4VECMUL_HPP + +#include +#include +#include + +class Mat4VecMul : public ShaderNode +{ + public: + Mat4VecMul(ShaderGraph& graph); + ~Mat4VecMul() = default; + + Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; + + QString caption() const override; + QString name() const override; + + unsigned int nPorts(QtNodes::PortType portType) const override; + + QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + + std::shared_ptr outData(QtNodes::PortIndex port) override; + + void setInData(std::shared_ptr value, int index) override; + + QtNodes::NodeValidationState validationState() const override; + QString validationMessage() const override; + + private: + bool ComputePreview(QPixmap& pixmap) override; + void UpdateOutput(); + + std::shared_ptr m_lhs; + std::shared_ptr m_rhs; + std::shared_ptr m_output; +}; + +#include + +#endif diff --git a/src/ShaderNode/DataModels/Mat4VecMul.inl b/src/ShaderNode/DataModels/Mat4VecMul.inl new file mode 100644 index 000000000..a798943a8 --- /dev/null +++ b/src/ShaderNode/DataModels/Mat4VecMul.inl @@ -0,0 +1 @@ +#include diff --git a/src/ShaderNode/DataModels/OutputValue.cpp b/src/ShaderNode/DataModels/OutputValue.cpp index b86c46879..6f30a9b66 100644 --- a/src/ShaderNode/DataModels/OutputValue.cpp +++ b/src/ShaderNode/DataModels/OutputValue.cpp @@ -1,6 +1,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -62,23 +65,7 @@ Nz::ShaderNodes::ExpressionPtr OutputValue::GetExpression(Nz::ShaderNodes::Expre throw std::runtime_error("no output"); const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex); - - Nz::ShaderNodes::BasicType expression = [&] - { - switch (outputEntry.type) - { - case PrimitiveType::Bool: return Nz::ShaderNodes::BasicType::Boolean; - case PrimitiveType::Float1: return Nz::ShaderNodes::BasicType::Float1; - case PrimitiveType::Float2: return Nz::ShaderNodes::BasicType::Float2; - case PrimitiveType::Float3: return Nz::ShaderNodes::BasicType::Float3; - case PrimitiveType::Float4: return Nz::ShaderNodes::BasicType::Float4; - } - - assert(false); - throw std::runtime_error("Unhandled output type"); - }(); - - auto output = Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Output(outputEntry.name, expression)); + auto output = Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Output(outputEntry.name, ShaderGraph::ToShaderExpressionType(outputEntry.type))); return Nz::ShaderBuilder::Assign(std::move(output), *expressions); } @@ -92,18 +79,7 @@ QtNodes::NodeDataType OutputValue::dataType(QtNodes::PortType portType, QtNodes: return VecData::Type(); const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex); - switch (outputEntry.type) - { - //case InOutType::Bool: return Nz::ShaderNodes::BasicType::Boolean; - //case InOutType::Float1: return Nz::ShaderNodes::BasicType::Float1; - case PrimitiveType::Float2: - case PrimitiveType::Float3: - case PrimitiveType::Float4: - return VecData::Type(); - } - - assert(false); - throw std::runtime_error("Unhandled output type"); + return ShaderGraph::ToNodeDataType(outputEntry.type); } unsigned int OutputValue::nPorts(QtNodes::PortType portType) const @@ -124,14 +100,11 @@ std::shared_ptr OutputValue::outData(QtNodes::PortIndex /*por void OutputValue::setInData(std::shared_ptr value, int index) { + if (!m_currentOutputIndex) + return; + assert(index == 0); - if (value) - { - assert(dynamic_cast(value.get()) != nullptr); - m_input = std::static_pointer_cast(value); - } - else - m_input.reset(); + m_input = std::move(value); UpdatePreview(); } @@ -142,8 +115,23 @@ QtNodes::NodeValidationState OutputValue::validationState() const return QtNodes::NodeValidationState::Error; const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex); - if (GetComponentCount(outputEntry.type) != m_input->componentCount) - return QtNodes::NodeValidationState::Error; + switch (outputEntry.type) + { + case PrimitiveType::Bool: + case PrimitiveType::Float1: + case PrimitiveType::Mat4x4: + break; + + case PrimitiveType::Float2: + case PrimitiveType::Float3: + case PrimitiveType::Float4: + { + assert(dynamic_cast(m_input.get()) != nullptr); + const VecData& vec = static_cast(*m_input); + if (GetComponentCount(outputEntry.type) != vec.componentCount) + return QtNodes::NodeValidationState::Error; + } + } return QtNodes::NodeValidationState::Valid; } @@ -157,10 +145,26 @@ QString OutputValue::validationMessage() const return "Missing input"; const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex); - std::size_t outputComponentCount = GetComponentCount(outputEntry.type); + switch (outputEntry.type) + { + case PrimitiveType::Bool: + case PrimitiveType::Float1: + case PrimitiveType::Mat4x4: + break; - if (m_input->componentCount != outputComponentCount) - return "Incompatible component count (expected " + QString::number(outputComponentCount) + ", got " + QString::number(m_input->componentCount) + ")"; + case PrimitiveType::Float2: + case PrimitiveType::Float3: + case PrimitiveType::Float4: + { + assert(dynamic_cast(m_input.get()) != nullptr); + const VecData& vec = static_cast(*m_input); + + std::size_t outputComponentCount = GetComponentCount(outputEntry.type); + + if (outputComponentCount != vec.componentCount) + return "Incompatible component count (expected " + QString::number(outputComponentCount) + ", got " + QString::number(vec.componentCount) + ")"; + } + } return QString(); } @@ -170,8 +174,49 @@ bool OutputValue::ComputePreview(QPixmap& pixmap) if (!m_input) return false; - pixmap = QPixmap::fromImage(m_input->preview.GenerateImage()); - return true; + const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex); + switch (outputEntry.type) + { + case PrimitiveType::Bool: + { + assert(dynamic_cast(m_input.get()) != nullptr); + const BoolData& data = static_cast(*m_input); + + pixmap = QPixmap::fromImage(data.preview.GenerateImage()); + return true; + } + + case PrimitiveType::Float1: + { + assert(dynamic_cast(m_input.get()) != nullptr); + const FloatData& data = static_cast(*m_input); + + pixmap = QPixmap::fromImage(data.preview.GenerateImage()); + return true; + } + + case PrimitiveType::Mat4x4: + { + //TODO + /*assert(dynamic_cast(m_input.get()) != nullptr); + const Matrix4Data& data = static_cast(*m_input);*/ + + return false; + } + + case PrimitiveType::Float2: + case PrimitiveType::Float3: + case PrimitiveType::Float4: + { + assert(dynamic_cast(m_input.get()) != nullptr); + const VecData& data = static_cast(*m_input); + + pixmap = QPixmap::fromImage(data.preview.GenerateImage()); + return true; + } + } + + return false; } void OutputValue::OnOutputListUpdate() diff --git a/src/ShaderNode/DataModels/OutputValue.hpp b/src/ShaderNode/DataModels/OutputValue.hpp index 284e302ea..12c812c5c 100644 --- a/src/ShaderNode/DataModels/OutputValue.hpp +++ b/src/ShaderNode/DataModels/OutputValue.hpp @@ -1,7 +1,7 @@ #pragma once -#ifndef NAZARA_SHADERNODES_FRAGMENTOUTPUT_HPP -#define NAZARA_SHADERNODES_FRAGMENTOUTPUT_HPP +#ifndef NAZARA_SHADERNODES_OUTPUTVALUE_HPP +#define NAZARA_SHADERNODES_OUTPUTVALUE_HPP #include #include @@ -44,7 +44,7 @@ class OutputValue : public ShaderNode NazaraSlot(ShaderGraph, OnOutputUpdate, m_onOutputUpdateSlot); std::optional m_currentOutputIndex; - std::shared_ptr m_input; + std::shared_ptr m_input; std::string m_currentOutputText; }; diff --git a/src/ShaderNode/DataTypes/Matrix4Data.cpp b/src/ShaderNode/DataTypes/Matrix4Data.cpp new file mode 100644 index 000000000..24dfe95a2 --- /dev/null +++ b/src/ShaderNode/DataTypes/Matrix4Data.cpp @@ -0,0 +1 @@ +#include diff --git a/src/ShaderNode/DataTypes/Matrix4Data.hpp b/src/ShaderNode/DataTypes/Matrix4Data.hpp new file mode 100644 index 000000000..fdfbf1897 --- /dev/null +++ b/src/ShaderNode/DataTypes/Matrix4Data.hpp @@ -0,0 +1,19 @@ +#pragma once + +#ifndef NAZARA_SHADERNODES_MATRIXDATA_HPP +#define NAZARA_SHADERNODES_MATRIXDATA_HPP + +#include +#include +#include + +struct Matrix4Data : public QtNodes::NodeData +{ + inline QtNodes::NodeDataType type() const override; + + static inline QtNodes::NodeDataType Type(); +}; + +#include + +#endif diff --git a/src/ShaderNode/DataTypes/Matrix4Data.inl b/src/ShaderNode/DataTypes/Matrix4Data.inl new file mode 100644 index 000000000..157e35810 --- /dev/null +++ b/src/ShaderNode/DataTypes/Matrix4Data.inl @@ -0,0 +1,11 @@ +#include + +inline QtNodes::NodeDataType Matrix4Data::type() const +{ + return Type(); +} + +inline QtNodes::NodeDataType Matrix4Data::Type() +{ + return { "mat4", "Matrix4x4" }; +} diff --git a/src/ShaderNode/Enums.cpp b/src/ShaderNode/Enums.cpp index 610078d65..2c924c3ed 100644 --- a/src/ShaderNode/Enums.cpp +++ b/src/ShaderNode/Enums.cpp @@ -10,6 +10,7 @@ std::size_t GetComponentCount(PrimitiveType type) case PrimitiveType::Float2: return 2; case PrimitiveType::Float3: return 3; case PrimitiveType::Float4: return 4; + case PrimitiveType::Mat4x4: return 16; } assert(false); @@ -50,6 +51,7 @@ const char* EnumToString(PrimitiveType input) case PrimitiveType::Float2: return "Float2"; case PrimitiveType::Float3: return "Float3"; case PrimitiveType::Float4: return "Float4"; + case PrimitiveType::Mat4x4: return "Mat4x4"; } assert(false); diff --git a/src/ShaderNode/Enums.hpp b/src/ShaderNode/Enums.hpp index 41e8f4360..e59d66424 100644 --- a/src/ShaderNode/Enums.hpp +++ b/src/ShaderNode/Enums.hpp @@ -35,8 +35,9 @@ enum class PrimitiveType Float2, Float3, Float4, + Mat4x4, - Max = Float4 + Max = Mat4x4 }; constexpr std::size_t PrimitiveTypeCount = static_cast(PrimitiveType::Max) + 1; diff --git a/src/ShaderNode/ShaderGraph.cpp b/src/ShaderNode/ShaderGraph.cpp index 22d74dca2..5b248bfc3 100644 --- a/src/ShaderNode/ShaderGraph.cpp +++ b/src/ShaderNode/ShaderGraph.cpp @@ -8,11 +8,18 @@ #include #include #include +#include +#include #include #include #include #include #include +#include +#include +#include +#include +#include #include #include #include @@ -591,6 +598,29 @@ void ShaderGraph::UpdateTexturePreview(std::size_t textureIndex, QImage preview) OnTexturePreviewUpdate(this, textureIndex); } +QtNodes::NodeDataType ShaderGraph::ToNodeDataType(PrimitiveType type) +{ + switch (type) + { + case PrimitiveType::Bool: + return BoolData::Type(); + + case PrimitiveType::Float1: + return FloatData::Type(); + + case PrimitiveType::Float2: + case PrimitiveType::Float3: + case PrimitiveType::Float4: + return VecData::Type(); + + case PrimitiveType::Mat4x4: + return Matrix4Data::Type(); + } + + assert(false); + throw std::runtime_error("Unhandled input type"); +} + Nz::ShaderExpressionType ShaderGraph::ToShaderExpressionType(PrimitiveType type) { switch (type) @@ -600,6 +630,7 @@ Nz::ShaderExpressionType ShaderGraph::ToShaderExpressionType(PrimitiveType type) case PrimitiveType::Float2: return Nz::ShaderNodes::BasicType::Float2; case PrimitiveType::Float3: return Nz::ShaderNodes::BasicType::Float3; case PrimitiveType::Float4: return Nz::ShaderNodes::BasicType::Float4; + case PrimitiveType::Mat4x4: return Nz::ShaderNodes::BasicType::Mat4x4; } assert(false); @@ -629,6 +660,10 @@ std::shared_ptr ShaderGraph::BuildRegistry() RegisterShaderNode(*this, registry, "Outputs"); RegisterShaderNode(*this, registry, "Texture"); RegisterShaderNode(*this, registry, "Texture"); + RegisterShaderNode(*this, registry, "Matrix operations"); + RegisterShaderNode(*this, registry, "Matrix operations"); + RegisterShaderNode(*this, registry, "Matrix operations"); + RegisterShaderNode(*this, registry, "Matrix operations"); RegisterShaderNode(*this, registry, "Vector operations"); RegisterShaderNode(*this, registry, "Vector operations"); RegisterShaderNode(*this, registry, "Vector operations"); diff --git a/src/ShaderNode/ShaderGraph.hpp b/src/ShaderNode/ShaderGraph.hpp index 0cab330d0..e91127cb5 100644 --- a/src/ShaderNode/ShaderGraph.hpp +++ b/src/ShaderNode/ShaderGraph.hpp @@ -122,6 +122,7 @@ class ShaderGraph NazaraSignal(OnTexturePreviewUpdate, ShaderGraph*, std::size_t /*textureIndex*/); NazaraSignal(OnTextureUpdate, ShaderGraph*, std::size_t /*textureIndex*/); + static QtNodes::NodeDataType ToNodeDataType(PrimitiveType type); static Nz::ShaderExpressionType ToShaderExpressionType(PrimitiveType type); static Nz::ShaderExpressionType ToShaderExpressionType(TextureType type);