remove layer usage to reduce vram consumption

This commit is contained in:
2026-10-03 20:26:00 +02:00
parent fc672924d1
commit dc99d6677c
20 changed files with 1455 additions and 114 deletions
+43 -13
View File
@@ -19,6 +19,8 @@ layout(std140, binding = 0) uniform buf {
vec4 invertedOuter;
vec4 invertedInner;
vec4 rectData[80];
float shadowRadius;
vec4 shadowColor;
};
float sdRoundedBox(vec2 p, vec2 center, vec2 halfSize, float radius) {
@@ -63,9 +65,10 @@ float smaxSharpA(float a, float b, float k) {
void main() {
vec2 pixel = vec2(paddedX, paddedY) + qt_TexCoord0 * vec2(paddedW, paddedH);
// Phase 1: compute per-rect SDF, track owner. We can't smin yet because
// excluded pairs need to skip the smooth blend, which requires pairwise pass
// below.
// Phase 1: compute per-rect SDF, and track which rect owns the pixel for the
// per-shape path (BlobGroup). The single group draw (BlobGroup2) has no owner:
// myIndex stays -2, so the ownership test is skipped and this pass writes every
// pixel the quad covers. Excluded pairs still need the pairwise pass below.
float dArr[16];
int owner = -2;
float minDist = 1e10;
@@ -82,8 +85,10 @@ 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);
// AABB early-out: skip rects far from this pixel. The reach has to include the
// shadow, otherwise a rect that is only inside the shadow range would be
// skipped and its distance could not be used.
vec2 extent = sh.xy + vec2(smoothFactor * 1.5 + shadowRadius);
if (abs(pixel.x - center.x) > extent.x ||
abs(pixel.y - center.y) > extent.y) {
dArr[i] = 1e10;
@@ -251,14 +256,39 @@ void main() {
}
}
// Each renderer only outputs pixels it owns, but allow rendering
// blend zones to prevent gaps (mergedSdf < smoothFactor means in blend)
// myIndex == -1: inverted rect renders border-owned pixels
// myIndex >= 0: individual rect renders its owned pixels
if (owner != myIndex && mergedSdf > smoothFactor)
// A pixel this far from every rect cannot have a value, so it is not written.
// The one-unit margin keeps the outermost pixels of the quad out of the AA: their
// derivatives are undefined (the quad neighbour is outside the primitive), which
// is what drew a line along the coverage edge.
float reach = max(smoothFactor, shadowRadius);
if (mergedSdf > reach - 1.0)
discard;
float fw = fwidth(mergedSdf);
float alpha = 1.0 - smoothstep(-fw, fw, mergedSdf);
fragColor = vec4(color.rgb * alpha, alpha) * qt_Opacity;
// Only the owner writes a pixel, which is what makes the per-shape path look
// like one surface: qt_Opacity is applied once per pixel instead of once per
// overlapping draw. The single group draw has no owner (myIndex == -2), so the
// test is skipped and the value below is the only value a pixel can have.
if (myIndex >= -1 && owner != myIndex)
discard;
// Fixed-width AA: fwidth is capped at one unit, so a bad derivative near the quad
// boundary cannot make a wide edge.
float fw = min(fwidth(mergedSdf), 1.0);
float materialAlpha = 1.0 - smoothstep(-fw, fw, mergedSdf);
// Phase 2: the shadow, as a distance falloff from the merged surface. The
// quadratic reaches zero with zero slope at its outer edge, so that edge needs no
// AA of its own. Only the single group draw writes a shadow: in the per-shape
// path overlapping draws would darken the same area twice.
float shadowAlpha = 0.0;
if (shadowRadius > 0.0 && myIndex == -2) {
float t = clamp(mergedSdf / shadowRadius, 0.0, 1.0);
shadowAlpha = (1.0 - t) * (1.0 - t) * shadowColor.a;
}
// Material over shadow, premultiplied.
float totalAlpha = materialAlpha + shadowAlpha * (1.0 - materialAlpha);
vec3 rgb = color.rgb * materialAlpha
+ shadowColor.rgb * shadowAlpha * (1.0 - materialAlpha);
fragColor = vec4(rgb, totalAlpha) * qt_Opacity;
}