218 lines
4.5 KiB
C++
218 lines
4.5 KiB
C++
#include <ShaderNode/ShaderGraph.hpp>
|
|
#include <ShaderNode/DataModels/SampleTexture.hpp>
|
|
#include <NZSL/ShaderBuilder.hpp>
|
|
|
|
SampleTexture::SampleTexture(ShaderGraph& graph) :
|
|
ShaderNode(graph)
|
|
{
|
|
m_output = std::make_shared<VecData>(4);
|
|
|
|
UpdateOutput();
|
|
}
|
|
|
|
unsigned int SampleTexture::nPorts(QtNodes::PortType portType) const
|
|
{
|
|
switch (portType)
|
|
{
|
|
case QtNodes::PortType::In: return 2;
|
|
case QtNodes::PortType::Out: return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void SampleTexture::UpdateOutput()
|
|
{
|
|
PreviewValues& output = m_output->preview;
|
|
|
|
if (!m_texture || !m_uv)
|
|
{
|
|
output = PreviewValues(1, 1);
|
|
output.Fill(nzsl::Vector4f32(0.f, 0.f, 0.f, 0.f));
|
|
return;
|
|
}
|
|
|
|
const PreviewValues& texturePreview = m_texture->preview;
|
|
|
|
std::size_t textureWidth = texturePreview.GetWidth();
|
|
std::size_t textureHeight = texturePreview.GetHeight();
|
|
|
|
const PreviewValues& uv = m_uv->preview;
|
|
|
|
std::size_t uvWidth = uv.GetWidth();
|
|
std::size_t uvHeight = uv.GetHeight();
|
|
|
|
output = PreviewValues(uvWidth, uvHeight);
|
|
|
|
for (std::size_t y = 0; y < uvHeight; ++y)
|
|
{
|
|
for (std::size_t x = 0; x < uvWidth; ++x)
|
|
{
|
|
nzsl::Vector4f32 uvValue = uv(x, y);
|
|
|
|
if (textureWidth > 0 && textureHeight > 0)
|
|
output(x, y) = texturePreview.Sample(uvValue.x(), uvValue.y());
|
|
else
|
|
output(x, y) = nzsl::Vector4f32(0.f, 0.f, 0.f, 1.f);
|
|
}
|
|
}
|
|
|
|
Q_EMIT dataUpdated(0);
|
|
|
|
UpdatePreview();
|
|
}
|
|
|
|
bool SampleTexture::ComputePreview(QPixmap& pixmap)
|
|
{
|
|
if (!m_texture || !m_uv)
|
|
return false;
|
|
|
|
pixmap = QPixmap::fromImage(m_output->preview.GenerateImage());
|
|
return true;
|
|
}
|
|
|
|
nzsl::Ast::NodePtr SampleTexture::BuildNode(nzsl::Ast::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
|
|
{
|
|
assert(m_texture);
|
|
assert(m_uv);
|
|
assert(count == 2);
|
|
assert(outputIndex == 0);
|
|
|
|
std::vector<nzsl::Ast::ExpressionPtr> params;
|
|
params.push_back(std::move(expressions[0]));
|
|
params.push_back(std::move(expressions[1]));
|
|
|
|
return nzsl::ShaderBuilder::Intrinsic(nzsl::Ast::IntrinsicType::SampleTexture, std::move(params));
|
|
}
|
|
|
|
auto SampleTexture::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType
|
|
{
|
|
switch (portType)
|
|
{
|
|
case QtNodes::PortType::In:
|
|
{
|
|
switch (portIndex)
|
|
{
|
|
case 0: return Texture2Data::Type();
|
|
case 1: return VecData::Type();
|
|
}
|
|
|
|
assert(false);
|
|
throw std::runtime_error("invalid port index");
|
|
}
|
|
|
|
case QtNodes::PortType::Out:
|
|
{
|
|
assert(portIndex == 0);
|
|
return VecData::Type();
|
|
}
|
|
|
|
default:
|
|
assert(false);
|
|
throw std::runtime_error("invalid PortType");
|
|
}
|
|
}
|
|
|
|
QString SampleTexture::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
|
{
|
|
switch (portType)
|
|
{
|
|
case QtNodes::PortType::In:
|
|
{
|
|
switch (portIndex)
|
|
{
|
|
case 0: return tr("Texture");
|
|
case 1: return tr("UV");
|
|
}
|
|
|
|
assert(false);
|
|
throw std::runtime_error("invalid port index");
|
|
}
|
|
|
|
case QtNodes::PortType::Out:
|
|
{
|
|
assert(portIndex == 0);
|
|
return tr("Sample");
|
|
}
|
|
|
|
default:
|
|
assert(false);
|
|
throw std::runtime_error("Invalid PortType");
|
|
}
|
|
}
|
|
|
|
bool SampleTexture::portCaptionVisible(QtNodes::PortType /*portType*/, QtNodes::PortIndex /*portIndex*/) const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
std::shared_ptr<QtNodes::NodeData> SampleTexture::outData(QtNodes::PortIndex port)
|
|
{
|
|
assert(port == 0);
|
|
|
|
return m_output;
|
|
}
|
|
|
|
void SampleTexture::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
|
{
|
|
switch (index)
|
|
{
|
|
case 0:
|
|
{
|
|
if (value && value->type().id == Texture2Data::Type().id)
|
|
{
|
|
assert(dynamic_cast<Texture2Data*>(value.get()) != nullptr);
|
|
m_texture = std::static_pointer_cast<Texture2Data>(value);
|
|
}
|
|
else
|
|
m_texture.reset();
|
|
|
|
break;
|
|
}
|
|
|
|
case 1:
|
|
{
|
|
if (value && value->type().id == VecData::Type().id)
|
|
{
|
|
assert(dynamic_cast<VecData*>(value.get()) != nullptr);
|
|
m_uv = std::static_pointer_cast<VecData>(value);
|
|
}
|
|
else
|
|
m_uv.reset();
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
assert(false);
|
|
throw std::runtime_error("Invalid PortType");
|
|
}
|
|
|
|
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();
|
|
}
|