ShaderNode: Handle vector component count at runtime
This commit is contained in:
parent
2ecc624fe4
commit
effd1b4552
|
|
@ -258,6 +258,7 @@ namespace Nz
|
|||
{
|
||||
public:
|
||||
inline Cast(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second = nullptr, ExpressionPtr third = nullptr, ExpressionPtr fourth = nullptr);
|
||||
inline Cast(ExpressionType castTo, ExpressionPtr* expressions, std::size_t expressionCount);
|
||||
|
||||
ExpressionType GetExpressionType() const override;
|
||||
void Register(ShaderWriter& visitor) override;
|
||||
|
|
@ -265,6 +266,9 @@ namespace Nz
|
|||
|
||||
ExpressionType exprType;
|
||||
std::array<ExpressionPtr, 4> expressions;
|
||||
|
||||
private:
|
||||
void Validate() const;
|
||||
};
|
||||
|
||||
class NAZARA_RENDERER_API Constant : public Expression
|
||||
|
|
|
|||
|
|
@ -169,19 +169,16 @@ namespace Nz
|
|||
exprType(castTo),
|
||||
expressions({ {first, second, third, fourth} })
|
||||
{
|
||||
unsigned int componentCount = 0;
|
||||
unsigned int requiredComponents = GetComponentCount(exprType);
|
||||
for (const auto& exprPtr : expressions)
|
||||
{
|
||||
if (!exprPtr)
|
||||
break;
|
||||
Validate();
|
||||
}
|
||||
|
||||
componentCount += GetComponentCount(exprPtr->GetExpressionType());
|
||||
}
|
||||
inline Cast::Cast(ExpressionType castTo, ExpressionPtr* Expressions, std::size_t expressionCount) :
|
||||
exprType(castTo)
|
||||
{
|
||||
for (std::size_t i = 0; i < expressionCount; ++i)
|
||||
expressions[i] = Expressions[i];
|
||||
|
||||
//TODO: AstParseError
|
||||
if (componentCount != requiredComponents)
|
||||
throw std::runtime_error("Component count doesn't match required component count");
|
||||
Validate();
|
||||
}
|
||||
|
||||
inline Constant::Constant(bool value) :
|
||||
|
|
|
|||
|
|
@ -200,6 +200,23 @@ namespace Nz::ShaderAst
|
|||
visitor.Write(*this);
|
||||
}
|
||||
|
||||
void Cast::Validate() const
|
||||
{
|
||||
unsigned int componentCount = 0;
|
||||
unsigned int requiredComponents = GetComponentCount(exprType);
|
||||
for (const auto& exprPtr : expressions)
|
||||
{
|
||||
if (!exprPtr)
|
||||
break;
|
||||
|
||||
componentCount += GetComponentCount(exprPtr->GetExpressionType());
|
||||
}
|
||||
|
||||
//TODO: AstParseError
|
||||
if (componentCount != requiredComponents)
|
||||
throw std::runtime_error("Component count doesn't match required component count");
|
||||
}
|
||||
|
||||
|
||||
ExpressionCategory SwizzleOp::GetExpressionCategory() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
|
||||
template<typename From, typename To>
|
||||
template<std::size_t ToComponentCount>
|
||||
class CastVec : public ShaderNode
|
||||
{
|
||||
public:
|
||||
|
|
@ -31,25 +31,21 @@ class CastVec : public ShaderNode
|
|||
|
||||
void setInData(std::shared_ptr<QtNodes::NodeData> value, int index) override;
|
||||
|
||||
private:
|
||||
static constexpr std::size_t FromComponents = From::ComponentCount;
|
||||
static constexpr std::size_t ToComponents = To::ComponentCount;
|
||||
static constexpr std::size_t ComponentDiff = (ToComponents >= FromComponents) ? ToComponents - FromComponents : 0;
|
||||
QtNodes::NodeValidationState validationState() const override;
|
||||
QString validationMessage() const override;
|
||||
|
||||
private:
|
||||
bool ComputePreview(QPixmap& pixmap) override;
|
||||
void UpdateOutput();
|
||||
|
||||
VecType<ComponentDiff> m_overflowComponents;
|
||||
std::shared_ptr<From> m_input;
|
||||
std::shared_ptr<To> m_output;
|
||||
std::shared_ptr<VecData> m_input;
|
||||
std::shared_ptr<VecData> m_output;
|
||||
VecType<ToComponentCount> m_overflowComponents;
|
||||
};
|
||||
|
||||
using CastVec2ToVec3 = CastVec<Vec2Data, Vec3Data>;
|
||||
using CastVec2ToVec4 = CastVec<Vec2Data, Vec4Data>;
|
||||
using CastVec3ToVec2 = CastVec<Vec3Data, Vec2Data>;
|
||||
using CastVec3ToVec4 = CastVec<Vec3Data, Vec4Data>;
|
||||
using CastVec4ToVec2 = CastVec<Vec4Data, Vec2Data>;
|
||||
using CastVec4ToVec3 = CastVec<Vec4Data, Vec3Data>;
|
||||
using CastToVec2 = CastVec<2>;
|
||||
using CastToVec3 = CastVec<3>;
|
||||
using CastToVec4 = CastVec<4>;
|
||||
|
||||
#include <ShaderNode/DataModels/Cast.inl>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,21 +4,32 @@
|
|||
#include <QtWidgets/QFormLayout>
|
||||
#include <stdexcept>
|
||||
|
||||
template<typename From, typename To>
|
||||
CastVec<From, To>::CastVec(ShaderGraph& graph) :
|
||||
template<std::size_t ToComponentCount>
|
||||
CastVec<ToComponentCount>::CastVec(ShaderGraph& graph) :
|
||||
ShaderNode(graph)
|
||||
{
|
||||
static_assert(ComponentDiff <= s_vectorComponents.size());
|
||||
static_assert(ToComponentCount <= s_vectorComponents.size());
|
||||
|
||||
m_overflowComponents.fill(0.f);
|
||||
|
||||
m_output = std::make_shared<VecData>(ToComponentCount);
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
void CastVec<From, To>::BuildNodeEdition(QFormLayout* layout)
|
||||
template<std::size_t ToComponentCount>
|
||||
void CastVec<ToComponentCount>::BuildNodeEdition(QFormLayout* layout)
|
||||
{
|
||||
ShaderNode::BuildNodeEdition(layout);
|
||||
|
||||
if constexpr (ComponentDiff > 0)
|
||||
if (!m_input)
|
||||
return;
|
||||
|
||||
std::size_t fromComponentCount = m_input->componentCount;
|
||||
|
||||
if (ToComponentCount > fromComponentCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < ComponentDiff; ++i)
|
||||
std::size_t overflowComponentCount = ToComponentCount - fromComponentCount;
|
||||
|
||||
for (std::size_t i = 0; i < overflowComponentCount; ++i)
|
||||
{
|
||||
QDoubleSpinBox* spinbox = new QDoubleSpinBox;
|
||||
spinbox->setDecimals(6);
|
||||
|
|
@ -30,31 +41,36 @@ void CastVec<From, To>::BuildNodeEdition(QFormLayout* layout)
|
|||
UpdateOutput();
|
||||
});
|
||||
|
||||
layout->addRow(QString::fromUtf8(&s_vectorComponents[FromComponents + i], 1), spinbox);
|
||||
layout->addRow(QString::fromUtf8(&s_vectorComponents[fromComponentCount + i], 1), spinbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
Nz::ShaderAst::ExpressionPtr CastVec<From, To>::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
|
||||
template<std::size_t ToComponentCount>
|
||||
Nz::ShaderAst::ExpressionPtr CastVec<ToComponentCount>::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
|
||||
{
|
||||
assert(m_input);
|
||||
assert(count == 1);
|
||||
|
||||
if constexpr (ComponentDiff > 0)
|
||||
{
|
||||
std::array<Nz::ShaderAst::ExpressionPtr, ComponentDiff> constants;
|
||||
for (std::size_t i = 0; i < ComponentDiff; ++i)
|
||||
constants[i] = Nz::ShaderBuilder::Constant(m_overflowComponents[i]);
|
||||
std::size_t fromComponentCount = m_input->componentCount;
|
||||
|
||||
return std::apply([&](auto&&... values)
|
||||
{
|
||||
return Nz::ShaderBuilder::Cast<To::ExpressionType>(expressions[0], values...); //< TODO: Forward
|
||||
}, constants);
|
||||
}
|
||||
else
|
||||
if (ToComponentCount > fromComponentCount)
|
||||
{
|
||||
std::array<Nz::ShaderAst::SwizzleComponent, ToComponents> swizzleComponents;
|
||||
for (std::size_t i = 0; i < ToComponents; ++i)
|
||||
std::size_t overflowComponentCount = ToComponentCount - fromComponentCount;
|
||||
|
||||
std::array<Nz::ShaderAst::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(), overflowComponentCount);
|
||||
}
|
||||
else if (ToComponentCount < fromComponentCount)
|
||||
{
|
||||
std::array<Nz::ShaderAst::SwizzleComponent, ToComponentCount> swizzleComponents;
|
||||
for (std::size_t i = 0; i < ToComponentCount; ++i)
|
||||
swizzleComponents[i] = static_cast<Nz::ShaderAst::SwizzleComponent>(static_cast<std::size_t>(Nz::ShaderAst::SwizzleComponent::First) + i);
|
||||
|
||||
return std::apply([&](auto... components)
|
||||
|
|
@ -63,39 +79,41 @@ Nz::ShaderAst::ExpressionPtr CastVec<From, To>::GetExpression(Nz::ShaderAst::Exp
|
|||
return Nz::ShaderBuilder::Swizzle(expressions[0], componentList);
|
||||
}, swizzleComponents);
|
||||
}
|
||||
else
|
||||
return expressions[0]; //< no-op
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
QString CastVec<From, To>::caption() const
|
||||
template<std::size_t ToComponentCount>
|
||||
QString CastVec<ToComponentCount>::caption() const
|
||||
{
|
||||
static QString caption = From::Type().name + " to " + To::Type().name;
|
||||
static QString caption = "To Vector" + QString::number(ToComponentCount);
|
||||
return caption;
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
QString CastVec<From, To>::name() const
|
||||
template<std::size_t ToComponentCount>
|
||||
QString CastVec<ToComponentCount>::name() const
|
||||
{
|
||||
static QString name = From::Type().id + "to" + To::Type().id;
|
||||
static QString name = "cast_vec" + QString::number(ToComponentCount);
|
||||
return name;
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
QtNodes::NodeDataType CastVec<From, To>::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
template<std::size_t ToComponentCount>
|
||||
QtNodes::NodeDataType CastVec<ToComponentCount>::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return From::Type();
|
||||
case QtNodes::PortType::Out: return To::Type();
|
||||
case QtNodes::PortType::In: return VecData::Type();
|
||||
case QtNodes::PortType::Out: return VecData::Type();
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Invalid port type");
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
unsigned int CastVec<From, To>::nPorts(QtNodes::PortType portType) const
|
||||
template<std::size_t ToComponentCount>
|
||||
unsigned int CastVec<ToComponentCount>::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
|
|
@ -106,8 +124,8 @@ unsigned int CastVec<From, To>::nPorts(QtNodes::PortType portType) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
std::shared_ptr<QtNodes::NodeData> CastVec<From, To>::outData(QtNodes::PortIndex port)
|
||||
template<std::size_t ToComponentCount>
|
||||
std::shared_ptr<QtNodes::NodeData> CastVec<ToComponentCount>::outData(QtNodes::PortIndex port)
|
||||
{
|
||||
assert(port == 0);
|
||||
|
||||
|
|
@ -117,14 +135,14 @@ std::shared_ptr<QtNodes::NodeData> CastVec<From, To>::outData(QtNodes::PortIndex
|
|||
return m_output;
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
void CastVec<From, To>::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||
template<std::size_t ToComponentCount>
|
||||
void CastVec<ToComponentCount>::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||
{
|
||||
assert(index == 0);
|
||||
if (value)
|
||||
{
|
||||
assert(dynamic_cast<From*>(value.get()) != nullptr);
|
||||
m_input = std::static_pointer_cast<From>(value);
|
||||
assert(dynamic_cast<VecData*>(value.get()) != nullptr);
|
||||
m_input = std::static_pointer_cast<VecData>(value);
|
||||
}
|
||||
else
|
||||
m_input.reset();
|
||||
|
|
@ -132,8 +150,26 @@ void CastVec<From, To>::setInData(std::shared_ptr<QtNodes::NodeData> value, int
|
|||
UpdateOutput();
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
bool CastVec<From, To>::ComputePreview(QPixmap& pixmap)
|
||||
template<std::size_t ToComponentCount>
|
||||
QtNodes::NodeValidationState CastVec<ToComponentCount>::validationState() const
|
||||
{
|
||||
if (!m_input)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
|
||||
return QtNodes::NodeValidationState::Valid;
|
||||
}
|
||||
|
||||
template<std::size_t ToComponentCount>
|
||||
QString CastVec<ToComponentCount>::validationMessage() const
|
||||
{
|
||||
if (!m_input)
|
||||
return "Missing input";
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
template<std::size_t ToComponentCount>
|
||||
bool CastVec<ToComponentCount>::ComputePreview(QPixmap& pixmap)
|
||||
{
|
||||
if (!m_input)
|
||||
return false;
|
||||
|
|
@ -142,8 +178,8 @@ bool CastVec<From, To>::ComputePreview(QPixmap& pixmap)
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
void CastVec<From, To>::UpdateOutput()
|
||||
template<std::size_t ToComponentCount>
|
||||
void CastVec<ToComponentCount>::UpdateOutput()
|
||||
{
|
||||
if (!m_input)
|
||||
{
|
||||
|
|
@ -160,10 +196,15 @@ void CastVec<From, To>::UpdateOutput()
|
|||
QImage& output = m_output->preview;
|
||||
output = QImage(inputWidth, inputHeight, QImage::Format_RGBA8888);
|
||||
|
||||
std::array<std::uint8_t, ComponentDiff> constants;
|
||||
if constexpr (ComponentDiff > 0)
|
||||
std::size_t fromComponentCount = m_input->componentCount;
|
||||
std::size_t commonComponents = std::min(fromComponentCount, ToComponentCount);
|
||||
std::size_t overflowComponentCount = (ToComponentCount > fromComponentCount) ? ToComponentCount - fromComponentCount : 0;
|
||||
std::size_t voidComponents = 4 - overflowComponentCount - commonComponents;
|
||||
|
||||
std::array<std::uint8_t, 4> constants;
|
||||
if (ToComponentCount > fromComponentCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < ComponentDiff; ++i)
|
||||
for (std::size_t i = 0; i < overflowComponentCount; ++i)
|
||||
constants[i] = static_cast<std::uint8_t>(std::clamp(int(m_overflowComponents[i] * 255), 0, 255));
|
||||
}
|
||||
|
||||
|
|
@ -173,17 +214,14 @@ void CastVec<From, To>::UpdateOutput()
|
|||
{
|
||||
for (int x = 0; x < inputWidth; ++x)
|
||||
{
|
||||
constexpr std::size_t CommonComponents = std::min(FromComponents, ToComponents);
|
||||
constexpr std::size_t VoidComponents = 4 - ComponentDiff - CommonComponents;
|
||||
|
||||
for (std::size_t i = 0; i < CommonComponents; ++i)
|
||||
for (std::size_t i = 0; i < commonComponents; ++i)
|
||||
*outputPtr++ = inputPtr[i];
|
||||
|
||||
for (std::size_t i = 0; i < ComponentDiff; ++i)
|
||||
for (std::size_t i = 0; i < overflowComponentCount; ++i)
|
||||
*outputPtr++ = constants[i];
|
||||
|
||||
for (std::size_t i = 0; i < VoidComponents; ++i)
|
||||
*outputPtr++ = (i == VoidComponents - 1) ? 255 : 0;
|
||||
for (std::size_t i = 0; i < voidComponents; ++i)
|
||||
*outputPtr++ = (i == voidComponents - 1) ? 255 : 0;
|
||||
|
||||
inputPtr += 4;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,16 +121,17 @@ auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portInd
|
|||
assert(portIndex == 0);
|
||||
|
||||
if (!m_currentInputIndex)
|
||||
return Vec4Data::Type();
|
||||
return VecData::Type();
|
||||
|
||||
const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex);
|
||||
switch (inputEntry.type)
|
||||
{
|
||||
//case InputType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
|
||||
//case InputType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
|
||||
case InOutType::Float2: return Vec2Data::Type();
|
||||
case InOutType::Float3: return Vec3Data::Type();
|
||||
case InOutType::Float4: return Vec4Data::Type();
|
||||
case InOutType::Float2:
|
||||
case InOutType::Float3:
|
||||
case InOutType::Float4:
|
||||
return VecData::Type();
|
||||
}
|
||||
|
||||
assert(false);
|
||||
|
|
@ -148,8 +149,24 @@ std::shared_ptr<QtNodes::NodeData> InputValue::outData(QtNodes::PortIndex port)
|
|||
const auto& inputEntry = graph.GetInput(*m_currentInputIndex);
|
||||
const auto& preview = graph.GetPreviewModel();
|
||||
|
||||
auto vecData = std::make_shared<Vec2Data>();
|
||||
auto vecData = std::make_shared<VecData>(GetComponentCount(inputEntry.type));
|
||||
vecData->preview = preview.GetImage(inputEntry.role, inputEntry.roleIndex);
|
||||
|
||||
return vecData;
|
||||
}
|
||||
|
||||
QtNodes::NodeValidationState InputValue::validationState() const
|
||||
{
|
||||
if (!m_currentInputIndex)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
|
||||
return QtNodes::NodeValidationState::Valid;
|
||||
}
|
||||
|
||||
QString InputValue::validationMessage() const
|
||||
{
|
||||
if (!m_currentInputIndex)
|
||||
return "No input selected";
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ class InputValue : public ShaderNode
|
|||
|
||||
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
||||
|
||||
QtNodes::NodeValidationState validationState() const override;
|
||||
QString validationMessage() const override;
|
||||
|
||||
private:
|
||||
bool ComputePreview(QPixmap& pixmap) override;
|
||||
void OnInputListUpdate();
|
||||
|
|
|
|||
|
|
@ -87,16 +87,17 @@ QtNodes::NodeDataType OutputValue::dataType(QtNodes::PortType portType, QtNodes:
|
|||
assert(portIndex == 0);
|
||||
|
||||
if (!m_currentOutputIndex)
|
||||
return Vec4Data::Type();
|
||||
return VecData::Type();
|
||||
|
||||
const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex);
|
||||
switch (outputEntry.type)
|
||||
{
|
||||
//case InOutType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
|
||||
//case InOutType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
|
||||
case InOutType::Float2: return Vec2Data::Type();
|
||||
case InOutType::Float3: return Vec3Data::Type();
|
||||
case InOutType::Float4: return Vec4Data::Type();
|
||||
case InOutType::Float2:
|
||||
case InOutType::Float3:
|
||||
case InOutType::Float4:
|
||||
return VecData::Type();
|
||||
}
|
||||
|
||||
assert(false);
|
||||
|
|
@ -124,8 +125,8 @@ void OutputValue::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
|||
assert(index == 0);
|
||||
if (value)
|
||||
{
|
||||
assert(dynamic_cast<Vec4Data*>(value.get()) != nullptr);
|
||||
m_input = std::static_pointer_cast<Vec4Data>(value);
|
||||
assert(dynamic_cast<VecData*>(value.get()) != nullptr);
|
||||
m_input = std::static_pointer_cast<VecData>(value);
|
||||
}
|
||||
else
|
||||
m_input.reset();
|
||||
|
|
@ -133,6 +134,35 @@ void OutputValue::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
|||
UpdatePreview();
|
||||
}
|
||||
|
||||
QtNodes::NodeValidationState OutputValue::validationState() const
|
||||
{
|
||||
if (!m_currentOutputIndex || !m_input)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
|
||||
const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex);
|
||||
if (GetComponentCount(outputEntry.type) != m_input->componentCount)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
|
||||
return QtNodes::NodeValidationState::Valid;
|
||||
}
|
||||
|
||||
QString OutputValue::validationMessage() const
|
||||
{
|
||||
if (!m_currentOutputIndex)
|
||||
return "No output selected";
|
||||
|
||||
if (!m_input)
|
||||
return "Missing input";
|
||||
|
||||
const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex);
|
||||
std::size_t outputComponentCount = GetComponentCount(outputEntry.type);
|
||||
|
||||
if (m_input->componentCount != outputComponentCount)
|
||||
return "Incompatible component count (expected " + QString::number(outputComponentCount) + ", got " + QString::number(m_input->componentCount) + ")";
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool OutputValue::ComputePreview(QPixmap& pixmap)
|
||||
{
|
||||
if (!m_input)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ class OutputValue : public ShaderNode
|
|||
|
||||
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 OnOutputListUpdate();
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
SampleTexture::SampleTexture(ShaderGraph& graph) :
|
||||
ShaderNode(graph)
|
||||
{
|
||||
m_output = std::make_shared<Vec4Data>();
|
||||
m_output = std::make_shared<VecData>(4);
|
||||
|
||||
UpdateOutput();
|
||||
}
|
||||
|
|
@ -82,9 +82,8 @@ bool SampleTexture::ComputePreview(QPixmap& pixmap)
|
|||
|
||||
Nz::ShaderAst::ExpressionPtr SampleTexture::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
|
||||
{
|
||||
if (!m_texture || !m_uv)
|
||||
throw std::runtime_error("invalid inputs");
|
||||
|
||||
assert(m_texture);
|
||||
assert(m_uv);
|
||||
assert(count == 2);
|
||||
|
||||
return Nz::ShaderBuilder::Sample2D(expressions[0], expressions[1]);
|
||||
|
|
@ -99,7 +98,7 @@ auto SampleTexture::dataType(QtNodes::PortType portType, QtNodes::PortIndex port
|
|||
switch (portIndex)
|
||||
{
|
||||
case 0: return Texture2Data::Type();
|
||||
case 1: return Vec2Data::Type();
|
||||
case 1: return VecData::Type();
|
||||
}
|
||||
|
||||
assert(false);
|
||||
|
|
@ -109,7 +108,7 @@ auto SampleTexture::dataType(QtNodes::PortType portType, QtNodes::PortIndex port
|
|||
case QtNodes::PortType::Out:
|
||||
{
|
||||
assert(portIndex == 0);
|
||||
return Vec4Data::Type();
|
||||
return VecData::Type();
|
||||
}
|
||||
|
||||
default:
|
||||
|
|
@ -180,9 +179,9 @@ void SampleTexture::setInData(std::shared_ptr<QtNodes::NodeData> value, int inde
|
|||
{
|
||||
if (value)
|
||||
{
|
||||
assert(dynamic_cast<Vec2Data*>(value.get()) != nullptr);
|
||||
assert(dynamic_cast<VecData*>(value.get()) != nullptr);
|
||||
|
||||
m_uv = std::static_pointer_cast<Vec2Data>(value);
|
||||
m_uv = std::static_pointer_cast<VecData>(value);
|
||||
}
|
||||
else
|
||||
m_uv.reset();
|
||||
|
|
@ -197,3 +196,28 @@ void SampleTexture::setInData(std::shared_ptr<QtNodes::NodeData> value, int inde
|
|||
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
QtNodes::NodeValidationState SampleTexture::validationState() const
|
||||
{
|
||||
if (!m_texture || !m_uv)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
|
||||
if (m_uv->componentCount != 2)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
|
||||
return QtNodes::NodeValidationState::Valid;
|
||||
}
|
||||
|
||||
QString SampleTexture::validationMessage() const
|
||||
{
|
||||
if (!m_texture)
|
||||
return "Missing texture";
|
||||
|
||||
if (!m_uv)
|
||||
return "Missing uv";
|
||||
|
||||
if (m_uv->componentCount != 2)
|
||||
return "Incompatible UV (expected 2, got " + QString::number(m_uv->componentCount) + ")";
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,13 +34,16 @@ class SampleTexture : public ShaderNode
|
|||
|
||||
void setInData(std::shared_ptr<QtNodes::NodeData> value, int index) override;
|
||||
|
||||
QtNodes::NodeValidationState validationState() const override;
|
||||
QString validationMessage() const override;
|
||||
|
||||
protected:
|
||||
bool ComputePreview(QPixmap& pixmap) override;
|
||||
void UpdateOutput();
|
||||
|
||||
std::shared_ptr<Texture2Data> m_texture;
|
||||
std::shared_ptr<Vec2Data> m_uv;
|
||||
std::shared_ptr<Vec4Data> m_output;
|
||||
std::shared_ptr<VecData> m_uv;
|
||||
std::shared_ptr<VecData> m_output;
|
||||
};
|
||||
|
||||
#include <ShaderNode/DataModels/SampleTexture.inl>
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ void TextureValue::BuildNodeEdition(QFormLayout* layout)
|
|||
Nz::ShaderAst::ExpressionPtr TextureValue::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
|
||||
{
|
||||
if (!m_currentTextureIndex)
|
||||
throw std::runtime_error("invalid inputs");
|
||||
throw std::runtime_error("invalid texture input");
|
||||
|
||||
assert(count == 0);
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ auto TextureValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portI
|
|||
assert(portType == QtNodes::PortType::Out);
|
||||
assert(portIndex == 0);
|
||||
|
||||
return Vec4Data::Type();
|
||||
return VecData::Type();
|
||||
}
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> TextureValue::outData(QtNodes::PortIndex port)
|
||||
|
|
@ -145,3 +145,19 @@ std::shared_ptr<QtNodes::NodeData> TextureValue::outData(QtNodes::PortIndex port
|
|||
|
||||
return textureData;
|
||||
}
|
||||
|
||||
QtNodes::NodeValidationState TextureValue::validationState() const
|
||||
{
|
||||
if (!m_currentTextureIndex)
|
||||
return QtNodes::NodeValidationState::Error;
|
||||
|
||||
return QtNodes::NodeValidationState::Valid;
|
||||
}
|
||||
|
||||
QString TextureValue::validationMessage() const
|
||||
{
|
||||
if (!m_currentTextureIndex)
|
||||
return "No texture selected";
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ class TextureValue : public ShaderNode
|
|||
|
||||
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
||||
|
||||
QtNodes::NodeValidationState validationState() const override;
|
||||
QString validationMessage() const override;
|
||||
|
||||
protected:
|
||||
bool ComputePreview(QPixmap& pixmap) override;
|
||||
void OnTextureListUpdate();
|
||||
|
|
|
|||
|
|
@ -1 +1,73 @@
|
|||
#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 std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
{
|
||||
unsigned int lValue = left[i];
|
||||
unsigned int rValue = right[i];
|
||||
|
||||
output[i] = static_cast<std::uint8_t>(std::min(lValue + rValue, 255U));
|
||||
}
|
||||
}
|
||||
|
||||
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 std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
{
|
||||
unsigned int lValue = left[i];
|
||||
unsigned int rValue = right[i];
|
||||
|
||||
output[i] = static_cast<std::uint8_t>(lValue * rValue / 255);
|
||||
}
|
||||
}
|
||||
|
||||
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 std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
{
|
||||
unsigned int lValue = left[i];
|
||||
unsigned int rValue = right[i];
|
||||
|
||||
unsigned int sub = (lValue >= rValue) ? lValue - rValue : 0u;
|
||||
|
||||
output[i] = static_cast<std::uint8_t>(sub);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
|
||||
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
||||
template<Nz::ShaderAst::BinaryType BinOp>
|
||||
class VecBinOp : public ShaderNode
|
||||
{
|
||||
public:
|
||||
|
|
@ -29,16 +29,15 @@ class VecBinOp : public ShaderNode
|
|||
bool ComputePreview(QPixmap& pixmap) override;
|
||||
void UpdateOutput();
|
||||
|
||||
std::shared_ptr<Data> m_lhs;
|
||||
std::shared_ptr<Data> m_rhs;
|
||||
std::shared_ptr<Data> m_output;
|
||||
std::shared_ptr<VecData> m_lhs;
|
||||
std::shared_ptr<VecData> m_rhs;
|
||||
std::shared_ptr<VecData> m_output;
|
||||
};
|
||||
|
||||
template<typename Data>
|
||||
class VecAdd : public VecBinOp<Data, Nz::ShaderAst::BinaryType::Add>
|
||||
class VecAdd : public VecBinOp<Nz::ShaderAst::BinaryType::Add>
|
||||
{
|
||||
public:
|
||||
using VecBinOp<Data, Nz::ShaderAst::BinaryType::Add>::VecBinOp;
|
||||
using VecBinOp<Nz::ShaderAst::BinaryType::Add>::VecBinOp;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
|
@ -46,11 +45,10 @@ class VecAdd : public VecBinOp<Data, Nz::ShaderAst::BinaryType::Add>
|
|||
void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override;
|
||||
};
|
||||
|
||||
template<typename Data>
|
||||
class VecMul : public VecBinOp<Data, Nz::ShaderAst::BinaryType::Multiply>
|
||||
class VecMul : public VecBinOp<Nz::ShaderAst::BinaryType::Multiply>
|
||||
{
|
||||
public:
|
||||
using VecBinOp<Data, Nz::ShaderAst::BinaryType::Multiply>::VecBinOp;
|
||||
using VecBinOp<Nz::ShaderAst::BinaryType::Multiply>::VecBinOp;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
|
@ -58,11 +56,10 @@ class VecMul : public VecBinOp<Data, Nz::ShaderAst::BinaryType::Multiply>
|
|||
void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override;
|
||||
};
|
||||
|
||||
template<typename Data>
|
||||
class VecSub : public VecBinOp<Data, Nz::ShaderAst::BinaryType::Substract>
|
||||
class VecSub : public VecBinOp<Nz::ShaderAst::BinaryType::Substract>
|
||||
{
|
||||
public:
|
||||
using VecBinOp<Data, Nz::ShaderAst::BinaryType::Substract>::VecBinOp;
|
||||
using VecBinOp<Nz::ShaderAst::BinaryType::Substract>::VecBinOp;
|
||||
|
||||
QString caption() const override;
|
||||
QString name() const override;
|
||||
|
|
@ -70,18 +67,6 @@ class VecSub : public VecBinOp<Data, Nz::ShaderAst::BinaryType::Substract>
|
|||
void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override;
|
||||
};
|
||||
|
||||
using Vec2Add = VecAdd<Vec2Data>;
|
||||
using Vec3Add = VecAdd<Vec3Data>;
|
||||
using Vec4Add = VecAdd<Vec4Data>;
|
||||
|
||||
using Vec2Mul = VecMul<Vec2Data>;
|
||||
using Vec3Mul = VecMul<Vec3Data>;
|
||||
using Vec4Mul = VecMul<Vec4Data>;
|
||||
|
||||
using Vec2Sub = VecSub<Vec2Data>;
|
||||
using Vec3Sub = VecSub<Vec3Data>;
|
||||
using Vec4Sub = VecSub<Vec4Data>;
|
||||
|
||||
#include <ShaderNode/DataModels/VecBinOp.inl>
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
#include <ShaderNode/DataModels/VecBinOp.hpp>
|
||||
#include <Nazara/Renderer/ShaderBuilder.hpp>
|
||||
|
||||
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
||||
VecBinOp<Data, BinOp>::VecBinOp(ShaderGraph& graph) :
|
||||
template<Nz::ShaderAst::BinaryType BinOp>
|
||||
VecBinOp<BinOp>::VecBinOp(ShaderGraph& graph) :
|
||||
ShaderNode(graph)
|
||||
{
|
||||
m_output = std::make_shared<Data>();
|
||||
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
||||
Nz::ShaderAst::ExpressionPtr VecBinOp<Data, BinOp>::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
|
||||
template<Nz::ShaderAst::BinaryType BinOp>
|
||||
Nz::ShaderAst::ExpressionPtr VecBinOp<BinOp>::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
|
||||
{
|
||||
assert(count == 2);
|
||||
using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder<BinOp>;
|
||||
|
|
@ -19,16 +17,16 @@ Nz::ShaderAst::ExpressionPtr VecBinOp<Data, BinOp>::GetExpression(Nz::ShaderAst:
|
|||
return builder(expressions[0], expressions[1]);
|
||||
}
|
||||
|
||||
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
||||
QtNodes::NodeDataType VecBinOp<Data, BinOp>::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const
|
||||
template<Nz::ShaderAst::BinaryType BinOp>
|
||||
QtNodes::NodeDataType VecBinOp<BinOp>::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portIndex == 0 || portIndex == 1);
|
||||
|
||||
return Data::Type();
|
||||
return VecData::Type();
|
||||
}
|
||||
|
||||
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
||||
unsigned int VecBinOp<Data, BinOp>::nPorts(QtNodes::PortType portType) const
|
||||
template<Nz::ShaderAst::BinaryType BinOp>
|
||||
unsigned int VecBinOp<BinOp>::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
|
|
@ -39,24 +37,24 @@ unsigned int VecBinOp<Data, BinOp>::nPorts(QtNodes::PortType portType) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
||||
std::shared_ptr<QtNodes::NodeData> VecBinOp<Data, BinOp>::outData(QtNodes::PortIndex port)
|
||||
template<Nz::ShaderAst::BinaryType BinOp>
|
||||
std::shared_ptr<QtNodes::NodeData> VecBinOp<BinOp>::outData(QtNodes::PortIndex port)
|
||||
{
|
||||
assert(port == 0);
|
||||
return m_output;
|
||||
}
|
||||
|
||||
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
||||
void VecBinOp<Data, BinOp>::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||
template<Nz::ShaderAst::BinaryType BinOp>
|
||||
void VecBinOp<BinOp>::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||
{
|
||||
assert(index == 0 || index == 1);
|
||||
|
||||
std::shared_ptr<Data> castedValue;
|
||||
std::shared_ptr<VecData> castedValue;
|
||||
if (value)
|
||||
{
|
||||
assert(dynamic_cast<Data*>(value.get()) != nullptr);
|
||||
assert(dynamic_cast<VecData*>(value.get()) != nullptr);
|
||||
|
||||
castedValue = std::static_pointer_cast<Data>(value);
|
||||
castedValue = std::static_pointer_cast<VecData>(value);
|
||||
}
|
||||
|
||||
if (index == 0)
|
||||
|
|
@ -67,8 +65,8 @@ void VecBinOp<Data, BinOp>::setInData(std::shared_ptr<QtNodes::NodeData> value,
|
|||
UpdateOutput();
|
||||
}
|
||||
|
||||
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
||||
bool VecBinOp<Data, BinOp>::ComputePreview(QPixmap& pixmap)
|
||||
template<Nz::ShaderAst::BinaryType BinOp>
|
||||
bool VecBinOp<BinOp>::ComputePreview(QPixmap& pixmap)
|
||||
{
|
||||
if (!m_lhs || !m_rhs)
|
||||
return false;
|
||||
|
|
@ -77,16 +75,19 @@ bool VecBinOp<Data, BinOp>::ComputePreview(QPixmap& pixmap)
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
||||
void VecBinOp<Data, BinOp>::UpdateOutput()
|
||||
template<Nz::ShaderAst::BinaryType BinOp>
|
||||
void VecBinOp<BinOp>::UpdateOutput()
|
||||
{
|
||||
if (!m_lhs || !m_rhs)
|
||||
if (!m_lhs || !m_rhs || m_lhs->componentCount != m_rhs->componentCount)
|
||||
{
|
||||
m_output = std::make_shared<VecData>(4);
|
||||
m_output->preview = QImage(1, 1, QImage::Format_RGBA8888);
|
||||
m_output->preview.fill(QColor::fromRgb(0, 0, 0, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
m_output = std::make_shared<VecData>(m_lhs->componentCount);
|
||||
|
||||
const QImage& leftPreview = m_lhs->preview;
|
||||
const QImage& rightPreview = m_rhs->preview;
|
||||
int maxWidth = std::max(leftPreview.width(), rightPreview.width());
|
||||
|
|
@ -108,83 +109,3 @@ void VecBinOp<Data, BinOp>::UpdateOutput()
|
|||
|
||||
UpdatePreview();
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
QString VecAdd<Data>::caption() const
|
||||
{
|
||||
static QString caption = Data::Type().name + " addition";
|
||||
return caption;
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
QString VecAdd<Data>::name() const
|
||||
{
|
||||
static QString name = Data::Type().name + "add";
|
||||
return name;
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
void VecAdd<Data>::ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
{
|
||||
unsigned int lValue = left[i];
|
||||
unsigned int rValue = right[i];
|
||||
|
||||
output[i] = static_cast<std::uint8_t>(std::min(lValue + rValue, 255U));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
QString VecMul<Data>::caption() const
|
||||
{
|
||||
static QString caption = Data::Type().name + " multiplication";
|
||||
return caption;
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
QString VecMul<Data>::name() const
|
||||
{
|
||||
static QString name = Data::Type().name + "mul";
|
||||
return name;
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
void VecMul<Data>::ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
{
|
||||
unsigned int lValue = left[i];
|
||||
unsigned int rValue = right[i];
|
||||
|
||||
output[i] = static_cast<std::uint8_t>(lValue * rValue / 255);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
QString VecSub<Data>::caption() const
|
||||
{
|
||||
static QString caption = Data::Type().name + " subtraction";
|
||||
return caption;
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
QString VecSub<Data>::name() const
|
||||
{
|
||||
static QString name = Data::Type().name + "sub";
|
||||
return name;
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
void VecSub<Data>::ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount)
|
||||
{
|
||||
for (std::size_t i = 0; i < pixelCount; ++i)
|
||||
{
|
||||
unsigned int lValue = left[i];
|
||||
unsigned int rValue = right[i];
|
||||
|
||||
unsigned int sub = (lValue >= rValue) ? lValue - rValue : 0u;
|
||||
|
||||
output[i] = static_cast<std::uint8_t>(sub);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
#include <array>
|
||||
|
||||
template<typename Data>
|
||||
template<std::size_t ComponentCount>
|
||||
class VecValue : public ShaderNode
|
||||
{
|
||||
public:
|
||||
|
|
@ -34,16 +34,14 @@ class VecValue : public ShaderNode
|
|||
private:
|
||||
bool ComputePreview(QPixmap& pixmap) override;
|
||||
|
||||
static constexpr std::size_t ComponentCount = Data::ComponentCount;
|
||||
|
||||
QColor ToColor() const;
|
||||
|
||||
VecType<ComponentCount> m_value;
|
||||
};
|
||||
|
||||
using Vec2Value = VecValue<Vec2Data>;
|
||||
using Vec3Value = VecValue<Vec3Data>;
|
||||
using Vec4Value = VecValue<Vec4Data>;
|
||||
using Vec2Value = VecValue<2>;
|
||||
using Vec3Value = VecValue<3>;
|
||||
using Vec4Value = VecValue<4>;
|
||||
|
||||
#include <ShaderNode/DataModels/VecValue.inl>
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
#include <array>
|
||||
#include <tuple>
|
||||
|
||||
template<typename Data>
|
||||
VecValue<Data>::VecValue(ShaderGraph& graph) :
|
||||
template<std::size_t ComponentCount>
|
||||
VecValue<ComponentCount>::VecValue(ShaderGraph& graph) :
|
||||
ShaderNode(graph)
|
||||
{
|
||||
static_assert(ComponentCount <= s_vectorComponents.size());
|
||||
|
|
@ -21,55 +21,55 @@ ShaderNode(graph)
|
|||
UpdatePreview();
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
QString VecValue<Data>::caption() const
|
||||
template<std::size_t ComponentCount>
|
||||
QString VecValue<ComponentCount>::caption() const
|
||||
{
|
||||
static QString caption = Data::Type().name + " constant";
|
||||
static QString caption = "Vector" + QString::number(ComponentCount) + " constant";
|
||||
return caption;
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
QString VecValue<Data>::name() const
|
||||
template<std::size_t ComponentCount>
|
||||
QString VecValue<ComponentCount>::name() const
|
||||
{
|
||||
static QString name = Data::Type().id + "Value";
|
||||
static QString name = "vec" + QString::number(ComponentCount) + "_constant";
|
||||
return name;
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
QtNodes::NodeDataType VecValue<Data>::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
template<std::size_t ComponentCount>
|
||||
QtNodes::NodeDataType VecValue<ComponentCount>::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
||||
{
|
||||
assert(portType == QtNodes::PortType::Out);
|
||||
assert(portIndex == 0);
|
||||
|
||||
return Data::Type();
|
||||
return VecData::Type();
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
unsigned int VecValue<Data>::nPorts(QtNodes::PortType portType) const
|
||||
template<std::size_t ComponentCount>
|
||||
unsigned int VecValue<ComponentCount>::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return 0;
|
||||
case QtNodes::PortType::In: return 0;
|
||||
case QtNodes::PortType::Out: return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
std::shared_ptr<QtNodes::NodeData> VecValue<Data>::outData(QtNodes::PortIndex port)
|
||||
template<std::size_t ComponentCount>
|
||||
std::shared_ptr<QtNodes::NodeData> VecValue<ComponentCount>::outData(QtNodes::PortIndex port)
|
||||
{
|
||||
assert(port == 0);
|
||||
|
||||
auto out = std::make_shared<Data>();
|
||||
auto out = std::make_shared<VecData>(ComponentCount);
|
||||
out->preview = QImage(1, 1, QImage::Format_RGBA8888);
|
||||
out->preview.fill(ToColor());
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
void VecValue<Data>::BuildNodeEdition(QFormLayout* layout)
|
||||
template<std::size_t ComponentCount>
|
||||
void VecValue<ComponentCount>::BuildNodeEdition(QFormLayout* layout)
|
||||
{
|
||||
ShaderNode::BuildNodeEdition(layout);
|
||||
|
||||
|
|
@ -91,23 +91,23 @@ void VecValue<Data>::BuildNodeEdition(QFormLayout* layout)
|
|||
}
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
Nz::ShaderAst::ExpressionPtr VecValue<Data>::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
|
||||
template<std::size_t ComponentCount>
|
||||
Nz::ShaderAst::ExpressionPtr VecValue<ComponentCount>::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
|
||||
{
|
||||
assert(count == 0);
|
||||
|
||||
return Nz::ShaderBuilder::Constant(m_value);
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
bool VecValue<Data>::ComputePreview(QPixmap& pixmap)
|
||||
template<std::size_t ComponentCount>
|
||||
bool VecValue<ComponentCount>::ComputePreview(QPixmap& pixmap)
|
||||
{
|
||||
pixmap.fill(ToColor());
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
QColor VecValue<Data>::ToColor() const
|
||||
template<std::size_t ComponentCount>
|
||||
QColor VecValue<ComponentCount>::ToColor() const
|
||||
{
|
||||
std::array<float, 4> values = { 0.f, 0.f, 0.f, 1.f };
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_FLOATDATA_HPP
|
||||
#define NAZARA_SHADERNODES_FLOATDATA_HPP
|
||||
|
||||
#include <nodes/NodeData>
|
||||
#include <QtGui/QImage>
|
||||
|
||||
struct FloatData : public QtNodes::NodeData
|
||||
{
|
||||
inline FloatData();
|
||||
|
||||
QtNodes::NodeDataType type() const override
|
||||
{
|
||||
return Type();
|
||||
}
|
||||
|
||||
static QtNodes::NodeDataType Type()
|
||||
{
|
||||
return { "float", "Float" };
|
||||
}
|
||||
|
||||
QImage preview;
|
||||
};
|
||||
|
||||
#include <ShaderNode/DataTypes/FloatData.inl>
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
#include <ShaderNode/DataTypes/FloatData.hpp>
|
||||
|
||||
inline FloatData::FloatData() :
|
||||
preview(1, 1, QImage::Format_RGBA8888)
|
||||
{
|
||||
preview.fill(QColor::fromRgb(255, 255, 255, 0));
|
||||
}
|
||||
|
|
@ -1 +1,18 @@
|
|||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
|
||||
Nz::ShaderAst::ExpressionType VecData::GetExpressionType() const
|
||||
{
|
||||
switch (componentCount)
|
||||
{
|
||||
case 2: return Nz::ShaderAst::ExpressionType::Float2;
|
||||
case 3: return Nz::ShaderAst::ExpressionType::Float3;
|
||||
case 4: return Nz::ShaderAst::ExpressionType::Float4;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("invalid component count");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,59 +9,48 @@
|
|||
|
||||
struct VecData : public QtNodes::NodeData
|
||||
{
|
||||
inline VecData();
|
||||
inline VecData(std::size_t componentCount);
|
||||
|
||||
inline QtNodes::NodeDataType type() const override;
|
||||
|
||||
Nz::ShaderAst::ExpressionType GetExpressionType() const;
|
||||
|
||||
static inline QtNodes::NodeDataType Type();
|
||||
|
||||
std::size_t componentCount;
|
||||
QImage preview;
|
||||
};
|
||||
|
||||
struct Vec2Data : public VecData
|
||||
template<std::size_t N>
|
||||
struct VecExpressionTypeHelper;
|
||||
|
||||
template<>
|
||||
struct VecExpressionTypeHelper<1>
|
||||
{
|
||||
static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float1;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct VecExpressionTypeHelper<2>
|
||||
{
|
||||
static constexpr std::size_t ComponentCount = 2;
|
||||
static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float2;
|
||||
|
||||
QtNodes::NodeDataType type() const override
|
||||
{
|
||||
return Type();
|
||||
}
|
||||
|
||||
static QtNodes::NodeDataType Type()
|
||||
{
|
||||
return { "vec2", "Vec2" };
|
||||
}
|
||||
};
|
||||
|
||||
struct Vec3Data : public VecData
|
||||
template<>
|
||||
struct VecExpressionTypeHelper<3>
|
||||
{
|
||||
static constexpr std::size_t ComponentCount = 3;
|
||||
static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float3;
|
||||
|
||||
QtNodes::NodeDataType type() const override
|
||||
{
|
||||
return Type();
|
||||
}
|
||||
|
||||
static QtNodes::NodeDataType Type()
|
||||
{
|
||||
return { "vec3", "Vec3" };
|
||||
}
|
||||
};
|
||||
|
||||
struct Vec4Data : public VecData
|
||||
template<>
|
||||
struct VecExpressionTypeHelper<4>
|
||||
{
|
||||
static constexpr std::size_t ComponentCount = 4;
|
||||
static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float4;
|
||||
|
||||
QtNodes::NodeDataType type() const override
|
||||
{
|
||||
return Type();
|
||||
}
|
||||
|
||||
static QtNodes::NodeDataType Type()
|
||||
{
|
||||
return { "vec4", "Vec4" };
|
||||
}
|
||||
};
|
||||
|
||||
template<std::size_t N> constexpr Nz::ShaderAst::ExpressionType VecExpressionType = VecExpressionTypeHelper<N>::template ExpressionType;
|
||||
|
||||
|
||||
struct VecTypeDummy {};
|
||||
|
||||
template<std::size_t N>
|
||||
|
|
@ -76,7 +65,7 @@ struct VecTypeHelper<0>
|
|||
template<>
|
||||
struct VecTypeHelper<1>
|
||||
{
|
||||
using Type = std::array<float, 1>;
|
||||
using Type = std::array<float, 1>; //< To allow [0]
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,18 @@
|
|||
#include <ShaderNode/DataTypes/VecData.hpp>
|
||||
|
||||
inline VecData::VecData() :
|
||||
inline VecData::VecData(std::size_t ComponentCount) :
|
||||
componentCount(ComponentCount),
|
||||
preview(64, 64, QImage::Format_RGBA8888)
|
||||
{
|
||||
preview.fill(QColor::fromRgb(255, 255, 255, 0));
|
||||
}
|
||||
|
||||
inline QtNodes::NodeDataType VecData::type() const
|
||||
{
|
||||
return Type();
|
||||
}
|
||||
|
||||
inline QtNodes::NodeDataType VecData::Type()
|
||||
{
|
||||
return { "vector", "Vector" };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,21 @@
|
|||
#include <ShaderNode/Enums.hpp>
|
||||
#include <cassert>
|
||||
|
||||
std::size_t GetComponentCount(InOutType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case InOutType::Bool: return 1;
|
||||
case InOutType::Float1: return 1;
|
||||
case InOutType::Float2: return 2;
|
||||
case InOutType::Float3: return 3;
|
||||
case InOutType::Float4: return 4;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* EnumToString(InputRole role)
|
||||
{
|
||||
switch (role)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ enum class TextureType
|
|||
|
||||
constexpr std::size_t TextureTypeCount = static_cast<std::size_t>(TextureType::Max) + 1;
|
||||
|
||||
|
||||
std::size_t GetComponentCount(InOutType type);
|
||||
const char* EnumToString(InputRole role);
|
||||
const char* EnumToString(InOutType input);
|
||||
const char* EnumToString(TextureType textureType);
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ m_flowScene(BuildRegistry())
|
|||
auto& node3 = m_flowScene.createNode(std::make_unique<SampleTexture>(*this));
|
||||
node3.nodeGraphicsObject().setPos(200, 200);
|
||||
|
||||
auto& node4 = m_flowScene.createNode(std::make_unique<Vec4Mul>(*this));
|
||||
auto& node4 = m_flowScene.createNode(std::make_unique<VecMul>(*this));
|
||||
node4.nodeGraphicsObject().setPos(400, 200);
|
||||
|
||||
auto& node5 = m_flowScene.createNode(std::make_unique<OutputValue>(*this));
|
||||
|
|
@ -154,6 +154,8 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
|
|||
HandleNode = [&](QtNodes::Node* node) -> Nz::ShaderAst::ExpressionPtr
|
||||
{
|
||||
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())
|
||||
|
|
@ -211,21 +213,13 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
|
|||
return expression;
|
||||
};
|
||||
|
||||
try
|
||||
m_flowScene.iterateOverNodes([&](QtNodes::Node* node)
|
||||
{
|
||||
m_flowScene.iterateOverNodes([&](QtNodes::Node* node)
|
||||
if (node->nodeDataModel()->nPorts(QtNodes::PortType::Out) == 0)
|
||||
{
|
||||
if (node->nodeDataModel()->nPorts(QtNodes::PortType::Out) == 0)
|
||||
{
|
||||
statements.emplace_back(Nz::ShaderBuilder::ExprStatement(HandleNode(node)));
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
statements.emplace_back(Nz::ShaderBuilder::ExprStatement(HandleNode(node)));
|
||||
}
|
||||
});
|
||||
|
||||
return std::make_shared<Nz::ShaderAst::StatementBlock>(std::move(statements));
|
||||
}
|
||||
|
|
@ -265,25 +259,16 @@ void ShaderGraph::UpdateTexturePreview(std::size_t textureIndex, QImage preview)
|
|||
std::shared_ptr<QtNodes::DataModelRegistry> ShaderGraph::BuildRegistry()
|
||||
{
|
||||
auto registry = std::make_shared<QtNodes::DataModelRegistry>();
|
||||
RegisterShaderNode<CastVec2ToVec3>(*this, registry, "Casts");
|
||||
RegisterShaderNode<CastVec2ToVec4>(*this, registry, "Casts");
|
||||
RegisterShaderNode<CastVec3ToVec2>(*this, registry, "Casts");
|
||||
RegisterShaderNode<CastVec3ToVec4>(*this, registry, "Casts");
|
||||
RegisterShaderNode<CastVec4ToVec2>(*this, registry, "Casts");
|
||||
RegisterShaderNode<CastVec4ToVec3>(*this, registry, "Casts");
|
||||
RegisterShaderNode<CastToVec2>(*this, registry, "Casts");
|
||||
RegisterShaderNode<CastToVec3>(*this, registry, "Casts");
|
||||
RegisterShaderNode<CastToVec4>(*this, registry, "Casts");
|
||||
RegisterShaderNode<InputValue>(*this, registry, "Inputs");
|
||||
RegisterShaderNode<OutputValue>(*this, registry, "Outputs");
|
||||
RegisterShaderNode<SampleTexture>(*this, registry, "Texture");
|
||||
RegisterShaderNode<TextureValue>(*this, registry, "Texture");
|
||||
RegisterShaderNode<Vec2Add>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<Vec2Mul>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<Vec2Sub>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<Vec3Add>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<Vec3Mul>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<Vec3Sub>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<Vec4Add>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<Vec4Mul>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<Vec4Sub>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<VecAdd>(*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");
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <nodes/FlowView>
|
||||
#include <QtWidgets/QDockWidget>
|
||||
#include <QtWidgets/QMenuBar>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QTextEdit>
|
||||
#include <iostream>
|
||||
|
||||
|
|
@ -83,15 +84,22 @@ void MainWindow::BuildMenu()
|
|||
|
||||
void MainWindow::OnCompileToGLSL()
|
||||
{
|
||||
Nz::GlslWriter writer;
|
||||
Nz::String glsl = writer.Generate(m_shaderGraph.ToAst());
|
||||
try
|
||||
{
|
||||
Nz::GlslWriter writer;
|
||||
Nz::String glsl = writer.Generate(m_shaderGraph.ToAst());
|
||||
|
||||
std::cout << glsl << std::endl;
|
||||
std::cout << glsl << std::endl;
|
||||
|
||||
QTextEdit* output = new QTextEdit;
|
||||
output->setReadOnly(true);
|
||||
output->setText(QString::fromUtf8(glsl.GetConstBuffer(), int(glsl.GetSize())));
|
||||
output->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
output->setWindowTitle("GLSL Output");
|
||||
output->show();
|
||||
QTextEdit* output = new QTextEdit;
|
||||
output->setReadOnly(true);
|
||||
output->setText(QString::fromUtf8(glsl.GetConstBuffer(), int(glsl.GetSize())));
|
||||
output->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
output->setWindowTitle("GLSL Output");
|
||||
output->show();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Compilation failed"), QString("Compilation failed: ") + e.what());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue