diff --git a/backend/src/glass/LiquidField.zig b/backend/src/glass/LiquidField.zig index fe9332052..145c4fd41 100644 --- a/backend/src/glass/LiquidField.zig +++ b/backend/src/glass/LiquidField.zig @@ -63,6 +63,12 @@ pub const Shape = struct { shapes: [max_shapes]Shape = undefined, len: usize = 0, +/// The place the glass belongs to: a view's card, rounded or square. Its outside is one more +/// shape the others run into, so a shape near its outline joins the edge by a neck, metaball-like, +/// and its outline cuts the glass, so none of it crosses. Never drawn on its own: only the shapes, +/// and their necks where they come near the edge. It takes the program's last shape slot, so a +/// field with it holds one shape fewer. +edge: ?Edge = null, /// Physical pixels: how far apart two shapes still bridge. 0 never joins. merge_px: f32 = 0, scale: f32 = 1, @@ -77,11 +83,45 @@ refraction: f32 = 1, /// It carries text — a dialog, a menu — and takes the window's colour as the opacity has it /// (`glass_look.forText`). text: bool = false, +/// The window's own material (`tint`, the window's base colour, translucent): its colour in place +/// of what is behind it, as see-through as that colour is, so the desktop shows through it as it +/// does through the window round a card. Glass that reads as the window's edge reaching into a +/// card. Its tint is kept over the published look, as `surface`'s is. +window: bool = false, +/// Drawn as over an opaque window wherever it is (`publishOpaqueWindow`): glass that must be glass +/// even where the window is see-through behind it, as a place's corner button over the explorer, +/// which is the window's own material. Off, it is as see-through there as the window is. +solid: bool = false, +/// Its tint and mix are its own, kept over the look the app publishes (`publishLook`): glass that +/// must read as part of a surface, as a place's corner at rest does its card's fill. +surface: bool = false, /// It is a lens over a picture of the caller's own (`drawPicture`): its middle the picture as it /// is, only the band along its edge glass (`glass_look.forLens`). lens: bool = false, +/// A drop's rim lit from the top right rather than the top left: lit along the other diagonal, +/// top right and bottom left, and shaded across top left and bottom right. The glass program's +/// only; the fallback without it (`liquid_glass`) keeps its light at the top left. For glass whose edges +/// that show face that way, as a piece in a place's top-right corner does — its arc down and to +/// the left, its cut up and to the right — where the usual light would leave both in shade. +light_across: bool = false, + +/// A place's outline (`edge`), physical: its rect and its corner radii, top-left, top-right, +/// bottom-right, bottom-left. +pub const Edge = struct { + rect: dvui.Rect.Physical, + radii: [4]f32 = @splat(0), + /// Cut by the outline with an edge of its own there, rather than joined to the outside: a + /// rim and a bend along the cut, as a piece of glass laid in the place, its edge against the + /// place's, bending what lies along it (a focus ring, the place's border). Joined, the glass + /// carries on past the outline as far as its light and bend go, and the cut shows neither. + cut: bool = false, +}; + +/// Pixels past its place's outline the outside of the place begins: `EDGE_GAP` in the program. +const edge_gap: f32 = 1; pub fn add(self: *LiquidField, shape: Shape) void { + if (self.len >= max_shapes - 1 and self.edge != null) return; if (self.len >= max_shapes) return; self.shapes[self.len] = shape; self.len += 1; @@ -91,7 +131,15 @@ pub fn add(self: *LiquidField, shape: Shape) void { pub fn bounds(self: *const LiquidField) dvui.Rect.Physical { var r: dvui.Rect.Physical = .{}; for (self.shapes[0..self.len], 0..) |s, i| r = if (i == 0) s.rect else r.unionWith(s.rect); - return r.outsetAll(self.merge_px * 0.25 + 1); + return self.withReach(r); +} + +/// `r`, some shapes' rect, with room for what joins them: the bridges between them, and with an +/// edge, the neck to it (as far as a shape can be from the outline and still join it, half the +/// merge width), kept inside the place. +fn withReach(self: *const LiquidField, r: dvui.Rect.Physical) dvui.Rect.Physical { + const e = self.edge orelse return r.outsetAll(self.merge_px * 0.25 + 1); + return r.outsetAll(self.merge_px * 0.5 + 1).intersect(e.rect.outsetAll(1)); } // ── Groups ────────────────────────────────────────────────────────────────────────────────────── @@ -209,7 +257,7 @@ pub fn pack(self: *const LiquidField, covered: dvui.Rect.Physical, has_sharp: bo .depths = .{ self.merge_px, liquid_glass.softness * rim, liquid_glass.depthPx(self.look(), rim), liquid_glass.falloff * glow }, .rim = .{ liquid_glass.refraction * rim * self.refraction, liquid_glass.clarity * @min(1, self.refraction), rim_line_width * s, @min(1, self.refraction) }, .tint = tint, - .face = .{ std.math.clamp(self.mix, 0, 1), std.math.clamp(self.lift, 0, 1), if (self.tint != null) 1 else 0, if (has_sharp) 1 else 0 }, + .face = .{ if (self.window) 2 else std.math.clamp(self.mix, 0, 1), std.math.clamp(self.lift, 0, 1), if (self.tint != null) 1 else 0, if (has_sharp) 1 else 0 }, .dither = .{ 1.0 / 255.0, 0, 0, 0 }, .shapes = undefined, }; @@ -223,6 +271,17 @@ pub fn pack(self: *const LiquidField, covered: dvui.Rect.Physical, has_sharp: bo .{ sh.blur, sh.lens, sh.light, if (sh.round) 1 else 0 }, }; } + if (self.edge) |e| { + // In the last slot, flagged 2: the program reads it there, whatever the groups. Its glass is + // the first shape's, where they meet. + const first: Shape = if (self.len > 0) self.shapes[0] else .{ .rect = e.rect }; + u.shapes[max_shapes - 1] = .{ + .{ e.rect.x + e.rect.w / 2, e.rect.y + e.rect.h / 2, e.rect.w / 2, e.rect.h / 2 }, + e.radii, + // 3: cut, with an edge of its own (`Edge.cut`); 2: joined to the outside. + .{ first.blur, first.lens, 0, if (e.cut) 3 else 2 }, + }; + } return u; } @@ -304,9 +363,12 @@ fn applyLook(self: *const LiquidField, u: *Uniforms, l: glass_look.InApp) void { u.backdrop[3] = l.bevel_cap * self.scale; u.rim[1] = l.clarity * bend_scale; u.rim[3] = l.rim; - u.face[0] = std.math.clamp(l.mix, 0, 1); - u.face[1] = std.math.clamp(l.lift, 0, 1); + if (!self.surface and !self.window) { + u.face[0] = std.math.clamp(l.mix, 0, 1); + u.face[1] = std.math.clamp(l.lift, 0, 1); + } for (u.shapes[0..self.len]) |*sh| sh[2][0] *= l.frost; + if (self.edge != null) u.shapes[max_shapes - 1][2][0] *= l.frost; } /// Whether `draw` would draw now: programs here, switched on, compiled. @@ -330,7 +392,9 @@ pub fn draw(self: *const LiquidField, frost: dvui.Texture, covered: dvui.Rect.Ph const groups = self.clusters(); var u = self.pack(covered, sharp != null, groups.order[0..self.len]); // The window behind the glass, published for this frame. - u.backdrop[0] = if (opaqueWindow()) 1 else 0; + // And the light turned (`light_across`): +2 on the same lane, so it holds on every look, + // published or not. + u.backdrop[0] = (if (opaqueWindow() or self.solid) @as(f32, 1) else 0) + (if (self.light_across) @as(f32, 2) else 0); // And the glass the sliders make of it this frame (`publishLook`). if (publishedLook()) |l| self.applyLook(&u, if (self.lens) glass_look.forLens(l) else if (self.text) glass_look.forText(l) else glass_look.forDrops(l)); const textures = [_]?*anyopaque{programs.handle(sharp)}; @@ -403,7 +467,8 @@ fn quads(self: *const LiquidField, groups: Clusters, glass: bool, frost: dvui.Te const n = groups.size[g]; var r = self.shapes[groups.order[first]].rect; for (groups.order[first..][0..n]) |i| r = r.unionWith(self.shapes[i].rect); - r = r.outsetAll(self.merge_px * 0.25 + 1); + r = self.withReach(r); + if (r.empty()) continue; const col: dvui.Color.PMA = .{ .r = if (glass) 255 else 0, .g = first, .b = n, .a = 255 }; const base: dvui.Vertex.Index = @intCast(4 * g); for ([_]dvui.Point.Physical{ r.topLeft(), r.topRight(), r.bottomRight(), r.bottomLeft() }) |p| { @@ -474,16 +539,58 @@ pub fn sample(self: *const LiquidField, p: dvui.Point.Physical) Sample { o2 = o; } } + // The place (`edge`): its outside one more shape, its outline cutting the coverage. + var in_place: f32 = -big; + var place_out: [2]f32 = .{ 0, 0 }; + const cut = if (self.edge) |e| e.cut else false; + if (self.edge) |e| { + const c: [2]f32 = .{ e.rect.x + e.rect.w / 2, e.rect.y + e.rect.h / 2 }; + const half: [2]f32 = .{ e.rect.w / 2, e.rect.h / 2 }; + const lim = @min(half[0], half[1]); + const radii: [4]f32 = .{ @min(e.radii[0], lim), @min(e.radii[1], lim), @min(e.radii[2], lim), @min(e.radii[3], lim) }; + var g: [2]f32 = undefined; + in_place = roundBox(.{ p.x - c[0], p.y - c[1] }, half, radii, &g); + place_out = g; + } + if (self.edge != null and !cut) { + const d = edge_gap - in_place; + const mat: [3]f32 = .{ m1[0], m1[1], 0 }; + if (d < d1) { + d2 = d1; + m2 = m1; + d1 = d; + m1 = mat; + } else if (d < d2) { + d2 = d; + m2 = mat; + } + const o: [2]f32 = .{ -place_out[0], -place_out[1] }; + if (d < f1) { + f2 = f1; + o2 = o1; + f1 = d; + o1 = o; + } else if (d < f2) { + f2 = d; + o2 = o; + } + } const k = @max(self.merge_px, 0.0001); var wm: f32 = 0; var wf: f32 = 0; const d = smin(d1, d2, k, &wm); - const f = smin(f1, f2, k, &wf); + var f = smin(f1, f2, k, &wf); + var out: [2]f32 = .{ std.math.lerp(o1[0], o2[0], wf), std.math.lerp(o1[1], o2[1], wf) }; + // Cut: where the place's outline is nearer than the shapes' own, the glass's edge is the cut. + if (cut and in_place > f) { + f = in_place; + out = place_out; + } const soft = @max(0, -f); return .{ - .d = d, - .coverage = std.math.clamp(0.5 - d, 0, 1), - .out = .{ .x = std.math.lerp(o1[0], o2[0], wf), .y = std.math.lerp(o1[1], o2[1], wf) }, + .d = @max(d, in_place), + .coverage = std.math.clamp(0.5 - @max(d, in_place), 0, 1), + .out = .{ .x = out[0], .y = out[1] }, .steep = @exp(-soft / liquid_glass.depthPx(self.look(), rim)), .blur = std.math.lerp(m1[0], m2[0], wm), .lens = std.math.lerp(m1[1], m2[1], wm), diff --git a/backend/src/glass/shaders/compiled/dxil/liquid_glass.fragment.dxil b/backend/src/glass/shaders/compiled/dxil/liquid_glass.fragment.dxil index 24e69dce5..081c06c55 100644 Binary files a/backend/src/glass/shaders/compiled/dxil/liquid_glass.fragment.dxil and b/backend/src/glass/shaders/compiled/dxil/liquid_glass.fragment.dxil differ diff --git a/backend/src/glass/shaders/compiled/glsl/liquid_glass.fragment.glsl b/backend/src/glass/shaders/compiled/glsl/liquid_glass.fragment.glsl index 3c3f45f42..a0b099fe2 100644 --- a/backend/src/glass/shaders/compiled/glsl/liquid_glass.fragment.glsl +++ b/backend/src/glass/shaders/compiled/glsl/liquid_glass.fragment.glsl @@ -12,191 +12,191 @@ layout(location = 0) out highp vec4 out_var_SV_Target0; void main() { - highp vec4 _678; + highp vec4 _853; do { - int _90 = int((vColor.y * 255.0) + 0.5); - int _95 = int((vColor.z * 255.0) + 0.5); - bool _111 = uData[5].y > 0.0; - highp float _113; - highp float _116; - highp vec2 _118; - highp vec2 _120; - highp vec4 _122; + int _96 = int((vColor.y * 255.0) + 0.5); + int _101 = int((vColor.z * 255.0) + 0.5); + bool _117 = uData[5].y > 0.0; + highp float _119; + highp vec2 _122; highp vec4 _124; - highp float _126; + highp vec2 _126; highp float _128; highp float _130; - highp float _132; - _113 = 1000000000.0; - _116 = 1000000000.0; - _118 = vec2(0.0); - _120 = vec2(0.0); - _122 = vec4(0.0); + highp vec4 _132; + highp float _134; + highp float _136; + highp float _138; + _119 = 1000000000.0; + _122 = vec2(0.0); _124 = vec4(0.0); - _126 = 1000000000.0; + _126 = vec2(0.0); _128 = 1000000000.0; _130 = 1000000000.0; - _132 = 1000000000.0; - highp float _117; - highp vec2 _121; + _132 = vec4(0.0); + _134 = 1000000000.0; + _136 = 1000000000.0; + _138 = 1000000000.0; + highp vec2 _127; + highp float _131; + highp vec4 _133; + highp float _137; + highp float _139; + highp float _120; + highp vec2 _123; highp vec4 _125; highp float _129; - highp float _133; - highp float _114; - highp vec2 _119; - highp vec4 _123; - highp float _127; - highp float _131; - int _134 = _90; + highp float _135; + int _140 = _96; for (;;) { - bool _143; - if (_134 < (_90 + _95)) + bool _149; + if (_140 < (_96 + _101)) { - _143 = _134 < 16; + _149 = _140 < 16; } else { - _143 = false; + _149 = false; } - if (_143) + if (_149) { - int _145 = 3 * _134; - int _146 = 7 + _145; - int _152 = _145 + 9; - highp vec2 _156 = vTextureCoord - uData[_146 * 1 + 0].xy; - highp float _160 = min(uData[_146 * 1 + 0].z, uData[_146 * 1 + 0].w); - highp vec4 _162 = min(uData[(_145 + 8) * 1 + 0], vec4(_160)); - highp float _163 = _156.x; - highp float _184; - if (_163 > 0.0) + int _151 = 3 * _140; + int _152 = 7 + _151; + int _158 = _151 + 9; + highp vec2 _162 = vTextureCoord - uData[_152 * 1 + 0].xy; + highp float _166 = min(uData[_152 * 1 + 0].z, uData[_152 * 1 + 0].w); + highp vec4 _168 = min(uData[(_151 + 8) * 1 + 0], vec4(_166)); + highp float _169 = _162.x; + highp float _190; + if (_169 > 0.0) { - highp float _175; - if (_156.y > 0.0) + highp float _181; + if (_162.y > 0.0) { - _175 = _162.z; + _181 = _168.z; } else { - _175 = _162.y; + _181 = _168.y; } - _184 = _175; + _190 = _181; } else { - highp float _183; - if (_156.y > 0.0) + highp float _189; + if (_162.y > 0.0) { - _183 = _162.w; + _189 = _168.w; } else { - _183 = _162.x; + _189 = _168.x; } - _184 = _183; + _190 = _189; } - highp vec2 _188 = (abs(_156) - uData[_146 * 1 + 0].zw) + vec2(_184); - highp float _190 = (_163 < 0.0) ? (-1.0) : 1.0; - highp float _193 = (_156.y < 0.0) ? (-1.0) : 1.0; - highp float _195 = _188.x; - bool _201; - if (_195 > 0.0) + highp vec2 _194 = (abs(_162) - uData[_152 * 1 + 0].zw) + vec2(_190); + highp float _196 = (_169 < 0.0) ? (-1.0) : 1.0; + highp float _199 = (_162.y < 0.0) ? (-1.0) : 1.0; + highp float _201 = _194.x; + bool _207; + if (_201 > 0.0) { - _201 = _188.y > 0.0; + _207 = _194.y > 0.0; } else { - _201 = false; + _207 = false; } - highp vec2 _215; - if (_201) + highp vec2 _221; + if (_207) { - _215 = normalize(_188) * vec2(_190, _193); + _221 = normalize(_194) * vec2(_196, _199); } else { - highp vec2 _214; - if (_195 > _188.y) + highp vec2 _220; + if (_201 > _194.y) { - _214 = vec2(_190, 0.0); + _220 = vec2(_196, 0.0); } else { - _214 = vec2(0.0, _193); + _220 = vec2(0.0, _199); } - _215 = _214; + _221 = _220; } - highp float _222 = (min(max(_195, _188.y), 0.0) + length(max(_188, vec2(0.0)))) - _184; - bool _223 = _222 < _132; - if (_223) + highp float _228 = (min(max(_201, _194.y), 0.0) + length(max(_194, vec2(0.0)))) - _190; + bool _229 = _228 < _136; + if (_229) { - _114 = _116; - _123 = _124; - _131 = _132; + _120 = _138; + _125 = _132; + _135 = _136; } else { - bool _227 = _222 < _130; - bvec4 _229 = bvec4(_227); - _114 = _227 ? _160 : _113; - _123 = vec4(_229.x ? uData[_152 * 1 + 0].x : _122.x, _229.y ? uData[_152 * 1 + 0].y : _122.y, _229.z ? uData[_152 * 1 + 0].z : _122.z, _229.w ? uData[_152 * 1 + 0].w : _122.w); - _131 = _227 ? _222 : _130; + bool _233 = _228 < _134; + bvec4 _235 = bvec4(_233); + _120 = _233 ? _166 : _119; + _125 = vec4(_235.x ? uData[_158 * 1 + 0].x : _124.x, _235.y ? uData[_158 * 1 + 0].y : _124.y, _235.z ? uData[_158 * 1 + 0].z : _124.z, _235.w ? uData[_158 * 1 + 0].w : _124.w); + _135 = _233 ? _228 : _134; } - _117 = _223 ? _160 : _116; - bvec4 _232 = bvec4(_223); - _125 = vec4(_232.x ? uData[_152 * 1 + 0].x : _124.x, _232.y ? uData[_152 * 1 + 0].y : _124.y, _232.z ? uData[_152 * 1 + 0].z : _124.z, _232.w ? uData[_152 * 1 + 0].w : _124.w); - _133 = _223 ? _222 : _132; - highp vec2 _277; - highp float _278; - if (uData[_152 * 1 + 0].w < 0.5) + bvec4 _238 = bvec4(_229); + _133 = vec4(_238.x ? uData[_158 * 1 + 0].x : _132.x, _238.y ? uData[_158 * 1 + 0].y : _132.y, _238.z ? uData[_158 * 1 + 0].z : _132.z, _238.w ? uData[_158 * 1 + 0].w : _132.w); + _137 = _229 ? _228 : _136; + _139 = _229 ? _166 : _138; + highp vec2 _283; + highp float _284; + if (uData[_158 * 1 + 0].w < 0.5) { - highp float _243 = (vTextureCoord.x - uData[_146 * 1 + 0].x) + uData[_146 * 1 + 0].z; - highp float _245 = (uData[_146 * 1 + 0].x + uData[_146 * 1 + 0].z) - vTextureCoord.x; - highp float _250 = (vTextureCoord.y - uData[_146 * 1 + 0].y) + uData[_146 * 1 + 0].w; - highp float _252 = (uData[_146 * 1 + 0].y + uData[_146 * 1 + 0].w) - vTextureCoord.y; - highp float _256 = min(min(_243, _245), min(_250, _252)); - highp vec4 _261 = exp((vec4(_256) - vec4(_243, _245, _250, _252)) / vec4(uData[1].y)); - highp float _262 = _261.x; - highp float _263 = _261.y; - highp float _265 = _261.z; - highp float _267 = _261.w; - highp float _268 = ((_262 + _263) + _265) + _267; - _277 = vec2(_263 - _262, _267 - _265) / vec2(_268); - _278 = (uData[1].y * log(_268)) - _256; + highp float _249 = (vTextureCoord.x - uData[_152 * 1 + 0].x) + uData[_152 * 1 + 0].z; + highp float _251 = (uData[_152 * 1 + 0].x + uData[_152 * 1 + 0].z) - vTextureCoord.x; + highp float _256 = (vTextureCoord.y - uData[_152 * 1 + 0].y) + uData[_152 * 1 + 0].w; + highp float _258 = (uData[_152 * 1 + 0].y + uData[_152 * 1 + 0].w) - vTextureCoord.y; + highp float _262 = min(min(_249, _251), min(_256, _258)); + highp vec4 _267 = exp((vec4(_262) - vec4(_249, _251, _256, _258)) / vec4(uData[1].y)); + highp float _268 = _267.x; + highp float _269 = _267.y; + highp float _271 = _267.z; + highp float _273 = _267.w; + highp float _274 = ((_268 + _269) + _271) + _273; + _283 = vec2(_269 - _268, _273 - _271) / vec2(_274); + _284 = (uData[1].y * log(_274)) - _262; } else { - _277 = _215; - _278 = _222; + _283 = _221; + _284 = _228; } - bool _279 = _278 < _128; - if (_279) + bool _285 = _284 < _130; + if (_285) { - _119 = _120; - _127 = _128; + _123 = _126; + _129 = _130; } else { - bool _283 = _278 < _126; - bvec2 _284 = bvec2(_283); - _119 = vec2(_284.x ? _277.x : _118.x, _284.y ? _277.y : _118.y); - _127 = _283 ? _278 : _126; + bool _289 = _284 < _128; + bvec2 _290 = bvec2(_289); + _123 = vec2(_290.x ? _283.x : _122.x, _290.y ? _283.y : _122.y); + _129 = _289 ? _284 : _128; } - bvec2 _287 = bvec2(_279); - _121 = vec2(_287.x ? _277.x : _120.x, _287.y ? _277.y : _120.y); - _129 = _279 ? _278 : _128; - _113 = _114; - _116 = _117; - _118 = _119; - _120 = _121; + bvec2 _293 = bvec2(_285); + _127 = vec2(_293.x ? _283.x : _126.x, _293.y ? _283.y : _126.y); + _131 = _285 ? _284 : _130; + _119 = _120; _122 = _123; _124 = _125; _126 = _127; _128 = _129; _130 = _131; _132 = _133; - _134++; + _134 = _135; + _136 = _137; + _138 = _139; + _140++; continue; } else @@ -204,274 +204,477 @@ void main() break; } } - highp float _289 = max(uData[1].x, 9.9999997473787516355514526367188e-05); - highp float _294 = max(_289 - abs(_132 - _130), 0.0) / _289; - highp float _295 = _294 * _294; - highp float _296 = _295 * 0.5; - highp float _301; - if (_130 < _132) + bool _297 = uData[54].w > 2.5; + bool _298 = uData[54].w > 1.5; + highp float _373; + highp vec2 _374; + if (_298) + { + highp vec2 _306 = vTextureCoord - uData[52].xy; + highp vec4 _312 = min(uData[53], vec4(min(uData[52].z, uData[52].w))); + highp float _313 = _306.x; + highp float _334; + if (_313 > 0.0) + { + highp float _325; + if (_306.y > 0.0) + { + _325 = _312.z; + } + else + { + _325 = _312.y; + } + _334 = _325; + } + else + { + highp float _333; + if (_306.y > 0.0) + { + _333 = _312.w; + } + else + { + _333 = _312.x; + } + _334 = _333; + } + highp vec2 _338 = (abs(_306) - uData[52].zw) + vec2(_334); + highp float _340 = (_313 < 0.0) ? (-1.0) : 1.0; + highp float _343 = (_306.y < 0.0) ? (-1.0) : 1.0; + highp float _345 = _338.x; + bool _351; + if (_345 > 0.0) + { + _351 = _338.y > 0.0; + } + else + { + _351 = false; + } + highp vec2 _365; + if (_351) + { + _365 = normalize(_338) * vec2(_340, _343); + } + else + { + highp vec2 _364; + if (_345 > _338.y) + { + _364 = vec2(_340, 0.0); + } + else + { + _364 = vec2(0.0, _343); + } + _365 = _364; + } + _373 = (min(max(_345, _338.y), 0.0) + length(max(_338, vec2(0.0)))) - _334; + _374 = _365; + } + else { - _301 = 1.0 - _296; + _373 = -1000000000.0; + _374 = vec2(0.0); + } + bool _378; + if (_298) + { + _378 = !_297; } else { - _301 = _296; + _378 = false; + } + highp float _411; + highp vec2 _412; + highp vec2 _413; + highp vec4 _414; + highp vec4 _415; + highp float _416; + highp float _417; + highp float _418; + highp float _419; + if (_378) + { + highp float _381 = 1.0 - _373; + bool _382 = _381 < _136; + highp float _391; + highp vec4 _392; + highp float _393; + if (_382) + { + _391 = _138; + _392 = _132; + _393 = _136; + } + else + { + bool _386 = _381 < _134; + bvec4 _388 = bvec4(_386); + _391 = _386 ? _138 : _119; + _392 = vec4(_388.x ? uData[54].x : _124.x, _388.y ? uData[54].y : _124.y, _388.z ? uData[54].z : _124.z, _388.w ? uData[54].w : _124.w); + _393 = _386 ? _381 : _134; + } + bvec4 _394 = bvec4(_382); + highp vec2 _397 = -_374; + bool _398 = _381 < _130; + highp vec2 _406; + highp float _407; + if (_398) + { + _406 = _126; + _407 = _130; + } + else + { + bool _402 = _381 < _128; + bvec2 _403 = bvec2(_402); + _406 = vec2(_403.x ? _397.x : _122.x, _403.y ? _397.y : _122.y); + _407 = _402 ? _381 : _128; + } + bvec2 _408 = bvec2(_398); + _411 = _391; + _412 = _406; + _413 = vec2(_408.x ? _397.x : _126.x, _408.y ? _397.y : _126.y); + _414 = _392; + _415 = vec4(_394.x ? uData[54].x : _132.x, _394.y ? uData[54].y : _132.y, _394.z ? uData[54].z : _132.z, _394.w ? uData[54].w : _132.w); + _416 = _407; + _417 = _398 ? _381 : _130; + _418 = _393; + _419 = _382 ? _381 : _136; } - highp float _305 = min(_132, _130) - ((_295 * _289) * 0.25); - highp float _310 = max(_289 - abs(_128 - _126), 0.0) / _289; - highp float _311 = _310 * _310; - highp float _312 = _311 * 0.5; - highp float _317; - if (_126 < _128) + else { - _317 = 1.0 - _312; + _411 = _119; + _412 = _122; + _413 = _126; + _414 = _124; + _415 = _132; + _416 = _128; + _417 = _130; + _418 = _134; + _419 = _136; + } + highp float _421 = max(uData[1].x, 9.9999997473787516355514526367188e-05); + highp float _426 = max(_421 - abs(_419 - _418), 0.0) / _421; + highp float _427 = _426 * _426; + highp float _428 = _427 * 0.5; + highp float _433; + if (_418 < _419) + { + _433 = 1.0 - _428; } else { - _317 = _312; + _433 = _428; } - highp float _323 = clamp(0.5 - _305, 0.0, 1.0); - if (_323 <= 0.0) + highp float _437 = min(_419, _418) - ((_427 * _421) * 0.25); + highp float _442 = max(_421 - abs(_417 - _416), 0.0) / _421; + highp float _443 = _442 * _442; + highp float _444 = _443 * 0.5; + highp float _449; + if (_416 < _417) + { + _449 = 1.0 - _444; + } + else + { + _449 = _444; + } + highp float _453 = min(_417, _416) - ((_443 * _421) * 0.25); + highp float _457; + if (_297) + { + _457 = max(_437, _373); + } + else + { + _457 = _437; + } + highp float _460 = clamp(0.5 - max(_457, _373), 0.0, 1.0); + if (_460 <= 0.0) { discard; } if (vColor.x < 0.5) { - _678 = vec4(0.0, 0.0, 0.0, _323); + _853 = vec4(0.0, 0.0, 0.0, _460); break; } - highp vec4 _334 = mix(_124, _122, vec4(_301)); - highp vec2 _336 = mix(_120, _118, vec2(_317)); - highp float _338 = max(0.0, -(min(_128, _126) - ((_311 * _289) * 0.25))); - highp float _339 = -_338; - highp float _342 = exp(_339 / uData[1].z); - highp float _348 = _334.y; - highp float _382; - highp float _383; - highp vec2 _384; - if (_111) - { - highp float _356 = max(min(uData[5].y * mix(_116, _113, _301), uData[6].w), 1.0); - highp float _359 = clamp(1.0 - (_338 / _356), 0.0, 1.0); - highp float _364 = (((uData[5].z * _356) * _348) * _359) * _359; - _382 = _359; - _383 = _364; - _384 = clamp(((vTextureCoord - (_336 * _364)) - uData[0].xy) * uData[0].zw, vec2(0.0), vec2(1.0)); + highp vec4 _471 = mix(_415, _414, vec4(_433)); + highp vec2 _473 = mix(_413, _412, vec2(_449)); + bool _477; + if (_297) + { + _477 = _373 > _453; + } + else + { + _477 = false; + } + bvec2 _478 = bvec2(_477); + highp vec2 _479 = vec2(_478.x ? _374.x : _473.x, _478.y ? _374.y : _473.y); + highp float _482 = max(0.0, -(_477 ? _373 : _453)); + highp float _483 = -_482; + highp float _486 = exp(_483 / uData[1].z); + highp float _492 = _471.y; + highp float _526; + highp float _527; + highp vec2 _528; + if (_117) + { + highp float _500 = max(min(uData[5].y * mix(_138, _411, _433), uData[6].w), 1.0); + highp float _503 = clamp(1.0 - (_482 / _500), 0.0, 1.0); + highp float _508 = (((uData[5].z * _500) * _492) * _503) * _503; + _526 = _503; + _527 = _508; + _528 = clamp(((vTextureCoord - (_479 * _508)) - uData[0].xy) * uData[0].zw, vec2(0.0), vec2(1.0)); } else { - _382 = 0.0; - _383 = 0.0; - _384 = clamp(((vTextureCoord + (_336 * ((uData[2].x * _348) * _342))) - uData[0].xy) * uData[0].zw, vec2(0.0), vec2(1.0)); + _526 = 0.0; + _527 = 0.0; + _528 = clamp(((vTextureCoord + (_479 * ((uData[2].x * _492) * _486))) - uData[0].xy) * uData[0].zw, vec2(0.0), vec2(1.0)); } - highp vec4 _388 = textureLod(uSampler, _384, 0.0); - bool _390 = uData[4].w > 0.5; - highp vec4 _398; - if (_390) + highp vec4 _532 = textureLod(uSampler, _528, 0.0); + bool _534 = uData[4].w > 0.5; + highp vec4 _542; + if (_534) { - _398 = textureLod(uTex1, _384, 0.0); + _542 = textureLod(uTex1, _528, 0.0); } else { - _398 = _388; + _542 = _532; } - bool _403; - if (_111) + bool _547; + if (_117) { - _403 = uData[6].y > 0.0; + _547 = uData[6].y > 0.0; } else { - _403 = false; + _547 = false; } - bool _407; - if (_403) + bool _551; + if (_547) { - _407 = _383 > 0.5; + _551 = _527 > 0.5; } else { - _407 = false; - } - highp vec4 _468; - highp vec4 _469; - if (_407) - { - highp vec2 _415 = (_336 * ((_383 * 0.039999999105930328369140625) * uData[6].y)) * uData[0].zw; - highp vec2 _417 = clamp(_384 + _415, vec2(0.0), vec2(1.0)); - highp vec2 _419 = clamp(_384 - _415, vec2(0.0), vec2(1.0)); - highp vec4 _423 = textureLod(uSampler, _417, 0.0); - highp float _428 = _388.w; - highp float _429 = (_423.x / max(_423.w, 9.9999997473787516355514526367188e-05)) * _428; - highp vec4 _430 = _388; - _430.x = _429; - highp vec4 _434 = textureLod(uSampler, _419, 0.0); - highp float _439 = (_434.z / max(_434.w, 9.9999997473787516355514526367188e-05)) * _428; - _430.z = _439; - highp vec4 _467; - if (_390) + _551 = false; + } + highp vec4 _612; + highp vec4 _613; + if (_551) + { + highp vec2 _559 = (_479 * ((_527 * 0.039999999105930328369140625) * uData[6].y)) * uData[0].zw; + highp vec2 _561 = clamp(_528 + _559, vec2(0.0), vec2(1.0)); + highp vec2 _563 = clamp(_528 - _559, vec2(0.0), vec2(1.0)); + highp vec4 _567 = textureLod(uSampler, _561, 0.0); + highp float _572 = _532.w; + highp float _573 = (_567.x / max(_567.w, 9.9999997473787516355514526367188e-05)) * _572; + highp vec4 _574 = _532; + _574.x = _573; + highp vec4 _578 = textureLod(uSampler, _563, 0.0); + highp float _583 = (_578.z / max(_578.w, 9.9999997473787516355514526367188e-05)) * _572; + _574.z = _583; + highp vec4 _611; + if (_534) { - highp vec4 _447 = textureLod(uTex1, _417, 0.0); - highp vec4 _454 = _398; - _454.x = (_447.x / max(_447.w, 9.9999997473787516355514526367188e-05)) * _398.w; - highp vec4 _458 = textureLod(uTex1, _419, 0.0); - _454.z = (_458.z / max(_458.w, 9.9999997473787516355514526367188e-05)) * _398.w; - _467 = _454; + highp vec4 _591 = textureLod(uTex1, _561, 0.0); + highp vec4 _598 = _542; + _598.x = (_591.x / max(_591.w, 9.9999997473787516355514526367188e-05)) * _542.w; + highp vec4 _602 = textureLod(uTex1, _563, 0.0); + _598.z = (_602.z / max(_602.w, 9.9999997473787516355514526367188e-05)) * _542.w; + _611 = _598; } else { - highp vec4 _465 = _398; - _465.x = _429; - _465.z = _439; - _467 = _465; + highp vec4 _609 = _542; + _609.x = _573; + _609.z = _583; + _611 = _609; } - _468 = _467; - _469 = _430; + _612 = _611; + _613 = _574; } else { - _468 = _398; - _469 = _388; + _612 = _542; + _613 = _532; } - highp float _477; - if (uData[6].x > 0.5) + bool _615 = uData[4].x > 1.5; + highp float _629; + if (_615) { - _477 = 1.0; + _629 = uData[3].w; } else { - _477 = _469.w; + highp float _628; + if ((uData[6].x - 2.0 * trunc(uData[6].x / 2.0)) > 0.5) + { + _628 = 1.0; + } + else + { + _628 = _613.w; + } + _629 = _628; } - highp vec4 _486 = vec4(_469.xyz / vec3(max(_469.w, 9.9999997473787516355514526367188e-05)), 1.0); - highp vec4 _495 = vec4(_468.xyz / vec3(max(_468.w, 9.9999997473787516355514526367188e-05)), 1.0); - bool _497 = uData[4].z > 0.5; - highp float _502; - if (_497) + highp vec4 _638 = vec4(_613.xyz / vec3(max(_613.w, 9.9999997473787516355514526367188e-05)), 1.0); + highp vec4 _647 = vec4(_612.xyz / vec3(max(_612.w, 9.9999997473787516355514526367188e-05)), 1.0); + highp float _654; + if (_615) { - _502 = uData[4].x; + _654 = 1.0; } else { - _502 = 0.0; + _654 = (uData[4].z > 0.5) ? uData[4].x : 0.0; } - highp float _511; - if (_111) + bool _658; + if (_117) { - _511 = _502 * (1.0 - ((_382 * _382) * (1.0 - smoothstep(0.800000011920928955078125, 1.0, _502)))); + _658 = !_615; } else { - _511 = _502; + _658 = false; } - highp float _514 = 1.0 - _511; - highp float _522; - if (_111) + highp float _667; + if (_658) { - _522 = _382; + _667 = _654 * (1.0 - ((_526 * _526) * (1.0 - smoothstep(0.800000011920928955078125, 1.0, _654)))); } else { - _522 = _342 * _342; + _667 = _654; } - highp float _525 = clamp(((uData[2].y * _348) * _522) * _514, 0.0, 1.0); - highp vec4 _531 = ((_495 * _525) + ((mix(_495, _486, vec4(clamp(_334.x, 0.0, 1.0))) * _514) * (1.0 - _525))) + (uData[3] * _511); - highp float _536 = dot(_336, vec2(-0.707106769084930419921875)); - highp float _537 = max(_536, 0.0); - highp float _539 = max(-_536, 0.0); - highp float _542 = abs(_536); - bool _547; - if (_111) + highp float _670 = 1.0 - _667; + highp float _678; + if (_117) { - _547 = uData[6].z > 0.0; + _678 = _526; } else { - _547 = false; + _678 = _486 * _486; } - highp float _567; - if (_547) + highp float _681 = clamp(((uData[2].y * _492) * _678) * _670, 0.0, 1.0); + highp vec4 _687 = ((_647 * _681) + ((mix(_647, _638, vec4(clamp(_471.x, 0.0, 1.0))) * _670) * (1.0 - _681))) + (uData[3] * _667); + highp vec4 _704; + if (_615) + { + _704 = vec4(uData[3].xyz / vec3(max(uData[3].w, 9.9999997473787516355514526367188e-05)), 1.0); + } + else + { + _704 = _687 + (_638 * (1.0 - _687.w)); + } + bvec2 _707 = bvec2(uData[6].x > 1.5); + highp float _710 = dot(_479, vec2(_707.x ? vec2(0.707106769084930419921875, -0.707106769084930419921875).x : vec2(-0.707106769084930419921875).x, _707.y ? vec2(0.707106769084930419921875, -0.707106769084930419921875).y : vec2(-0.707106769084930419921875).y)); + highp float _711 = max(_710, 0.0); + highp float _713 = max(-_710, 0.0); + highp float _716 = abs(_710); + bool _720; + if (_117) + { + _720 = uData[6].z > 0.0; + } + else { - _567 = (uData[6].z * (1.0 - smoothstep(0.20000000298023223876953125, 0.699999988079071044921875, _542))) * exp((-max(0.0, -_305)) / (uData[2].z * 2.5)); + _720 = false; + } + highp float _739; + if (_720) + { + _739 = (uData[6].z * (1.0 - smoothstep(0.20000000298023223876953125, 0.699999988079071044921875, _716))) * exp((-max(0.0, -_457)) / (uData[2].z * 2.5)); } else { - _567 = 0.85000002384185791015625 * (1.0 - smoothstep(0.0, uData[2].z * 0.625, -_305)); + _739 = 0.85000002384185791015625 * (1.0 - smoothstep(0.0, uData[2].z * 0.625, -_457)); } - highp float _575; - if (_111) + highp float _749; + if (_117) { - _575 = max((uData[5].w * _382) * _382, _567); + _749 = max((uData[5].w * _526) * _526, _739) * min(_492, 1.0); } else { - _575 = 0.0; + _749 = 0.0; } - highp float _578 = _477 * (1.0 - _575); - highp vec4 _584 = vec4((_531 + (_486 * (1.0 - _531.w))).xyz * _578, _578 + _575); - highp float _603; - if (_111) + highp float _752 = _629 * (1.0 - _749); + highp vec4 _758 = vec4(_704.xyz * _752, _752 + _749); + highp float _776; + if (_117) { - highp float _594; - if (_547) + highp float _767; + if (_720) { - _594 = uData[6].z * smoothstep(0.75, 1.0, _542); + _767 = uData[6].z * smoothstep(0.75, 1.0, _716); } else { - _594 = 0.25; + _767 = 0.25; } - _603 = _594; + _776 = _767; } else { - _603 = (0.449999988079071044921875 * ((_537 * sqrt(_537)) + ((0.75 * _539) * sqrt(_539)))) + 0.0599999986588954925537109375; + _776 = (0.449999988079071044921875 * ((_711 * sqrt(_711)) + ((0.75 * _713) * sqrt(_713)))) + 0.0599999986588954925537109375; } - highp float _630; - if (_547) + highp float _803; + if (_720) { - _630 = exp((-max(0.0, -_305)) / (uData[2].z * 1.25)); + _803 = exp((-max(0.0, -_457)) / (uData[2].z * 1.25)); } else { - highp float _629; - if (_111) + highp float _802; + if (_117) { - highp float _617 = -_305; - _629 = smoothstep(uData[2].z * 0.3125, uData[2].z * 0.625, _617) * (1.0 - smoothstep(uData[2].z * 1.5, uData[2].z * 2.0, _617)); + highp float _790 = -_457; + _802 = smoothstep(uData[2].z * 0.3125, uData[2].z * 0.625, _790) * (1.0 - smoothstep(uData[2].z * 1.5, uData[2].z * 2.0, _790)); } else { - _629 = exp((-max(0.0, -_305)) / uData[2].z); + _802 = exp((-max(0.0, -_457)) / uData[2].z); } - _630 = _629; + _803 = _802; } - highp float _637; - if (_111) + highp float _810; + if (_117) { - _637 = 0.0; + _810 = 0.0; } else { - _637 = (0.039999999105930328369140625 * exp(_339 / uData[1].w)) * _537; + _810 = (0.039999999105930328369140625 * exp(_483 / uData[1].w)) * _711; } - highp float _643; - if (_497) + highp float _818; + if (uData[4].z > 0.5) { - _643 = uData[4].y; + _818 = uData[4].y; } else { - _643 = 0.0; + _818 = 0.0; } - highp vec3 _653 = _584.xyz + vec3(clamp((_643 + _334.z) + ((_348 * uData[2].w) * ((_630 * _603) + _637)), 0.0, 1.0)); - highp vec4 _655 = clamp(vec4(_653.x, _653.y, _653.z, _584.w), vec4(0.0), vec4(1.0)); - highp float _662 = max(_655.w, max(_655.x, max(_655.y, _655.z))); - highp vec4 _663 = _655; - _663.w = _662; - highp vec3 _674 = _663.xyz + vec3(((fract(52.98291778564453125 * fract(dot(vTextureCoord, vec2(0.067110560834407806396484375, 0.005837149918079376220703125)))) - 0.5) * uData[5].x) * _662); - _678 = clamp(vec4(_674.x, _674.y, _674.z, _663.w), vec4(0.0), vec4(1.0)) * _323; + highp vec3 _828 = _758.xyz + vec3(clamp((_818 + _471.z) + ((_492 * uData[2].w) * ((_803 * _776) + _810)), 0.0, 1.0)); + highp vec4 _830 = clamp(vec4(_828.x, _828.y, _828.z, _758.w), vec4(0.0), vec4(1.0)); + highp float _837 = max(_830.w, max(_830.x, max(_830.y, _830.z))); + highp vec4 _838 = _830; + _838.w = _837; + highp vec3 _849 = _838.xyz + vec3(((fract(52.98291778564453125 * fract(dot(vTextureCoord, vec2(0.067110560834407806396484375, 0.005837149918079376220703125)))) - 0.5) * uData[5].x) * _837); + _853 = clamp(vec4(_849.x, _849.y, _849.z, _838.w), vec4(0.0), vec4(1.0)) * _460; break; } while(false); - out_var_SV_Target0 = _678; + out_var_SV_Target0 = _853; } diff --git a/backend/src/glass/shaders/compiled/msl/liquid_glass.fragment.msl b/backend/src/glass/shaders/compiled/msl/liquid_glass.fragment.msl index bce3c888d..d3d722a4e 100644 --- a/backend/src/glass/shaders/compiled/msl/liquid_glass.fragment.msl +++ b/backend/src/glass/shaders/compiled/msl/liquid_glass.fragment.msl @@ -22,187 +22,187 @@ struct main0_in fragment main0_out main0(main0_in in [[stage_in]], constant type_Uniforms& Uniforms [[buffer(0)]], texture2d Frost [[texture(0)]], texture2d Sharp [[texture(1)]], sampler FrostSampler [[sampler(0)]], sampler SharpSampler [[sampler(1)]]) { main0_out out = {}; - float4 _678; + float4 _853; do { - int _90 = int((in.in_var_COLOR.y * 255.0) + 0.5); - int _95 = int((in.in_var_COLOR.z * 255.0) + 0.5); - bool _111 = Uniforms.uData[5].y > 0.0; - float _113; - float _116; - float2 _118; - float2 _120; - float4 _122; + int _96 = int((in.in_var_COLOR.y * 255.0) + 0.5); + int _101 = int((in.in_var_COLOR.z * 255.0) + 0.5); + bool _117 = Uniforms.uData[5].y > 0.0; + float _119; + float2 _122; float4 _124; - float _126; + float2 _126; float _128; float _130; - float _132; - _113 = 1000000000.0; - _116 = 1000000000.0; - _118 = float2(0.0); - _120 = float2(0.0); - _122 = float4(0.0); + float4 _132; + float _134; + float _136; + float _138; + _119 = 1000000000.0; + _122 = float2(0.0); _124 = float4(0.0); - _126 = 1000000000.0; + _126 = float2(0.0); _128 = 1000000000.0; _130 = 1000000000.0; - _132 = 1000000000.0; - float _117; - float2 _121; + _132 = float4(0.0); + _134 = 1000000000.0; + _136 = 1000000000.0; + _138 = 1000000000.0; + float2 _127; + float _131; + float4 _133; + float _137; + float _139; + float _120; + float2 _123; float4 _125; float _129; - float _133; - float _114; - float2 _119; - float4 _123; - float _127; - float _131; - int _134 = _90; + float _135; + int _140 = _96; for (;;) { - bool _143; - if (_134 < (_90 + _95)) + bool _149; + if (_140 < (_96 + _101)) { - _143 = _134 < 16; + _149 = _140 < 16; } else { - _143 = false; + _149 = false; } - if (_143) + if (_149) { - int _145 = 3 * _134; - int _146 = 7 + _145; - int _152 = _145 + 9; - float2 _156 = in.in_var_TEXCOORD0 - Uniforms.uData[_146].xy; - float _160 = precise::min(Uniforms.uData[_146].z, Uniforms.uData[_146].w); - float4 _162 = precise::min(Uniforms.uData[_145 + 8], float4(_160)); - float _163 = _156.x; - float _184; - if (_163 > 0.0) + int _151 = 3 * _140; + int _152 = 7 + _151; + int _158 = _151 + 9; + float2 _162 = in.in_var_TEXCOORD0 - Uniforms.uData[_152].xy; + float _166 = precise::min(Uniforms.uData[_152].z, Uniforms.uData[_152].w); + float4 _168 = precise::min(Uniforms.uData[_151 + 8], float4(_166)); + float _169 = _162.x; + float _190; + if (_169 > 0.0) { - float _175; - if (_156.y > 0.0) + float _181; + if (_162.y > 0.0) { - _175 = _162.z; + _181 = _168.z; } else { - _175 = _162.y; + _181 = _168.y; } - _184 = _175; + _190 = _181; } else { - float _183; - if (_156.y > 0.0) + float _189; + if (_162.y > 0.0) { - _183 = _162.w; + _189 = _168.w; } else { - _183 = _162.x; + _189 = _168.x; } - _184 = _183; + _190 = _189; } - float2 _188 = (abs(_156) - Uniforms.uData[_146].zw) + float2(_184); - float _190 = (_163 < 0.0) ? (-1.0) : 1.0; - float _193 = (_156.y < 0.0) ? (-1.0) : 1.0; - float _195 = _188.x; - bool _201; - if (_195 > 0.0) + float2 _194 = (abs(_162) - Uniforms.uData[_152].zw) + float2(_190); + float _196 = (_169 < 0.0) ? (-1.0) : 1.0; + float _199 = (_162.y < 0.0) ? (-1.0) : 1.0; + float _201 = _194.x; + bool _207; + if (_201 > 0.0) { - _201 = _188.y > 0.0; + _207 = _194.y > 0.0; } else { - _201 = false; + _207 = false; } - float2 _215; - if (_201) + float2 _221; + if (_207) { - _215 = fast::normalize(_188) * float2(_190, _193); + _221 = fast::normalize(_194) * float2(_196, _199); } else { - float2 _214; - if (_195 > _188.y) + float2 _220; + if (_201 > _194.y) { - _214 = float2(_190, 0.0); + _220 = float2(_196, 0.0); } else { - _214 = float2(0.0, _193); + _220 = float2(0.0, _199); } - _215 = _214; + _221 = _220; } - float _222 = (precise::min(precise::max(_195, _188.y), 0.0) + length(precise::max(_188, float2(0.0)))) - _184; - bool _223 = _222 < _132; - if (_223) + float _228 = (precise::min(precise::max(_201, _194.y), 0.0) + length(precise::max(_194, float2(0.0)))) - _190; + bool _229 = _228 < _136; + if (_229) { - _114 = _116; - _123 = _124; - _131 = _132; + _120 = _138; + _125 = _132; + _135 = _136; } else { - bool _227 = _222 < _130; - _114 = _227 ? _160 : _113; - _123 = select(_122, Uniforms.uData[_152], bool4(_227)); - _131 = _227 ? _222 : _130; + bool _233 = _228 < _134; + _120 = _233 ? _166 : _119; + _125 = select(_124, Uniforms.uData[_158], bool4(_233)); + _135 = _233 ? _228 : _134; } - _117 = _223 ? _160 : _116; - _125 = select(_124, Uniforms.uData[_152], bool4(_223)); - _133 = _223 ? _222 : _132; - float2 _277; - float _278; - if (Uniforms.uData[_152].w < 0.5) + _133 = select(_132, Uniforms.uData[_158], bool4(_229)); + _137 = _229 ? _228 : _136; + _139 = _229 ? _166 : _138; + float2 _283; + float _284; + if (Uniforms.uData[_158].w < 0.5) { - float _243 = (in.in_var_TEXCOORD0.x - Uniforms.uData[_146].x) + Uniforms.uData[_146].z; - float _245 = (Uniforms.uData[_146].x + Uniforms.uData[_146].z) - in.in_var_TEXCOORD0.x; - float _250 = (in.in_var_TEXCOORD0.y - Uniforms.uData[_146].y) + Uniforms.uData[_146].w; - float _252 = (Uniforms.uData[_146].y + Uniforms.uData[_146].w) - in.in_var_TEXCOORD0.y; - float _256 = precise::min(precise::min(_243, _245), precise::min(_250, _252)); - float4 _261 = exp((float4(_256) - float4(_243, _245, _250, _252)) / float4(Uniforms.uData[1].y)); - float _262 = _261.x; - float _263 = _261.y; - float _265 = _261.z; - float _267 = _261.w; - float _268 = ((_262 + _263) + _265) + _267; - _277 = float2(_263 - _262, _267 - _265) / float2(_268); - _278 = (Uniforms.uData[1].y * log(_268)) - _256; + float _249 = (in.in_var_TEXCOORD0.x - Uniforms.uData[_152].x) + Uniforms.uData[_152].z; + float _251 = (Uniforms.uData[_152].x + Uniforms.uData[_152].z) - in.in_var_TEXCOORD0.x; + float _256 = (in.in_var_TEXCOORD0.y - Uniforms.uData[_152].y) + Uniforms.uData[_152].w; + float _258 = (Uniforms.uData[_152].y + Uniforms.uData[_152].w) - in.in_var_TEXCOORD0.y; + float _262 = precise::min(precise::min(_249, _251), precise::min(_256, _258)); + float4 _267 = exp((float4(_262) - float4(_249, _251, _256, _258)) / float4(Uniforms.uData[1].y)); + float _268 = _267.x; + float _269 = _267.y; + float _271 = _267.z; + float _273 = _267.w; + float _274 = ((_268 + _269) + _271) + _273; + _283 = float2(_269 - _268, _273 - _271) / float2(_274); + _284 = (Uniforms.uData[1].y * log(_274)) - _262; } else { - _277 = _215; - _278 = _222; + _283 = _221; + _284 = _228; } - bool _279 = _278 < _128; - if (_279) + bool _285 = _284 < _130; + if (_285) { - _119 = _120; - _127 = _128; + _123 = _126; + _129 = _130; } else { - bool _283 = _278 < _126; - _119 = select(_118, _277, bool2(_283)); - _127 = _283 ? _278 : _126; + bool _289 = _284 < _128; + _123 = select(_122, _283, bool2(_289)); + _129 = _289 ? _284 : _128; } - _121 = select(_120, _277, bool2(_279)); - _129 = _279 ? _278 : _128; - _113 = _114; - _116 = _117; - _118 = _119; - _120 = _121; + _127 = select(_126, _283, bool2(_285)); + _131 = _285 ? _284 : _130; + _119 = _120; _122 = _123; _124 = _125; _126 = _127; _128 = _129; _130 = _131; _132 = _133; - _134++; + _134 = _135; + _136 = _137; + _138 = _139; + _140++; continue; } else @@ -210,275 +210,471 @@ fragment main0_out main0(main0_in in [[stage_in]], constant type_Uniforms& Unifo break; } } - float _289 = precise::max(Uniforms.uData[1].x, 9.9999997473787516355514526367188e-05); - float _294 = precise::max(_289 - abs(_132 - _130), 0.0) / _289; - float _295 = _294 * _294; - float _296 = _295 * 0.5; - float _301; - if (_130 < _132) + bool _297 = Uniforms.uData[54].w > 2.5; + bool _298 = Uniforms.uData[54].w > 1.5; + float _373; + float2 _374; + if (_298) + { + float2 _306 = in.in_var_TEXCOORD0 - Uniforms.uData[52].xy; + float4 _312 = precise::min(Uniforms.uData[53], float4(precise::min(Uniforms.uData[52].z, Uniforms.uData[52].w))); + float _313 = _306.x; + float _334; + if (_313 > 0.0) + { + float _325; + if (_306.y > 0.0) + { + _325 = _312.z; + } + else + { + _325 = _312.y; + } + _334 = _325; + } + else + { + float _333; + if (_306.y > 0.0) + { + _333 = _312.w; + } + else + { + _333 = _312.x; + } + _334 = _333; + } + float2 _338 = (abs(_306) - Uniforms.uData[52].zw) + float2(_334); + float _340 = (_313 < 0.0) ? (-1.0) : 1.0; + float _343 = (_306.y < 0.0) ? (-1.0) : 1.0; + float _345 = _338.x; + bool _351; + if (_345 > 0.0) + { + _351 = _338.y > 0.0; + } + else + { + _351 = false; + } + float2 _365; + if (_351) + { + _365 = fast::normalize(_338) * float2(_340, _343); + } + else + { + float2 _364; + if (_345 > _338.y) + { + _364 = float2(_340, 0.0); + } + else + { + _364 = float2(0.0, _343); + } + _365 = _364; + } + _373 = (precise::min(precise::max(_345, _338.y), 0.0) + length(precise::max(_338, float2(0.0)))) - _334; + _374 = _365; + } + else { - _301 = 1.0 - _296; + _373 = -1000000000.0; + _374 = float2(0.0); + } + bool _378; + if (_298) + { + _378 = !_297; } else { - _301 = _296; + _378 = false; + } + float _411; + float2 _412; + float2 _413; + float4 _414; + float4 _415; + float _416; + float _417; + float _418; + float _419; + if (_378) + { + float _381 = 1.0 - _373; + bool _382 = _381 < _136; + float _391; + float4 _392; + float _393; + if (_382) + { + _391 = _138; + _392 = _132; + _393 = _136; + } + else + { + bool _386 = _381 < _134; + _391 = _386 ? _138 : _119; + _392 = select(_124, Uniforms.uData[54], bool4(_386)); + _393 = _386 ? _381 : _134; + } + float2 _397 = -_374; + bool _398 = _381 < _130; + float2 _406; + float _407; + if (_398) + { + _406 = _126; + _407 = _130; + } + else + { + bool _402 = _381 < _128; + _406 = select(_122, _397, bool2(_402)); + _407 = _402 ? _381 : _128; + } + _411 = _391; + _412 = _406; + _413 = select(_126, _397, bool2(_398)); + _414 = _392; + _415 = select(_132, Uniforms.uData[54], bool4(_382)); + _416 = _407; + _417 = _398 ? _381 : _130; + _418 = _393; + _419 = _382 ? _381 : _136; } - float _305 = precise::min(_132, _130) - ((_295 * _289) * 0.25); - float _310 = precise::max(_289 - abs(_128 - _126), 0.0) / _289; - float _311 = _310 * _310; - float _312 = _311 * 0.5; - float _317; - if (_126 < _128) + else { - _317 = 1.0 - _312; + _411 = _119; + _412 = _122; + _413 = _126; + _414 = _124; + _415 = _132; + _416 = _128; + _417 = _130; + _418 = _134; + _419 = _136; + } + float _421 = precise::max(Uniforms.uData[1].x, 9.9999997473787516355514526367188e-05); + float _426 = precise::max(_421 - abs(_419 - _418), 0.0) / _421; + float _427 = _426 * _426; + float _428 = _427 * 0.5; + float _433; + if (_418 < _419) + { + _433 = 1.0 - _428; } else { - _317 = _312; + _433 = _428; } - float _323 = fast::clamp(0.5 - _305, 0.0, 1.0); - if (_323 <= 0.0) + float _437 = precise::min(_419, _418) - ((_427 * _421) * 0.25); + float _442 = precise::max(_421 - abs(_417 - _416), 0.0) / _421; + float _443 = _442 * _442; + float _444 = _443 * 0.5; + float _449; + if (_416 < _417) + { + _449 = 1.0 - _444; + } + else + { + _449 = _444; + } + float _453 = precise::min(_417, _416) - ((_443 * _421) * 0.25); + float _457; + if (_297) + { + _457 = precise::max(_437, _373); + } + else + { + _457 = _437; + } + float _460 = fast::clamp(0.5 - precise::max(_457, _373), 0.0, 1.0); + if (_460 <= 0.0) { discard_fragment(); } if (in.in_var_COLOR.x < 0.5) { - _678 = float4(0.0, 0.0, 0.0, _323); + _853 = float4(0.0, 0.0, 0.0, _460); break; } - float4 _334 = mix(_124, _122, float4(_301)); - float2 _336 = mix(_120, _118, float2(_317)); - float _338 = precise::max(0.0, -(precise::min(_128, _126) - ((_311 * _289) * 0.25))); - float _339 = -_338; - float _342 = exp(_339 / Uniforms.uData[1].z); - float _348 = _334.y; - float _382; - float _383; - float2 _384; - if (_111) - { - float _356 = precise::max(precise::min(Uniforms.uData[5].y * mix(_116, _113, _301), Uniforms.uData[6].w), 1.0); - float _359 = fast::clamp(1.0 - (_338 / _356), 0.0, 1.0); - float _364 = (((Uniforms.uData[5].z * _356) * _348) * _359) * _359; - _382 = _359; - _383 = _364; - _384 = fast::clamp(((in.in_var_TEXCOORD0 - (_336 * _364)) - Uniforms.uData[0].xy) * Uniforms.uData[0].zw, float2(0.0), float2(1.0)); + float4 _471 = mix(_415, _414, float4(_433)); + bool _477; + if (_297) + { + _477 = _373 > _453; + } + else + { + _477 = false; + } + float2 _479 = select(mix(_413, _412, float2(_449)), _374, bool2(_477)); + float _482 = precise::max(0.0, -(_477 ? _373 : _453)); + float _483 = -_482; + float _486 = exp(_483 / Uniforms.uData[1].z); + float _492 = _471.y; + float _526; + float _527; + float2 _528; + if (_117) + { + float _500 = precise::max(precise::min(Uniforms.uData[5].y * mix(_138, _411, _433), Uniforms.uData[6].w), 1.0); + float _503 = fast::clamp(1.0 - (_482 / _500), 0.0, 1.0); + float _508 = (((Uniforms.uData[5].z * _500) * _492) * _503) * _503; + _526 = _503; + _527 = _508; + _528 = fast::clamp(((in.in_var_TEXCOORD0 - (_479 * _508)) - Uniforms.uData[0].xy) * Uniforms.uData[0].zw, float2(0.0), float2(1.0)); } else { - _382 = 0.0; - _383 = 0.0; - _384 = fast::clamp(((in.in_var_TEXCOORD0 + (_336 * ((Uniforms.uData[2].x * _348) * _342))) - Uniforms.uData[0].xy) * Uniforms.uData[0].zw, float2(0.0), float2(1.0)); + _526 = 0.0; + _527 = 0.0; + _528 = fast::clamp(((in.in_var_TEXCOORD0 + (_479 * ((Uniforms.uData[2].x * _492) * _486))) - Uniforms.uData[0].xy) * Uniforms.uData[0].zw, float2(0.0), float2(1.0)); } - float4 _388 = Frost.sample(FrostSampler, _384, level(0.0)); - bool _390 = Uniforms.uData[4].w > 0.5; - float4 _398; - if (_390) + float4 _532 = Frost.sample(FrostSampler, _528, level(0.0)); + bool _534 = Uniforms.uData[4].w > 0.5; + float4 _542; + if (_534) { - _398 = Sharp.sample(SharpSampler, _384, level(0.0)); + _542 = Sharp.sample(SharpSampler, _528, level(0.0)); } else { - _398 = _388; + _542 = _532; } - bool _403; - if (_111) + bool _547; + if (_117) { - _403 = Uniforms.uData[6].y > 0.0; + _547 = Uniforms.uData[6].y > 0.0; } else { - _403 = false; + _547 = false; } - bool _407; - if (_403) + bool _551; + if (_547) { - _407 = _383 > 0.5; + _551 = _527 > 0.5; } else { - _407 = false; - } - float4 _468; - float4 _469; - if (_407) - { - float2 _415 = (_336 * ((_383 * 0.039999999105930328369140625) * Uniforms.uData[6].y)) * Uniforms.uData[0].zw; - float2 _417 = fast::clamp(_384 + _415, float2(0.0), float2(1.0)); - float2 _419 = fast::clamp(_384 - _415, float2(0.0), float2(1.0)); - float4 _423 = Frost.sample(FrostSampler, _417, level(0.0)); - float _428 = _388.w; - float _429 = (_423.x / precise::max(_423.w, 9.9999997473787516355514526367188e-05)) * _428; - float4 _430 = _388; - _430.x = _429; - float4 _434 = Frost.sample(FrostSampler, _419, level(0.0)); - float _439 = (_434.z / precise::max(_434.w, 9.9999997473787516355514526367188e-05)) * _428; - _430.z = _439; - float4 _467; - if (_390) + _551 = false; + } + float4 _612; + float4 _613; + if (_551) + { + float2 _559 = (_479 * ((_527 * 0.039999999105930328369140625) * Uniforms.uData[6].y)) * Uniforms.uData[0].zw; + float2 _561 = fast::clamp(_528 + _559, float2(0.0), float2(1.0)); + float2 _563 = fast::clamp(_528 - _559, float2(0.0), float2(1.0)); + float4 _567 = Frost.sample(FrostSampler, _561, level(0.0)); + float _572 = _532.w; + float _573 = (_567.x / precise::max(_567.w, 9.9999997473787516355514526367188e-05)) * _572; + float4 _574 = _532; + _574.x = _573; + float4 _578 = Frost.sample(FrostSampler, _563, level(0.0)); + float _583 = (_578.z / precise::max(_578.w, 9.9999997473787516355514526367188e-05)) * _572; + _574.z = _583; + float4 _611; + if (_534) { - float4 _447 = Sharp.sample(SharpSampler, _417, level(0.0)); - float4 _454 = _398; - _454.x = (_447.x / precise::max(_447.w, 9.9999997473787516355514526367188e-05)) * _398.w; - float4 _458 = Sharp.sample(SharpSampler, _419, level(0.0)); - _454.z = (_458.z / precise::max(_458.w, 9.9999997473787516355514526367188e-05)) * _398.w; - _467 = _454; + float4 _591 = Sharp.sample(SharpSampler, _561, level(0.0)); + float4 _598 = _542; + _598.x = (_591.x / precise::max(_591.w, 9.9999997473787516355514526367188e-05)) * _542.w; + float4 _602 = Sharp.sample(SharpSampler, _563, level(0.0)); + _598.z = (_602.z / precise::max(_602.w, 9.9999997473787516355514526367188e-05)) * _542.w; + _611 = _598; } else { - float4 _465 = _398; - _465.x = _429; - _465.z = _439; - _467 = _465; + float4 _609 = _542; + _609.x = _573; + _609.z = _583; + _611 = _609; } - _468 = _467; - _469 = _430; + _612 = _611; + _613 = _574; } else { - _468 = _398; - _469 = _388; + _612 = _542; + _613 = _532; } - float _477; - if (Uniforms.uData[6].x > 0.5) + bool _615 = Uniforms.uData[4].x > 1.5; + float _629; + if (_615) { - _477 = 1.0; + _629 = Uniforms.uData[3].w; } else { - _477 = _469.w; + float _628; + if (fmod(Uniforms.uData[6].x, 2.0) > 0.5) + { + _628 = 1.0; + } + else + { + _628 = _613.w; + } + _629 = _628; } - float4 _486 = float4(_469.xyz / float3(precise::max(_469.w, 9.9999997473787516355514526367188e-05)), 1.0); - float4 _495 = float4(_468.xyz / float3(precise::max(_468.w, 9.9999997473787516355514526367188e-05)), 1.0); - bool _497 = Uniforms.uData[4].z > 0.5; - float _502; - if (_497) + float4 _638 = float4(_613.xyz / float3(precise::max(_613.w, 9.9999997473787516355514526367188e-05)), 1.0); + float4 _647 = float4(_612.xyz / float3(precise::max(_612.w, 9.9999997473787516355514526367188e-05)), 1.0); + float _654; + if (_615) { - _502 = Uniforms.uData[4].x; + _654 = 1.0; } else { - _502 = 0.0; + _654 = (Uniforms.uData[4].z > 0.5) ? Uniforms.uData[4].x : 0.0; } - float _511; - if (_111) + bool _658; + if (_117) { - _511 = _502 * (1.0 - ((_382 * _382) * (1.0 - smoothstep(0.800000011920928955078125, 1.0, _502)))); + _658 = !_615; } else { - _511 = _502; + _658 = false; } - float _514 = 1.0 - _511; - float _522; - if (_111) + float _667; + if (_658) { - _522 = _382; + _667 = _654 * (1.0 - ((_526 * _526) * (1.0 - smoothstep(0.800000011920928955078125, 1.0, _654)))); } else { - _522 = _342 * _342; + _667 = _654; } - float _525 = fast::clamp(((Uniforms.uData[2].y * _348) * _522) * _514, 0.0, 1.0); - float4 _531 = ((_495 * _525) + ((mix(_495, _486, float4(fast::clamp(_334.x, 0.0, 1.0))) * _514) * (1.0 - _525))) + (Uniforms.uData[3] * _511); - float _536 = dot(_336, float2(-0.707106769084930419921875)); - float _537 = precise::max(_536, 0.0); - float _539 = precise::max(-_536, 0.0); - float _542 = abs(_536); - bool _547; - if (_111) + float _670 = 1.0 - _667; + float _678; + if (_117) { - _547 = Uniforms.uData[6].z > 0.0; + _678 = _526; } else { - _547 = false; + _678 = _486 * _486; } - float _567; - if (_547) + float _681 = fast::clamp(((Uniforms.uData[2].y * _492) * _678) * _670, 0.0, 1.0); + float4 _687 = ((_647 * _681) + ((mix(_647, _638, float4(fast::clamp(_471.x, 0.0, 1.0))) * _670) * (1.0 - _681))) + (Uniforms.uData[3] * _667); + float4 _704; + if (_615) + { + _704 = float4(Uniforms.uData[3].xyz / float3(precise::max(Uniforms.uData[3].w, 9.9999997473787516355514526367188e-05)), 1.0); + } + else + { + _704 = _687 + (_638 * (1.0 - _687.w)); + } + float _710 = dot(_479, select(float2(-0.707106769084930419921875), float2(0.707106769084930419921875, -0.707106769084930419921875), bool2(Uniforms.uData[6].x > 1.5))); + float _711 = precise::max(_710, 0.0); + float _713 = precise::max(-_710, 0.0); + float _716 = abs(_710); + bool _720; + if (_117) + { + _720 = Uniforms.uData[6].z > 0.0; + } + else { - _567 = (Uniforms.uData[6].z * (1.0 - smoothstep(0.20000000298023223876953125, 0.699999988079071044921875, _542))) * exp((-precise::max(0.0, -_305)) / (Uniforms.uData[2].z * 2.5)); + _720 = false; + } + float _739; + if (_720) + { + _739 = (Uniforms.uData[6].z * (1.0 - smoothstep(0.20000000298023223876953125, 0.699999988079071044921875, _716))) * exp((-precise::max(0.0, -_457)) / (Uniforms.uData[2].z * 2.5)); } else { - _567 = 0.85000002384185791015625 * (1.0 - smoothstep(0.0, Uniforms.uData[2].z * 0.625, -_305)); + _739 = 0.85000002384185791015625 * (1.0 - smoothstep(0.0, Uniforms.uData[2].z * 0.625, -_457)); } - float _575; - if (_111) + float _749; + if (_117) { - _575 = precise::max((Uniforms.uData[5].w * _382) * _382, _567); + _749 = precise::max((Uniforms.uData[5].w * _526) * _526, _739) * precise::min(_492, 1.0); } else { - _575 = 0.0; + _749 = 0.0; } - float _578 = _477 * (1.0 - _575); - float4 _584 = float4((_531 + (_486 * (1.0 - _531.w))).xyz * _578, _578 + _575); - float _603; - if (_111) + float _752 = _629 * (1.0 - _749); + float4 _758 = float4(_704.xyz * _752, _752 + _749); + float _776; + if (_117) { - float _594; - if (_547) + float _767; + if (_720) { - _594 = Uniforms.uData[6].z * smoothstep(0.75, 1.0, _542); + _767 = Uniforms.uData[6].z * smoothstep(0.75, 1.0, _716); } else { - _594 = 0.25; + _767 = 0.25; } - _603 = _594; + _776 = _767; } else { - _603 = (0.449999988079071044921875 * ((_537 * sqrt(_537)) + ((0.75 * _539) * sqrt(_539)))) + 0.0599999986588954925537109375; + _776 = (0.449999988079071044921875 * ((_711 * sqrt(_711)) + ((0.75 * _713) * sqrt(_713)))) + 0.0599999986588954925537109375; } - float _630; - if (_547) + float _803; + if (_720) { - _630 = exp((-precise::max(0.0, -_305)) / (Uniforms.uData[2].z * 1.25)); + _803 = exp((-precise::max(0.0, -_457)) / (Uniforms.uData[2].z * 1.25)); } else { - float _629; - if (_111) + float _802; + if (_117) { - float _617 = -_305; - _629 = smoothstep(Uniforms.uData[2].z * 0.3125, Uniforms.uData[2].z * 0.625, _617) * (1.0 - smoothstep(Uniforms.uData[2].z * 1.5, Uniforms.uData[2].z * 2.0, _617)); + float _790 = -_457; + _802 = smoothstep(Uniforms.uData[2].z * 0.3125, Uniforms.uData[2].z * 0.625, _790) * (1.0 - smoothstep(Uniforms.uData[2].z * 1.5, Uniforms.uData[2].z * 2.0, _790)); } else { - _629 = exp((-precise::max(0.0, -_305)) / Uniforms.uData[2].z); + _802 = exp((-precise::max(0.0, -_457)) / Uniforms.uData[2].z); } - _630 = _629; + _803 = _802; } - float _637; - if (_111) + float _810; + if (_117) { - _637 = 0.0; + _810 = 0.0; } else { - _637 = (0.039999999105930328369140625 * exp(_339 / Uniforms.uData[1].w)) * _537; + _810 = (0.039999999105930328369140625 * exp(_483 / Uniforms.uData[1].w)) * _711; } - float _643; - if (_497) + float _818; + if (Uniforms.uData[4].z > 0.5) { - _643 = Uniforms.uData[4].y; + _818 = Uniforms.uData[4].y; } else { - _643 = 0.0; + _818 = 0.0; } - float3 _653 = _584.xyz + float3(fast::clamp((_643 + _334.z) + ((_348 * Uniforms.uData[2].w) * ((_630 * _603) + _637)), 0.0, 1.0)); - float4 _655 = fast::clamp(float4(_653.x, _653.y, _653.z, _584.w), float4(0.0), float4(1.0)); - float _662 = precise::max(_655.w, precise::max(_655.x, precise::max(_655.y, _655.z))); - float4 _663 = _655; - _663.w = _662; - float3 _674 = _663.xyz + float3(((fract(52.98291778564453125 * fract(dot(in.in_var_TEXCOORD0, float2(0.067110560834407806396484375, 0.005837149918079376220703125)))) - 0.5) * Uniforms.uData[5].x) * _662); - _678 = fast::clamp(float4(_674.x, _674.y, _674.z, _663.w), float4(0.0), float4(1.0)) * _323; + float3 _828 = _758.xyz + float3(fast::clamp((_818 + _471.z) + ((_492 * Uniforms.uData[2].w) * ((_803 * _776) + _810)), 0.0, 1.0)); + float4 _830 = fast::clamp(float4(_828.x, _828.y, _828.z, _758.w), float4(0.0), float4(1.0)); + float _837 = precise::max(_830.w, precise::max(_830.x, precise::max(_830.y, _830.z))); + float4 _838 = _830; + _838.w = _837; + float3 _849 = _838.xyz + float3(((fract(52.98291778564453125 * fract(dot(in.in_var_TEXCOORD0, float2(0.067110560834407806396484375, 0.005837149918079376220703125)))) - 0.5) * Uniforms.uData[5].x) * _837); + _853 = fast::clamp(float4(_849.x, _849.y, _849.z, _838.w), float4(0.0), float4(1.0)) * _460; break; } while(false); - out.out_var_SV_Target0 = _678; + out.out_var_SV_Target0 = _853; return out; } diff --git a/backend/src/glass/shaders/compiled/spv/liquid_glass.fragment.spv b/backend/src/glass/shaders/compiled/spv/liquid_glass.fragment.spv index 4a36459a9..8221ca3b8 100644 Binary files a/backend/src/glass/shaders/compiled/spv/liquid_glass.fragment.spv and b/backend/src/glass/shaders/compiled/spv/liquid_glass.fragment.spv differ diff --git a/backend/src/glass/shaders/liquid_glass.fragment.hlsl b/backend/src/glass/shaders/liquid_glass.fragment.hlsl index 31f1d22f2..559448a15 100644 --- a/backend/src/glass/shaders/liquid_glass.fragment.hlsl +++ b/backend/src/glass/shaders/liquid_glass.fragment.hlsl @@ -17,6 +17,9 @@ #define G 7 #define MAX_SHAPES 16 +// How far past its place's outline the outside of the place begins, in pixels: far enough that no +// sliver of it shows inside, near enough that a shape at the outline still runs into it. +#define EDGE_GAP 1.0 // No SV_POSITION: D3D12 links a pixel shader's inputs to the vertex shader's outputs by register, // and the default vertex shader's third output (the instance) sits where a pixel position read @@ -92,7 +95,7 @@ float4 main(PSInput input) : SV_Target0 float4 g3 = uData[3]; float4 g4 = uData[4]; float4 g5 = uData[5]; // dither; the lens: its band's share of the shape, its bend, its shade - float4 g6 = uData[6]; // opaque window; the lens: dispersion, a drop's diagonal light (0: a window's hairline), the band's cap + float4 g6 = uData[6]; // opaque window (+1) and the light turned to the top right (+2); the lens: dispersion, a drop's diagonal light (0: a window's hairline), the band's cap // Apple's lens (`glass_look.inApp`): the picture pulled inward from a band near the rim, // magnified and, past a bend of 1, folded there. Off, the earlier glass: pulled from outside. bool inward = g5.y > 0.0; @@ -118,16 +121,45 @@ float4 main(PSInput input) : SV_Target0 } if (f < f1) { f2 = f1; o2 = o1; f1 = f; o1 = o; } else if (f < f2) { f2 = f; o2 = o; } } + // The place the glass belongs to (`LiquidField.edge`), in the last slot, flagged 2. Its outside + // is one more shape: a shape near the outline runs into it, a neck that joins it to the edge. + // Its outline cuts the glass's coverage, so none of it crosses; the rim and the bend come from + // the joined shape, so there is no rim along the cut, as if the glass carried on past it. + // Flagged 3, cut (`LiquidField.Edge.cut`): not joined, and the cut is an edge of the glass's + // own, its rim and bend along it. + float inPlace = -1e9; + float2 placeOut = float2(0.0, 0.0); + float4 e2 = uData[G + 3 * (MAX_SHAPES - 1) + 2]; + bool cutEdge = e2.w > 2.5; + if (e2.w > 1.5) { + float4 e0 = uData[G + 3 * (MAX_SHAPES - 1)]; + float4 e1 = uData[G + 3 * (MAX_SHAPES - 1) + 1]; + float2 ge; + inPlace = sdRoundBox(p - e0.xy, e0.zw, min(e1, (float4)min(e0.z, e0.w)), ge); + placeOut = ge; + } + if (e2.w > 1.5 && !cutEdge) { + float2 ge = placeOut; + float d = EDGE_GAP - inPlace; + float hs = h1; + if (d < d1) { d2 = d1; m2 = m1; h2 = h1; d1 = d; m1 = e2; h1 = hs; } else if (d < d2) { d2 = d; m2 = e2; h2 = hs; } + float2 o = -ge; + if (d < f1) { f2 = f1; o2 = o1; f1 = d; o1 = o; } else if (d < f2) { f2 = d; o2 = o; } + } float k = max(g1.x, 0.0001); float wm; float wf; float D = smin(d1, d2, k, wm); float F = smin(f1, f2, k, wf); - float cov = clamp(0.5 - D, 0.0, 1.0); + // Cut: the glass's outline, and so its rim line, runs along the place's where that is nearer. + if (cutEdge) D = max(D, inPlace); + float cov = clamp(0.5 - max(D, inPlace), 0.0, 1.0); if (cov <= 0.0) discard; if (input.color.r < 0.5) return float4(0.0, 0.0, 0.0, cov); float4 mat = lerp(m1, m2, wm); float2 outv = lerp(o1, o2, wf); + // Cut: where the place's outline is nearer than the shapes' own, the glass's edge is the cut. + if (cutEdge && inPlace > F) { F = inPlace; outv = placeOut; } float soft = max(0.0, -F); float steepR = exp(-soft / g1.z); float steepL = exp(-soft / g1.w); @@ -180,18 +212,22 @@ float4 main(PSInput input) : SV_Target0 // over the translucent picture as it was, the rim — where the clear glass lies over the // frost — came out more opaque than the face, and the material lit the face and not the rim. // Opaque where the window is (`LiquidField.publishOpaqueWindow`): its alpha is only its shape. - float under = uData[6].x > 0.5 ? 1.0 : frost.a; + // Glass that is the window's own material (`LiquidField.window`, its mix 2): the window's colour, + // the tint, in place of what is behind it, as see-through as that colour is, so the desktop's + // material shows through it as it does through the window round a card. + bool window = g4.x > 1.5; + float under = window ? g3.a : (fmod(uData[6].x, 2.0) > 0.5 ? 1.0 : frost.a); frost = float4(frost.rgb / max(frost.a, 1e-4), 1.0); sharp = float4(sharp.rgb / max(sharp.a, 1e-4), 1.0); // The frost at its share of a frost / tint mix, the blur coming in from sharp. The window's // colour comes in whatever the blur: the opacity is the colour, under clear glass too. - float mixv = g4.z > 0.5 ? g4.x : 0.0; + float mixv = window ? 1.0 : (g4.z > 0.5 ? g4.x : 0.0); // Apple's lens: the window's colour fades out across the band, as an OS window's does // (`glass_look.window`, its feather: strong most of the way, gone at the edge), so the edge stays // the lens bending what is behind it — unless the colour is near whole, when it covers the edge // too (`glass_look.shine_start`, 0.8 to 1). - if (inward) mixv *= 1.0 - t * t * (1.0 - smoothstep(0.8, 1.0, mixv)); + if (inward && !window) mixv *= 1.0 - t * t * (1.0 - smoothstep(0.8, 1.0, mixv)); float4 c = lerp(sharp, frost, b) * (1.0 - mixv); // The rim's clearer glass over it (`drawClear`): for Apple's lens, the band, so the rim stays // clear glass while the middle frosts. @@ -201,9 +237,17 @@ float4 main(PSInput input) : SV_Target0 c += g3 * mixv; // A translucent tint lies over the frost, not over what is behind the window: the glass is // opaque here, and `under` alone says how much of the desktop's material shows through it. - c += frost * (1.0 - c.a); + if (window) { + c = float4(g3.rgb / max(g3.a, 1e-4), 1.0); + } else { + c += frost * (1.0 - c.a); + } // The way the edge faces, against a light from the top left. - float facing = dot(outv, float2(-0.70710678, -0.70710678)); + // From the top left, or turned a quarter to the top right (`LiquidField.light_across`, +2 on the + // opaque window's flag): on every look, a window's hairline as much as a drop's diagonal. + float2 lightDir = g6.x > 1.5 ? float2(0.70710678, -0.70710678) : float2(-0.70710678, -0.70710678); + float dg = g6.z; + float facing = dot(outv, lightDir); float toward = max(facing, 0.0); float away = max(-facing, 0.0); // Apple's lens has two edges, measured beside the OS's (`g6.z`, `glass_look.InApp.diagonal`): @@ -217,13 +261,15 @@ float4 main(PSInput input) : SV_Target0 // pixels (the rim line's width is 0.8 of one, `LiquidField.rim_line_width`). float px = g2.z * 1.25; float af = abs(facing); - bool diagonal = inward && g6.z > 0.0; - float edge_dark = diagonal ? g6.z * (1.0 - smoothstep(0.2, 0.7, af)) * exp(-max(0.0, -D) / (2.0 * px)) + bool diagonal = inward && dg > 0.0; + float edge_dark = diagonal ? dg * (1.0 - smoothstep(0.2, 0.7, af)) * exp(-max(0.0, -D) / (2.0 * px)) : 0.85 * (1.0 - smoothstep(0.0, 0.5 * px, -D)); - float shade = inward ? max(g5.w * t * t, edge_dark) : 0.0; + // As much as the edge has formed (`lens`), as its bend, clearing and light are: glass that is + // barely a lens yet — a drop sunk into its place's edge — draws no dark line round itself. + float shade = inward ? max(g5.w * t * t, edge_dark) * min(lens, 1.0) : 0.0; float4 o = float4(c.rgb * (under * (1.0 - shade)), under * (1.0 - shade) + shade); // The lift and the rim's light (`drawLift`), brightest facing the top left. - float spec = inward ? (diagonal ? g6.z * smoothstep(0.75, 1.0, af) : 0.25) + float spec = inward ? (diagonal ? dg * smoothstep(0.75, 1.0, af) : 0.25) : 0.45 * (toward * sqrt(toward) + 0.75 * away * sqrt(away)) + 0.06; float line_ = diagonal ? exp(-max(0.0, -D) / px) : inward ? smoothstep(0.25 * px, 0.5 * px, -D) * (1.0 - smoothstep(1.2 * px, 1.6 * px, -D)) diff --git a/core/dialogs.zig b/core/dialogs.zig index d41661af2..98973c9b9 100644 --- a/core/dialogs.zig +++ b/core/dialogs.zig @@ -117,6 +117,23 @@ pub fn dialogFrost() ?widgets.FloatingWindowWidget.Frost { }; } +const window_base_key = "fizzy_window_base"; + +/// Host only, each frame: the colour the main window is drawn on — its base at its opacity over the +/// OS's material, clear on a window of OS glass — for glass that is the window's own material +/// (`BubblesOptions.window`). +pub fn publishWindowBase(c: dvui.Color) void { + const cw = dvui.currentWindow(); + dvui.dataSet(null, cw.data().id, window_base_key, c); +} + +/// The colour the main window is drawn on (`publishWindowBase`), or the chrome's before the host +/// has said. +pub fn windowBase() dvui.Color { + const cw = dvui.currentWindow(); + return dvui.dataGet(null, cw.data().id, window_base_key, dvui.Color) orelse style().chromeColor(); +} + /// Where the host records the dialog refraction setting — its own key beside the style, so a /// plugin built before it existed reads the style it knows and simply never asks for this. const refraction_key = "fizzy_dialog_refraction"; @@ -251,6 +268,11 @@ pub const Bubble = struct { /// `radius`: glass cut to fit a corner of something else, as a place's corner is to its card's /// curve. Each is held to half the shorter side. radii: ?[4]f32 = null, + /// How much of a lens it is, 0…1: its edge's bend, clearing, light and dark line + /// (`LiquidField.Shape.lens`). Less, it lies flatter in what it is over. + lens: f32 = 1, + /// How frosted it is, 0 (what is behind, sharp) to 1 (`LiquidField.Shape.blur`). + blur: f32 = 1, fn cornerRadius(self: Bubble) f32 { const half = @min(self.rect.w, self.rect.h) / 2; @@ -283,6 +305,25 @@ pub const BubblesOptions = struct { /// A signature of what lies under the bubbles, as `frostPaneKept`'s: the frost is read again /// only when it changes. Null reads it every frame. witness: ?u64 = null, + /// The place the bubbles belong to (`LiquidField.edge`): a bubble near its outline joins it by a + /// neck, and none crosses it. Physical. No shadow rings with it (`shadow`). Without the glass + /// program, the bubbles are only cut to its rect. + edge: ?widgets.LiquidField.Edge = null, + /// The glass's colour and how much of it, over the dialog style's (`LiquidField.surface`): for + /// glass that must read as part of a surface, as a place's corner at rest does its card's fill. + /// Without the glass program, the fill it falls back to. + tint: ?dvui.Color = null, + mix: f32 = 1, + /// Glass even where the window behind it is see-through (`LiquidField.solid`): a control that + /// must look the same over a bare stretch of the window's material as over a card. + solid: bool = false, + /// The window's own material (`LiquidField.window`): the window's base colour (`windowBase`) in + /// place of what is behind the glass, as see-through as the window is, so over a card the glass + /// reads as the window's edge reaching into it. Over `tint`. + window: bool = false, + /// A drop's rim lit from the top right (`LiquidField.light_across`): for glass whose edges that + /// show face across the usual light. + light_across: bool = false, }; /// A rounded box's smallest corner, in points, for its glass to bend along its own outline as a @@ -298,13 +339,15 @@ const round_corner: f32 = 4; pub fn glassBubbles(id: dvui.Id, bubbles: []const Bubble, scale: f32, opts: BubblesOptions) void { const bs = surfaceShadow(); // The ring after the glass, so the glass never blurs it in. - defer if (opts.shadow > 0) for (bubbles) |b| { + // None for bubbles merged with an edge: a ring round each bubble's own outline would lie across + // its neck, splitting it from the edge it is one glass with. + defer if (opts.shadow > 0 and opts.edge == null) for (bubbles) |b| { if (b.rect.w < 1 or b.rect.h < 1) continue; glassShadow(b.rect, b.corners(scale), scale, bs, opts.shadow); }; if (widgets.LiquidField.ready()) { if (widgets.liquidFrost()) |frost| { - var field: widgets.LiquidField = .{ .merge_px = opts.merge * scale, .scale = scale }; + var field: widgets.LiquidField = .{ .merge_px = opts.merge * scale, .scale = scale, .edge = opts.edge, .solid = opts.solid, .light_across = opts.light_across }; for (bubbles) |b| { if (b.rect.w < 1 or b.rect.h < 1) continue; // Its edge bends along its own outline, as a drop's does, with a drop's rim of light: @@ -315,22 +358,35 @@ pub fn glassBubbles(id: dvui.Id, bubbles: []const Bubble, scale: f32, opts: Bubb const capsule = b.radius == null and b.radii == null; const radii: [4]f32 = if (capsule) @splat(@min(b.rect.w, b.rect.h)) else b.cornerRadii(); const round = capsule or @reduce(.Min, @as(@Vector(4, f32), radii)) >= round_corner * scale; - field.add(.{ .rect = b.rect, .radii = radii, .round = round, .light = b.light }); + field.add(.{ .rect = b.rect, .radii = radii, .round = round, .light = b.light, .lens = b.lens, .blur = b.blur }); } var pane = frost; pane.form = 1; + if (opts.tint) |t| { + pane.tint = t; + pane.mix = opts.mix; + field.surface = true; + } + if (opts.window) { + pane.tint = windowBase(); + pane.mix = 1; + field.window = true; + } pane.witness = opts.witness; widgets.BlurBackdrop.fieldPane(id, field, scale, pane); return; } } + const prev_clip = dvui.clipGet(); + defer dvui.clipSet(prev_clip); + if (opts.edge) |e| dvui.clipSet(prev_clip.intersect(e.rect)); for (bubbles, 0..) |b, i| { if (b.rect.w < 1 or b.rect.h < 1) continue; const round = b.corners(scale); const physical = round.scale(scale, dvui.CornerRect.Physical); const piece = id.update(std.mem.asBytes(&i)); const frosted = if (opts.witness) |w| frostPaneKept(piece, b.rect, round, scale, w) else frostPane(piece, b.rect, round, scale); - if (!frosted) b.rect.fill(physical, .{ .color = .{ .color = dialogFill() }, .fade = 1 }); + if (!frosted) b.rect.fill(physical, .{ .color = .{ .color = if (opts.tint) |t| t.opacity(opts.mix) else dialogFill() }, .fade = 1 }); if (b.light >= bubble_press) { b.rect.fill(physical, .{ .color = .{ .color = rowPress() }, .fade = 1 }); } else if (b.light > 0) { diff --git a/src/editor/Editor.zig b/src/editor/Editor.zig index b7e82e021..b892fff3e 100644 --- a/src/editor/Editor.zig +++ b/src/editor/Editor.zig @@ -4595,6 +4595,8 @@ pub fn tick(editor: *Editor) !dvui.App.Result { // app's), the base is its colour over that material at this opacity (`materialBase`): clear // on Liquid Glass, whose colour is the glass's. Elsewhere fizzy's own (`windowBase`). const window_color = fizzy.backend.windowMaterialBase(dvui.currentWindow(), dvui.themeGet().color(.content, .fill), editor.window_opacity_anim.value, windowGlassLook(editor.window_opacity_anim.value, dvui.windowRect().size())) orelse windowBase(editor.window_opacity_anim.value); + // For glass that is the window's own material (`core.dialogs.windowBase`). + fizzy.core.dialogs.publishWindowBase(window_color); // Linux: the window is transparent and undecorated (`linux_titlebar`), so its shape is // this fill's — rounded while windowed, as the desktop rounds its own, with a hairline diff --git a/tests/integration.zig b/tests/integration.zig index dc781c089..32a88c9c5 100644 --- a/tests/integration.zig +++ b/tests/integration.zig @@ -5169,6 +5169,35 @@ test "liquid field: a rounded box's outline is its rect with its own corner per try std.testing.expect(f.hit(.{ .x = 50, .y = 30 }) and !f.hit(.{ .x = 2, .y = 2 })); } +test "liquid field: a shape near its place's edge joins it by a neck, and none of it crosses the edge" { + const LF = fizzy.core.LiquidField; + // A place 200 x 100 at the origin, a 24 radius at its top right; a drop 6px in from its top. + var f: LF = .{ .merge_px = 16, .edge = .{ .rect = .{ .x = 0, .y = 0, .w = 200, .h = 100 }, .radii = .{ 0, 24, 0, 0 } } }; + f.add(LF.Shape.circle(.{ .x = 100, .y = 26 }, 20)); + // Between the drop and the edge, a neck: glass where the drop alone has none. + try std.testing.expect(f.sample(.{ .x = 100, .y = 3 }).d < 0); + var alone: LF = .{ .merge_px = 16 }; + alone.add(LF.Shape.circle(.{ .x = 100, .y = 26 }, 20)); + try std.testing.expect(alone.sample(.{ .x = 100, .y = 3 }).d > 0); + // The neck is only near the drop: along the edge away from it, no glass, not even a sliver. + try std.testing.expectEqual(@as(f32, 0), f.sample(.{ .x = 20, .y = 0.5 }).coverage); + try std.testing.expectEqual(@as(f32, 0), f.sample(.{ .x = 20, .y = 3 }).coverage); + // A drop pushed past the edge is cut at it: none of it outside the place. + var past: LF = .{ .merge_px = 16, .edge = .{ .rect = .{ .x = 0, .y = 0, .w = 200, .h = 100 } } }; + past.add(LF.Shape.circle(.{ .x = 100, .y = 0 }, 20)); + try std.testing.expectEqual(@as(f32, 0), past.sample(.{ .x = 100, .y = -5 }).coverage); + try std.testing.expect(past.sample(.{ .x = 100, .y = 5 }).d < 0); + // Round the curved corner too: a point past the curve, inside the rect, is outside the place. + var corner: LF = .{ .merge_px = 16, .edge = .{ .rect = .{ .x = 0, .y = 0, .w = 200, .h = 100 }, .radii = .{ 0, 24, 0, 0 } } }; + corner.add(LF.Shape.circle(.{ .x = 200, .y = 0 }, 20)); + try std.testing.expectEqual(@as(f32, 0), corner.sample(.{ .x = 199, .y = 1 }).coverage); + try std.testing.expect(corner.sample(.{ .x = 190, .y = 10 }).d < 0); + // A field with an edge holds one shape fewer: the last slot is the edge's. + var full: LF = .{ .edge = .{ .rect = .{ .x = 0, .y = 0, .w = 200, .h = 100 } } }; + for (0..LF.max_shapes) |_| full.add(LF.Shape.circle(.{ .x = 50, .y = 50 }, 5)); + try std.testing.expectEqual(LF.max_shapes - 1, full.len); +} + test "liquid field: shapes bridge within the merge width, swell no more than a quarter of it, and part beyond" { const LF = fizzy.core.LiquidField; var f: LF = .{ .merge_px = 16 };