ShaderNode: Handle vector component count at runtime

This commit is contained in:
Lynix 2020-05-31 18:39:28 +02:00
parent 2ecc624fe4
commit effd1b4552
28 changed files with 529 additions and 339 deletions

View File

@ -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

View File

@ -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) :

View File

@ -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
{

View File

@ -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>

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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();

View File

@ -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)

View File

@ -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();

View File

@ -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();
}

View File

@ -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>

View File

@ -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();
}

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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 };

View File

@ -0,0 +1 @@
#include <ShaderNode/DataTypes/VecData.hpp>

View File

@ -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

View File

@ -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));
}

View File

@ -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");
}

View File

@ -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<>

View File

@ -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" };
}

View File

@ -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)

View File

@ -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);

View File

@ -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");

View File

@ -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());
}
}