diff --git a/src/ShaderNode/DataModels/Cast.inl b/src/ShaderNode/DataModels/Cast.inl index ccb15385c..fb088b3a0 100644 --- a/src/ShaderNode/DataModels/Cast.inl +++ b/src/ShaderNode/DataModels/Cast.inl @@ -176,7 +176,7 @@ bool CastVec::ComputePreview(QPixmap& pixmap) if (!m_input) return false; - pixmap = QPixmap::fromImage(m_output->preview); + pixmap = QPixmap::fromImage(m_output->preview.GenerateImage()); return true; } @@ -185,47 +185,38 @@ void CastVec::UpdateOutput() { if (!m_input) { - m_output->preview = QImage(1, 1, QImage::Format_RGBA8888); - m_output->preview.fill(QColor::fromRgb(0, 0, 0, 0)); + m_output->preview = PreviewValues(1, 1); + m_output->preview(0, 0) = Nz::Vector4f::Zero(); return; } - const QImage& input = m_input->preview; + const PreviewValues& input = m_input->preview; - int inputWidth = input.width(); - int inputHeight = input.height(); + std::size_t inputWidth = input.GetWidth(); + std::size_t inputHeight = input.GetHeight(); - QImage& output = m_output->preview; - output = QImage(inputWidth, inputHeight, QImage::Format_RGBA8888); + PreviewValues& output = m_output->preview; + output = PreviewValues(inputWidth, inputHeight); 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 constants; - if (ToComponentCount > fromComponentCount) + for (std::size_t y = 0; y < inputHeight; ++y) { - for (std::size_t i = 0; i < overflowComponentCount; ++i) - constants[i] = static_cast(std::clamp(int(m_overflowComponents[i] * 255), 0, 255)); - } - - std::uint8_t* outputPtr = output.bits(); - const std::uint8_t* inputPtr = input.constBits(); - for (int y = 0; y < inputHeight; ++y) - { - for (int x = 0; x < inputWidth; ++x) + for (std::size_t x = 0; x < inputWidth; ++x) { - for (std::size_t i = 0; i < commonComponents; ++i) - *outputPtr++ = inputPtr[i]; + Nz::Vector4f color = input(x, y); + float* colorPtr = &color.x; for (std::size_t i = 0; i < overflowComponentCount; ++i) - *outputPtr++ = constants[i]; + *colorPtr++ = m_overflowComponents[i]; for (std::size_t i = 0; i < voidComponents; ++i) - *outputPtr++ = (i == voidComponents - 1) ? 255 : 0; + *colorPtr++ = (i == voidComponents - 1) ? 1.f : 0.f; - inputPtr += 4; + output(x, y) = color; } } diff --git a/src/ShaderNode/DataModels/FloatValue.cpp b/src/ShaderNode/DataModels/FloatValue.cpp index f9c25074b..c30ea8874 100644 --- a/src/ShaderNode/DataModels/FloatValue.cpp +++ b/src/ShaderNode/DataModels/FloatValue.cpp @@ -46,7 +46,7 @@ std::shared_ptr FloatValue::outData(QtNodes::PortIndex port) assert(port == 0); auto out = std::make_shared(); - out->preview.fill(ToColor()); + out->preview(0, 0) = Nz::Vector4f(m_value, m_value, m_value, 1.f); return out; } diff --git a/src/ShaderNode/DataModels/InputValue.cpp b/src/ShaderNode/DataModels/InputValue.cpp index 5a2b088dd..e0b117e83 100644 --- a/src/ShaderNode/DataModels/InputValue.cpp +++ b/src/ShaderNode/DataModels/InputValue.cpp @@ -48,7 +48,7 @@ bool InputValue::ComputePreview(QPixmap& pixmap) const auto& inputEntry = graph.GetInput(*m_currentInputIndex); const auto& preview = graph.GetPreviewModel(); - pixmap = QPixmap::fromImage(preview.GetImage(inputEntry.role, inputEntry.roleIndex)); + pixmap = QPixmap::fromImage(preview.GetPreview(inputEntry.role, inputEntry.roleIndex).GenerateImage()); return true; } @@ -171,7 +171,7 @@ std::shared_ptr InputValue::outData(QtNodes::PortIndex port) const auto& preview = graph.GetPreviewModel(); auto vecData = std::make_shared(GetComponentCount(inputEntry.type)); - vecData->preview = preview.GetImage(inputEntry.role, inputEntry.roleIndex); + vecData->preview = preview.GetPreview(inputEntry.role, inputEntry.roleIndex); return vecData; } diff --git a/src/ShaderNode/DataModels/OutputValue.cpp b/src/ShaderNode/DataModels/OutputValue.cpp index 7cf6fedec..a6b644be3 100644 --- a/src/ShaderNode/DataModels/OutputValue.cpp +++ b/src/ShaderNode/DataModels/OutputValue.cpp @@ -170,7 +170,7 @@ bool OutputValue::ComputePreview(QPixmap& pixmap) if (!m_input) return false; - pixmap = QPixmap::fromImage(m_input->preview); + pixmap = QPixmap::fromImage(m_input->preview.GenerateImage()); return true; } diff --git a/src/ShaderNode/DataModels/SampleTexture.cpp b/src/ShaderNode/DataModels/SampleTexture.cpp index 2c9e2dcac..131a8b161 100644 --- a/src/ShaderNode/DataModels/SampleTexture.cpp +++ b/src/ShaderNode/DataModels/SampleTexture.cpp @@ -23,57 +23,37 @@ unsigned int SampleTexture::nPorts(QtNodes::PortType portType) const void SampleTexture::UpdateOutput() { - QImage& output = m_output->preview; + PreviewValues& output = m_output->preview; if (!m_texture || !m_uv) { - output = QImage(1, 1, QImage::Format_RGBA8888); - output.fill(QColor::fromRgb(0, 0, 0, 0)); + output = PreviewValues(1, 1); + output.Fill(Nz::Vector4f::Zero()); return; } - const QImage& texturePreview = m_texture->preview; + const PreviewValues& texturePreview = m_texture->preview; - int textureWidth = texturePreview.width(); - int textureHeight = texturePreview.height(); + std::size_t textureWidth = texturePreview.GetWidth(); + std::size_t textureHeight = texturePreview.GetHeight(); - const QImage& uv = m_uv->preview; + const PreviewValues& uv = m_uv->preview; - int uvWidth = uv.width(); - int uvHeight = uv.height(); + std::size_t uvWidth = uv.GetWidth(); + std::size_t uvHeight = uv.GetHeight(); - output = QImage(uvWidth, uvHeight, QImage::Format_RGBA8888); + output = PreviewValues(uvWidth, uvHeight); - std::uint8_t* outputPtr = output.bits(); - const std::uint8_t* uvPtr = uv.constBits(); - const std::uint8_t* texturePtr = texturePreview.constBits(); - for (int y = 0; y < uvHeight; ++y) + for (std::size_t y = 0; y < uvHeight; ++y) { - for (int x = 0; x < uvWidth; ++x) + for (std::size_t x = 0; x < uvWidth; ++x) { - float u = float(uvPtr[0]) / 255; - float v = float(uvPtr[1]) / 255; + Nz::Vector4f uvValue = uv(x, y); if (textureWidth > 0 && textureHeight > 0) - { - int texX = std::clamp(int(u * textureWidth), 0, textureWidth - 1); - int texY = std::clamp(int(v * textureHeight), 0, textureHeight - 1); - int texPixel = (texY * textureWidth + texX) * 4; - - *outputPtr++ = texturePtr[texPixel + 0]; - *outputPtr++ = texturePtr[texPixel + 1]; - *outputPtr++ = texturePtr[texPixel + 2]; - *outputPtr++ = texturePtr[texPixel + 3]; - } + output(x, y) = texturePreview.Sample(uvValue.x, uvValue.y); else - { - *outputPtr++ = 0; - *outputPtr++ = 0; - *outputPtr++ = 0; - *outputPtr++ = 0xFF; - } - - uvPtr += 4; + output(x, y) = Nz::Vector4f(0.f, 0.f, 0.f, 1.f); } } @@ -87,7 +67,7 @@ bool SampleTexture::ComputePreview(QPixmap& pixmap) if (!m_texture || !m_uv) return false; - pixmap = QPixmap::fromImage(m_output->preview); + pixmap = QPixmap::fromImage(m_output->preview.GenerateImage()); return true; } diff --git a/src/ShaderNode/DataModels/TextureValue.cpp b/src/ShaderNode/DataModels/TextureValue.cpp index 2e25eaa03..d0237e8bd 100644 --- a/src/ShaderNode/DataModels/TextureValue.cpp +++ b/src/ShaderNode/DataModels/TextureValue.cpp @@ -158,7 +158,18 @@ std::shared_ptr TextureValue::outData(QtNodes::PortIndex port assert(textureData); - textureData->preview = textureEntry.preview; + const QImage& previewImage = textureEntry.preview; + + textureData->preview = PreviewValues(previewImage.width(), previewImage.height()); + for (std::size_t y = 0; y < textureData->preview.GetHeight(); ++y) + { + for (std::size_t x = 0; x < textureData->preview.GetWidth(); ++x) + { + QColor pixelColor = previewImage.pixelColor(int(x), int(y)); + + textureData->preview(x, y) = Nz::Vector4f(pixelColor.redF(), pixelColor.greenF(), pixelColor.blueF(), pixelColor.alphaF()); + } + } return textureData; } diff --git a/src/ShaderNode/DataModels/VecBinOp.cpp b/src/ShaderNode/DataModels/VecBinOp.cpp index 3ea2838f3..f99591420 100644 --- a/src/ShaderNode/DataModels/VecBinOp.cpp +++ b/src/ShaderNode/DataModels/VecBinOp.cpp @@ -12,15 +12,10 @@ QString VecAdd::name() const return name; } -void VecAdd::ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) +void VecAdd::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* 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::min(lValue + rValue, 255U)); - } + output[i] = left[i] + right[i]; } QString VecMul::caption() const @@ -35,15 +30,10 @@ QString VecMul::name() const return name; } -void VecMul::ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) +void VecMul::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* 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(lValue * rValue / 255); - } + output[i] = left[i] * right[i]; } QString VecSub::caption() const @@ -59,17 +49,10 @@ QString VecSub::name() const return name; } -void VecSub::ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) +void VecSub::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* 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(sub); - } + output[i] = left[i] - right[i]; } QString VecDiv::caption() const @@ -85,21 +68,8 @@ QString VecDiv::name() const return name; } -void VecDiv::ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) +void VecDiv::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* 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 res; - if (rValue != 0) - res = lValue / rValue; - else if (lValue != 0) - res = 0xFF; //< positive / 0 = +inf, which we clamp to 0xFF - else - res = 0; //< 0 / 0 = NaN, which we set to zero - - output[i] = static_cast(res); - } + output[i] = left[i] / right[i]; } diff --git a/src/ShaderNode/DataModels/VecBinOp.hpp b/src/ShaderNode/DataModels/VecBinOp.hpp index d00049c04..3c0a5aebd 100644 --- a/src/ShaderNode/DataModels/VecBinOp.hpp +++ b/src/ShaderNode/DataModels/VecBinOp.hpp @@ -27,7 +27,7 @@ class VecBinOp : public ShaderNode QString validationMessage() const override; private: - virtual void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) = 0; + virtual void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) = 0; bool ComputePreview(QPixmap& pixmap) override; void UpdateOutput(); @@ -45,7 +45,7 @@ class VecAdd : public VecBinOp QString caption() const override; QString name() const override; - void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override; + void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; }; class VecMul : public VecBinOp @@ -56,7 +56,7 @@ class VecMul : public VecBinOp QString caption() const override; QString name() const override; - void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override; + void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; }; class VecSub : public VecBinOp @@ -67,7 +67,7 @@ class VecSub : public VecBinOp QString caption() const override; QString name() const override; - void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override; + void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; }; class VecDiv : public VecBinOp @@ -78,7 +78,7 @@ class VecDiv : public VecBinOp QString caption() const override; QString name() const override; - void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override; + void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; }; #include diff --git a/src/ShaderNode/DataModels/VecBinOp.inl b/src/ShaderNode/DataModels/VecBinOp.inl index 255946543..d159545be 100644 --- a/src/ShaderNode/DataModels/VecBinOp.inl +++ b/src/ShaderNode/DataModels/VecBinOp.inl @@ -95,7 +95,7 @@ bool VecBinOp::ComputePreview(QPixmap& pixmap) if (!m_lhs || !m_rhs) return false; - pixmap = QPixmap::fromImage(m_output->preview); + pixmap = QPixmap::fromImage(m_output->preview.GenerateImage()); return true; } @@ -105,29 +105,29 @@ void VecBinOp::UpdateOutput() if (validationState() != QtNodes::NodeValidationState::Valid) { m_output = std::make_shared(4); - m_output->preview = QImage(1, 1, QImage::Format_RGBA8888); - m_output->preview.fill(QColor::fromRgb(0, 0, 0, 0)); + m_output->preview = PreviewValues(1, 1); + m_output->preview.Fill(Nz::Vector4f::Zero()); return; } m_output = std::make_shared(m_lhs->componentCount); - 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()); + const PreviewValues& leftPreview = m_lhs->preview; + const PreviewValues& rightPreview = m_rhs->preview; + std::size_t maxWidth = std::max(leftPreview.GetWidth(), rightPreview.GetWidth()); + std::size_t maxHeight = std::max(leftPreview.GetHeight(), rightPreview.GetHeight()); - // Exploit COW - QImage leftResized = leftPreview; - if (leftResized.width() != maxWidth || leftResized.height() != maxHeight) - leftResized = leftResized.scaled(maxWidth, maxHeight); + // FIXME: Prevent useless copy + PreviewValues leftResized = leftPreview; + if (leftResized.GetWidth() != maxWidth || leftResized.GetHeight() != maxHeight) + leftResized = leftResized.Resized(maxWidth, maxHeight); - QImage rightResized = rightPreview; - if (rightResized.width() != maxWidth || rightResized.height() != maxHeight) - rightResized = rightResized.scaled(maxWidth, maxHeight); + PreviewValues rightResized = rightPreview; + if (rightResized.GetWidth() != maxWidth || rightResized.GetHeight() != maxHeight) + rightResized = rightResized.Resized(maxWidth, maxHeight); - m_output->preview = QImage(maxWidth, maxHeight, QImage::Format_RGBA8888); - ApplyOp(leftResized.constBits(), rightResized.constBits(), m_output->preview.bits(), maxWidth * maxHeight * 4); + m_output->preview = PreviewValues(maxWidth, maxHeight); + ApplyOp(leftResized.GetData(), rightResized.GetData(), m_output->preview.GetData(), maxWidth * maxHeight); Q_EMIT dataUpdated(0); diff --git a/src/ShaderNode/DataModels/VecDot.cpp b/src/ShaderNode/DataModels/VecDot.cpp index 48aac108c..818a68a2a 100644 --- a/src/ShaderNode/DataModels/VecDot.cpp +++ b/src/ShaderNode/DataModels/VecDot.cpp @@ -112,7 +112,7 @@ bool VecDot::ComputePreview(QPixmap& pixmap) if (validationState() != QtNodes::NodeValidationState::Valid) return false; - pixmap = QPixmap::fromImage(m_output->preview); + pixmap = QPixmap::fromImage(m_output->preview.GenerateImage()); return true; } @@ -120,45 +120,41 @@ void VecDot::UpdateOutput() { if (validationState() != QtNodes::NodeValidationState::Valid) { - m_output->preview = QImage(1, 1, QImage::Format_RGBA8888); - m_output->preview.fill(QColor::fromRgb(0, 0, 0, 0)); + m_output->preview = PreviewValues(1, 1); + m_output->preview.Fill(Nz::Vector4f::Zero()); return; } - 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()); + const PreviewValues& leftPreview = m_lhs->preview; + const PreviewValues& rightPreview = m_rhs->preview; + std::size_t maxWidth = std::max(leftPreview.GetWidth(), rightPreview.GetWidth()); + std::size_t maxHeight = std::max(leftPreview.GetHeight(), rightPreview.GetHeight()); - // Exploit COW - QImage leftResized = leftPreview; - if (leftResized.width() != maxWidth || leftResized.height() != maxHeight) - leftResized = leftResized.scaled(maxWidth, maxHeight); + // FIXME: Prevent useless copy + PreviewValues leftResized = leftPreview; + if (leftResized.GetWidth() != maxWidth || leftResized.GetHeight() != maxHeight) + leftResized = leftResized.Resized(maxWidth, maxHeight); - QImage rightResized = rightPreview; - if (rightResized.width() != maxWidth || rightResized.height() != maxHeight) - rightResized = rightResized.scaled(maxWidth, maxHeight); + PreviewValues rightResized = rightPreview; + if (rightResized.GetWidth() != maxWidth || rightResized.GetHeight() != maxHeight) + rightResized = rightResized.Resized(maxWidth, maxHeight); - m_output->preview = QImage(maxWidth, maxHeight, QImage::Format_RGBA8888); + m_output->preview = PreviewValues(maxWidth, maxHeight); - const uchar* left = leftResized.constBits(); - const uchar* right = rightPreview.constBits(); - uchar* output = m_output->preview.bits(); + const Nz::Vector4f* left = leftResized.GetData(); + const Nz::Vector4f* right = rightPreview.GetData(); + Nz::Vector4f* output = m_output->preview.GetData(); std::size_t pixelCount = maxWidth * maxHeight; for (std::size_t i = 0; i < pixelCount; ++i) { - unsigned int acc = 0; + float acc = 0.f; for (std::size_t j = 0; j < m_lhs->componentCount; ++j) - acc += left[j] * right[j] / 255; + acc += left[i][j] * right[i][j]; - unsigned int result = static_cast(std::min(acc, 255U)); for (std::size_t j = 0; j < 3; ++j) - *output++ = result; - *output++ = 255; //< leave alpha at maximum - - left += 4; - right += 4; + output[i][j] = acc; + output[i][3] = 1.f; //< leave alpha at maximum } Q_EMIT dataUpdated(0); diff --git a/src/ShaderNode/DataModels/VecFloatMul.cpp b/src/ShaderNode/DataModels/VecFloatMul.cpp index 3c10d08e2..c1ecf50d2 100644 --- a/src/ShaderNode/DataModels/VecFloatMul.cpp +++ b/src/ShaderNode/DataModels/VecFloatMul.cpp @@ -132,7 +132,7 @@ bool VecFloatMul::ComputePreview(QPixmap& pixmap) if (validationState() != QtNodes::NodeValidationState::Valid) return false; - pixmap = QPixmap::fromImage(m_output->preview); + pixmap = QPixmap::fromImage(m_output->preview.GenerateImage()); return true; } @@ -141,41 +141,36 @@ void VecFloatMul::UpdateOutput() if (validationState() != QtNodes::NodeValidationState::Valid) { m_output = std::make_shared(4); - m_output->preview = QImage(1, 1, QImage::Format_RGBA8888); - m_output->preview.fill(QColor::fromRgb(0, 0, 0, 0)); + m_output->preview = PreviewValues(1, 1); + m_output->preview.Fill(Nz::Vector4f::Zero()); return; } m_output = std::make_shared(m_rhs->componentCount); - 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()); + const PreviewValues& leftPreview = m_lhs->preview; + const PreviewValues& rightPreview = m_rhs->preview; + std::size_t maxWidth = std::max(leftPreview.GetWidth(), rightPreview.GetWidth()); + std::size_t maxHeight = std::max(leftPreview.GetHeight(), rightPreview.GetHeight()); - // Exploit COW - QImage leftResized = leftPreview; - if (leftResized.width() != maxWidth || leftResized.height() != maxHeight) - leftResized = leftResized.scaled(maxWidth, maxHeight); + // FIXME: Prevent useless copy + PreviewValues leftResized = leftPreview; + if (leftResized.GetWidth() != maxWidth || leftResized.GetHeight() != maxHeight) + leftResized = leftResized.Resized(maxWidth, maxHeight); - QImage rightResized = rightPreview; - if (rightResized.width() != maxWidth || rightResized.height() != maxHeight) - rightResized = rightResized.scaled(maxWidth, maxHeight); + PreviewValues rightResized = rightPreview; + if (rightResized.GetWidth() != maxWidth || rightResized.GetHeight() != maxHeight) + rightResized = rightResized.Resized(maxWidth, maxHeight); - m_output->preview = QImage(maxWidth, maxHeight, QImage::Format_RGBA8888); + m_output->preview = PreviewValues(maxWidth, maxHeight); - const uchar* left = leftResized.constBits(); - const uchar* right = rightPreview.constBits(); - uchar* output = m_output->preview.bits(); + const Nz::Vector4f* left = leftResized.GetData(); + const Nz::Vector4f* right = rightPreview.GetData(); + Nz::Vector4f* output = m_output->preview.GetData(); - std::size_t pixelCount = maxWidth * maxHeight * 4; + std::size_t pixelCount = maxWidth * maxHeight; for (std::size_t i = 0; i < pixelCount; ++i) - { - unsigned int lValue = left[i]; - unsigned int rValue = right[i]; - - output[i] = static_cast(lValue * rValue / 255); - } + output[i] = left[i] * right[i]; Q_EMIT dataUpdated(0); diff --git a/src/ShaderNode/DataModels/VecValue.inl b/src/ShaderNode/DataModels/VecValue.inl index 8e158b94b..8b72d1186 100644 --- a/src/ShaderNode/DataModels/VecValue.inl +++ b/src/ShaderNode/DataModels/VecValue.inl @@ -63,8 +63,14 @@ std::shared_ptr VecValue::outData(QtNodes::Po assert(port == 0); auto out = std::make_shared(ComponentCount); - out->preview = QImage(1, 1, QImage::Format_RGBA8888); - out->preview.fill(ToColor()); + + std::array values = { 0.f, 0.f, 0.f, 1.f }; + + for (std::size_t i = 0; i < ComponentCount; ++i) + values[i] = m_value[i]; + + out->preview = PreviewValues(1, 1); + out->preview(0, 0) = Nz::Vector4f(values[0], values[1], values[2], values[3]); return out; } diff --git a/src/ShaderNode/DataTypes/FloatData.hpp b/src/ShaderNode/DataTypes/FloatData.hpp index e0f0451d2..d33d12b5d 100644 --- a/src/ShaderNode/DataTypes/FloatData.hpp +++ b/src/ShaderNode/DataTypes/FloatData.hpp @@ -3,8 +3,8 @@ #ifndef NAZARA_SHADERNODES_FLOATDATA_HPP #define NAZARA_SHADERNODES_FLOATDATA_HPP +#include #include -#include struct FloatData : public QtNodes::NodeData { @@ -20,7 +20,7 @@ struct FloatData : public QtNodes::NodeData return { "float", "Float" }; } - QImage preview; + PreviewValues preview; }; #include diff --git a/src/ShaderNode/DataTypes/FloatData.inl b/src/ShaderNode/DataTypes/FloatData.inl index 3960c5811..4f889aa90 100644 --- a/src/ShaderNode/DataTypes/FloatData.inl +++ b/src/ShaderNode/DataTypes/FloatData.inl @@ -1,7 +1,7 @@ #include inline FloatData::FloatData() : -preview(1, 1, QImage::Format_RGBA8888) +preview(1, 1) { - preview.fill(QColor::fromRgb(255, 255, 255, 0)); + preview(0, 0) = Nz::Vector4f(1.f, 1.f, 1.f, 0.f); } diff --git a/src/ShaderNode/DataTypes/TextureData.hpp b/src/ShaderNode/DataTypes/TextureData.hpp index 632fa5bde..b6f7b4433 100644 --- a/src/ShaderNode/DataTypes/TextureData.hpp +++ b/src/ShaderNode/DataTypes/TextureData.hpp @@ -3,15 +3,15 @@ #ifndef NAZARA_SHADERNODES_TEXTUREDATA_HPP #define NAZARA_SHADERNODES_TEXTUREDATA_HPP +#include #include #include -#include struct TextureData : public QtNodes::NodeData { inline TextureData(); - QImage preview; + PreviewValues preview; }; struct Texture2Data : public TextureData diff --git a/src/ShaderNode/DataTypes/TextureData.inl b/src/ShaderNode/DataTypes/TextureData.inl index e3ae7014f..b542dff60 100644 --- a/src/ShaderNode/DataTypes/TextureData.inl +++ b/src/ShaderNode/DataTypes/TextureData.inl @@ -1,7 +1,7 @@ #include inline TextureData::TextureData() : -preview(64, 64, QImage::Format_RGBA8888) +preview(64, 64) { - preview.fill(QColor::fromRgb(255, 255, 255, 0)); + preview.Fill(Nz::Vector4f(1.f, 1.f, 1.f, 0.f)); } diff --git a/src/ShaderNode/DataTypes/VecData.hpp b/src/ShaderNode/DataTypes/VecData.hpp index f333f9483..3c6a8f096 100644 --- a/src/ShaderNode/DataTypes/VecData.hpp +++ b/src/ShaderNode/DataTypes/VecData.hpp @@ -4,8 +4,8 @@ #define NAZARA_SHADERNODES_VECDATA_HPP #include +#include #include -#include struct VecData : public QtNodes::NodeData { @@ -18,7 +18,7 @@ struct VecData : public QtNodes::NodeData static inline QtNodes::NodeDataType Type(); std::size_t componentCount; - QImage preview; + PreviewValues preview; }; template diff --git a/src/ShaderNode/DataTypes/VecData.inl b/src/ShaderNode/DataTypes/VecData.inl index a84b5c344..7264ca7e9 100644 --- a/src/ShaderNode/DataTypes/VecData.inl +++ b/src/ShaderNode/DataTypes/VecData.inl @@ -2,9 +2,9 @@ inline VecData::VecData(std::size_t ComponentCount) : componentCount(ComponentCount), -preview(64, 64, QImage::Format_RGBA8888) +preview(64, 64) { - preview.fill(QColor::fromRgb(255, 255, 255, 0)); + preview.Fill(Nz::Vector4f(1.f, 1.f, 1.f, 0.f)); } inline QtNodes::NodeDataType VecData::type() const diff --git a/src/ShaderNode/Previews/PreviewModel.hpp b/src/ShaderNode/Previews/PreviewModel.hpp index 6ed8ec3ef..17b49fef2 100644 --- a/src/ShaderNode/Previews/PreviewModel.hpp +++ b/src/ShaderNode/Previews/PreviewModel.hpp @@ -5,7 +5,7 @@ #include -class QImage; +class PreviewValues; class PreviewModel { @@ -13,7 +13,7 @@ class PreviewModel PreviewModel() = default; virtual ~PreviewModel(); - virtual QImage GetImage(InputRole role, std::size_t roleIndex) const = 0; + virtual PreviewValues GetPreview(InputRole role, std::size_t roleIndex) const = 0; }; #include diff --git a/src/ShaderNode/Previews/PreviewValues.cpp b/src/ShaderNode/Previews/PreviewValues.cpp new file mode 100644 index 000000000..e44055333 --- /dev/null +++ b/src/ShaderNode/Previews/PreviewValues.cpp @@ -0,0 +1,95 @@ +#include +#include + +PreviewValues::PreviewValues() : +PreviewValues(0, 0) +{ +} + +PreviewValues::PreviewValues(std::size_t width, std::size_t height) : +m_height(height), +m_width(width) +{ + m_values.resize(m_width * m_height); //< RGBA +} + +void PreviewValues::Fill(const Nz::Vector4f& value) +{ + std::fill(m_values.begin(), m_values.end(), value); +} + +QImage PreviewValues::GenerateImage() const +{ + QImage preview(int(m_width), int(m_height), QImage::Format_RGBA8888); + + Nz::UInt8* ptr = preview.bits(); + + const Nz::Vector4f* src = m_values.data(); + for (std::size_t i = 0; i < m_values.size(); ++i) + { + for (std::size_t y = 0; y < 4; ++y) + *ptr++ = static_cast(std::clamp((*src)[y] * 0xFF, 0.f, 255.f)); + + *src++; + } + + return preview; +} + +PreviewValues PreviewValues::Resized(std::size_t newWidth, std::size_t newHeight) const +{ + PreviewValues resizedPreview(newWidth, newHeight); + + float xStep = 1.f / newWidth; + float yStep = 1.f / newHeight; + + for (std::size_t y = 0; y < newHeight; ++y) + { + for (std::size_t x = 0; x < newWidth; ++x) + resizedPreview(x, y) = Sample(x * xStep, y * yStep); + } + + return resizedPreview; +} + +Nz::Vector4f PreviewValues::Sample(float u, float v) const +{ + // Bilinear filtering + float x = std::clamp(u * m_width, 0.f, m_width - 1.f); + float y = std::clamp(v * m_height, 0.f, m_height - 1.f); + + std::size_t iX = static_cast(x); + std::size_t iY = static_cast(y); + + float dX = x - iX; + float dY = y - iY; + + auto ColorAt = [&](std::size_t x, std::size_t y) -> Nz::Vector4f + { + x = std::min(x, m_width - 1); + y = std::min(y, m_height - 1); + + return m_values[y * m_width + x]; + }; + + Nz::Vector4f d00 = ColorAt(iX, iY); + Nz::Vector4f d10 = ColorAt(iX + 1, iY); + Nz::Vector4f d01 = ColorAt(iX, iY + 1); + Nz::Vector4f d11 = ColorAt(iX + 1, iY + 1); + + return Nz::Lerp(Nz::Lerp(d00, d10, dX), Nz::Lerp(d01, d11, dX), dY); +} + +Nz::Vector4f& PreviewValues::operator()(std::size_t x, std::size_t y) +{ + assert(x < m_width); + assert(y < m_height); + return m_values[y * m_width + x]; +} + +Nz::Vector4f PreviewValues::operator()(std::size_t x, std::size_t y) const +{ + assert(x < m_width); + assert(y < m_height); + return m_values[y * m_width + x]; +} diff --git a/src/ShaderNode/Previews/PreviewValues.hpp b/src/ShaderNode/Previews/PreviewValues.hpp new file mode 100644 index 000000000..47ce14680 --- /dev/null +++ b/src/ShaderNode/Previews/PreviewValues.hpp @@ -0,0 +1,50 @@ +#pragma once + +#ifndef NAZARA_SHADERNODES_PREVIEWVALUES_HPP +#define NAZARA_SHADERNODES_PREVIEWVALUES_HPP + +#include +#include +#include +#include +#include + +class QImage; + +class PreviewValues +{ + public: + PreviewValues(); + PreviewValues(std::size_t width, std::size_t height); + PreviewValues(const PreviewValues&) = default; + PreviewValues(PreviewValues&&) = default; + ~PreviewValues() = default; + + void Fill(const Nz::Vector4f& value); + + QImage GenerateImage() const; + + inline Nz::Vector4f* GetData(); + inline const Nz::Vector4f* GetData() const; + inline std::size_t GetHeight() const; + inline std::size_t GetWidth() const; + + PreviewValues Resized(std::size_t newWidth, std::size_t newHeight) const; + + Nz::Vector4f Sample(float u, float v) const; + + Nz::Vector4f& operator()(std::size_t x, std::size_t y); + Nz::Vector4f operator()(std::size_t x, std::size_t y) const; + + PreviewValues& operator=(const PreviewValues&) = default; + PreviewValues& operator=(PreviewValues&&) = default; + + private: + std::size_t m_height; + std::size_t m_width; + std::vector m_values; +}; + +#include + +#endif diff --git a/src/ShaderNode/Previews/PreviewValues.inl b/src/ShaderNode/Previews/PreviewValues.inl new file mode 100644 index 000000000..06ca202ec --- /dev/null +++ b/src/ShaderNode/Previews/PreviewValues.inl @@ -0,0 +1,21 @@ +#include + +inline Nz::Vector4f* PreviewValues::GetData() +{ + return m_values.data(); +} + +inline const Nz::Vector4f* PreviewValues::GetData() const +{ + return m_values.data(); +} + +inline std::size_t PreviewValues::GetHeight() const +{ + return m_width; +} + +inline std::size_t PreviewValues::GetWidth() const +{ + return m_height; +} diff --git a/src/ShaderNode/Previews/QuadPreview.cpp b/src/ShaderNode/Previews/QuadPreview.cpp index ef064417d..a4edc9267 100644 --- a/src/ShaderNode/Previews/QuadPreview.cpp +++ b/src/ShaderNode/Previews/QuadPreview.cpp @@ -1,27 +1,22 @@ #include #include -QImage QuadPreview::GetImage(InputRole role, std::size_t roleIndex) const +PreviewValues QuadPreview::GetPreview(InputRole role, std::size_t roleIndex) const { if (role != InputRole::TexCoord) { - QImage dummy(1, 1, QImage::Format_RGBA8888); - dummy.fill(QColor::fromRgb(0, 0, 0, 0)); + PreviewValues dummy(1, 1); + dummy(0, 0) = Nz::Vector4f::Zero(); + return dummy; } - QImage uv(128, 128, QImage::Format_RGBA8888); + PreviewValues uv(128, 128); - std::uint8_t* content = uv.bits(); for (std::size_t y = 0; y < 128; ++y) { for (std::size_t x = 0; x < 128; ++x) - { - *content++ = (x * 255) / 128; - *content++ = (y * 255) / 128; - *content++ = 0; - *content++ = 255; - } + uv(x, y) = Nz::Vector4f(x / 128.f, y / 128.f, 0.f, 1.f); } return uv; diff --git a/src/ShaderNode/Previews/QuadPreview.hpp b/src/ShaderNode/Previews/QuadPreview.hpp index 6c980ae34..947b4d637 100644 --- a/src/ShaderNode/Previews/QuadPreview.hpp +++ b/src/ShaderNode/Previews/QuadPreview.hpp @@ -4,7 +4,7 @@ #define NAZARA_SHADERNODES_QUADPREVIEW_HPP #include -#include +#include class QuadPreview : public PreviewModel { @@ -12,7 +12,7 @@ class QuadPreview : public PreviewModel QuadPreview() = default; ~QuadPreview() = default; - QImage GetImage(InputRole role, std::size_t roleIndex) const override; + PreviewValues GetPreview(InputRole role, std::size_t roleIndex) const override; }; #include