improve performace of SDF
- Avoid fullscreen shading every pixel
- Evaluate each BlobRect: localized quad, only nearby rects, instead of all 8 rects
- O(1-3) per pixel for most passes, rather than O(N²) with N=8(~72 iterations).
- Closed panels excluded entirely from loop.
This commit is contained in:
parent
f6d7e40f35
commit
6103ce19e8
5 changed files with 139 additions and 21 deletions
|
|
@ -153,7 +153,6 @@ Variants {
|
|||
PanelBg {
|
||||
id: dashBg
|
||||
|
||||
group: blobGroup
|
||||
panel: panels.dashboard
|
||||
bar: bar
|
||||
deformAmount: 0.1
|
||||
|
|
@ -162,7 +161,6 @@ Variants {
|
|||
PanelBg {
|
||||
id: launcherBg
|
||||
|
||||
group: blobGroup
|
||||
panel: panels.launcher
|
||||
bar: bar
|
||||
deformAmount: 0.1
|
||||
|
|
@ -171,7 +169,6 @@ Variants {
|
|||
PanelBg {
|
||||
id: sessionBg
|
||||
|
||||
group: blobGroup
|
||||
panel: panels.session
|
||||
bar: bar
|
||||
deformAmount: 0.25
|
||||
|
|
@ -180,7 +177,6 @@ Variants {
|
|||
PanelBg {
|
||||
id: sidebarBg
|
||||
|
||||
group: blobGroup
|
||||
panel: panels.sidebar
|
||||
bar: bar
|
||||
deformAmount: 0
|
||||
|
|
@ -189,7 +185,6 @@ Variants {
|
|||
PanelBg {
|
||||
id: osdBg
|
||||
|
||||
group: blobGroup
|
||||
panel: panels.osd
|
||||
bar: bar
|
||||
deformAmount: 0.3
|
||||
|
|
@ -198,7 +193,6 @@ Variants {
|
|||
PanelBg {
|
||||
id: notifsBg
|
||||
|
||||
group: blobGroup
|
||||
panel: panels.notifications
|
||||
bar: bar
|
||||
}
|
||||
|
|
@ -206,7 +200,6 @@ Variants {
|
|||
PanelBg {
|
||||
id: utilsBg
|
||||
|
||||
group: blobGroup
|
||||
panel: panels.utilities
|
||||
bar: bar
|
||||
}
|
||||
|
|
@ -214,7 +207,6 @@ Variants {
|
|||
PanelBg {
|
||||
id: popoutBg
|
||||
|
||||
group: blobGroup
|
||||
panel: panels.popouts
|
||||
bar: bar
|
||||
|
||||
|
|
@ -306,6 +298,7 @@ Variants {
|
|||
required property Item bar
|
||||
property real deformAmount: 0.15
|
||||
|
||||
group: panel.width > 0 && panel.height > 0 ? blobGroup : null
|
||||
x: panel.x + bar.implicitWidth
|
||||
y: panel.y + Config.border.thickness
|
||||
implicitWidth: panel.width
|
||||
|
|
|
|||
|
|
@ -1,9 +1,126 @@
|
|||
#include "blobinvertedrect.hpp"
|
||||
#include "blobgroup.hpp"
|
||||
#include "blobmaterial.hpp"
|
||||
|
||||
#include <qsggeometry.h>
|
||||
#include <qsgnode.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
BlobInvertedRect::BlobInvertedRect(QQuickItem* parent)
|
||||
: BlobShape(parent) {}
|
||||
|
||||
static void setFrameIndices(quint16* idx) {
|
||||
// Top strip: 0-1-4, 1-5-4
|
||||
idx[0] = 0; idx[1] = 1; idx[2] = 4;
|
||||
idx[3] = 1; idx[4] = 5; idx[5] = 4;
|
||||
// Right strip: 1-2-5, 2-6-5
|
||||
idx[6] = 1; idx[7] = 2; idx[8] = 5;
|
||||
idx[9] = 2; idx[10] = 6; idx[11] = 5;
|
||||
// Bottom strip: 2-3-6, 3-7-6
|
||||
idx[12] = 2; idx[13] = 3; idx[14] = 6;
|
||||
idx[15] = 3; idx[16] = 7; idx[17] = 6;
|
||||
// Left strip: 3-0-7, 0-4-7
|
||||
idx[18] = 3; idx[19] = 0; idx[20] = 7;
|
||||
idx[21] = 0; idx[22] = 4; idx[23] = 7;
|
||||
}
|
||||
|
||||
QSGNode* BlobInvertedRect::updatePaintNode(
|
||||
QSGNode* oldNode, UpdatePaintNodeData*) {
|
||||
if (!m_group) {
|
||||
delete oldNode;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const float pad = static_cast<float>(m_group->smoothing());
|
||||
|
||||
// Compute inner hole boundary in local coords
|
||||
// Inset past the inner border edge by 2x smoothing to cover the blend zone
|
||||
const float inset = pad * 2.0f;
|
||||
const float holeLeft = static_cast<float>(m_borderLeft) + inset;
|
||||
const float holeTop = static_cast<float>(m_borderTop) + inset;
|
||||
const float holeRight = static_cast<float>(width() - m_borderRight) - inset;
|
||||
const float holeBot = static_cast<float>(height() - m_borderBottom) - inset;
|
||||
|
||||
// If the hole is too small or invalid, fall back to full quad
|
||||
if (holeLeft >= holeRight || holeTop >= holeBot)
|
||||
return BlobShape::updatePaintNode(oldNode, nullptr);
|
||||
|
||||
auto* node = static_cast<QSGGeometryNode*>(oldNode);
|
||||
|
||||
const bool needsRebuild = !node || node->geometry()->vertexCount() != 8;
|
||||
|
||||
if (needsRebuild) {
|
||||
delete oldNode;
|
||||
node = new QSGGeometryNode;
|
||||
|
||||
auto* geometry = new QSGGeometry(
|
||||
QSGGeometry::defaultAttributes_TexturedPoint2D(), 8, 24,
|
||||
QSGGeometry::UnsignedShortType);
|
||||
geometry->setDrawingMode(QSGGeometry::DrawTriangles);
|
||||
node->setGeometry(geometry);
|
||||
node->setFlag(QSGNode::OwnsGeometry);
|
||||
|
||||
setFrameIndices(geometry->indexDataAsUShort());
|
||||
|
||||
auto* material = new BlobMaterial;
|
||||
material->setFlag(QSGMaterial::Blending);
|
||||
node->setMaterial(material);
|
||||
node->setFlag(QSGNode::OwnsMaterial);
|
||||
}
|
||||
|
||||
// Outer bounds (local coords)
|
||||
const float x0 = static_cast<float>(m_localPaddedRect.x());
|
||||
const float y0 = static_cast<float>(m_localPaddedRect.y());
|
||||
const float x1 = x0 + static_cast<float>(m_localPaddedRect.width());
|
||||
const float y1 = y0 + static_cast<float>(m_localPaddedRect.height());
|
||||
const float w = x1 - x0;
|
||||
const float h = y1 - y0;
|
||||
|
||||
// Update vertex positions and texture coordinates
|
||||
auto* v = node->geometry()->vertexDataAsTexturedPoint2D();
|
||||
|
||||
// Outer corners
|
||||
v[0].set(x0, y0, 0.0f, 0.0f);
|
||||
v[1].set(x1, y0, 1.0f, 0.0f);
|
||||
v[2].set(x1, y1, 1.0f, 1.0f);
|
||||
v[3].set(x0, y1, 0.0f, 1.0f);
|
||||
// Inner corners (hole)
|
||||
v[4].set(holeLeft, holeTop, (holeLeft - x0) / w, (holeTop - y0) / h);
|
||||
v[5].set(holeRight, holeTop, (holeRight - x0) / w, (holeTop - y0) / h);
|
||||
v[6].set(holeRight, holeBot, (holeRight - x0) / w, (holeBot - y0) / h);
|
||||
v[7].set(holeLeft, holeBot, (holeLeft - x0) / w, (holeBot - y0) / h);
|
||||
|
||||
node->markDirty(QSGNode::DirtyGeometry);
|
||||
|
||||
// Update material uniforms
|
||||
auto* material = static_cast<BlobMaterial*>(node->material());
|
||||
material->m_paddedX = m_cachedPaddedX;
|
||||
material->m_paddedY = m_cachedPaddedY;
|
||||
material->m_paddedW = m_cachedPaddedW;
|
||||
material->m_paddedH = m_cachedPaddedH;
|
||||
material->m_smoothFactor = pad;
|
||||
material->m_myIndex = m_cachedMyIndex;
|
||||
material->m_color = m_group->color();
|
||||
material->m_hasInverted = m_cachedHasInverted ? 1 : 0;
|
||||
material->m_invertedRadius = m_cachedInvertedRadius;
|
||||
memcpy(material->m_invertedOuter, m_cachedInvertedOuter,
|
||||
sizeof(m_cachedInvertedOuter));
|
||||
memcpy(material->m_invertedInner, m_cachedInvertedInner,
|
||||
sizeof(m_cachedInvertedInner));
|
||||
|
||||
const int count =
|
||||
static_cast<int>(qMin(m_cachedRects.size(), qsizetype(16)));
|
||||
material->m_rectCount = count;
|
||||
for (int i = 0; i < count; ++i)
|
||||
material->m_rects[i] = m_cachedRects[i];
|
||||
|
||||
node->markDirty(QSGNode::DirtyMaterial);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
BlobInvertedRect::~BlobInvertedRect() {
|
||||
if (m_group)
|
||||
m_group->clearInvertedRect(this);
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ signals:
|
|||
protected:
|
||||
bool isInvertedRect() const override { return true; }
|
||||
|
||||
QSGNode* updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) override;
|
||||
|
||||
void registerWithGroup() override;
|
||||
void unregisterFromGroup() override;
|
||||
|
||||
|
|
|
|||
|
|
@ -102,10 +102,6 @@ void BlobShape::updatePolish() {
|
|||
// Ensure all shapes have up-to-date physics (only once per frame)
|
||||
m_group->ensurePhysicsUpdated();
|
||||
|
||||
// When inverted rect renders everything, skip spatial query for others
|
||||
if (!isInvertedRect() && m_group->invertedRect())
|
||||
return;
|
||||
|
||||
const QPointF scenePos = mapToScene(QPointF(0, 0));
|
||||
const float pad = static_cast<float>(m_group->smoothing());
|
||||
|
||||
|
|
@ -142,6 +138,10 @@ void BlobShape::updatePolish() {
|
|||
if (other->isInvertedRect())
|
||||
continue;
|
||||
|
||||
// Skip zero-size rects
|
||||
if (other->width() <= 0 || other->height() <= 0)
|
||||
continue;
|
||||
|
||||
const QPointF otherScene = other->mapToScene(QPointF(0, 0));
|
||||
|
||||
bool include = false;
|
||||
|
|
@ -299,12 +299,6 @@ QSGNode* BlobShape::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// When an inverted rect exists, it renders everything in a single pass
|
||||
if (!isInvertedRect() && m_group->invertedRect()) {
|
||||
delete oldNode;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* node = static_cast<QSGGeometryNode*>(oldNode);
|
||||
if (!node) {
|
||||
node = new QSGGeometryNode;
|
||||
|
|
|
|||
|
|
@ -85,6 +85,11 @@ void main() {
|
|||
// Offset center for asymmetric deformation
|
||||
vec2 center = rect.xy + props.yz;
|
||||
|
||||
// AABB early-out: skip rects far from this pixel
|
||||
vec2 extent = sh.xy + vec2(smoothFactor * 1.5);
|
||||
if (abs(pixel.x - center.x) > extent.x || abs(pixel.y - center.y) > extent.y)
|
||||
continue;
|
||||
|
||||
// Apply pre-computed inverse deformation to the evaluation point
|
||||
mat2 invDeform = mat2(invDm.xy, invDm.zw);
|
||||
vec2 transformedPixel = center + invDeform * (pixel - center);
|
||||
|
|
@ -157,6 +162,12 @@ void main() {
|
|||
vec2 jSh = rectData[j * 5 + 3].xy;
|
||||
vec2 jC = jR.xy + jP.yz;
|
||||
|
||||
// Skip non-adjacent rects
|
||||
float sinkRange = smoothFactor * 1.5;
|
||||
if (abs(center.x - jC.x) > iSh.x + jSh.x + sinkRange ||
|
||||
abs(center.y - jC.y) > iSh.y + jSh.y + sinkRange)
|
||||
continue;
|
||||
|
||||
// Penetration of j past i's edges (positive = past)
|
||||
float pT = (jC.y + jSh.y) - (center.y - iSh.y) - sinkOff;
|
||||
float pB = (center.y + iSh.y) - (jC.y - jSh.y) - sinkOff;
|
||||
|
|
@ -266,9 +277,10 @@ void main() {
|
|||
}
|
||||
}
|
||||
|
||||
// myIndex == -1: inverted rect renders everything (frame + blobs)
|
||||
// myIndex >= 0: individual rect renders only its owned pixels
|
||||
if (myIndex >= 0 && owner != myIndex)
|
||||
// Each renderer only outputs pixels it owns
|
||||
// myIndex == -1: inverted rect renders border-owned pixels
|
||||
// myIndex >= 0: individual rect renders its owned pixels
|
||||
if (owner != myIndex)
|
||||
discard;
|
||||
|
||||
float fw = fwidth(mergedSdf);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue