instantshader 0.3.0 → 0.4.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/dist/index.d.ts +4 -1
- package/dist/index.js +243 -6
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -123,6 +123,9 @@ declare const flow: ShaderDef;
|
|
|
123
123
|
//#region src/shaders/beam.d.ts
|
|
124
124
|
declare const beam: ShaderDef;
|
|
125
125
|
//#endregion
|
|
126
|
+
//#region src/shaders/bloom.d.ts
|
|
127
|
+
declare const bloom: ShaderDef;
|
|
128
|
+
//#endregion
|
|
126
129
|
//#region src/registry.d.ts
|
|
127
130
|
declare const shaders: readonly ShaderDef[];
|
|
128
131
|
declare function getShader(id: string): ShaderDef | undefined;
|
|
@@ -188,4 +191,4 @@ declare function renderGradientFrame(opts: {
|
|
|
188
191
|
*/
|
|
189
192
|
declare function buildPaletteRamp(colors: string[]): Uint8Array;
|
|
190
193
|
//#endregion
|
|
191
|
-
export { type MountHandle, type MountOptions, type ParamDef, type RenderFrameResult, type Renderer, type RendererOptions, type ShaderDef, beam, buildPaletteRamp, createRenderer, flow, getShader, mountGradient, renderGradientFrame, shaders };
|
|
194
|
+
export { type MountHandle, type MountOptions, type ParamDef, type RenderFrameResult, type Renderer, type RendererOptions, type ShaderDef, beam, bloom, buildPaletteRamp, createRenderer, flow, getShader, mountGradient, renderGradientFrame, shaders };
|
package/dist/index.js
CHANGED
|
@@ -190,7 +190,7 @@ float grain(vec2 uv, float time) {
|
|
|
190
190
|
|
|
191
191
|
//#endregion
|
|
192
192
|
//#region src/shaders/flow.ts
|
|
193
|
-
const FRAGMENT$
|
|
193
|
+
const FRAGMENT$2 = `
|
|
194
194
|
uniform float u_scale;
|
|
195
195
|
uniform float u_curl;
|
|
196
196
|
uniform float u_drift;
|
|
@@ -327,7 +327,7 @@ void main() {
|
|
|
327
327
|
const flow = {
|
|
328
328
|
id: "flow",
|
|
329
329
|
label: "Flow",
|
|
330
|
-
fragment: FRAGMENT$
|
|
330
|
+
fragment: FRAGMENT$2,
|
|
331
331
|
params: [
|
|
332
332
|
{
|
|
333
333
|
key: "scale",
|
|
@@ -383,7 +383,7 @@ const flow = {
|
|
|
383
383
|
|
|
384
384
|
//#endregion
|
|
385
385
|
//#region src/shaders/beam.ts
|
|
386
|
-
const FRAGMENT = `
|
|
386
|
+
const FRAGMENT$1 = `
|
|
387
387
|
uniform float u_scale;
|
|
388
388
|
uniform float u_width;
|
|
389
389
|
uniform float u_glow;
|
|
@@ -637,7 +637,7 @@ void main() {
|
|
|
637
637
|
const beam = {
|
|
638
638
|
id: "beam",
|
|
639
639
|
label: "Beam",
|
|
640
|
-
fragment: FRAGMENT,
|
|
640
|
+
fragment: FRAGMENT$1,
|
|
641
641
|
params: [
|
|
642
642
|
{
|
|
643
643
|
key: "scale",
|
|
@@ -691,9 +691,246 @@ const beam = {
|
|
|
691
691
|
}
|
|
692
692
|
};
|
|
693
693
|
|
|
694
|
+
//#endregion
|
|
695
|
+
//#region src/shaders/bloom.ts
|
|
696
|
+
const FRAGMENT = `
|
|
697
|
+
uniform float u_scale;
|
|
698
|
+
uniform float u_petals;
|
|
699
|
+
uniform float u_pinch;
|
|
700
|
+
uniform float u_bend;
|
|
701
|
+
uniform float u_sway;
|
|
702
|
+
uniform float u_colorflow;
|
|
703
|
+
uniform float u_grain;
|
|
704
|
+
|
|
705
|
+
${SIMPLEX_2D}
|
|
706
|
+
${GRAIN}
|
|
707
|
+
|
|
708
|
+
const float PI = 3.14159265;
|
|
709
|
+
|
|
710
|
+
// Triangle-wave ping-pong: period 2, range [0,1], IDENTITY on [0,1] when the
|
|
711
|
+
// phase is zero -- so colorflow=off renders the plain radial ramp, and any
|
|
712
|
+
// moving phase slides color bands through the pattern with no fract() seam
|
|
713
|
+
// anywhere (the wave reflects instead of jumping).
|
|
714
|
+
float tri(float x) {
|
|
715
|
+
return 1.0 - abs(1.0 - 2.0 * fract(0.5 * x));
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
void main() {
|
|
719
|
+
vec2 uv = worldUv();
|
|
720
|
+
|
|
721
|
+
// Isotropic frame, same construction as beam: worldUv() is 0-1 on both
|
|
722
|
+
// axes of a 16:9 world, so raw uv would render every petal 1.78x wider
|
|
723
|
+
// than tall and the fan would smear sideways. Scaling x by the world
|
|
724
|
+
// aspect makes a unit circle a screen circle; halfIso is the frame's
|
|
725
|
+
// visible half-extents in that space (cover-fit aware), used to place the
|
|
726
|
+
// origin against the actual frame edges at any canvas aspect.
|
|
727
|
+
float worldAspect = 1000.0 / 562.5;
|
|
728
|
+
float canvasAspect = u_resolution.x / u_resolution.y;
|
|
729
|
+
vec2 iso = (uv - 0.5) * vec2(worldAspect, 1.0);
|
|
730
|
+
vec2 halfIso = vec2(0.5 * min(1.0, canvasAspect / worldAspect),
|
|
731
|
+
0.5 * min(1.0, worldAspect / canvasAspect))
|
|
732
|
+
* vec2(worldAspect, 1.0);
|
|
733
|
+
|
|
734
|
+
// ---- per-instance composition, all derived from u_seed ----------------
|
|
735
|
+
float seedRow = u_seed * 0.61 + 7.0;
|
|
736
|
+
|
|
737
|
+
// Origin: anywhere along the bottom edge (references use bottom-left and
|
|
738
|
+
// bottom-center), from slightly inside the frame (the hot core peeks in,
|
|
739
|
+
// as in all three references) to a bit below it.
|
|
740
|
+
float ox = snoise(vec2(seedRow, 1.3)) * 0.8 * halfIso.x;
|
|
741
|
+
// At or just below the edge -- never inside: an origin inside the frame
|
|
742
|
+
// shows petals radiating in every direction (a starburst), while the
|
|
743
|
+
// references always crop the fan at its base.
|
|
744
|
+
float oy = -halfIso.y * (1.02 + 0.11 * (1.0 + snoise(vec2(seedRow, 9.1))));
|
|
745
|
+
vec2 origin = vec2(ox, oy);
|
|
746
|
+
|
|
747
|
+
// Fan rotation. The rose envelope has k lobes evenly spaced around the
|
|
748
|
+
// full circle, so any rotation leaves several pointing into the frame;
|
|
749
|
+
// this just varies WHICH part of the fan the frame crops.
|
|
750
|
+
float theta0 = snoise(vec2(seedRow, 5.2)) * PI;
|
|
751
|
+
|
|
752
|
+
vec2 rel = iso - origin;
|
|
753
|
+
float r = length(rel);
|
|
754
|
+
float theta = atan(rel.y, rel.x);
|
|
755
|
+
|
|
756
|
+
// ---- sway: the shapes move ---------------------------------------------
|
|
757
|
+
// Lean: the whole fan pivots a few degrees around the origin. Shear pulse:
|
|
758
|
+
// the bend term below oscillates, so petals flex along their length rather
|
|
759
|
+
// than rotating rigidly. Both sinusoidal through loopFreq, so they are
|
|
760
|
+
// exactly periodic when looping (and freeze, rather than speed up, when
|
|
761
|
+
// the loop is too short for their tuned rates -- see loopFreq).
|
|
762
|
+
// The sines alone are not enough: loopFreq freezes them at loops shorter
|
|
763
|
+
// than ~half their period (its documented anti-throb choice), which left
|
|
764
|
+
// sway with NO motion at all at 4-8s loops. wdrift is the non-freezing
|
|
765
|
+
// half -- a loopDrift walk through the per-petal noise (below) and the
|
|
766
|
+
// lean, exactly periodic at ANY loop length by construction, same as the
|
|
767
|
+
// siblings' primary motion.
|
|
768
|
+
vec2 wdrift = loopDrift(0.05 * u_sway, vec2(1.0, 0.0));
|
|
769
|
+
float lean = u_sway * (0.06 * sin(loopFreq(0.21) * u_time + u_seed)
|
|
770
|
+
+ 0.05 * snoise(vec2(seedRow * 0.47, 9.3) + wdrift));
|
|
771
|
+
float shearPulse = u_sway * 0.08 * sin(loopFreq(0.15) * u_time + 2.3 + u_seed);
|
|
772
|
+
|
|
773
|
+
// Bend: angular shear proportional to r curves each petal progressively
|
|
774
|
+
// toward its tip -- the gentle bow the reference petals have -- instead of
|
|
775
|
+
// rotating the fan rigidly.
|
|
776
|
+
float th = theta - theta0 - lean + (u_bend + shearPulse) * r;
|
|
777
|
+
|
|
778
|
+
// ---- rose-curve envelope ------------------------------------------------
|
|
779
|
+
// k is snapped to an integer: |cos| has period pi, so integer k makes the
|
|
780
|
+
// envelope exactly 2pi-periodic and the atan branch cut at theta = +-pi is
|
|
781
|
+
// invisible. A fractional k would draw a hard radial seam there.
|
|
782
|
+
float k = floor(u_petals + 0.5);
|
|
783
|
+
float a = 0.5 * k * th;
|
|
784
|
+
float e = pow(abs(cos(a)), u_pinch);
|
|
785
|
+
|
|
786
|
+
// Per-petal identity: which lobe this pixel belongs to, expressed as the
|
|
787
|
+
// lobe's center ANGLE and hashed through cos/sin so it is periodic around
|
|
788
|
+
// the circle -- a raw lobe index would jump by k across the branch cut and
|
|
789
|
+
// tear the per-petal variation along that ray. The discontinuity between
|
|
790
|
+
// ADJACENT lobes is harmless: it sits exactly in the crease, where e ~ 0
|
|
791
|
+
// pushes both sides to the background color anyway.
|
|
792
|
+
float lobe = floor(a / PI + 0.5);
|
|
793
|
+
float cAngle = theta0 + 2.0 * PI * lobe / k;
|
|
794
|
+
float perLobe = 0.28 * snoise(vec2(cos(cAngle), sin(cAngle)) * 1.9
|
|
795
|
+
+ vec2(seedRow * 0.13, seedRow * 0.29) + wdrift);
|
|
796
|
+
|
|
797
|
+
// Breathing: each petal's length swells ~10%, phase-offset around the fan
|
|
798
|
+
// by 2*cAngle (integer multiple of the angle, so it survives the branch
|
|
799
|
+
// cut) -- the petals ripple in sequence instead of pulsing in lockstep.
|
|
800
|
+
float breathe = u_sway * 0.10 * sin(loopFreq(0.32) * u_time + 2.0 * cAngle + u_seed * 0.7);
|
|
801
|
+
float len = 1.0 + perLobe + breathe;
|
|
802
|
+
|
|
803
|
+
// ---- the field ----------------------------------------------------------
|
|
804
|
+
// eps = 0.075 is the crease floor (see header). R = 1.4 at scale 1 puts
|
|
805
|
+
// the default tips just past the frame's top edge with the origin at the
|
|
806
|
+
// bottom, matching the references' crop.
|
|
807
|
+
float R = 1.4 * u_scale;
|
|
808
|
+
float t = r / (R * len * (e + 0.075));
|
|
809
|
+
|
|
810
|
+
// Radial shaping: pow < 1 compresses the ramp's early stops into a small
|
|
811
|
+
// hot core at the origin and hands most of each petal's length to the
|
|
812
|
+
// later stops -- in the references the petals are dominated by ONE body
|
|
813
|
+
// color (the second-to-last stop) for ~70% of their length, with the core
|
|
814
|
+
// colors confined to the base. Linear t spread the early stops across half
|
|
815
|
+
// the petal and the body color only appeared at the rim.
|
|
816
|
+
t = pow(t, 0.5);
|
|
817
|
+
|
|
818
|
+
// ---- colorflow: the colors move ----------------------------------------
|
|
819
|
+
// Phase in tri-units (period 2 = one full out-and-back palette cycle).
|
|
820
|
+
// Not looping: linear crawl; the +37 base offset means the knob has a
|
|
821
|
+
// visible effect even at t=0 (and 37 is deliberately not a multiple of the
|
|
822
|
+
// period). Looping: exactly n cycles per loop, floored at ONE -- unlike
|
|
823
|
+
// the sway sines, colorflow is a headline motion, and freezing it at
|
|
824
|
+
// common loop lengths (loopFreq's choice) would read as the feature being
|
|
825
|
+
// broken rather than as restraint. One cycle over a short loop is simply a
|
|
826
|
+
// faster flow, which is what a short loop asks for.
|
|
827
|
+
float pRate = 0.05 * u_colorflow;
|
|
828
|
+
float p;
|
|
829
|
+
if (u_loop <= 0.0) {
|
|
830
|
+
p = pRate * (u_time + 37.0);
|
|
831
|
+
} else {
|
|
832
|
+
p = 2.0 * max(1.0, floor(pRate * u_loop * 0.5 + 0.5)) * (u_time / u_loop);
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// The flow lives INSIDE the silhouette: the mask fades it out across the
|
|
836
|
+
// tips so the background (t >= 1) stays pinned to the last stop and the
|
|
837
|
+
// negative space never pulses. Gated on u_colorflow so 0 is exactly the
|
|
838
|
+
// static field even while looping (where p above moves regardless).
|
|
839
|
+
float flowMix = (1.0 - smoothstep(0.82, 1.0, t)) * smoothstep(0.0, 0.08, u_colorflow);
|
|
840
|
+
float tc = mix(min(t, 1.0), tri(t - p), flowMix);
|
|
841
|
+
|
|
842
|
+
vec3 color = palette(tc);
|
|
843
|
+
|
|
844
|
+
// Grain: cheap per-pixel dither, centered at 0 so it can darken or
|
|
845
|
+
// lighten symmetrically instead of just brightening the whole frame.
|
|
846
|
+
float g = grain(uv, u_time) - 0.5;
|
|
847
|
+
color += g * u_grain;
|
|
848
|
+
|
|
849
|
+
gl_FragColor = vec4(clamp(color, 0.0, 1.0), 1.0);
|
|
850
|
+
}
|
|
851
|
+
`;
|
|
852
|
+
const bloom = {
|
|
853
|
+
id: "bloom",
|
|
854
|
+
label: "Bloom",
|
|
855
|
+
fragment: FRAGMENT,
|
|
856
|
+
params: [
|
|
857
|
+
{
|
|
858
|
+
key: "scale",
|
|
859
|
+
label: "Scale",
|
|
860
|
+
min: .5,
|
|
861
|
+
max: 2,
|
|
862
|
+
step: .05,
|
|
863
|
+
default: .9
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
key: "petals",
|
|
867
|
+
label: "Petals",
|
|
868
|
+
min: 6,
|
|
869
|
+
max: 16,
|
|
870
|
+
step: 1,
|
|
871
|
+
default: 11
|
|
872
|
+
},
|
|
873
|
+
{
|
|
874
|
+
key: "pinch",
|
|
875
|
+
label: "Pinch",
|
|
876
|
+
min: .35,
|
|
877
|
+
max: 2.5,
|
|
878
|
+
step: .05,
|
|
879
|
+
default: .6
|
|
880
|
+
},
|
|
881
|
+
{
|
|
882
|
+
key: "bend",
|
|
883
|
+
label: "Bend",
|
|
884
|
+
min: -.9,
|
|
885
|
+
max: .9,
|
|
886
|
+
step: .05,
|
|
887
|
+
default: .25
|
|
888
|
+
},
|
|
889
|
+
{
|
|
890
|
+
key: "sway",
|
|
891
|
+
label: "Sway",
|
|
892
|
+
min: 0,
|
|
893
|
+
max: 1,
|
|
894
|
+
step: .01,
|
|
895
|
+
default: .5
|
|
896
|
+
},
|
|
897
|
+
{
|
|
898
|
+
key: "colorflow",
|
|
899
|
+
label: "Color flow",
|
|
900
|
+
min: 0,
|
|
901
|
+
max: 1,
|
|
902
|
+
step: .01,
|
|
903
|
+
default: 0
|
|
904
|
+
},
|
|
905
|
+
{
|
|
906
|
+
key: "grain",
|
|
907
|
+
label: "Grain",
|
|
908
|
+
min: 0,
|
|
909
|
+
max: .3,
|
|
910
|
+
step: .01,
|
|
911
|
+
default: .08
|
|
912
|
+
}
|
|
913
|
+
],
|
|
914
|
+
randomParams(rand) {
|
|
915
|
+
return {
|
|
916
|
+
scale: .7 + rand() * .9000000000000001,
|
|
917
|
+
petals: Math.floor(8 + rand() * 7),
|
|
918
|
+
pinch: .5 + rand() * 1.1,
|
|
919
|
+
bend: -.6 + rand() * 1.2,
|
|
920
|
+
sway: .2 + rand() * .7,
|
|
921
|
+
colorflow: rand() * .8,
|
|
922
|
+
grain: .08
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
};
|
|
926
|
+
|
|
694
927
|
//#endregion
|
|
695
928
|
//#region src/registry.ts
|
|
696
|
-
const shaders = [
|
|
929
|
+
const shaders = [
|
|
930
|
+
flow,
|
|
931
|
+
beam,
|
|
932
|
+
bloom
|
|
933
|
+
];
|
|
697
934
|
function getShader(id) {
|
|
698
935
|
return shaders.find((s) => s.id === id);
|
|
699
936
|
}
|
|
@@ -1343,4 +1580,4 @@ function renderGradientFrame(opts) {
|
|
|
1343
1580
|
}
|
|
1344
1581
|
|
|
1345
1582
|
//#endregion
|
|
1346
|
-
export { beam, buildPaletteRamp, createRenderer, flow, getShader, mountGradient, renderGradientFrame, shaders };
|
|
1583
|
+
export { beam, bloom, buildPaletteRamp, createRenderer, flow, getShader, mountGradient, renderGradientFrame, shaders };
|