mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-06-13 14:36:32 -04:00
Refactor shadow handling & improve connected chrome rendering
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
// (an inverted rounded rectangle) smooth-unioned with each active chrome
|
||||
// (popout/modal, dock, notification). The smooth-min radius IS the connector
|
||||
// fillet. Antialiasing is analytic via fwidth -> crisp at any scale, no FBO.
|
||||
// The elevation shadow samples the same field at the light offset, so both
|
||||
// elevation states render in this one pass.
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
@@ -16,19 +18,27 @@ layout(std140, binding = 0) uniform buf {
|
||||
float cutoutRadius;
|
||||
vec4 cutout; // inner cutout edges in px: x=left y=top z=right w=bottom
|
||||
vec4 surfaceColor; // straight (non-premultiplied) rgba
|
||||
// Up to four chrome slots. rect = x,y,w,h (px). corner = per-corner radii
|
||||
// (topLeft, topRight, bottomRight, bottomLeft). param = connectorR, active, 0, 0
|
||||
vec4 shadowColor; // straight rgba; a = 0 disables both shadow terms
|
||||
vec4 shadowParam; // key: x = blur px, y = spread px, z,w = offset px
|
||||
vec4 ambientParam; // ambient: x = blur px, y = spread px, z = alpha
|
||||
// Up to four chrome slots. rect = x,y,w,h (px). corner = per-corner radii,
|
||||
// k = per-corner junction fillet radii (both topLeft, topRight, bottomRight,
|
||||
// bottomLeft; a corner is sharp exactly where its k > 0). param = active, 0, 0, 0
|
||||
vec4 chromeRect0;
|
||||
vec4 chromeCorner0;
|
||||
vec4 chromeK0;
|
||||
vec4 chromeParam0;
|
||||
vec4 chromeRect1;
|
||||
vec4 chromeCorner1;
|
||||
vec4 chromeK1;
|
||||
vec4 chromeParam1;
|
||||
vec4 chromeRect2;
|
||||
vec4 chromeCorner2;
|
||||
vec4 chromeK2;
|
||||
vec4 chromeParam2;
|
||||
vec4 chromeRect3;
|
||||
vec4 chromeCorner3;
|
||||
vec4 chromeK3;
|
||||
vec4 chromeParam3;
|
||||
} ubuf;
|
||||
|
||||
@@ -64,9 +74,13 @@ float chromeDist(vec2 px, vec4 rect, vec4 corner) {
|
||||
return sdRoundBox4(px, c, rect.zw * 0.5, corner);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 px = qt_TexCoord0 * vec2(ubuf.widthPx, ubuf.heightPx);
|
||||
// Per-corner junction fillet radius, selected by chrome-rect quadrant.
|
||||
float chromeK(vec2 px, vec4 rect, vec4 ks) {
|
||||
vec2 p = px - (rect.xy + rect.zw * 0.5);
|
||||
return (p.x >= 0.0) ? (p.y >= 0.0 ? ks.z : ks.y) : (p.y >= 0.0 ? ks.w : ks.x);
|
||||
}
|
||||
|
||||
float sceneDist(vec2 px) {
|
||||
// Frame ring: inside the screen rect AND outside the rounded cutout (hole).
|
||||
vec2 sc = vec2(ubuf.widthPx, ubuf.heightPx) * 0.5;
|
||||
float dOuter = sdBox(px, sc, sc);
|
||||
@@ -75,18 +89,35 @@ void main() {
|
||||
float dCut = sdRoundBox(px, cutC, cutH, ubuf.cutoutRadius);
|
||||
float d = max(dOuter, -dCut);
|
||||
|
||||
// Smooth-union the active chrome surfaces; smin radius = connector fillet.
|
||||
if (ubuf.chromeParam0.y > 0.5)
|
||||
d = smin(d, chromeDist(px, ubuf.chromeRect0, ubuf.chromeCorner0), ubuf.chromeParam0.x);
|
||||
if (ubuf.chromeParam1.y > 0.5)
|
||||
d = smin(d, chromeDist(px, ubuf.chromeRect1, ubuf.chromeCorner1), ubuf.chromeParam1.x);
|
||||
if (ubuf.chromeParam2.y > 0.5)
|
||||
d = smin(d, chromeDist(px, ubuf.chromeRect2, ubuf.chromeCorner2), ubuf.chromeParam2.x);
|
||||
if (ubuf.chromeParam3.y > 0.5)
|
||||
d = smin(d, chromeDist(px, ubuf.chromeRect3, ubuf.chromeCorner3), ubuf.chromeParam3.x);
|
||||
// Smooth-union the active chrome surfaces; smin radius = junction fillet.
|
||||
if (ubuf.chromeParam0.x > 0.5)
|
||||
d = smin(d, chromeDist(px, ubuf.chromeRect0, ubuf.chromeCorner0), chromeK(px, ubuf.chromeRect0, ubuf.chromeK0));
|
||||
if (ubuf.chromeParam1.x > 0.5)
|
||||
d = smin(d, chromeDist(px, ubuf.chromeRect1, ubuf.chromeCorner1), chromeK(px, ubuf.chromeRect1, ubuf.chromeK1));
|
||||
if (ubuf.chromeParam2.x > 0.5)
|
||||
d = smin(d, chromeDist(px, ubuf.chromeRect2, ubuf.chromeCorner2), chromeK(px, ubuf.chromeRect2, ubuf.chromeK2));
|
||||
if (ubuf.chromeParam3.x > 0.5)
|
||||
d = smin(d, chromeDist(px, ubuf.chromeRect3, ubuf.chromeCorner3), chromeK(px, ubuf.chromeRect3, ubuf.chromeK3));
|
||||
return d;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 px = qt_TexCoord0 * vec2(ubuf.widthPx, ubuf.heightPx);
|
||||
float d = sceneDist(px);
|
||||
float fw = max(fwidth(d), 1e-4);
|
||||
float cov = 1.0 - smoothstep(-fw, fw, d);
|
||||
float a = ubuf.surfaceColor.a * cov * ubuf.qt_Opacity;
|
||||
fragColor = vec4(ubuf.surfaceColor.rgb * a, a);
|
||||
// Opaque silhouette over shadow, then the surface alpha applied to the
|
||||
// whole result — matches the old flattened-FBO + group-opacity look.
|
||||
vec4 col = vec4(ubuf.surfaceColor.rgb, 1.0) * cov;
|
||||
if (ubuf.shadowColor.a > 0.0) {
|
||||
float dk = sceneDist(px - ubuf.shadowParam.zw) - ubuf.shadowParam.y;
|
||||
float bk = max(ubuf.shadowParam.x, fw);
|
||||
float covK = 1.0 - smoothstep(-bk, bk, dk);
|
||||
// Ambient wrap reuses the field already computed for the silhouette.
|
||||
float ba = max(ubuf.ambientParam.x, fw);
|
||||
float covA = 1.0 - smoothstep(-ba, ba, d - ubuf.ambientParam.y);
|
||||
float sh = 1.0 - (1.0 - covK * ubuf.shadowColor.a) * (1.0 - covA * ubuf.ambientParam.z);
|
||||
col += vec4(ubuf.shadowColor.rgb, 1.0) * (sh * (1.0 - col.a));
|
||||
}
|
||||
fragColor = col * (ubuf.surfaceColor.a * ubuf.qt_Opacity);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#version 450
|
||||
|
||||
// Popout-local connected chrome as a signed-distance field: the body rounded
|
||||
// rect smooth-unioned against the bar-edge half-plane, so the connector
|
||||
// fillets form analytically — the SDF twin of the old ConnectedShape +
|
||||
// ConnectedCorner + MultiEffect FBO. Key + ambient shadows sample the same
|
||||
// field; shadow is masked outside the silhouette.
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
float widthPx;
|
||||
float heightPx;
|
||||
vec4 surfaceColor; // straight (non-premultiplied) rgba
|
||||
vec4 shadowColor; // straight rgba; a = 0 disables both shadow terms
|
||||
vec4 shadowParam; // key: x = blur px, y = spread px, z,w = offset px
|
||||
vec4 ambientParam; // ambient: x = blur px, y = spread px, z = alpha
|
||||
vec4 bodyRect; // body rounded rect in item px: x, y, w, h
|
||||
vec4 cornerRadius; // topLeft, topRight, bottomRight, bottomLeft
|
||||
vec4 edgeParam; // x = bar side (0 top, 1 bottom, 2 left, 3 right), y = fillet k
|
||||
} ubuf;
|
||||
|
||||
// Per-corner rounded box. r = (topLeft, topRight, bottomRight, bottomLeft).
|
||||
float sdRoundBox4(vec2 p, vec2 c, vec2 hs, vec4 r) {
|
||||
p -= c;
|
||||
float rr = (p.x >= 0.0) ? (p.y >= 0.0 ? r.z : r.y) : (p.y >= 0.0 ? r.w : r.x);
|
||||
rr = min(rr, min(hs.x, hs.y));
|
||||
vec2 q = abs(p) - hs + rr;
|
||||
return min(max(q.x, q.y), 0.0) + length(max(q, vec2(0.0))) - rr;
|
||||
}
|
||||
|
||||
// Circular smooth-min: blends two SDFs with a fillet of radius k.
|
||||
float smin(float a, float b, float k) {
|
||||
if (k <= 0.0)
|
||||
return min(a, b);
|
||||
return max(k, min(a, b)) - length(max(vec2(k) - vec2(a, b), vec2(0.0)));
|
||||
}
|
||||
|
||||
float sceneDist(vec2 px) {
|
||||
// Bar edge as a half-plane whose interior lies off-item, on the bar's
|
||||
// side; only its fillet contribution is visible.
|
||||
float side = ubuf.edgeParam.x;
|
||||
float dEdge = side < 0.5 ? px.y
|
||||
: side < 1.5 ? (ubuf.heightPx - px.y)
|
||||
: side < 2.5 ? px.x
|
||||
: (ubuf.widthPx - px.x);
|
||||
vec2 hs = ubuf.bodyRect.zw * 0.5;
|
||||
float dBody = sdRoundBox4(px, ubuf.bodyRect.xy + hs, hs, ubuf.cornerRadius);
|
||||
return smin(dEdge, dBody, ubuf.edgeParam.y);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 px = qt_TexCoord0 * vec2(ubuf.widthPx, ubuf.heightPx);
|
||||
float d = sceneDist(px);
|
||||
float fw = max(fwidth(d), 1e-4);
|
||||
float cov = 1.0 - smoothstep(-fw, fw, d);
|
||||
vec4 col = vec4(ubuf.surfaceColor.rgb, 1.0) * cov;
|
||||
if (ubuf.shadowColor.a > 0.0) {
|
||||
float dk = sceneDist(px - ubuf.shadowParam.zw) - ubuf.shadowParam.y;
|
||||
float bk = max(ubuf.shadowParam.x, fw);
|
||||
float covK = 1.0 - smoothstep(-bk, bk, dk);
|
||||
float ba = max(ubuf.ambientParam.x, fw);
|
||||
float covA = 1.0 - smoothstep(-ba, ba, d - ubuf.ambientParam.y);
|
||||
float sh = 1.0 - (1.0 - covK * ubuf.shadowColor.a) * (1.0 - covA * ubuf.ambientParam.z);
|
||||
col += vec4(ubuf.shadowColor.rgb, 1.0) * (sh * (1.0 - col.a));
|
||||
}
|
||||
fragColor = col * (ubuf.surfaceColor.a * ubuf.qt_Opacity);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#version 450
|
||||
|
||||
// Standalone elevation surface as a signed-distance field: one quad draws the
|
||||
// rounded-rect fill, its border, and the M3 two-part shadow (directional key +
|
||||
// non-directional ambient) analytically — no FBO, no blur passes. The shadow
|
||||
// is masked to outside the silhouette, so translucent fills never get
|
||||
// interior darkening.
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
float widthPx;
|
||||
float heightPx;
|
||||
float borderWidth;
|
||||
vec4 rectPx; // rounded rect in item px: x, y, w, h
|
||||
vec4 cornerRadius; // topLeft, topRight, bottomRight, bottomLeft
|
||||
vec4 fillColor; // straight (non-premultiplied) rgba
|
||||
vec4 borderColor; // straight rgba
|
||||
vec4 shadowColor; // straight rgba; a = 0 disables both shadow terms
|
||||
vec4 shadowParam; // key: x = blur px, y = spread px, z,w = offset px
|
||||
vec4 ambientParam; // ambient: x = blur px, y = spread px, z = alpha
|
||||
} ubuf;
|
||||
|
||||
// Per-corner rounded box. r = (topLeft, topRight, bottomRight, bottomLeft).
|
||||
float sdRoundBox4(vec2 p, vec2 c, vec2 hs, vec4 r) {
|
||||
p -= c;
|
||||
float rr = (p.x >= 0.0) ? (p.y >= 0.0 ? r.z : r.y) : (p.y >= 0.0 ? r.w : r.x);
|
||||
rr = min(rr, min(hs.x, hs.y));
|
||||
vec2 q = abs(p) - hs + rr;
|
||||
return min(max(q.x, q.y), 0.0) + length(max(q, vec2(0.0))) - rr;
|
||||
}
|
||||
|
||||
float rectDist(vec2 px) {
|
||||
vec2 hs = ubuf.rectPx.zw * 0.5;
|
||||
return sdRoundBox4(px, ubuf.rectPx.xy + hs, hs, ubuf.cornerRadius);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 px = qt_TexCoord0 * vec2(ubuf.widthPx, ubuf.heightPx);
|
||||
float d = rectDist(px);
|
||||
float fw = max(fwidth(d), 1e-4);
|
||||
float cov = 1.0 - smoothstep(-fw, fw, d);
|
||||
// Qt Rectangle semantics: border band on the rim, fill inset inside it.
|
||||
float covInner = 1.0 - smoothstep(-fw, fw, d + ubuf.borderWidth);
|
||||
vec4 col = vec4(ubuf.fillColor.rgb, 1.0) * (ubuf.fillColor.a * covInner)
|
||||
+ vec4(ubuf.borderColor.rgb, 1.0) * (ubuf.borderColor.a * max(0.0, cov - covInner));
|
||||
if (ubuf.shadowColor.a > 0.0) {
|
||||
float dk = rectDist(px - ubuf.shadowParam.zw) - ubuf.shadowParam.y;
|
||||
float bk = max(ubuf.shadowParam.x, fw);
|
||||
float covK = 1.0 - smoothstep(-bk, bk, dk);
|
||||
float ba = max(ubuf.ambientParam.x, fw);
|
||||
float covA = 1.0 - smoothstep(-ba, ba, d - ubuf.ambientParam.y);
|
||||
float sh = 1.0 - (1.0 - covK * ubuf.shadowColor.a) * (1.0 - covA * ubuf.ambientParam.z);
|
||||
col += vec4(ubuf.shadowColor.rgb, 1.0) * (sh * (1.0 - cov));
|
||||
}
|
||||
fragColor = col * ubuf.qt_Opacity;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#version 450
|
||||
|
||||
// Frame perimeter ring as a signed-distance field: the window rectangle minus
|
||||
// a rounded-rectangle cutout. Antialiasing is analytic via fwidth -> crisp at
|
||||
// any scale, no FBO and no mask textures.
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
float widthPx;
|
||||
float heightPx;
|
||||
float cutoutRadius;
|
||||
vec4 cutout; // inner cutout edges in px: x=left y=top z=right w=bottom
|
||||
vec4 surfaceColor; // straight (non-premultiplied) rgba
|
||||
} ubuf;
|
||||
|
||||
float sdBox(vec2 p, vec2 c, vec2 hs) {
|
||||
vec2 q = abs(p - c) - hs;
|
||||
return min(max(q.x, q.y), 0.0) + length(max(q, vec2(0.0)));
|
||||
}
|
||||
|
||||
float sdRoundBox(vec2 p, vec2 c, vec2 hs, float r) {
|
||||
r = min(r, min(hs.x, hs.y));
|
||||
vec2 q = abs(p - c) - hs + r;
|
||||
return min(max(q.x, q.y), 0.0) + length(max(q, vec2(0.0))) - r;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 px = qt_TexCoord0 * vec2(ubuf.widthPx, ubuf.heightPx);
|
||||
vec2 sc = vec2(ubuf.widthPx, ubuf.heightPx) * 0.5;
|
||||
float dOuter = sdBox(px, sc, sc);
|
||||
vec2 cutC = vec2((ubuf.cutout.x + ubuf.cutout.z) * 0.5, (ubuf.cutout.y + ubuf.cutout.w) * 0.5);
|
||||
vec2 cutH = vec2((ubuf.cutout.z - ubuf.cutout.x) * 0.5, (ubuf.cutout.w - ubuf.cutout.y) * 0.5);
|
||||
float dCut = sdRoundBox(px, cutC, cutH, ubuf.cutoutRadius);
|
||||
float d = max(dOuter, -dCut);
|
||||
|
||||
float fw = max(fwidth(d), 1e-4);
|
||||
float cov = 1.0 - smoothstep(-fw, fw, d);
|
||||
float a = ubuf.surfaceColor.a * cov * ubuf.qt_Opacity;
|
||||
fragColor = vec4(ubuf.surfaceColor.rgb * a, a);
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user