@pixerate/flair 0.23.0 → 0.24.0
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/CHANGELOG.md +14 -0
- package/README.md +124 -6
- package/dist/catalog/index.d.ts +2 -2
- package/dist/catalog/index.js +1 -1
- package/dist/{chunk-4F4KL4KU.js → chunk-OQ4EWZ3B.js} +765 -7
- package/dist/chunk-OQ4EWZ3B.js.map +1 -0
- package/dist/editor/index.d.ts +1 -1
- package/dist/editor/index.js +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +1 -1
- package/dist/svelte/index.d.ts +1 -1
- package/dist/svelte/index.js +1 -1
- package/dist/{types-DLkbOX8d.d.ts → types-DUOMxZaq.d.ts} +1 -1
- package/package.json +5 -1
- package/dist/chunk-4F4KL4KU.js.map +0 -1
|
@@ -3715,6 +3715,53 @@ var liftCard = {
|
|
|
3715
3715
|
};
|
|
3716
3716
|
var shadowEffects = [liftCard];
|
|
3717
3717
|
|
|
3718
|
+
// src/catalog/lighting.ts
|
|
3719
|
+
var sway = (deg) => `rotate(${deg} 120 0)`;
|
|
3720
|
+
var pull = (step) => [
|
|
3721
|
+
{ id: "lampSwitchCord", step, attrs: { y2: [122, 135] }, ms: 110, ease: "out" },
|
|
3722
|
+
{ id: "lampSwitchCord", step, attrs: { y2: [135, 122] }, delay: 110, ms: 260, ease: "in-out" },
|
|
3723
|
+
{ id: "lampSwitchBead", step, attrs: { cy: [125, 138] }, ms: 110, ease: "out" },
|
|
3724
|
+
{ id: "lampSwitchBead", step, attrs: { cy: [138, 125] }, delay: 110, ms: 260, ease: "in-out" },
|
|
3725
|
+
{ id: "lampSwitchRig", step, attrs: { transform: [sway(0), sway(2.5)] }, delay: 110, ms: 260, ease: "out" },
|
|
3726
|
+
{ id: "lampSwitchRig", step, attrs: { transform: [sway(2.5), sway(-1.4)] }, delay: 370, ms: 380, ease: "in-out" },
|
|
3727
|
+
{ id: "lampSwitchRig", step, attrs: { transform: [sway(-1.4), sway(0)] }, delay: 750, ms: 420, ease: "in-out" }
|
|
3728
|
+
];
|
|
3729
|
+
var fade = (step, from, to, delay, ms) => ["lampSwitchCone", "lampSwitchPool", "lampSwitchRoomLit"].map((id) => ({ id, step, attrs: { opacity: [from, to] }, delay, ms, ease: "out" }));
|
|
3730
|
+
var lampSwitch = {
|
|
3731
|
+
kind: "vector",
|
|
3732
|
+
id: "lamp-switch",
|
|
3733
|
+
name: "Lamp switch",
|
|
3734
|
+
description: "A pendant lamp in a dark room: a click tugs its pull cord, the bulb flickers on and a warm cone of light fades in over the scene; the next click turns it off.",
|
|
3735
|
+
category: "lighting",
|
|
3736
|
+
tags: ["lighting", "lamp", "light", "switch", "toggle", "click", "interactive", "warm", "ui", "illustration"],
|
|
3737
|
+
trigger: "click",
|
|
3738
|
+
hold: 900,
|
|
3739
|
+
presets: [
|
|
3740
|
+
{ name: "Cool LED", values: { light: [0.78, 0.9, 1], shade: [0.85, 0.87, 0.9], lit: [0.16, 0.2, 0.26] } },
|
|
3741
|
+
{ name: "Brass", values: { shade: [0.75, 0.55, 0.22], light: [1, 0.72, 0.38], background: [0.08, 0.07, 0.06], lit: [0.3, 0.22, 0.14] } }
|
|
3742
|
+
],
|
|
3743
|
+
motion: {
|
|
3744
|
+
svg: `<svg viewBox="0 0 240 200"><!-- {{background: color default=#14121C label='Room'}} {{lit: color default=#3B2F2A label='Lit room'}} {{shade: color default=#2F7A72 label='Shade'}} {{bulbOff: color default=#57525E label='Bulb (off)'}} {{light: color default=#FFD27A label='Light'}} {{intensity: float min=0.2 max=1 default=0.8 label='Light strength'}} --><defs><linearGradient id="lampSwitchConeFade" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="{{light}}" stop-opacity="0.75"/><stop offset="1" stop-color="{{light}}" stop-opacity="0.05"/></linearGradient><radialGradient id="lampSwitchPoolFade"><stop offset="0" stop-color="{{light}}" stop-opacity="0.9"/><stop offset="1" stop-color="{{light}}" stop-opacity="0"/></radialGradient><filter id="lampSwitchBlur" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="6"/></filter><filter id="lampSwitchSoft" x="-20%" y="-20%" width="140%" height="140%"><feGaussianBlur stdDeviation="3"/></filter></defs><rect width="240" height="200" fill="{{background}}"/><rect id="lampSwitchRoomLit" width="240" height="200" fill="{{lit}}" opacity="0"/><rect x="0" y="186" width="240" height="14" fill="#000000" opacity="0.25"/><ellipse id="lampSwitchPool" cx="120" cy="188" rx="96" ry="16" fill="url(#lampSwitchPoolFade)" opacity="0"/><g fill="#000000" opacity="0.45"><rect x="92" y="160" width="56" height="5" rx="2"/><rect x="98" y="165" width="4" height="22"/><rect x="138" y="165" width="4" height="22"/><rect x="112" y="148" width="12" height="12" rx="2"/></g><g id="lampSwitchRig" transform="${sway(0)}"><path id="lampSwitchCone" d="M84 90 L156 90 L236 196 L4 196 Z" fill="url(#lampSwitchConeFade)" opacity="0" filter="url(#lampSwitchSoft)"/><line x1="120" y1="0" x2="120" y2="54" stroke="#8A8494" stroke-width="2"/><circle id="lampSwitchGlow" cx="120" cy="94" r="24" fill="{{light}}" opacity="0" filter="url(#lampSwitchBlur)"/><circle id="lampSwitchBulb" cx="120" cy="92" r="9" fill="{{bulbOff}}"/><path d="M110 50 L130 50 L133 56 L107 56 Z" fill="{{shade}}"/><path d="M104 56 L136 56 L162 90 L78 90 Z" fill="{{shade}}"/><path d="M104 56 L136 56 L140 61 L100 61 Z" fill="#FFFFFF" opacity="0.12"/><ellipse id="lampSwitchInner" cx="120" cy="90" rx="42" ry="4" fill="{{light}}" opacity="0"/><line id="lampSwitchCord" x1="154" y1="82" x2="154" y2="122" stroke="#B9B2C4" stroke-width="1.5"/><circle id="lampSwitchBead" cx="154" cy="125" r="3.5" fill="#D9D2E4"/></g></svg>`,
|
|
3745
|
+
animate: [
|
|
3746
|
+
// Step 1, on: a tug, the bulb flickers on and the light fades in over the room.
|
|
3747
|
+
...pull(1),
|
|
3748
|
+
{ id: "lampSwitchBulb", step: 1, attrs: { fill: ["{{bulbOff}}", "{{light}}"] }, delay: 140, ms: 80 },
|
|
3749
|
+
{ id: "lampSwitchGlow", step: 1, attrs: { opacity: [0, 0.9] }, delay: 140, ms: 60 },
|
|
3750
|
+
{ id: "lampSwitchGlow", step: 1, attrs: { opacity: [0.9, 0.25] }, delay: 200, ms: 70 },
|
|
3751
|
+
{ id: "lampSwitchGlow", step: 1, attrs: { opacity: [0.25, 1] }, delay: 270, ms: 240, ease: "out" },
|
|
3752
|
+
{ id: "lampSwitchInner", step: 1, attrs: { opacity: [0, 0.9] }, delay: 140, ms: 200, ease: "out" },
|
|
3753
|
+
...fade(1, 0, "{{intensity}}", 270, 520),
|
|
3754
|
+
// Step 2, off: a tug and everything dims back to the start.
|
|
3755
|
+
...pull(2),
|
|
3756
|
+
{ id: "lampSwitchBulb", step: 2, attrs: { fill: ["{{light}}", "{{bulbOff}}"] }, delay: 140, ms: 200 },
|
|
3757
|
+
{ id: "lampSwitchGlow", step: 2, attrs: { opacity: [1, 0] }, delay: 140, ms: 260, ease: "out" },
|
|
3758
|
+
{ id: "lampSwitchInner", step: 2, attrs: { opacity: [0.9, 0] }, delay: 140, ms: 220, ease: "out" },
|
|
3759
|
+
...fade(2, "{{intensity}}", 0, 140, 380)
|
|
3760
|
+
]
|
|
3761
|
+
}
|
|
3762
|
+
};
|
|
3763
|
+
var lightingEffects = [lampSwitch];
|
|
3764
|
+
|
|
3718
3765
|
// src/catalog/electric.ts
|
|
3719
3766
|
var r18 = (v) => Math.round(v * 10) / 10;
|
|
3720
3767
|
var about5 = (cx, cy, s) => `translate(${cx} ${cy}) scale(${Math.round(s * 1e3) / 1e3}) translate(${-cx} ${-cy})`;
|
|
@@ -5618,17 +5665,17 @@ var particleMorph = {
|
|
|
5618
5665
|
{ id: `p${i}`, attrs: { cx: [n9(`${from}x${i}`), n9(`${mid}x${i}`)], cy: [n9(`${from}y${i}`), n9(`${mid}y${i}`)] }, delay: at3 + i * DOT_STAGGER, ms: 450, ease: "out" },
|
|
5619
5666
|
{ id: `p${i}`, attrs: { cx: [n9(`${mid}x${i}`), n9(`${to}x${i}`)], cy: [n9(`${mid}y${i}`), n9(`${to}y${i}`)], fill: colours }, delay: at3 + 450 + i * DOT_STAGGER, ms: 650, ease: "in-out" }
|
|
5620
5667
|
];
|
|
5621
|
-
const
|
|
5668
|
+
const fade2 = (id, at3, show) => ({ id, attrs: { opacity: show ? [0, n9("ghost")] : [n9("ghost"), 0] }, delay: at3, ms: 450, ease: "in-out" });
|
|
5622
5669
|
return {
|
|
5623
5670
|
svg: `<svg viewBox="0 0 200 200"><!-- {{from: text default='${PARTICLE_FROM}' label='From path'}} {{to: text default='${PARTICLE_TO}' label='To path'}} {{fromColor: color default=#F472B6 label='From colour'}} {{toColor: color default=#FBBF24 label='To colour'}} {{background: color default=#0C0A1D label='Background'}} {{size: float min=0.8 max=6 default=2.6 step=0.1 label='Dot size'}} {{scatter: float min=0 max=80 default=34 step=1 label='Scatter'}} {{ghost: float min=0 max=1 default=0.16 label='Shape fill'}} --><rect width="200" height="200" fill="{{background}}"/><path id="ghostA" d="{{a}}" fill="{{fromColor}}" fill-rule="evenodd" opacity="{{ghost}}"/><path id="ghostB" d="{{b}}" fill="{{toColor}}" fill-rule="evenodd" opacity="0"/>${Array.from(
|
|
5624
5671
|
{ length: DOTS4 },
|
|
5625
5672
|
(_, i) => `<circle id="p${i}" cx="{{ax${i}}}" cy="{{ay${i}}}" r="{{size}}" fill="{{fromColor}}"/>`
|
|
5626
5673
|
).join("")}</svg>`,
|
|
5627
5674
|
animate: [
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5675
|
+
fade2("ghostA", 400, false),
|
|
5676
|
+
fade2("ghostB", 400 + spread + 900, true),
|
|
5677
|
+
fade2("ghostB", back, false),
|
|
5678
|
+
fade2("ghostA", back + spread + 900, true),
|
|
5632
5679
|
...Array.from({ length: DOTS4 }, (_, i) => [
|
|
5633
5680
|
...leg(i, 400, "a", "s", "b", ["{{fromColor}}", "{{toColor}}"]),
|
|
5634
5681
|
...leg(i, back, "b", "t", "a", ["{{toColor}}", "{{fromColor}}"])
|
|
@@ -18878,12 +18925,722 @@ var distortionShaders = [
|
|
|
18878
18925
|
textureDisplace
|
|
18879
18926
|
];
|
|
18880
18927
|
|
|
18928
|
+
// src/catalog/shaders/lighting.ts
|
|
18929
|
+
var RELIEF = `
|
|
18930
|
+
float heightAt(vec2 uv, float lod) {
|
|
18931
|
+
vec3 c = textureSize(uImage, 0).x > 1 ? textureLod(uImage, uv, lod).rgb : testCard(fract(uv));
|
|
18932
|
+
return dot(c, vec3(0.2126, 0.7152, 0.0722));
|
|
18933
|
+
}
|
|
18934
|
+
|
|
18935
|
+
// The height's slope at uv, in height per sample step.
|
|
18936
|
+
vec2 heightSlope(vec2 uv) {
|
|
18937
|
+
ivec2 size = textureSize(uImage, 0);
|
|
18938
|
+
vec2 texel = size.x > 1 ? 1.0 / vec2(size) : 1.0 / iResolution.xy;
|
|
18939
|
+
float texH = size.x > 1 ? float(size.y) : iResolution.y;
|
|
18940
|
+
vec2 d = texel * 1.5;
|
|
18941
|
+
float tl = heightAt(uv + vec2(-d.x, d.y), 0.0);
|
|
18942
|
+
float tc = heightAt(uv + vec2(0.0, d.y), 0.0);
|
|
18943
|
+
float tr = heightAt(uv + d, 0.0);
|
|
18944
|
+
float ml = heightAt(uv - vec2(d.x, 0.0), 0.0);
|
|
18945
|
+
float mr = heightAt(uv + vec2(d.x, 0.0), 0.0);
|
|
18946
|
+
float bl = heightAt(uv - d, 0.0);
|
|
18947
|
+
float bc = heightAt(uv - vec2(0.0, d.y), 0.0);
|
|
18948
|
+
float br = heightAt(uv + vec2(d.x, -d.y), 0.0);
|
|
18949
|
+
vec2 fine = vec2(tr + 2.0 * mr + br - tl - 2.0 * ml - bl, tl + 2.0 * tc + tr - bl - 2.0 * bc - br) * 0.125;
|
|
18950
|
+
// Broader forms: 2% and 8% of the picture's height apart, each read as blurred as its taps are apart.
|
|
18951
|
+
float s1 = 0.02 * texH;
|
|
18952
|
+
vec2 d1 = texel * s1;
|
|
18953
|
+
float l1 = log2(max(s1, 1.0));
|
|
18954
|
+
vec2 mid = vec2(heightAt(uv + vec2(d1.x, 0.0), l1) - heightAt(uv - vec2(d1.x, 0.0), l1),
|
|
18955
|
+
heightAt(uv + vec2(0.0, d1.y), l1) - heightAt(uv - vec2(0.0, d1.y), l1)) * 0.5;
|
|
18956
|
+
float s2 = 0.08 * texH;
|
|
18957
|
+
vec2 d2 = texel * s2;
|
|
18958
|
+
float l2 = log2(max(s2, 1.0));
|
|
18959
|
+
vec2 broad = vec2(heightAt(uv + vec2(d2.x, 0.0), l2) - heightAt(uv - vec2(d2.x, 0.0), l2),
|
|
18960
|
+
heightAt(uv + vec2(0.0, d2.y), l2) - heightAt(uv - vec2(0.0, d2.y), l2)) * 0.5;
|
|
18961
|
+
return fine * 0.5 + mid * 0.6 + broad * 0.6;
|
|
18962
|
+
}
|
|
18963
|
+
|
|
18964
|
+
vec3 surfaceNormal(vec2 uv, float strength) {
|
|
18965
|
+
return normalize(vec3(-heightSlope(uv) * strength, 1.0));
|
|
18966
|
+
}
|
|
18967
|
+
|
|
18968
|
+
vec2 shade(vec3 n, vec3 l, float shininess) {
|
|
18969
|
+
float diff = max(dot(n, l), 0.0);
|
|
18970
|
+
vec3 h = normalize(l + vec3(0.0, 0.0, 1.0));
|
|
18971
|
+
float spec = pow(max(dot(n, h), 0.0), shininess) * step(0.0, diff - 1e-3);
|
|
18972
|
+
return vec2(diff, spec);
|
|
18973
|
+
}
|
|
18974
|
+
|
|
18975
|
+
// Light above 1 rolls off instead of clipping.
|
|
18976
|
+
vec3 rolloff(vec3 c) {
|
|
18977
|
+
return c / (1.0 + max(c - 1.0, 0.0));
|
|
18978
|
+
}`.trim();
|
|
18979
|
+
var relight2 = {
|
|
18980
|
+
kind: "shader",
|
|
18981
|
+
id: "relight",
|
|
18982
|
+
name: "Relight",
|
|
18983
|
+
description: "A picture relit by a directional light you can swing round and raise, its surfaces read from brightness so they catch the light or fall into shade.",
|
|
18984
|
+
category: "lighting",
|
|
18985
|
+
video: "filter",
|
|
18986
|
+
tags: ["lighting", "relight", "image", "normal-map", "directional", "shading", "filter"],
|
|
18987
|
+
source: glsl(
|
|
18988
|
+
`// Relight: normals from a Sobel height map of the picture's brightness, shaded by one directional light.
|
|
18989
|
+
uniform sampler2D uImage; // @control filter=mipmap wrap=clamp default=${SAMPLE_IMAGES.portrait} label="Image"
|
|
18990
|
+
uniform float uAzimuth; // @control min=0 max=360 default=150 label="Light from (\xB0)"
|
|
18991
|
+
uniform float uElevation; // @control min=5 max=90 default=35 label="Light height (\xB0)"
|
|
18992
|
+
uniform vec3 uLight; // @control color default=#FFE6C4 label="Light colour"
|
|
18993
|
+
uniform float uIntensity; // @control min=0 max=3 default=1.4 label="Intensity"
|
|
18994
|
+
uniform vec3 uAmbientColor; // @control color default=#8EA2C8 label="Ambient colour"
|
|
18995
|
+
uniform float uAmbient; // @control min=0 max=1 default=0.4 label="Ambient"
|
|
18996
|
+
uniform float uStrength; // @control min=0 max=10 default=4 label="Relief"
|
|
18997
|
+
uniform float uSpecular; // @control min=0 max=1 default=0.25 label="Specular"
|
|
18998
|
+
uniform float uFalloff; // @control min=0 max=1 default=0.3 label="Falloff across the frame"
|
|
18999
|
+
${BACKDROP_CONTROLS}`,
|
|
19000
|
+
PICTURE,
|
|
19001
|
+
RELIEF,
|
|
19002
|
+
`void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
19003
|
+
vec2 uv = fragCoord / iResolution.xy;
|
|
19004
|
+
vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
|
|
19005
|
+
float az = radians(uAzimuth);
|
|
19006
|
+
float el = radians(uElevation);
|
|
19007
|
+
vec3 l = vec3(cos(el) * cos(az), cos(el) * sin(az), sin(el));
|
|
19008
|
+
vec3 n = surfaceNormal(uv, uStrength);
|
|
19009
|
+
vec2 s = shade(n, l, 36.0);
|
|
19010
|
+
// The side of the frame nearer the light is a little brighter, more so the lower it is.
|
|
19011
|
+
float wash = max(1.0 + uFalloff * dot(p, l.xy) * 1.6 * (1.0 - 0.6 * l.z), 0.0);
|
|
19012
|
+
vec4 pic = pictureRGBA(uImage, uv);
|
|
19013
|
+
vec3 lit = uAmbientColor * uAmbient + uLight * uIntensity * s.x * wash;
|
|
19014
|
+
vec3 col = pic.rgb * lit + uLight * s.y * uSpecular * wash;
|
|
19015
|
+
fragColor = vec4(rolloff(col), pic.a);
|
|
19016
|
+
}`
|
|
19017
|
+
),
|
|
19018
|
+
presets: [
|
|
19019
|
+
{ name: "Morning side light", values: { uAzimuth: 175, uElevation: 16, uLight: [1, 0.78, 0.52], uIntensity: 1.8, uAmbientColor: [0.5, 0.62, 0.9], uAmbient: 0.35, uFalloff: 0.6 } },
|
|
19020
|
+
{ name: "Top light", values: { uAzimuth: 90, uElevation: 72, uLight: [1, 0.98, 0.94], uIntensity: 1.2, uAmbient: 0.25, uFalloff: 0.5, uSpecular: 0.35 } },
|
|
19021
|
+
{ name: "Dramatic", values: { uAzimuth: 20, uElevation: 10, uLight: [1, 0.9, 0.8], uIntensity: 2.6, uAmbient: 0.05, uStrength: 7, uSpecular: 0.5, uFalloff: 0.8 } }
|
|
19022
|
+
]
|
|
19023
|
+
};
|
|
19024
|
+
var pointLight = {
|
|
19025
|
+
kind: "shader",
|
|
19026
|
+
id: "point-light",
|
|
19027
|
+
name: "Point light",
|
|
19028
|
+
description: "A torch moving over a darkened picture, following the pointer while it hovers and drifting on its own otherwise, lighting the surfaces that face it.",
|
|
19029
|
+
category: "lighting",
|
|
19030
|
+
video: "interactive",
|
|
19031
|
+
tags: ["lighting", "torch", "flashlight", "image", "interactive", "hover", "normal-map", "dark"],
|
|
19032
|
+
source: glsl(
|
|
19033
|
+
`// Point light: a light just above the picture, at the pointer while hovered and drifting otherwise, shading normals from brightness.
|
|
19034
|
+
uniform sampler2D uImage; // @control filter=mipmap wrap=clamp default=${SAMPLE_IMAGES.landscape} label="Image"
|
|
19035
|
+
uniform vec3 uColor; // @control color default=#FFDDA8 label="Light colour"
|
|
19036
|
+
uniform float uIntensity; // @control min=0 max=4 default=1.8 label="Intensity"
|
|
19037
|
+
uniform float uRadius; // @control min=0.05 max=1.5 default=0.45 label="Falloff radius"
|
|
19038
|
+
uniform float uHeight; // @control min=0.02 max=0.5 default=0.1 label="Light height"
|
|
19039
|
+
uniform float uAmbient; // @control min=0 max=0.5 default=0.04 label="Ambient"
|
|
19040
|
+
uniform float uStrength; // @control min=0 max=10 default=4 label="Relief"
|
|
19041
|
+
uniform float uSpecular; // @control min=0 max=1 default=0.4 label="Specular"
|
|
19042
|
+
uniform float uSpeed; // @control min=0 max=2 default=0.6 label="Drift speed"
|
|
19043
|
+
${BACKDROP_CONTROLS}`,
|
|
19044
|
+
PICTURE,
|
|
19045
|
+
RELIEF,
|
|
19046
|
+
`void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
19047
|
+
vec2 uv = fragCoord / iResolution.xy;
|
|
19048
|
+
vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
|
|
19049
|
+
// Where the light is: the pointer while it hovers, else a slow wander.
|
|
19050
|
+
float t = iTime * uSpeed;
|
|
19051
|
+
vec2 drift = iResolution.xy * (0.5 + vec2(0.32 * sin(t * 0.63), 0.26 * sin(t * 0.91 + 1.3)));
|
|
19052
|
+
float hover = clamp(iPointer.z, 0.0, 1.0);
|
|
19053
|
+
vec2 at = (mix(drift, iPointer.xy, hover) - 0.5 * iResolution.xy) / iResolution.y;
|
|
19054
|
+
vec3 toLight = vec3(at - p, uHeight);
|
|
19055
|
+
float dist = length(toLight);
|
|
19056
|
+
vec3 l = toLight / dist;
|
|
19057
|
+
// Inverse-square near the light, faded to nothing past the radius.
|
|
19058
|
+
float k = dist / (0.35 * uRadius);
|
|
19059
|
+
float att = 1.0 / (1.0 + k * k) * (1.0 - smoothstep(0.4 * uRadius, 1.5 * uRadius, dist));
|
|
19060
|
+
vec3 n = surfaceNormal(uv, uStrength);
|
|
19061
|
+
vec2 s = shade(n, l, 28.0);
|
|
19062
|
+
vec4 pic = pictureRGBA(uImage, uv);
|
|
19063
|
+
vec3 light = uColor * uIntensity * att;
|
|
19064
|
+
vec3 col = pic.rgb * (vec3(uAmbient) * vec3(0.7, 0.8, 1.0) + light * s.x) + light * s.y * uSpecular;
|
|
19065
|
+
fragColor = vec4(rolloff(col), pic.a);
|
|
19066
|
+
}`
|
|
19067
|
+
),
|
|
19068
|
+
presets: [
|
|
19069
|
+
{ name: "Torch", values: { uColor: [1, 0.93, 0.8], uRadius: 0.35, uAmbient: 0.01, uIntensity: 2.4 } },
|
|
19070
|
+
{ name: "Lantern", values: { uColor: [1, 0.66, 0.3], uRadius: 0.8, uHeight: 0.2, uAmbient: 0.08, uSpecular: 0.2 } },
|
|
19071
|
+
{ name: "Inspection lamp", values: { uImage: SAMPLE_IMAGES.portrait, uColor: [0.85, 0.93, 1], uHeight: 0.04, uStrength: 8, uSpecular: 0.8, uAmbient: 0.1 } }
|
|
19072
|
+
]
|
|
19073
|
+
};
|
|
19074
|
+
var studioLighting = {
|
|
19075
|
+
kind: "shader",
|
|
19076
|
+
id: "studio-lighting",
|
|
19077
|
+
name: "Studio lighting",
|
|
19078
|
+
description: "Three-point lighting on a subject: a warm key from one side, a cool fill from the other and a bright rim tracing its silhouette, against a darkened studio backdrop.",
|
|
19079
|
+
category: "lighting",
|
|
19080
|
+
// Each frame is lit on its own, so it works live on a subject shot against a plain backdrop (or with alpha).
|
|
19081
|
+
video: "filter",
|
|
19082
|
+
tags: ["lighting", "studio", "portrait", "three-point", "key-light", "rim", "image", "filter"],
|
|
19083
|
+
source: glsl(
|
|
19084
|
+
`// Studio lighting: key and fill shade normals from brightness; a rim lights the subject's edge (alpha, or the corner colour keyed out) on the side away from the key.
|
|
19085
|
+
uniform sampler2D uImage; // @control filter=mipmap wrap=clamp default=${SAMPLE_IMAGES.portrait} label="Subject"
|
|
19086
|
+
uniform float uKeyAngle; // @control min=0 max=360 default=155 label="Key from (\xB0)"
|
|
19087
|
+
uniform vec3 uKeyColor; // @control color default=#FFD2A0 label="Key colour"
|
|
19088
|
+
uniform float uKey; // @control min=0 max=3 default=1.4 label="Key strength"
|
|
19089
|
+
uniform vec3 uFillColor; // @control color default=#86A8FF label="Fill colour"
|
|
19090
|
+
uniform float uFill; // @control min=0 max=2 default=0.5 label="Fill strength"
|
|
19091
|
+
uniform vec3 uRimColor; // @control color default=#EAF2FF label="Rim colour"
|
|
19092
|
+
uniform float uRim; // @control min=0 max=4 default=1.8 label="Rim strength"
|
|
19093
|
+
uniform float uRimWidth; // @control min=0.003 max=0.06 default=0.016 label="Rim width"
|
|
19094
|
+
uniform float uStrength; // @control min=0 max=10 default=4 label="Relief"
|
|
19095
|
+
uniform float uKeyOut; // @control min=0 max=0.5 default=0.12 label="Key out the corner colour (0 off)"
|
|
19096
|
+
uniform vec3 uStudio; // @control color default=#1B1D24 label="Studio backdrop"
|
|
19097
|
+
uniform float uStudioMix; // @control min=0 max=1 default=0.85 label="Replace the background"
|
|
19098
|
+
${BACKDROP_CONTROLS}`,
|
|
19099
|
+
PICTURE,
|
|
19100
|
+
RELIEF,
|
|
19101
|
+
`vec3 gKey;
|
|
19102
|
+
bool gKeyOn;
|
|
19103
|
+
|
|
19104
|
+
// How much of the subject there is at uv (alpha, less the backdrop colour when keyed), read at mip level lod.
|
|
19105
|
+
float subjectAt(vec2 uv, float lod) {
|
|
19106
|
+
if (textureSize(uImage, 0).x <= 1) return 1.0;
|
|
19107
|
+
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) return 0.0;
|
|
19108
|
+
vec4 c = textureLod(uImage, uv, lod);
|
|
19109
|
+
float a = c.a;
|
|
19110
|
+
if (gKeyOn) a *= smoothstep(uKeyOut, uKeyOut + 0.12, distance(c.rgb / max(c.a, 1e-3), gKey));
|
|
19111
|
+
return a;
|
|
19112
|
+
}
|
|
19113
|
+
|
|
19114
|
+
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
19115
|
+
vec2 uv = fragCoord / iResolution.xy;
|
|
19116
|
+
vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
|
|
19117
|
+
vec4 corner = textureLod(uImage, vec2(0.01, 0.99), 0.0);
|
|
19118
|
+
gKey = corner.rgb / max(corner.a, 1e-3);
|
|
19119
|
+
// A picture already cut out (a clear corner) keeps its alpha as the subject.
|
|
19120
|
+
gKeyOn = uKeyOut > 0.0 && corner.a > 0.5;
|
|
19121
|
+
ivec2 size = textureSize(uImage, 0);
|
|
19122
|
+
float texH = size.x > 1 ? float(size.y) : iResolution.y;
|
|
19123
|
+
vec2 aspect = vec2(size.x > 1 ? float(size.y) / float(size.x) : iResolution.y / iResolution.x, 1.0);
|
|
19124
|
+
|
|
19125
|
+
float ka = radians(uKeyAngle);
|
|
19126
|
+
vec2 keyDir = vec2(cos(ka), sin(ka));
|
|
19127
|
+
vec3 key = normalize(vec3(keyDir * 0.8, 0.6));
|
|
19128
|
+
vec3 fill = normalize(vec3(-keyDir * 0.9, 0.45));
|
|
19129
|
+
// The rim comes from behind, on the side away from the key and a little above.
|
|
19130
|
+
vec2 rimDir = normalize(vec2(-keyDir.x, 0.5 + 0.5 * abs(keyDir.y)));
|
|
19131
|
+
|
|
19132
|
+
vec3 n = surfaceNormal(uv, uStrength);
|
|
19133
|
+
vec2 ks = shade(n, key, 30.0);
|
|
19134
|
+
float fillWrap = clamp((dot(n, fill) + 0.4) / 1.4, 0.0, 1.0);
|
|
19135
|
+
|
|
19136
|
+
float subject = subjectAt(uv, 0.0);
|
|
19137
|
+
// The rim: the subject where what lies toward the rim light is backdrop, plus a little all round its edge.
|
|
19138
|
+
float lod = log2(max(uRimWidth * texH * 0.6, 1.0));
|
|
19139
|
+
vec2 w = rimDir * uRimWidth * aspect;
|
|
19140
|
+
float toward = 0.5 * (subjectAt(uv + w, lod) + subjectAt(uv + w * 0.5, lod - 1.0));
|
|
19141
|
+
float around = 0.25 * (subjectAt(uv + vec2(uRimWidth, 0.0) * aspect, lod) + subjectAt(uv - vec2(uRimWidth, 0.0) * aspect, lod)
|
|
19142
|
+
+ subjectAt(uv + vec2(0.0, uRimWidth), lod) + subjectAt(uv - vec2(0.0, uRimWidth), lod));
|
|
19143
|
+
float rim = subject * (clamp(1.0 - toward, 0.0, 1.0) + 0.3 * clamp(1.0 - around, 0.0, 1.0));
|
|
19144
|
+
rim = smoothstep(0.05, 0.6, rim);
|
|
19145
|
+
|
|
19146
|
+
vec4 pic = pictureRGBA(uImage, uv);
|
|
19147
|
+
vec3 lit = vec3(0.06) + uKeyColor * uKey * ks.x + uFillColor * uFill * fillWrap;
|
|
19148
|
+
vec3 col = pic.rgb * lit + uKeyColor * ks.y * uKey * 0.25 + uRimColor * rim * uRim * (0.6 + 0.4 * pic.rgb);
|
|
19149
|
+
|
|
19150
|
+
// The studio backdrop behind: its colour, a soft pool of key light on the key's side, darker toward the corners.
|
|
19151
|
+
float pool = exp(-2.5 * dot(p - keyDir * 0.35, p - keyDir * 0.35));
|
|
19152
|
+
vec3 studio = uStudio * (0.55 + 0.9 * pool) + uKeyColor * uStudio * pool * 0.6;
|
|
19153
|
+
float back = (1.0 - subject) * uStudioMix;
|
|
19154
|
+
col = mix(col, studio, back);
|
|
19155
|
+
// Where the picture is clear the backdrop's opacity holds, so a cut-out stays clear on a clear backdrop.
|
|
19156
|
+
fragColor = vec4(rolloff(col), pic.a);
|
|
19157
|
+
}`
|
|
19158
|
+
),
|
|
19159
|
+
presets: [
|
|
19160
|
+
{ name: "Classic portrait", values: { uKeyColor: [1, 0.9, 0.78], uFillColor: [0.75, 0.82, 1], uFill: 0.6, uRim: 1.2 } },
|
|
19161
|
+
{ name: "Noir", values: { uKeyColor: [1, 1, 1], uKey: 1.8, uFill: 0.08, uRimColor: [1, 1, 1], uRim: 2.6, uStudio: [0.04, 0.04, 0.05], uStudioMix: 1 } },
|
|
19162
|
+
{ name: "Music video", values: { uKeyColor: [1, 0.35, 0.65], uFillColor: [0.2, 0.55, 1], uFill: 1.2, uRimColor: [0.5, 1, 0.9], uRim: 2.6, uStudio: [0.08, 0.04, 0.14] } }
|
|
19163
|
+
]
|
|
19164
|
+
};
|
|
19165
|
+
var timeOfDay = {
|
|
19166
|
+
kind: "shader",
|
|
19167
|
+
id: "time-of-day",
|
|
19168
|
+
name: "Time of day",
|
|
19169
|
+
description: "A picture regraded and relit through the day, from cool dawn through white noon and golden hour to blue hour and a night where its brightest spots glow like lit windows.",
|
|
19170
|
+
category: "lighting",
|
|
19171
|
+
video: "filter",
|
|
19172
|
+
loop: 24,
|
|
19173
|
+
tags: ["lighting", "time-of-day", "golden-hour", "blue-hour", "night", "sun", "grade", "image", "filter"],
|
|
19174
|
+
source: glsl(
|
|
19175
|
+
`// Time of day: a sun on a 24-hour arc shades normals from brightness, a sky colour tints and darkens the picture, and its bright spots light up at night.
|
|
19176
|
+
uniform sampler2D uImage; // @control filter=mipmap wrap=clamp default=${SAMPLE_IMAGES.landscape} label="Image"
|
|
19177
|
+
uniform float uHour; // @control min=0 max=24 default=6 label="Hour"
|
|
19178
|
+
uniform float uSpeed; // @control min=0 max=4 default=1 label="Hours per second (0 holds)"
|
|
19179
|
+
uniform float uStrength; // @control min=0 max=10 default=3 label="Relief"
|
|
19180
|
+
uniform float uSkyTint; // @control min=0 max=1 default=0.6 label="Sky tint"
|
|
19181
|
+
uniform float uNightLights; // @control min=0 max=2 default=1 label="Night lights"
|
|
19182
|
+
uniform vec3 uLampColor; // @control color default=#FFC46B label="Night light colour"
|
|
19183
|
+
uniform float uThreshold; // @control min=0 max=1 default=0.62 label="Lights from brightness above"
|
|
19184
|
+
${BACKDROP_CONTROLS}`,
|
|
19185
|
+
PICTURE,
|
|
19186
|
+
RELIEF,
|
|
19187
|
+
`float luma(vec3 c) {
|
|
19188
|
+
return dot(c, vec3(0.2126, 0.7152, 0.0722));
|
|
19189
|
+
}
|
|
19190
|
+
|
|
19191
|
+
// Brightness above the lights' threshold at mip level lod, so the brightest spots light up at night.
|
|
19192
|
+
float glowAt(vec2 uv, float lod) {
|
|
19193
|
+
vec3 c = textureSize(uImage, 0).x > 1 ? textureLod(uImage, uv, lod).rgb : testCard(fract(uv));
|
|
19194
|
+
return smoothstep(uThreshold, min(uThreshold + 0.25, 1.0), luma(c));
|
|
19195
|
+
}
|
|
19196
|
+
|
|
19197
|
+
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
19198
|
+
vec2 uv = fragCoord / iResolution.xy;
|
|
19199
|
+
float hour = mod(uHour + iTime * uSpeed, 24.0);
|
|
19200
|
+
// The sun: up at 6, highest at 12, down at 18; it crosses from the left (morning) to the right (evening).
|
|
19201
|
+
float arc = (hour - 6.0) / 12.0 * 3.14159;
|
|
19202
|
+
float e = sin(arc);
|
|
19203
|
+
float across = -cos(arc);
|
|
19204
|
+
float morning = 1.0 - smoothstep(10.0, 14.0, hour) * (1.0 - smoothstep(22.0, 24.0, hour));
|
|
19205
|
+
vec3 l = normalize(vec3(across, 0.25 + 0.6 * max(e, 0.0), 0.2 + 0.9 * max(e, 0.0)));
|
|
19206
|
+
|
|
19207
|
+
float day = smoothstep(-0.04, 0.22, e);
|
|
19208
|
+
float night = 1.0 - smoothstep(-0.38, -0.12, e);
|
|
19209
|
+
// Sun colour: warm and low (pinker at dawn, deeper gold at dusk), near white overhead.
|
|
19210
|
+
vec3 low = mix(vec3(1.0, 0.5, 0.22), vec3(1.0, 0.62, 0.58), morning);
|
|
19211
|
+
vec3 sun = mix(low, vec3(1.0, 0.97, 0.92), smoothstep(0.12, 0.65, e));
|
|
19212
|
+
// Sky light: deep blue night, blue hour, a warm low-sun sky, then daylight blue.
|
|
19213
|
+
vec3 sky = mix(vec3(0.05, 0.07, 0.17), vec3(0.24, 0.32, 0.72), smoothstep(-0.4, -0.12, e));
|
|
19214
|
+
sky = mix(sky, mix(vec3(0.85, 0.55, 0.5), vec3(0.8, 0.62, 0.7), morning), smoothstep(-0.12, 0.04, e));
|
|
19215
|
+
sky = mix(sky, vec3(0.62, 0.74, 1.0), smoothstep(0.12, 0.55, e));
|
|
19216
|
+
|
|
19217
|
+
vec4 pic = pictureRGBA(uImage, uv);
|
|
19218
|
+
float lum = luma(pic.rgb);
|
|
19219
|
+
// Night sees in blue-grey: colour drains as it darkens.
|
|
19220
|
+
vec3 albedo = mix(pic.rgb, vec3(lum), night * 0.55);
|
|
19221
|
+
vec3 n = surfaceNormal(uv, uStrength);
|
|
19222
|
+
vec2 s = shade(n, l, 30.0);
|
|
19223
|
+
vec3 col = albedo * (sky * mix(0.55, 0.45, day) + sun * day * (0.25 + 1.0 * s.x)) + sun * day * s.y * 0.15;
|
|
19224
|
+
// The grade: the whole picture leans toward the sky's colour.
|
|
19225
|
+
vec3 tint = sky / max(luma(sky), 0.05);
|
|
19226
|
+
col *= mix(vec3(1.0), clamp(tint, 0.0, 2.0), uSkyTint * 0.4);
|
|
19227
|
+
|
|
19228
|
+
// Lights come on at dusk: the brightest spots glow, with a soft halo.
|
|
19229
|
+
float on = (1.0 - smoothstep(-0.22, 0.02, e)) * uNightLights;
|
|
19230
|
+
float lamp = glowAt(uv, 0.0);
|
|
19231
|
+
float halo = glowAt(uv, 3.0) * 0.6 + glowAt(uv, 5.0) * 0.5;
|
|
19232
|
+
col += uLampColor * on * (lamp * (0.6 + 0.6 * lum) + halo * 0.5);
|
|
19233
|
+
fragColor = vec4(rolloff(col), pic.a);
|
|
19234
|
+
}`
|
|
19235
|
+
),
|
|
19236
|
+
presets: [
|
|
19237
|
+
{ name: "Golden hour", values: { uHour: 17.4, uSpeed: 0 } },
|
|
19238
|
+
{ name: "Blue hour", values: { uHour: 19.3, uSpeed: 0 } },
|
|
19239
|
+
{ name: "Night city", values: { uImage: SAMPLE_IMAGES.city, uHour: 22, uSpeed: 0, uThreshold: 0.5, uNightLights: 1.4 } }
|
|
19240
|
+
]
|
|
19241
|
+
};
|
|
19242
|
+
var goboProjection = {
|
|
19243
|
+
kind: "shader",
|
|
19244
|
+
id: "gobo-projection",
|
|
19245
|
+
name: "Gobo projection",
|
|
19246
|
+
description: "A theatre light throwing a patterned gobo onto a picture (window panes, foliage, stars, venetian slats or your own text), softly focused and slowly drifting.",
|
|
19247
|
+
category: "lighting",
|
|
19248
|
+
video: "filter",
|
|
19249
|
+
tags: ["lighting", "gobo", "projection", "stage", "theatre", "pattern", "text", "image", "filter"],
|
|
19250
|
+
source: glsl(
|
|
19251
|
+
`// Gobo projection: a soft beam broken up by a pattern (or the gobo image's alpha), drifting, multiplied into the picture.
|
|
19252
|
+
uniform sampler2D uImage; // @control filter=linear wrap=clamp default=${SAMPLE_IMAGES.portrait} label="Image"
|
|
19253
|
+
uniform int uPattern; // @control min=0 max=4 default=1 label="Gobo (0 window, 1 foliage, 2 stars, 3 slats, 4 gobo image)"
|
|
19254
|
+
uniform sampler2D uGobo; // @control filter=mipmap wrap=clamp default=${textImage("LIGHTS")} label="Gobo image (alpha lets light through)"
|
|
19255
|
+
uniform vec3 uColor; // @control color default=#FFE4BC label="Light colour"
|
|
19256
|
+
uniform float uIntensity; // @control min=0 max=3 default=1.1 label="Intensity"
|
|
19257
|
+
uniform float uAmbient; // @control min=0 max=1 default=0.3 label="Ambient"
|
|
19258
|
+
uniform float uScale; // @control min=0.3 max=3 default=1 label="Scale"
|
|
19259
|
+
uniform float uAngle; // @control min=-180 max=180 default=-12 label="Angle (\xB0)"
|
|
19260
|
+
uniform float uSoftness; // @control min=0 max=1 default=0.3 label="Soft focus"
|
|
19261
|
+
uniform float uDrift; // @control min=0 max=2 default=0.6 label="Drift"
|
|
19262
|
+
${BACKDROP_CONTROLS}`,
|
|
19263
|
+
PICTURE,
|
|
19264
|
+
HASH,
|
|
19265
|
+
NOISE,
|
|
19266
|
+
FBM,
|
|
19267
|
+
ROTATE,
|
|
19268
|
+
`float windowPanes(vec2 q, float s) {
|
|
19269
|
+
vec2 frame = abs(q) - vec2(0.42, 0.34);
|
|
19270
|
+
float inside = smoothstep(s, -s, max(frame.x, frame.y));
|
|
19271
|
+
// Three panes across, two down, between glazing bars.
|
|
19272
|
+
vec2 g = abs(fract((q + vec2(0.42, 0.34)) / vec2(0.28, 0.34)) - 0.5);
|
|
19273
|
+
float bar = 0.07 + s * 0.5;
|
|
19274
|
+
float pane = smoothstep(0.5 - bar - s, 0.5 - bar + s, 0.5 - max(g.x * 1.0, g.y));
|
|
19275
|
+
return inside * pane;
|
|
19276
|
+
}
|
|
19277
|
+
|
|
19278
|
+
float foliage(vec2 q, float s, float t) {
|
|
19279
|
+
vec2 sway = vec2(sin(t * 0.7 + q.y * 2.0), cos(t * 0.5 + q.x * 1.7)) * 0.03 * uDrift;
|
|
19280
|
+
float n = fbm((q + sway) * 6.0 + 2.0, 5);
|
|
19281
|
+
float w = 0.02 + s * 0.1;
|
|
19282
|
+
return smoothstep(0.5 - w, 0.5 + w, n);
|
|
19283
|
+
}
|
|
19284
|
+
|
|
19285
|
+
float stars(vec2 q, float s) {
|
|
19286
|
+
vec2 cell = floor(q / 0.2);
|
|
19287
|
+
vec2 f = fract(q / 0.2) - 0.5;
|
|
19288
|
+
vec2 h = hash22(cell + 3.1);
|
|
19289
|
+
f -= (h - 0.5) * 0.35;
|
|
19290
|
+
f = rot(h.x * 6.28) * f;
|
|
19291
|
+
float r = length(f);
|
|
19292
|
+
float a = atan(f.y, f.x);
|
|
19293
|
+
float edge = (0.16 + 0.12 * h.y) * (0.55 + 0.45 * pow(abs(cos(2.5 * a)), 3.0));
|
|
19294
|
+
float keep = step(0.25, hash12(cell + 7.7));
|
|
19295
|
+
return keep * smoothstep(edge + 0.02 + s * 0.12, edge - 0.02 - s * 0.05, r);
|
|
19296
|
+
}
|
|
19297
|
+
|
|
19298
|
+
float slats(vec2 q, float s) {
|
|
19299
|
+
float f = fract(q.y * 8.0);
|
|
19300
|
+
float w = 0.04 + s * 0.25;
|
|
19301
|
+
float lit = smoothstep(0.0, w, f) * smoothstep(0.62 + w, 0.62, f);
|
|
19302
|
+
return lit * smoothstep(0.5 + s * 0.1, 0.44, abs(q.x));
|
|
19303
|
+
}
|
|
19304
|
+
|
|
19305
|
+
float goboImage(vec2 q, float s) {
|
|
19306
|
+
ivec2 size = textureSize(uGobo, 0);
|
|
19307
|
+
if (size.x <= 1) return 0.0;
|
|
19308
|
+
float aspect = float(size.x) / float(size.y);
|
|
19309
|
+
float w = min(1.3, 1.3 * aspect);
|
|
19310
|
+
vec2 g = q / vec2(w, w / aspect) + 0.5;
|
|
19311
|
+
if (g.x < 0.0 || g.x > 1.0 || g.y < 0.0 || g.y > 1.0) return 0.0;
|
|
19312
|
+
return textureLod(uGobo, g, log2(1.0 + s * 0.03 * float(size.y))).a;
|
|
19313
|
+
}
|
|
19314
|
+
|
|
19315
|
+
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
19316
|
+
vec2 uv = fragCoord / iResolution.xy;
|
|
19317
|
+
vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
|
|
19318
|
+
float t = iTime;
|
|
19319
|
+
vec2 shift = vec2(sin(t * 0.13), cos(t * 0.11)) * 0.05 * uDrift;
|
|
19320
|
+
vec2 q = rot(radians(uAngle) + sin(t * 0.09) * 0.06 * uDrift) * (p - shift) / uScale;
|
|
19321
|
+
float s = uSoftness * 0.06;
|
|
19322
|
+
float lit = uPattern == 0 ? windowPanes(q, s)
|
|
19323
|
+
: uPattern == 1 ? foliage(q, uSoftness, t)
|
|
19324
|
+
: uPattern == 2 ? stars(q, s)
|
|
19325
|
+
: uPattern == 3 ? slats(q, uSoftness)
|
|
19326
|
+
: goboImage(q, uSoftness);
|
|
19327
|
+
// The beam: a soft-edged spot round the gobo.
|
|
19328
|
+
float beam = 1.0 - smoothstep(0.45, 0.85 + 0.2 * uSoftness, length(q * vec2(0.75, 1.0)));
|
|
19329
|
+
vec4 pic = pictureRGBA(uImage, uv);
|
|
19330
|
+
vec3 light = mix(vec3(uAmbient) * vec3(0.92, 0.95, 1.0), uColor * uIntensity, lit * beam);
|
|
19331
|
+
vec3 col = pic.rgb * light;
|
|
19332
|
+
fragColor = vec4(col / (1.0 + max(col - 1.0, 0.0)), pic.a);
|
|
19333
|
+
}`
|
|
19334
|
+
),
|
|
19335
|
+
presets: [
|
|
19336
|
+
{ name: "Window", values: { uPattern: 0, uAngle: -8, uSoftness: 0.2, uColor: [1, 0.86, 0.66] } },
|
|
19337
|
+
{ name: "Starry stage", values: { uPattern: 2, uColor: [0.7, 0.8, 1], uAmbient: 0.15, uIntensity: 1.8, uScale: 1.2 } },
|
|
19338
|
+
{ name: "Marquee text", values: { uPattern: 4, uGobo: textImage("OPEN"), uAmbient: 0.2, uIntensity: 1.8, uSoftness: 0.15, uAngle: 0 } }
|
|
19339
|
+
]
|
|
19340
|
+
};
|
|
19341
|
+
var neonSpill = {
|
|
19342
|
+
kind: "shader",
|
|
19343
|
+
id: "neon-spill",
|
|
19344
|
+
name: "Neon spill",
|
|
19345
|
+
description: "Coloured light spilling onto a picture from a flickering two-colour neon tube, lighting the surfaces that face it and falling off with distance.",
|
|
19346
|
+
category: "lighting",
|
|
19347
|
+
video: "filter",
|
|
19348
|
+
tags: ["lighting", "neon", "cyberpunk", "night", "colour", "flicker", "image", "normal-map", "filter"],
|
|
19349
|
+
source: glsl(
|
|
19350
|
+
`// Neon spill: five point lights along a tube, one colour each half, inverse-square falloff, shading normals from brightness; the tube drawn on top.
|
|
19351
|
+
uniform sampler2D uImage; // @control filter=mipmap wrap=clamp default=${SAMPLE_IMAGES.portrait} label="Image"
|
|
19352
|
+
uniform vec2 uSource; // @control min=-1 max=1 default=-0.7,0.1 label="Neon position"
|
|
19353
|
+
uniform float uTubeAngle; // @control min=-90 max=90 default=80 label="Tube angle (\xB0)"
|
|
19354
|
+
uniform float uLength; // @control min=0 max=1 default=0.5 label="Tube length"
|
|
19355
|
+
uniform vec3 uColorA; // @control color default=#FF2E9A label="Colour A"
|
|
19356
|
+
uniform vec3 uColorB; // @control color default=#3EE4FF label="Colour B"
|
|
19357
|
+
uniform float uIntensity; // @control min=0 max=4 default=2.2 label="Power"
|
|
19358
|
+
uniform float uFlicker; // @control min=0 max=1 default=0.35 label="Flicker"
|
|
19359
|
+
uniform float uAmbient; // @control min=0 max=1 default=0.18 label="Ambient"
|
|
19360
|
+
uniform float uStrength; // @control min=0 max=10 default=4 label="Relief"
|
|
19361
|
+
uniform bool uShowTube; // @control default=true label="Show the tube"
|
|
19362
|
+
${BACKDROP_CONTROLS}`,
|
|
19363
|
+
PICTURE,
|
|
19364
|
+
HASH,
|
|
19365
|
+
RELIEF,
|
|
19366
|
+
`void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
19367
|
+
vec2 uv = fragCoord / iResolution.xy;
|
|
19368
|
+
vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
|
|
19369
|
+
float aspect = iResolution.x / iResolution.y;
|
|
19370
|
+
vec2 c = uSource * vec2(aspect, 1.0) * 0.5;
|
|
19371
|
+
float ta = radians(uTubeAngle);
|
|
19372
|
+
vec2 dir = vec2(cos(ta), sin(ta)) * uLength * 0.5;
|
|
19373
|
+
// Flicker: a fast buzz, and now and then a stutter.
|
|
19374
|
+
float t = iTime;
|
|
19375
|
+
float buzz = 0.08 * hash12(vec2(floor(t * 40.0), 1.0));
|
|
19376
|
+
float stutter = step(0.88, hash12(vec2(floor(t * 5.0), 2.0))) * step(0.5, hash12(vec2(floor(t * 30.0), 3.0)));
|
|
19377
|
+
float on = 1.0 - uFlicker * (buzz + 0.75 * stutter);
|
|
19378
|
+
|
|
19379
|
+
vec3 n = surfaceNormal(uv, uStrength);
|
|
19380
|
+
vec3 light = vec3(0.0);
|
|
19381
|
+
// The tube as five point lights a little off the wall, each falling off with the square of distance.
|
|
19382
|
+
for (int i = 0; i < 5; i++) {
|
|
19383
|
+
float k = float(i) * 0.25;
|
|
19384
|
+
vec2 at = c + dir * (k * 2.0 - 1.0);
|
|
19385
|
+
vec3 toLight = vec3(at - p, 0.2);
|
|
19386
|
+
float d2 = dot(toLight, toLight);
|
|
19387
|
+
float diff = max(dot(n, toLight * inversesqrt(d2)), 0.0);
|
|
19388
|
+
light += mix(uColorA, uColorB, smoothstep(0.3, 0.7, k)) * diff * 0.022 / (d2 + 0.04);
|
|
19389
|
+
}
|
|
19390
|
+
light *= uIntensity * on;
|
|
19391
|
+
vec4 pic = pictureRGBA(uImage, uv);
|
|
19392
|
+
vec3 col = pic.rgb * (vec3(uAmbient) * vec3(0.55, 0.6, 0.8) + light);
|
|
19393
|
+
|
|
19394
|
+
if (uShowTube) {
|
|
19395
|
+
vec2 a = c - dir;
|
|
19396
|
+
vec2 ab = 2.0 * dir;
|
|
19397
|
+
float h = clamp(dot(p - a, ab) / max(dot(ab, ab), 1e-6), 0.0, 1.0);
|
|
19398
|
+
float d = length(p - a - ab * h);
|
|
19399
|
+
vec3 tint = mix(uColorA, uColorB, smoothstep(0.45, 0.55, h));
|
|
19400
|
+
float core = smoothstep(0.009, 0.004, d);
|
|
19401
|
+
float halo = exp(-d * 40.0) * 0.8 + exp(-d * 12.0) * 0.3;
|
|
19402
|
+
col = mix(col, mix(tint, vec3(1.0), 0.7), core * on) + tint * halo * on * uIntensity * 0.5;
|
|
19403
|
+
}
|
|
19404
|
+
fragColor = vec4(rolloff(col), pic.a);
|
|
19405
|
+
}`
|
|
19406
|
+
),
|
|
19407
|
+
presets: [
|
|
19408
|
+
{ name: "Cyberpunk", values: { uColorA: [1, 0.15, 0.6], uColorB: [0.2, 0.5, 1], uAmbient: 0.1, uIntensity: 2 } },
|
|
19409
|
+
{ name: "Diner sign", values: { uSource: [0, 0.85], uTubeAngle: 0, uLength: 0.9, uColorA: [1, 0.3, 0.2], uColorB: [1, 0.75, 0.3], uFlicker: 0.6 } },
|
|
19410
|
+
{ name: "Steady", values: { uFlicker: 0, uShowTube: false, uColorA: [0.6, 0.2, 1], uColorB: [0.1, 1, 0.7] } }
|
|
19411
|
+
]
|
|
19412
|
+
};
|
|
19413
|
+
var candlelight = {
|
|
19414
|
+
kind: "shader",
|
|
19415
|
+
id: "candlelight",
|
|
19416
|
+
name: "Candlelight",
|
|
19417
|
+
description: "A picture lit only by a warm candle low in the frame, its flicker shifting the light and the deep shadows, with a soft warm bloom.",
|
|
19418
|
+
category: "lighting",
|
|
19419
|
+
video: "filter",
|
|
19420
|
+
tags: ["lighting", "candle", "fire", "warm", "flicker", "cosy", "dark", "image", "normal-map", "filter"],
|
|
19421
|
+
source: glsl(
|
|
19422
|
+
`// Candlelight: a flickering point light low in the frame shading normals from brightness, a small flame and a warm bloom.
|
|
19423
|
+
uniform sampler2D uImage; // @control filter=mipmap wrap=clamp default=${SAMPLE_IMAGES.portrait} label="Image"
|
|
19424
|
+
uniform vec2 uSource; // @control min=-1 max=1 default=-0.45,-0.8 label="Candle position"
|
|
19425
|
+
uniform vec3 uColor; // @control color default=#FF9A3D label="Flame colour"
|
|
19426
|
+
uniform float uIntensity; // @control min=0 max=4 default=2.2 label="Intensity"
|
|
19427
|
+
uniform float uFlicker; // @control min=0 max=1 default=0.6 label="Flicker"
|
|
19428
|
+
uniform float uReach; // @control min=0.2 max=2 default=1.2 label="Reach"
|
|
19429
|
+
uniform float uAmbient; // @control min=0 max=0.3 default=0.02 label="Ambient"
|
|
19430
|
+
uniform float uBloom; // @control min=0 max=1 default=0.5 label="Warm bloom"
|
|
19431
|
+
uniform float uStrength; // @control min=0 max=10 default=4 label="Relief"
|
|
19432
|
+
uniform bool uShowFlame; // @control default=true label="Show the flame"
|
|
19433
|
+
${BACKDROP_CONTROLS}`,
|
|
19434
|
+
PICTURE,
|
|
19435
|
+
HASH,
|
|
19436
|
+
NOISE,
|
|
19437
|
+
RELIEF,
|
|
19438
|
+
`void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
19439
|
+
vec2 uv = fragCoord / iResolution.xy;
|
|
19440
|
+
vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
|
|
19441
|
+
float aspect = iResolution.x / iResolution.y;
|
|
19442
|
+
float t = iTime;
|
|
19443
|
+
// Flicker: the flame dips and gutters, and leans a little as it does.
|
|
19444
|
+
float f = vnoise(vec2(t * 7.0, 0.5)) * 0.6 + vnoise(vec2(t * 17.0, 4.0)) * 0.4;
|
|
19445
|
+
float power = 1.0 - uFlicker * 0.45 * (1.0 - f);
|
|
19446
|
+
vec2 lean = vec2(vnoise(vec2(t * 3.0, 9.0)) - 0.5, vnoise(vec2(t * 5.0, 13.0)) - 0.5) * vec2(0.03, 0.015) * uFlicker;
|
|
19447
|
+
vec2 base = uSource * vec2(aspect, 1.0) * 0.5;
|
|
19448
|
+
vec2 flamePos = base + vec2(0.0, 0.035) + lean;
|
|
19449
|
+
|
|
19450
|
+
vec3 toLight = vec3(flamePos - p, 0.12);
|
|
19451
|
+
float dist = length(toLight);
|
|
19452
|
+
float k = dist / (0.3 * uReach);
|
|
19453
|
+
float att = 1.0 / (1.0 + k * k) * (1.0 - smoothstep(0.5 * uReach, 1.6 * uReach, dist));
|
|
19454
|
+
vec3 n = surfaceNormal(uv, uStrength);
|
|
19455
|
+
vec2 s = shade(n, toLight / dist, 20.0);
|
|
19456
|
+
vec4 pic = pictureRGBA(uImage, uv);
|
|
19457
|
+
vec3 warm = uColor * uIntensity * att * power;
|
|
19458
|
+
// Deep shadows: little ambient, and the lit colour pushed warm.
|
|
19459
|
+
vec3 col = pic.rgb * (vec3(uAmbient) * vec3(0.6, 0.6, 0.9) + warm * s.x) + warm * s.y * 0.2;
|
|
19460
|
+
// Bloom: the bright, lit parts bleed a little warm light, and the air glows round the flame.
|
|
19461
|
+
vec3 soft = textureSize(uImage, 0).x > 1 ? textureLod(uImage, uv, 4.0).rgb : pic.rgb;
|
|
19462
|
+
col += soft * warm * 0.25 * uBloom;
|
|
19463
|
+
float fd = length(p - flamePos);
|
|
19464
|
+
col += uColor * power * uBloom * (exp(-fd * 9.0) * 0.5 + exp(-fd * 30.0) * 0.6);
|
|
19465
|
+
|
|
19466
|
+
if (uShowFlame) {
|
|
19467
|
+
vec2 q = (p - flamePos) / vec2(0.012, 0.03);
|
|
19468
|
+
q.x += lean.x * 8.0 * max(q.y, 0.0);
|
|
19469
|
+
float shape = length(vec2(q.x * (1.0 + max(q.y, 0.0) * 0.9), q.y));
|
|
19470
|
+
float flame = smoothstep(1.0, 0.55, shape);
|
|
19471
|
+
float core = smoothstep(0.6, 0.1, length(vec2(q.x * 1.4, q.y + 0.45)));
|
|
19472
|
+
col = mix(col, mix(uColor * 1.4, vec3(1.0, 0.95, 0.8), core), flame * power);
|
|
19473
|
+
}
|
|
19474
|
+
fragColor = vec4(rolloff(col), pic.a);
|
|
19475
|
+
}`
|
|
19476
|
+
),
|
|
19477
|
+
presets: [
|
|
19478
|
+
{ name: "Single candle", values: { uReach: 0.6, uBloom: 0.7, uAmbient: 0 } },
|
|
19479
|
+
{ name: "Fireside", values: { uSource: [-0.85, -0.9], uColor: [1, 0.55, 0.2], uReach: 1.6, uIntensity: 2.4, uFlicker: 0.9, uShowFlame: false } }
|
|
19480
|
+
]
|
|
19481
|
+
};
|
|
19482
|
+
var poolCaustics = {
|
|
19483
|
+
kind: "shader",
|
|
19484
|
+
id: "pool-caustics",
|
|
19485
|
+
name: "Pool caustics",
|
|
19486
|
+
description: "Rippling caustic light reflected from a pool playing across a picture, as on a wall beside the water, in a cool blue-white.",
|
|
19487
|
+
category: "lighting",
|
|
19488
|
+
video: "filter",
|
|
19489
|
+
tags: ["lighting", "caustics", "water", "pool", "summer", "reflection", "image", "filter"],
|
|
19490
|
+
source: glsl(
|
|
19491
|
+
`// Pool caustics: two drifting Voronoi edge networks (F2 - F1), warped and stretched, multiplied into the picture as blue-white light.
|
|
19492
|
+
uniform sampler2D uImage; // @control filter=linear wrap=clamp default=${SAMPLE_IMAGES.portrait} label="Image"
|
|
19493
|
+
uniform vec3 uTint; // @control color default=#D4F1FF label="Light tint"
|
|
19494
|
+
uniform vec3 uShade; // @control color default=#2E6A96 label="Shade tint"
|
|
19495
|
+
uniform float uIntensity; // @control min=0 max=3 default=1.1 label="Intensity"
|
|
19496
|
+
uniform float uAmbient; // @control min=0 max=1 default=0.6 label="Ambient"
|
|
19497
|
+
uniform float uScale; // @control min=0.3 max=3 default=1 label="Scale"
|
|
19498
|
+
uniform float uSpeed; // @control min=0 max=3 default=0.6 label="Speed"
|
|
19499
|
+
uniform float uSharpness; // @control min=0 max=1 default=0.6 label="Sharpness"
|
|
19500
|
+
uniform float uStretch; // @control min=0 max=1 default=0.35 label="Stretch"
|
|
19501
|
+
${BACKDROP_CONTROLS}`,
|
|
19502
|
+
PICTURE,
|
|
19503
|
+
HASH,
|
|
19504
|
+
NOISE,
|
|
19505
|
+
`// A web of bright lines: how close q is to the edge between its two nearest moving points.
|
|
19506
|
+
float causticWeb(vec2 q, float t, float width) {
|
|
19507
|
+
vec2 cell = floor(q);
|
|
19508
|
+
vec2 f = fract(q);
|
|
19509
|
+
float f1 = 8.0;
|
|
19510
|
+
float f2 = 8.0;
|
|
19511
|
+
for (int j = -1; j <= 1; j++) {
|
|
19512
|
+
for (int i = -1; i <= 1; i++) {
|
|
19513
|
+
vec2 o = vec2(float(i), float(j));
|
|
19514
|
+
vec2 h = hash22(cell + o);
|
|
19515
|
+
vec2 pt = o + 0.5 + 0.4 * sin(t + 6.28318 * h);
|
|
19516
|
+
float d = length(pt - f);
|
|
19517
|
+
if (d < f1) { f2 = f1; f1 = d; } else if (d < f2) { f2 = d; }
|
|
19518
|
+
}
|
|
19519
|
+
}
|
|
19520
|
+
return 1.0 - smoothstep(0.0, width, f2 - f1);
|
|
19521
|
+
}
|
|
19522
|
+
|
|
19523
|
+
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
19524
|
+
vec2 uv = fragCoord / iResolution.xy;
|
|
19525
|
+
vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
|
|
19526
|
+
float t = iTime * uSpeed;
|
|
19527
|
+
// Thrown up from the water below, the pattern is stretched along the wall and wobbles as the surface moves.
|
|
19528
|
+
vec2 q = p * vec2(1.0, 1.0 - 0.5 * uStretch) * 5.0 / uScale;
|
|
19529
|
+
q += 0.35 * vec2(vnoise(q * 0.6 + t * 0.4), vnoise(q * 0.6 - t * 0.35 + 5.0));
|
|
19530
|
+
float width = mix(0.35, 0.08, uSharpness);
|
|
19531
|
+
float web = causticWeb(q, t, width) * 0.6 + causticWeb(q * 1.37 + 7.3, t * 1.3, width) * 0.6;
|
|
19532
|
+
web = pow(web, mix(1.0, 2.2, uSharpness));
|
|
19533
|
+
// Brighter and darker patches as the ripples gather and spread.
|
|
19534
|
+
web *= 0.6 + 0.6 * vnoise(p * 2.0 + vec2(t * 0.15, -t * 0.1));
|
|
19535
|
+
vec4 pic = pictureRGBA(uImage, uv);
|
|
19536
|
+
vec3 ambient = uAmbient * mix(vec3(1.0), uShade * 1.7, 0.6);
|
|
19537
|
+
vec3 col = pic.rgb * (ambient + uTint * web * uIntensity) + uTint * web * uIntensity * 0.06;
|
|
19538
|
+
fragColor = vec4(col / (1.0 + max(col - 1.0, 0.0)), pic.a);
|
|
19539
|
+
}`
|
|
19540
|
+
),
|
|
19541
|
+
presets: [
|
|
19542
|
+
{ name: "Midday pool", values: { uIntensity: 1.6, uAmbient: 0.75, uSharpness: 0.8 } },
|
|
19543
|
+
{ name: "Night pool", values: { uTint: [0.45, 0.85, 1], uShade: [0.05, 0.15, 0.35], uAmbient: 0.25, uIntensity: 1.8, uSpeed: 0.4 } }
|
|
19544
|
+
]
|
|
19545
|
+
};
|
|
19546
|
+
var partyLights = {
|
|
19547
|
+
kind: "shader",
|
|
19548
|
+
id: "party-lights",
|
|
19549
|
+
name: "Party lights",
|
|
19550
|
+
description: "Club lighting over a picture: coloured spot beams cutting through haze and pools of light sweeping across it, with mirror-ball sparkles and an optional strobe.",
|
|
19551
|
+
category: "lighting",
|
|
19552
|
+
video: "filter",
|
|
19553
|
+
tags: ["lighting", "party", "club", "disco", "stage", "concert", "strobe", "colour", "image", "filter"],
|
|
19554
|
+
source: glsl(
|
|
19555
|
+
`// Party lights: beams from above sweeping light pools across the picture, added as light, plus mirror-ball dots and a strobe.
|
|
19556
|
+
uniform sampler2D uImage; // @control filter=linear wrap=clamp default=${SAMPLE_IMAGES.city} label="Image"
|
|
19557
|
+
uniform int uCount; // @control min=1 max=8 default=5 label="Lights"
|
|
19558
|
+
uniform vec3 uColorA; // @control color default=#FF2D95 label="Colour A"
|
|
19559
|
+
uniform vec3 uColorB; // @control color default=#2DD4FF label="Colour B"
|
|
19560
|
+
uniform vec3 uColorC; // @control color default=#B6FF3B label="Colour C"
|
|
19561
|
+
uniform float uIntensity; // @control min=0 max=3 default=1.3 label="Intensity"
|
|
19562
|
+
uniform float uSpeed; // @control min=0 max=3 default=1 label="Speed"
|
|
19563
|
+
uniform float uPoolSize; // @control min=0.05 max=0.5 default=0.17 label="Pool size"
|
|
19564
|
+
uniform float uBeams; // @control min=0 max=1 default=0.5 label="Beams in the haze"
|
|
19565
|
+
uniform float uDarken; // @control min=0 max=1 default=0.55 label="Darken the room"
|
|
19566
|
+
uniform float uSparkle; // @control min=0 max=1 default=0.35 label="Mirror ball"
|
|
19567
|
+
uniform float uStrobe; // @control min=0 max=1 default=0 label="Strobe"
|
|
19568
|
+
${BACKDROP_CONTROLS}`,
|
|
19569
|
+
PICTURE,
|
|
19570
|
+
HASH,
|
|
19571
|
+
ROTATE,
|
|
19572
|
+
`vec3 lightColour(int i, float t) {
|
|
19573
|
+
int k = int(mod(float(i) + floor(t * 0.25), 3.0));
|
|
19574
|
+
return k == 0 ? uColorA : k == 1 ? uColorB : uColorC;
|
|
19575
|
+
}
|
|
19576
|
+
|
|
19577
|
+
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
19578
|
+
vec2 uv = fragCoord / iResolution.xy;
|
|
19579
|
+
vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
|
|
19580
|
+
float aspect = iResolution.x / iResolution.y;
|
|
19581
|
+
float t = iTime * uSpeed;
|
|
19582
|
+
vec3 light = vec3(0.0);
|
|
19583
|
+
vec3 haze = vec3(0.0);
|
|
19584
|
+
for (int i = 0; i < 8; i++) {
|
|
19585
|
+
if (i >= uCount) break;
|
|
19586
|
+
float fi = float(i);
|
|
19587
|
+
float h = hash12(vec2(fi, 4.2));
|
|
19588
|
+
// Each light hangs above the frame and swings its pool back and forth over the picture.
|
|
19589
|
+
vec2 src = vec2(((fi + 0.5) / float(uCount) - 0.5) * aspect * 0.9, 0.62);
|
|
19590
|
+
vec2 pool = vec2(sin(t * (0.5 + 0.4 * h) + fi * 2.1) * 0.45 * aspect, -0.1 + 0.3 * sin(t * (0.37 + 0.3 * h) + fi * 1.3));
|
|
19591
|
+
vec3 c = lightColour(i, t + fi);
|
|
19592
|
+
float size = uPoolSize * (0.8 + 0.4 * h);
|
|
19593
|
+
float d = length((p - pool) * vec2(1.0, 1.3));
|
|
19594
|
+
light += c * (smoothstep(size, size * 0.55, d) * 0.8 + exp(-d * d / (size * size)) * 0.5);
|
|
19595
|
+
// The beam: a cone from the light widening to the pool.
|
|
19596
|
+
vec2 ab = pool - src;
|
|
19597
|
+
float s = clamp(dot(p - src, ab) / dot(ab, ab), 0.0, 1.0);
|
|
19598
|
+
float w = mix(0.008, size * 0.9, s);
|
|
19599
|
+
float cone = smoothstep(w, w * 0.2, length(p - src - ab * s)) * s * s;
|
|
19600
|
+
haze += c * cone;
|
|
19601
|
+
}
|
|
19602
|
+
// Mirror ball: a sparse grid of dots turning slowly across the picture.
|
|
19603
|
+
vec2 g = rot(t * 0.15) * (p + vec2(0.0, 0.6)) * 22.0;
|
|
19604
|
+
vec2 cell = floor(g);
|
|
19605
|
+
float dotLit = step(0.94, hash12(cell)) * smoothstep(0.22, 0.05, length(fract(g) - 0.5));
|
|
19606
|
+
float twinkle = 0.5 + 0.5 * sin(iTime * 6.0 + hash12(cell + 1.7) * 20.0);
|
|
19607
|
+
vec3 sparkle = mix(vec3(1.0), lightColour(int(hash12(cell + 2.3) * 3.0), t), 0.5) * dotLit * twinkle * uSparkle;
|
|
19608
|
+
// Strobe: now and then a burst of white flashes.
|
|
19609
|
+
float burst = step(1.0 - uStrobe * 0.6, hash12(vec2(floor(iTime * 1.5), 9.0)));
|
|
19610
|
+
float strobe = uStrobe * burst * step(0.6, fract(iTime * 9.0));
|
|
19611
|
+
|
|
19612
|
+
vec4 pic = pictureRGBA(uImage, uv);
|
|
19613
|
+
vec3 room = pic.rgb * (1.0 - uDarken);
|
|
19614
|
+
vec3 col = room + pic.rgb * (light + sparkle) * uIntensity * 1.4 + (light * 0.08 + haze * uBeams * 0.6 + sparkle * 0.4) * uIntensity;
|
|
19615
|
+
col += strobe * mix(vec3(0.4), vec3(1.0), pic.rgb);
|
|
19616
|
+
fragColor = vec4(col / (1.0 + max(col - 1.0, 0.0)), pic.a);
|
|
19617
|
+
}`
|
|
19618
|
+
),
|
|
19619
|
+
presets: [
|
|
19620
|
+
{ name: "Disco", values: { uColorA: [1, 0.25, 0.55], uColorB: [1, 0.8, 0.2], uColorC: [0.4, 0.4, 1], uSparkle: 0.8, uBeams: 0.3 } },
|
|
19621
|
+
{ name: "Rave strobe", values: { uStrobe: 0.7, uSpeed: 2, uCount: 8, uDarken: 0.8, uBeams: 0.9, uColorC: [0.6, 0.2, 1] } },
|
|
19622
|
+
{ name: "Concert", values: { uImage: SAMPLE_IMAGES.portrait, uCount: 3, uColorA: [0.3, 0.5, 1], uColorB: [1, 0.4, 0.2], uColorC: [1, 1, 1], uSparkle: 0, uBeams: 0.9, uDarken: 0.7 } }
|
|
19623
|
+
]
|
|
19624
|
+
};
|
|
19625
|
+
var lightingShaders = [
|
|
19626
|
+
relight2,
|
|
19627
|
+
pointLight,
|
|
19628
|
+
studioLighting,
|
|
19629
|
+
timeOfDay,
|
|
19630
|
+
goboProjection,
|
|
19631
|
+
neonSpill,
|
|
19632
|
+
candlelight,
|
|
19633
|
+
poolCaustics,
|
|
19634
|
+
partyLights
|
|
19635
|
+
];
|
|
19636
|
+
|
|
18881
19637
|
// src/catalog/types.ts
|
|
18882
19638
|
var EFFECT_CATEGORIES = [
|
|
18883
19639
|
"gradient",
|
|
18884
19640
|
"organic",
|
|
18885
19641
|
"pattern",
|
|
18886
19642
|
"light",
|
|
19643
|
+
"lighting",
|
|
18887
19644
|
"space",
|
|
18888
19645
|
"retro",
|
|
18889
19646
|
"image",
|
|
@@ -20144,6 +20901,7 @@ var SHADER_EFFECTS = [
|
|
|
20144
20901
|
sparkles,
|
|
20145
20902
|
neonRipple,
|
|
20146
20903
|
lightRibbons,
|
|
20904
|
+
...lightingShaders,
|
|
20147
20905
|
starfield,
|
|
20148
20906
|
nebula,
|
|
20149
20907
|
blackHole,
|
|
@@ -20183,7 +20941,7 @@ var SHADER_EFFECTS = [
|
|
|
20183
20941
|
...distortionShaders,
|
|
20184
20942
|
...transitions
|
|
20185
20943
|
];
|
|
20186
|
-
var EFFECTS = [...SHADER_EFFECTS, ...vectorEffects, ...textEffects, ...morphEffects, ...interactionEffects, ...pyroEffects, ...timewarpEffects, ...meltEffects, ...electricEffects, ...pixelEffects, ...splatterEffects, ...bubbleEffects, ...stickerEffects, ...trailEffects, ...impactEffects, ...comicEffects, ...glowEffects, ...shadowEffects].sort(
|
|
20944
|
+
var EFFECTS = [...SHADER_EFFECTS, ...vectorEffects, ...textEffects, ...morphEffects, ...interactionEffects, ...pyroEffects, ...timewarpEffects, ...meltEffects, ...electricEffects, ...pixelEffects, ...splatterEffects, ...bubbleEffects, ...stickerEffects, ...trailEffects, ...impactEffects, ...comicEffects, ...glowEffects, ...shadowEffects, ...lightingEffects].sort(
|
|
20187
20945
|
(a, b) => EFFECT_CATEGORIES.indexOf(a.category) - EFFECT_CATEGORIES.indexOf(b.category)
|
|
20188
20946
|
);
|
|
20189
20947
|
var byId = new Map(EFFECTS.map((e) => [e.id, e]));
|
|
@@ -20259,4 +21017,4 @@ export {
|
|
|
20259
21017
|
effectControls,
|
|
20260
21018
|
effectDefaults
|
|
20261
21019
|
};
|
|
20262
|
-
//# sourceMappingURL=chunk-
|
|
21020
|
+
//# sourceMappingURL=chunk-OQ4EWZ3B.js.map
|