NazaraEngine/src/ShaderNode/DataModels/VecBinOp.inl

192 lines
5.0 KiB
C++

#include <ShaderNode/DataModels/VecBinOp.hpp>
#include <Nazara/Renderer/ShaderBuilder.hpp>
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
VecBinOp<Data, BinOp>::VecBinOp(ShaderGraph& graph) :
ShaderNode(graph)
{
m_output = std::make_shared<Data>();
m_pixmapLabel = new QLabel;
m_pixmapLabel->setStyleSheet("background-color: rgba(0,0,0,0)");
UpdatePreview();
}
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
Nz::ShaderAst::ExpressionPtr VecBinOp<Data, BinOp>::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
{
assert(count == 2);
using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder<BinOp>;
constexpr BuilderType builder;
return builder(expressions[0], expressions[1]);
}
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
QWidget* VecBinOp<Data, BinOp>::embeddedWidget()
{
return m_pixmapLabel;
}
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
QtNodes::NodeDataType VecBinOp<Data, BinOp>::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const
{
assert(portIndex == 0 || portIndex == 1);
return Data::Type();
}
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
unsigned int VecBinOp<Data, BinOp>::nPorts(QtNodes::PortType portType) const
{
switch (portType)
{
case QtNodes::PortType::In: return 2;
case QtNodes::PortType::Out: return 1;
}
return 0;
}
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
std::shared_ptr<QtNodes::NodeData> VecBinOp<Data, 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)
{
assert(index == 0 || index == 1);
std::shared_ptr<Data> castedValue;
if (value)
{
assert(dynamic_cast<Data*>(value.get()) != nullptr);
castedValue = std::static_pointer_cast<Data>(value);
}
if (index == 0)
m_lhs = std::move(castedValue);
else
m_rhs = std::move(castedValue);
UpdatePreview();
Q_EMIT dataUpdated(0);
}
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
void VecBinOp<Data, BinOp>::UpdatePreview()
{
if (m_lhs && m_rhs)
{
const QImage& leftPreview = m_lhs->preview;
const QImage& rightPreview = m_rhs->preview;
int maxWidth = std::max(leftPreview.width(), rightPreview.width());
int maxHeight = std::max(leftPreview.height(), rightPreview.height());
// Exploit COW
QImage leftResized = leftPreview;
if (leftResized.width() != maxWidth || leftResized.height() != maxHeight)
leftResized = leftResized.scaled(maxWidth, maxHeight);
QImage rightResized = rightPreview;
if (rightResized.width() != maxWidth || rightResized.height() != maxHeight)
rightResized = rightResized.scaled(maxWidth, maxHeight);
m_output->preview = QImage(maxWidth, maxHeight, QImage::Format_RGBA8888);
ApplyOp(leftResized.constBits(), rightResized.constBits(), m_output->preview.bits(), maxWidth * maxHeight * 4);
m_preview = QPixmap::fromImage(m_output->preview).scaled(64, 64);
}
else
{
m_preview = QPixmap(64, 64);
m_preview.fill(QColor::fromRgb(255, 255, 0, 0));
}
m_pixmapLabel->setPixmap(m_preview);
}
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);
}
}