@edinstvo/glass 0.1.0-beta.2 → 0.1.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -134
- package/dist/geometry.js +4 -1
- package/dist/geometry.js.map +1 -1
- package/dist/shader.d.ts +1 -1
- package/dist/shader.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,46 +1,16 @@
|
|
|
1
|
-
<
|
|
1
|
+
<img src="logo.png" alt="Edinstvo Glass" width="148">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Edinstvo Glass is a simple library for real glass on the web.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
At its core is a WebGL lens that bends light through a curved edge, splits colours and frosts what is behind it, the same on macOS and Windows. It comes as one web component with no dependencies.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
A WebGL lens with refraction, dispersion, frost and light,<br>
|
|
9
|
-
wrapped in a single web component that works in any framework.
|
|
10
|
-
</p>
|
|
7
|
+
## Documentation
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
<a href="https://www.npmjs.com/package/@edinstvo/glass"><img src="https://img.shields.io/npm/v/@edinstvo/glass?style=for-the-badge&labelColor=000000&color=1a1a1a&label=npm" alt="npm version"></a>
|
|
14
|
-
<img src="https://img.shields.io/badge/WebGL-2-1a1a1a?style=for-the-badge&labelColor=000000&logo=webgl&logoColor=white" alt="WebGL 2">
|
|
15
|
-
<img src="https://img.shields.io/badge/dependencies-0-1a1a1a?style=for-the-badge&labelColor=000000" alt="Zero dependencies">
|
|
16
|
-
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-1a1a1a?style=for-the-badge&labelColor=000000" alt="MIT license"></a>
|
|
17
|
-
</p>
|
|
9
|
+
See the full documentation, with a playground and examples, at [edinstvoai.github.io/edinstvo-glass-documentation-](https://edinstvoai.github.io/edinstvo-glass-documentation-/).
|
|
18
10
|
|
|
19
|
-
|
|
20
|
-
<a href="#install"><b>Install</b></a>
|
|
21
|
-
·
|
|
22
|
-
<a href="#material">Material</a>
|
|
23
|
-
·
|
|
24
|
-
<a href="#backdrop">Backdrop</a>
|
|
25
|
-
·
|
|
26
|
-
<a href="#limits">Limits</a>
|
|
27
|
-
</p>
|
|
11
|
+
## npm
|
|
28
12
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
<br>
|
|
32
|
-
|
|
33
|
-
## Principles
|
|
34
|
-
|
|
35
|
-
> **Optics, not blur.** Light bends through a curved edge by Snell's law, so glass behaves like glass
|
|
36
|
-
> instead of a tinted rectangle.
|
|
37
|
-
>
|
|
38
|
-
> **Quiet by default.** A frame is drawn only when something changes. Nothing on screen moves, nothing
|
|
39
|
-
> runs on the GPU.
|
|
40
|
-
>
|
|
41
|
-
> **One context.** Every element on the page shares a single WebGL context, however many there are.
|
|
42
|
-
|
|
43
|
-
## Install
|
|
13
|
+
To install from npm:
|
|
44
14
|
|
|
45
15
|
```bash
|
|
46
16
|
npm i @edinstvo/glass
|
|
@@ -51,118 +21,37 @@ npm i @edinstvo/glass
|
|
|
51
21
|
import "@edinstvo/glass/define";
|
|
52
22
|
</script>
|
|
53
23
|
|
|
54
|
-
<edinstvo-glass frost="0.4" refraction="0.5">
|
|
55
|
-
Hello
|
|
56
|
-
</edinstvo-glass>
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
The corner radius comes from CSS `border-radius`, the size from your layout. Everything else is optional.
|
|
60
|
-
|
|
61
|
-
Not a fan of custom elements? Attach glass to any node:
|
|
62
|
-
|
|
63
|
-
```js
|
|
64
|
-
import { attachGlass } from "@edinstvo/glass";
|
|
65
|
-
|
|
66
|
-
const glass = attachGlass(element, { material: { frost: 0.7 } });
|
|
67
|
-
glass.set({ material: { frost: 0.4 } });
|
|
68
|
-
glass.destroy();
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Material
|
|
72
|
-
|
|
73
|
-
There are no types of glass, only settings. Set anything with an attribute, a `--glass-*` CSS variable or the `material` property. The defaults are tuned against the system glass on macOS, pixel by pixel.
|
|
74
|
-
|
|
75
|
-
| Attribute | Range | What it does |
|
|
76
|
-
|---|---|---|
|
|
77
|
-
| `refraction` | 0 to 1 | How hard the edge bends what is behind it |
|
|
78
|
-
| `depth` | 0 to 96 px | Width of the curved edge |
|
|
79
|
-
| `splay` | 0 to 1 | Spreads the curve from the edge towards the centre |
|
|
80
|
-
| `dispersion` | 0 to 1 | How far colours split wherever the glass bends |
|
|
81
|
-
| `frost` | 0 to 1 | Matte surface, a true gaussian up to 20 px |
|
|
82
|
-
| `transparency` | 0 to 1 | How much of the backdrop survives the tint |
|
|
83
|
-
| `tint` | any CSS colour | Glass colour. `auto` follows the theme |
|
|
84
|
-
| `lift` | 0 to 1 | Brightens everything behind the glass |
|
|
85
|
-
| `light` | 0 to 1 | Shading across the curve, bright towards the light and dark away from it |
|
|
86
|
-
| `rim` | 0 to 1 | Thin light line along the edge, brightest in line with the light |
|
|
87
|
-
| `glint` | 0 to 1 | Sharp highlight along the edge. Off in every preset |
|
|
88
|
-
| `light-angle` | -180 to 180° | Where the light comes from. 0 is the top |
|
|
89
|
-
| `bloom` | 0 to 1 | Glow inside the glass and around it |
|
|
90
|
-
|
|
91
|
-
## Motion
|
|
92
|
-
|
|
93
|
-
Change an element's size or position in CSS and the glass flows there with a spring, overshoot included.
|
|
94
|
-
Each of these is its own setting, on a group or on a single child. `prefers-reduced-motion` turns them all off.
|
|
95
|
-
|
|
96
|
-
| Attribute | Range | What it does |
|
|
97
|
-
|---|---|---|
|
|
98
|
-
| `morph` | 0 to 1 | Softness of the flow. 0 jumps straight to the new shape |
|
|
99
|
-
| `jelly` | 0 to 1 | Stretch while moving and under a drag |
|
|
100
|
-
| `press` | 0 to 1 | How much the glass swells when held |
|
|
101
|
-
| `glow` | 0 to 1 | Light that spreads from under the finger |
|
|
102
|
-
| `follow` | 0 to 1 | How far the light chases the pointer |
|
|
103
|
-
| `merge` | 0 to 64 px | Melts this element into others that have it too. 0 stays separate |
|
|
104
|
-
|
|
105
|
-
### Merge
|
|
106
|
-
|
|
107
|
-
Merging is opt-in, per element. Give `merge` to the pieces that should become one shape: they melt together when they get close and pull apart like liquid. Everything else in the group stays separate.
|
|
108
|
-
|
|
109
|
-
```html
|
|
110
|
-
<edinstvo-glass-group>
|
|
111
|
-
<edinstvo-glass merge="28"></edinstvo-glass>
|
|
112
|
-
<edinstvo-glass merge="28"></edinstvo-glass>
|
|
113
|
-
<edinstvo-glass></edinstvo-glass>
|
|
114
|
-
</edinstvo-glass-group>
|
|
24
|
+
<edinstvo-glass frost="0.4" refraction="0.5">Hello</edinstvo-glass>
|
|
115
25
|
```
|
|
116
26
|
|
|
117
|
-
|
|
27
|
+
## Exports
|
|
118
28
|
|
|
119
|
-
|
|
29
|
+
- `@edinstvo/glass` - `attachGlass`, the element classes, defaults and ranges of every setting.
|
|
30
|
+
- `@edinstvo/glass/define` - Registers `edinstvo-glass` and `edinstvo-glass-group`.
|
|
31
|
+
- `@edinstvo/glass/glass.css` - Base materials on `backdrop-filter`, for pages without JavaScript or a GPU.
|
|
120
32
|
|
|
121
|
-
|
|
33
|
+
## Contributing
|
|
122
34
|
|
|
123
|
-
|
|
35
|
+
Edinstvo Glass is open source and we appreciate issue reports and pull requests.
|
|
124
36
|
|
|
125
|
-
|
|
37
|
+
### Setting up for development
|
|
126
38
|
|
|
127
|
-
|
|
128
|
-
<edinstvo-glass layer="1"></edinstvo-glass>
|
|
129
|
-
<edinstvo-glass layer="2"></edinstvo-glass>
|
|
130
|
-
```
|
|
39
|
+
Initialize the repo:
|
|
131
40
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
or solid colour under the element.
|
|
137
|
-
|
|
138
|
-
```html
|
|
139
|
-
<edinstvo-glass source="#scene"></edinstvo-glass>
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
```js
|
|
143
|
-
glass.source = canvas;
|
|
144
|
-
glass.invalidate();
|
|
41
|
+
```bash
|
|
42
|
+
git clone https://github.com/EdinstvoAI/edinstvo-glass.git
|
|
43
|
+
cd edinstvo-glass
|
|
44
|
+
npm ci
|
|
145
45
|
```
|
|
146
46
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
## Plain CSS
|
|
150
|
-
|
|
151
|
-
No JavaScript, or no GPU? `@edinstvo/glass/glass.css` gives you `.glass`, `.glass-clear` and `.glass-frost`
|
|
152
|
-
on top of `backdrop-filter`. The element falls back to the same look by itself when WebGL is missing.
|
|
153
|
-
|
|
154
|
-
## Limits
|
|
155
|
-
|
|
156
|
-
- Text and regular DOM behind the glass aren't refracted, only the sources listed above. Draw them to a canvas if you need them.
|
|
157
|
-
- CSS gradients aren't read yet. Glass skips them and looks further down the stack.
|
|
158
|
-
- Cross-origin images need CORS headers, otherwise that element falls back to CSS.
|
|
159
|
-
|
|
160
|
-
## Development
|
|
47
|
+
Run the bench:
|
|
161
48
|
|
|
162
49
|
```bash
|
|
163
50
|
npm run demo
|
|
164
51
|
```
|
|
165
52
|
|
|
53
|
+
Test:
|
|
54
|
+
|
|
166
55
|
```bash
|
|
167
56
|
npm test
|
|
168
57
|
```
|
package/dist/geometry.js
CHANGED
|
@@ -28,6 +28,9 @@ export function softPeak(halfW, halfH, radius) {
|
|
|
28
28
|
const a = halfW + radius;
|
|
29
29
|
const b = halfH + radius;
|
|
30
30
|
const lo = Math.min(a, b);
|
|
31
|
-
|
|
31
|
+
const soft = lo * (1 + (lo / Math.max(a, b)) ** 2.7) ** (-1 / 2.7) - radius;
|
|
32
|
+
const half = Math.min(halfW, halfH);
|
|
33
|
+
const round = half ? radius / half : 0;
|
|
34
|
+
return soft + (half - soft) * round;
|
|
32
35
|
}
|
|
33
36
|
//# sourceMappingURL=geometry.js.map
|
package/dist/geometry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geometry.js","sourceRoot":"","sources":["../src/geometry.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,MAAM,CAAC,GAAQ,EAAE,QAAgB,EAAE,QAAgB,EAAE,GAAQ;IAC3E,IAAI,GAAG,KAAK,MAAM,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ;QAAE,OAAO,GAAG,CAAC;IACzD,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC5E,MAAM,IAAI,GAAG,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;IACnD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;IACvD,MAAM,CAAC,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC3B,MAAM,CAAC,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC3B,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAmC,EAAE,GAAQ,EAAE,MAAc,EAAE,MAAc,EAAE,GAAW;IACpH,OAAO;QACL,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAU;QAC1E,QAAQ,EAAE,CAAC,MAAM,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAU;KACpE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,CAAS,EAAE,CAAS;IAC9D,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACjF,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,MAAM,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;IACxC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAa,EAAE,KAAa,EAAE,MAAc;IACnE,MAAM,CAAC,GAAG,KAAK,GAAG,MAAM,CAAC;IACzB,MAAM,CAAC,GAAG,KAAK,GAAG,MAAM,CAAC;IACzB,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1B,
|
|
1
|
+
{"version":3,"file":"geometry.js","sourceRoot":"","sources":["../src/geometry.ts"],"names":[],"mappings":"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"}
|
package/dist/shader.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export declare const vertex = "#version 300 es\nvoid main() {\n vec2 p = vec2((gl_VertexID << 1) & 2, gl_VertexID & 2);\n gl_Position = vec4(p * 2.0 - 1.0, 0.0, 1.0);\n}";
|
|
2
|
-
export declare const fragment = "#version 300 es\nprecision highp float;\n\nconst int MAX_SHAPES = 64;\nconst float SOFTNESS = 2.7;\n\nuniform sampler2D uBackdrop, uFrosted;\nuniform vec4 uBoxes[MAX_SHAPES];\nuniform vec2 uForms[MAX_SHAPES];\nuniform int uCount;\nuniform vec2 uCanvas, uUvOrigin, uUvPerPx, uTexSize, uLightDir;\nuniform vec3 uTint, uTouch;\nuniform float uViewY, uPad, uDpr, uPeak, uAppear, uLight, uTransparency, uRefraction, uDepth, uDispersion, uFrost, uSplay, uBloom, uGlint, uRim, uLift;\nout vec4 outColor;\n\nfloat roundedBox(vec2 p, vec2 b, float r) {\n vec2 q = abs(p) - b + r;\n return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - r;\n}\n\nfloat softMin(float a, float b) {\n float lo = min(a, b);\n return lo * pow(1.0 + pow(lo / max(a, b), SOFTNESS), -1.0 / SOFTNESS);\n}\n\nfloat blend(float a, float b, float k) {\n float h = max(k - abs(a - b), 0.0) / k;\n return min(a, b) - h * h * k * 0.25;\n}\n\n// \u2500\u2500 x is the distance to the merged outline, y how deep the point sits inside it, without creases\nvec2 field(vec2 p) {\n float joined = 1e5;\n float apart = 1e5;\n float inset = -1e5;\n for (int i = 0; i < MAX_SHAPES; i++) {\n if (i >= uCount) break;\n vec2 c = p - uBoxes[i].xy;\n vec2 b = uBoxes[i].zw;\n float r = uForms[i].x;\n float own = roundedBox(c, b, r);\n if (uForms[i].y > 0.0) joined = blend(joined, own, uForms[i].y);\n else apart = min(apart, own);\n if (own < 0.0) {\n vec2 edges = max(b - abs(c), 0.0) + r + 0.001;\n inset = max(inset, softMin(edges.x, edges.y) - r);\n }\n }\n float d = min(joined, apart);\n return vec2(d, max(inset, -d));\n}\n\nvec2 toUv(vec2 px) {\n return uUvOrigin + px * uUvPerPx;\n}\n\nvec3 pick(vec2 px, float lod) {\n return uFrost > 0.0 ? texture(uFrosted, toUv(px)).rgb : textureLod(uBackdrop, toUv(px), lod).rgb;\n}\n\nvoid main() {\n vec2 px = vec2(gl_FragCoord.x, uCanvas.y - (gl_FragCoord.y - uViewY));\n vec2 f = field(px);\n float d = f.x;\n float texels = max(uUvPerPx.x * uTexSize.x, uUvPerPx.y * uTexSize.y);\n float haloLod = log2(max(28.0 * uDpr * texels, 1.0));\n vec3 halo = textureLod(uBackdrop, toUv(px), haloLod).rgb;\n\n float mask = 1.0 - smoothstep(-0.75, 0.75, d);\n float spill = exp(-max(d, 0.0) / (uPad * 0.3)) * uBloom * 0.4 * uLight;\n vec3 spillColor = mix(halo, vec3(1.0), 0.6);\n\n float band = min(mix(max(uDepth * uDpr, 1.0), uPeak, uSplay * uSplay), uPeak);\n float s = 1.0 - clamp(f.y / band, 0.0, 1.0);\n float height = sqrt(max(1.0 - s * s, 0.0));\n float e = uDpr;\n vec2 slope = vec2(field(px - vec2(e, 0.0)).y - field(px + vec2(e, 0.0)).y, field(px - vec2(0.0, e)).y - field(px + vec2(0.0, e)).y);\n vec2 g = slope / max(length(slope), 0.0001);\n vec3 n = normalize(vec3(g * s * s / sqrt(1.02 - s * s), 1.0));\n\n vec3 ray = refract(vec3(0.0, 0.0, -1.0), n, 1.0 / 1.5);\n vec2 shift = ray.xy / max(-ray.z, 0.5) * band * (0.35 + height) * uRefraction * 1.2 * uAppear;\n\n vec2 fromTouch = px - uTouch.xy;\n float reach = 90.0 * uDpr;\n float touch = exp(-dot(fromTouch, fromTouch) / (reach * reach)) * uTouch.z;\n shift -= fromTouch * touch * 0.12;\n\n vec2 at = px + shift;\n float squeeze = log2(max(max(length(dFdx(at)), length(dFdy(at))) * texels, 1.0));\n float k = 0.04 + uDispersion * 0.3;\n vec3 col = vec3(\n pick(at - shift * k, squeeze).r,\n pick(at, squeeze).g,\n pick(at + shift * k, squeeze).b\n );\n\n col = mix(vec3(dot(col, vec3(0.2126, 0.7152, 0.0722))), col, 1.08);\n col = mix(uTint, col, uTransparency);\n col = col * (1.0 + uLift) + uLift * 0.12;\n col += halo * uBloom * 0.22 * s;\n\n float facing = dot(n.xy, uLightDir);\n vec2 centered = (px - uCanvas * 0.5) / (uCanvas * 0.5);\n col += uLight * (max(facing, 0.0) * 0.3 + dot(centered, uLightDir) * 0.03);\n col *= 1.0 - uLight * max(-facing, 0.0) * 0.2;\n\n float toward = dot(g, uLightDir);\n col += uGlint * pow(s, 5.0) * (pow(max(toward, 0.0), 6.0) + pow(max(-toward, 0.0), 6.0) * 0.4);\n\n float line = smoothstep(-1.6 * uDpr, -0.6 * uDpr, d);\n col += uRim * line * (0.18 + 0.82 * toward * toward);\n col += touch * (0.16 + halo * 0.3);\n\n vec3 inside = clamp(col, 0.0, 1.0) * mask;\n float rest = (1.0 - mask) * spill;\n outColor = vec4(inside + spillColor * rest, mask + rest) * uAppear;\n}";
|
|
2
|
+
export declare const fragment = "#version 300 es\nprecision highp float;\n\nconst int MAX_SHAPES = 64;\nconst float SOFTNESS = 2.7;\n\nuniform sampler2D uBackdrop, uFrosted;\nuniform vec4 uBoxes[MAX_SHAPES];\nuniform vec2 uForms[MAX_SHAPES];\nuniform int uCount;\nuniform vec2 uCanvas, uUvOrigin, uUvPerPx, uTexSize, uLightDir;\nuniform vec3 uTint, uTouch;\nuniform float uViewY, uPad, uDpr, uPeak, uAppear, uLight, uTransparency, uRefraction, uDepth, uDispersion, uFrost, uSplay, uBloom, uGlint, uRim, uLift;\nout vec4 outColor;\n\nfloat roundedBox(vec2 p, vec2 b, float r) {\n vec2 q = abs(p) - b + r;\n return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - r;\n}\n\nfloat softMin(float a, float b) {\n float lo = min(a, b);\n return lo * pow(1.0 + pow(lo / max(a, b), SOFTNESS), -1.0 / SOFTNESS);\n}\n\nfloat blend(float a, float b, float k) {\n float h = max(k - abs(a - b), 0.0) / k;\n return min(a, b) - h * h * k * 0.25;\n}\n\n// \u2500\u2500 x is the distance to the merged outline, y how deep the point sits inside it, without creases\nvec2 field(vec2 p) {\n float joined = 1e5;\n float apart = 1e5;\n float inset = -1e5;\n for (int i = 0; i < MAX_SHAPES; i++) {\n if (i >= uCount) break;\n vec2 c = p - uBoxes[i].xy;\n vec2 b = uBoxes[i].zw;\n float r = uForms[i].x;\n float own = roundedBox(c, b, r);\n if (uForms[i].y > 0.0) joined = blend(joined, own, uForms[i].y);\n else apart = min(apart, own);\n if (own < 0.0) {\n vec2 edges = max(b - abs(c), 0.0) + r + 0.001;\n inset = max(inset, mix(softMin(edges.x, edges.y) - r, -own, r / min(b.x, b.y)));\n }\n }\n float d = min(joined, apart);\n return vec2(d, max(inset, -d));\n}\n\nvec2 toUv(vec2 px) {\n return uUvOrigin + px * uUvPerPx;\n}\n\nvec3 pick(vec2 px, float lod) {\n return uFrost > 0.0 ? texture(uFrosted, toUv(px)).rgb : textureLod(uBackdrop, toUv(px), lod).rgb;\n}\n\nvoid main() {\n vec2 px = vec2(gl_FragCoord.x, uCanvas.y - (gl_FragCoord.y - uViewY));\n vec2 f = field(px);\n float d = f.x;\n float texels = max(uUvPerPx.x * uTexSize.x, uUvPerPx.y * uTexSize.y);\n float haloLod = log2(max(28.0 * uDpr * texels, 1.0));\n vec3 halo = textureLod(uBackdrop, toUv(px), haloLod).rgb;\n\n float mask = 1.0 - smoothstep(-0.75, 0.75, d);\n float spill = exp(-max(d, 0.0) / (uPad * 0.3)) * uBloom * 0.4 * uLight;\n vec3 spillColor = mix(halo, vec3(1.0), 0.6);\n\n float band = min(mix(max(uDepth * uDpr, 1.0), uPeak, uSplay * uSplay), uPeak);\n float s = 1.0 - clamp(f.y / band, 0.0, 1.0);\n float height = sqrt(max(1.0 - s * s, 0.0));\n float e = uDpr;\n vec2 slope = vec2(field(px - vec2(e, 0.0)).y - field(px + vec2(e, 0.0)).y, field(px - vec2(0.0, e)).y - field(px + vec2(0.0, e)).y);\n vec2 g = slope / max(length(slope), 0.0001);\n vec3 n = normalize(vec3(g * s * s / sqrt(1.02 - s * s), 1.0));\n\n vec3 ray = refract(vec3(0.0, 0.0, -1.0), n, 1.0 / 1.5);\n vec2 shift = ray.xy / max(-ray.z, 0.5) * band * (0.35 + height) * uRefraction * 1.2 * uAppear;\n\n vec2 fromTouch = px - uTouch.xy;\n float reach = 90.0 * uDpr;\n float touch = exp(-dot(fromTouch, fromTouch) / (reach * reach)) * uTouch.z;\n shift -= fromTouch * touch * 0.12;\n\n vec2 at = px + shift;\n float squeeze = log2(max(max(length(dFdx(at)), length(dFdy(at))) * texels, 1.0));\n float k = 0.04 + uDispersion * 0.3;\n vec3 col = vec3(\n pick(at - shift * k, squeeze).r,\n pick(at, squeeze).g,\n pick(at + shift * k, squeeze).b\n );\n\n col = mix(vec3(dot(col, vec3(0.2126, 0.7152, 0.0722))), col, 1.08);\n col = mix(uTint, col, uTransparency);\n col = col * (1.0 + uLift) + uLift * 0.12;\n col += halo * uBloom * 0.22 * s;\n\n float facing = dot(n.xy, uLightDir);\n vec2 centered = (px - uCanvas * 0.5) / (uCanvas * 0.5);\n col += uLight * (max(facing, 0.0) * 0.3 + dot(centered, uLightDir) * 0.03);\n col *= 1.0 - uLight * max(-facing, 0.0) * 0.2;\n\n float toward = dot(g, uLightDir);\n col += uGlint * pow(s, 5.0) * (pow(max(toward, 0.0), 6.0) + pow(max(-toward, 0.0), 6.0) * 0.4);\n\n float line = smoothstep(-1.6 * uDpr, -0.6 * uDpr, d);\n col += uRim * line * (0.18 + 0.82 * toward * toward);\n col += touch * (0.16 + halo * 0.3);\n\n vec3 inside = clamp(col, 0.0, 1.0) * mask;\n float rest = (1.0 - mask) * spill;\n outColor = vec4(inside + spillColor * rest, mask + rest) * uAppear;\n}";
|
|
3
3
|
export declare const blurFragment = "#version 300 es\nprecision highp float;\n\nuniform sampler2D uSource;\nuniform vec2 uStep, uInvSize;\nuniform float uLod;\nout vec4 outColor;\n\nvoid main() {\n vec2 uv = gl_FragCoord.xy * uInvSize;\n vec3 sum = vec3(0.0);\n float total = 0.0;\n for (int i = -8; i <= 8; i++) {\n float x = float(i);\n float weight = exp(-x * x / 18.0);\n sum += textureLod(uSource, uv + uStep * x, uLod).rgb * weight;\n total += weight;\n }\n outColor = vec4(sum / total, 1.0);\n}";
|
package/dist/shader.js
CHANGED
|
@@ -48,7 +48,7 @@ vec2 field(vec2 p) {
|
|
|
48
48
|
else apart = min(apart, own);
|
|
49
49
|
if (own < 0.0) {
|
|
50
50
|
vec2 edges = max(b - abs(c), 0.0) + r + 0.001;
|
|
51
|
-
inset = max(inset, softMin(edges.x, edges.y) - r);
|
|
51
|
+
inset = max(inset, mix(softMin(edges.x, edges.y) - r, -own, r / min(b.x, b.y)));
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
float d = min(joined, apart);
|