react-native-shine 0.2.2 → 0.3.1
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 +22 -7
- package/lib/module/components/Content.js +232 -0
- package/lib/module/components/Content.js.map +1 -0
- package/lib/module/components/Shine.js +33 -0
- package/lib/module/components/Shine.js.map +1 -0
- package/lib/module/components/ShineGroup.js +92 -0
- package/lib/module/components/ShineGroup.js.map +1 -0
- package/lib/module/enums/waveCallback.js +19 -0
- package/lib/module/enums/waveCallback.js.map +1 -0
- package/lib/module/hooks/useAnimationFrame.js +17 -0
- package/lib/module/hooks/useAnimationFrame.js.map +1 -0
- package/lib/module/hooks/useOrientation.js +10 -0
- package/lib/module/hooks/useOrientation.js.map +1 -0
- package/lib/module/index.js +6 -219
- package/lib/module/index.js.map +1 -1
- package/lib/module/shaders/bindGroupLayouts.js +41 -6
- package/lib/module/shaders/bindGroupLayouts.js.map +1 -1
- package/lib/module/shaders/bindGroupUtils.js +34 -41
- package/lib/module/shaders/bindGroupUtils.js.map +1 -1
- package/lib/module/shaders/fragmentShaders/colorMaskFragment.js +2 -2
- package/lib/module/shaders/fragmentShaders/colorMaskFragment.js.map +1 -1
- package/lib/module/shaders/fragmentShaders/glareFragment.js +115 -0
- package/lib/module/shaders/fragmentShaders/glareFragment.js.map +1 -0
- package/lib/module/shaders/fragmentShaders/holoFragment.js +28 -0
- package/lib/module/shaders/fragmentShaders/holoFragment.js.map +1 -0
- package/lib/module/shaders/fragmentShaders/maskFragment.js +20 -0
- package/lib/module/shaders/fragmentShaders/maskFragment.js.map +1 -0
- package/lib/module/shaders/fragmentShaders/reverseHoloFragment.js +46 -0
- package/lib/module/shaders/fragmentShaders/reverseHoloFragment.js.map +1 -0
- package/lib/module/shaders/pipelineSetups.js +72 -17
- package/lib/module/shaders/pipelineSetups.js.map +1 -1
- package/lib/module/shaders/{resourceManagement.js → resourceManagement/bitmaps.js} +2 -1
- package/lib/module/shaders/resourceManagement/bitmaps.js.map +1 -0
- package/lib/module/shaders/resourceManagement/bufferManager.js +46 -0
- package/lib/module/shaders/resourceManagement/bufferManager.js.map +1 -0
- package/lib/module/shaders/resourceManagement/textures.js +24 -0
- package/lib/module/shaders/resourceManagement/textures.js.map +1 -0
- package/lib/module/shaders/tgpuUtils.js +19 -1
- package/lib/module/shaders/tgpuUtils.js.map +1 -1
- package/lib/module/shaders/utils.js +8 -36
- package/lib/module/shaders/utils.js.map +1 -1
- package/lib/module/shaders/vertexShaders/mainRotationEffectVertex.js +47 -0
- package/lib/module/shaders/vertexShaders/mainRotationEffectVertex.js.map +1 -0
- package/lib/module/types/size.js +2 -0
- package/lib/module/types/size.js.map +1 -0
- package/lib/module/types/typeUtils.js +17 -19
- package/lib/module/types/typeUtils.js.map +1 -1
- package/lib/module/types/vector.js +2 -0
- package/lib/module/types/vector.js.map +1 -0
- package/lib/module/utils/size.js +25 -0
- package/lib/module/utils/size.js.map +1 -0
- package/lib/module/utils/vector.js +168 -0
- package/lib/module/utils/vector.js.map +1 -0
- package/lib/typescript/src/components/Content.d.ts +23 -0
- package/lib/typescript/src/components/Content.d.ts.map +1 -0
- package/lib/typescript/src/components/Shine.d.ts +7 -0
- package/lib/typescript/src/components/Shine.d.ts.map +1 -0
- package/lib/typescript/src/components/ShineGroup.d.ts +6 -0
- package/lib/typescript/src/components/ShineGroup.d.ts.map +1 -0
- package/lib/typescript/src/enums/waveCallback.d.ts +9 -0
- package/lib/typescript/src/enums/waveCallback.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useAnimationFrame.d.ts +2 -0
- package/lib/typescript/src/hooks/useAnimationFrame.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useOrientation.d.ts +4 -0
- package/lib/typescript/src/hooks/useOrientation.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +8 -11
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/shaders/bindGroupLayouts.d.ts +46 -8
- package/lib/typescript/src/shaders/bindGroupLayouts.d.ts.map +1 -1
- package/lib/typescript/src/shaders/bindGroupUtils.d.ts +9 -9
- package/lib/typescript/src/shaders/bindGroupUtils.d.ts.map +1 -1
- package/lib/typescript/src/shaders/fragmentShaders/glareFragment.d.ts +8 -0
- package/lib/typescript/src/shaders/fragmentShaders/glareFragment.d.ts.map +1 -0
- package/lib/typescript/src/shaders/fragmentShaders/holoFragment.d.ts +5 -0
- package/lib/typescript/src/shaders/fragmentShaders/holoFragment.d.ts.map +1 -0
- package/lib/typescript/src/shaders/fragmentShaders/maskFragment.d.ts +6 -0
- package/lib/typescript/src/shaders/fragmentShaders/maskFragment.d.ts.map +1 -0
- package/lib/typescript/src/shaders/fragmentShaders/reverseHoloFragment.d.ts +5 -0
- package/lib/typescript/src/shaders/fragmentShaders/reverseHoloFragment.d.ts.map +1 -0
- package/lib/typescript/src/shaders/pipelineSetups.d.ts +9 -4
- package/lib/typescript/src/shaders/pipelineSetups.d.ts.map +1 -1
- package/lib/typescript/src/shaders/{resourceManagement.d.ts → resourceManagement/bitmaps.d.ts} +1 -1
- package/lib/typescript/src/shaders/resourceManagement/bitmaps.d.ts.map +1 -0
- package/lib/typescript/src/shaders/resourceManagement/bufferManager.d.ts +28 -0
- package/lib/typescript/src/shaders/resourceManagement/bufferManager.d.ts.map +1 -0
- package/lib/typescript/src/shaders/resourceManagement/textures.d.ts +8 -0
- package/lib/typescript/src/shaders/resourceManagement/textures.d.ts.map +1 -0
- package/lib/typescript/src/shaders/tgpuUtils.d.ts +5 -1
- package/lib/typescript/src/shaders/tgpuUtils.d.ts.map +1 -1
- package/lib/typescript/src/shaders/utils.d.ts +3 -10
- package/lib/typescript/src/shaders/utils.d.ts.map +1 -1
- package/lib/typescript/src/shaders/vertexShaders/mainRotationEffectVertex.d.ts +6 -0
- package/lib/typescript/src/shaders/vertexShaders/mainRotationEffectVertex.d.ts.map +1 -0
- package/lib/typescript/src/types/size.d.ts +5 -0
- package/lib/typescript/src/types/size.d.ts.map +1 -0
- package/lib/typescript/src/types/typeUtils.d.ts +3 -5
- package/lib/typescript/src/types/typeUtils.d.ts.map +1 -1
- package/lib/typescript/src/types/types.d.ts +10 -3
- package/lib/typescript/src/types/types.d.ts.map +1 -1
- package/lib/typescript/src/types/vector.d.ts +11 -0
- package/lib/typescript/src/types/vector.d.ts.map +1 -0
- package/lib/typescript/src/utils/size.d.ts +5 -0
- package/lib/typescript/src/utils/size.d.ts.map +1 -0
- package/lib/typescript/src/utils/vector.d.ts +33 -0
- package/lib/typescript/src/utils/vector.d.ts.map +1 -0
- package/package.json +7 -5
- package/scripts/postinstall.js +16 -17
- package/src/components/Content.tsx +403 -0
- package/src/components/Shine.tsx +38 -0
- package/src/components/ShineGroup.tsx +100 -0
- package/src/enums/waveCallback.ts +22 -0
- package/src/hooks/useAnimationFrame.ts +21 -0
- package/src/hooks/useOrientation.ts +18 -0
- package/src/index.tsx +14 -322
- package/src/shaders/bindGroupLayouts.ts +45 -8
- package/src/shaders/bindGroupUtils.ts +50 -65
- package/src/shaders/fragmentShaders/colorMaskFragment.ts +2 -2
- package/src/shaders/fragmentShaders/glareFragment.ts +143 -0
- package/src/shaders/fragmentShaders/holoFragment.ts +35 -0
- package/src/shaders/fragmentShaders/maskFragment.ts +31 -0
- package/src/shaders/fragmentShaders/reverseHoloFragment.ts +71 -0
- package/src/shaders/pipelineSetups.ts +152 -20
- package/src/shaders/{resourceManagement.ts → resourceManagement/bitmaps.ts} +1 -0
- package/src/shaders/resourceManagement/bufferManager.ts +82 -0
- package/src/shaders/resourceManagement/textures.ts +42 -0
- package/src/shaders/tgpuUtils.ts +36 -1
- package/src/shaders/utils.ts +13 -57
- package/src/shaders/vertexShaders/mainRotationEffectVertex.ts +76 -0
- package/src/types/size.ts +4 -0
- package/src/types/typeUtils.ts +22 -36
- package/src/types/types.ts +19 -3
- package/src/types/vector.ts +13 -0
- package/src/utils/size.ts +12 -0
- package/src/utils/vector.ts +132 -0
- package/lib/module/shaders/fragmentShaders/bloomFragment.js +0 -66
- package/lib/module/shaders/fragmentShaders/bloomFragment.js.map +0 -1
- package/lib/module/shaders/resourceManagement.js.map +0 -1
- package/lib/typescript/src/shaders/fragmentShaders/bloomFragment.d.ts +0 -6
- package/lib/typescript/src/shaders/fragmentShaders/bloomFragment.d.ts.map +0 -1
- package/lib/typescript/src/shaders/resourceManagement.d.ts.map +0 -1
- package/src/shaders/fragmentShaders/bloomFragment.ts +0 -83
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import tgpu from 'typegpu';
|
|
2
|
+
import * as d from 'typegpu/data';
|
|
3
|
+
import * as std from 'typegpu/std';
|
|
4
|
+
import {
|
|
5
|
+
rotationBindGroupLayout,
|
|
6
|
+
textureBindGroupLayout,
|
|
7
|
+
glareBindGroupLayout,
|
|
8
|
+
// colorMaskBindGroupLayout,
|
|
9
|
+
} from '../bindGroupLayouts';
|
|
10
|
+
import { glareColorShift, hueShift, overlayChannels } from '../tgpuUtils';
|
|
11
|
+
|
|
12
|
+
export const glareFragment = tgpu['~unstable'].fragmentFn({
|
|
13
|
+
in: { uv: d.vec2f },
|
|
14
|
+
out: d.vec4f,
|
|
15
|
+
})((input) => {
|
|
16
|
+
const texcoord = d.vec2f(input.uv.x, 1.0 - input.uv.y);
|
|
17
|
+
const uv = d.vec2f(input.uv.x, 1.0 - input.uv.y);
|
|
18
|
+
const centeredCoords = std.sub(std.mul(uv, 2.0), 1); //-1 to 1
|
|
19
|
+
|
|
20
|
+
const rot = rotationBindGroupLayout.$.vec;
|
|
21
|
+
const center = std.add(d.vec2f(0.0), d.vec2f(rot.x, rot.y));
|
|
22
|
+
|
|
23
|
+
const glareOptions = glareBindGroupLayout.$.glareOptions;
|
|
24
|
+
const glareIntensity = glareOptions.glareIntensity;
|
|
25
|
+
const glowPower = glareOptions.glowPower;
|
|
26
|
+
const hueBlendPower = glareOptions.hueBlendPower;
|
|
27
|
+
const hueShiftAngleMax = glareOptions.hueShiftAngleMax;
|
|
28
|
+
const hueShiftAngleMin = glareOptions.hueShiftAngleMin;
|
|
29
|
+
const lightIntensity = glareOptions.lightIntensity;
|
|
30
|
+
|
|
31
|
+
// const mask = colorMaskBindGroupLayout.$.mask;
|
|
32
|
+
// const maskedColor = mask.baseColor;
|
|
33
|
+
// const rgbToleranceRange = mask.rgbToleranceRange;
|
|
34
|
+
|
|
35
|
+
let color = std.textureSample(
|
|
36
|
+
textureBindGroupLayout.$.texture,
|
|
37
|
+
textureBindGroupLayout.$.sampler,
|
|
38
|
+
texcoord
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
// const maskedColorLower = std.sub(maskedColor, rgbToleranceRange.lower);
|
|
42
|
+
// const maskedColorUpper = std.add(maskedColor, rgbToleranceRange.upper);
|
|
43
|
+
// const upperCheck = std.all(std.le(color.xyz, maskedColorUpper));
|
|
44
|
+
// const lowerCheck = std.all(std.ge(color.xyz, maskedColorLower));
|
|
45
|
+
// if (upperCheck && lowerCheck) {
|
|
46
|
+
// return color;
|
|
47
|
+
// }
|
|
48
|
+
|
|
49
|
+
//glareIntensity
|
|
50
|
+
const dst = std.exp(-std.distance(center, centeredCoords));
|
|
51
|
+
const distToCenter = std.smoothstep(0.0, 1 / glareIntensity, dst);
|
|
52
|
+
|
|
53
|
+
//glowPower
|
|
54
|
+
let glow = d.vec3f(distToCenter);
|
|
55
|
+
glow = std.mul(glow, glowPower * color.w);
|
|
56
|
+
|
|
57
|
+
//hueBlend
|
|
58
|
+
const hueBlend = (d.f32(hueBlendPower) * dst) / 10.0;
|
|
59
|
+
|
|
60
|
+
//lightIntensity
|
|
61
|
+
glow = std.add(glow, lightIntensity / 10.0);
|
|
62
|
+
let shiftedRGB = glareColorShift(color.xyz, dst / (lightIntensity * 2));
|
|
63
|
+
|
|
64
|
+
//hueShiftAngleMin/Max
|
|
65
|
+
const hueShiftAngle = std.smoothstep(
|
|
66
|
+
hueShiftAngleMin,
|
|
67
|
+
hueShiftAngleMax,
|
|
68
|
+
distToCenter
|
|
69
|
+
);
|
|
70
|
+
const shiftedHue = hueShift(shiftedRGB, hueShiftAngle);
|
|
71
|
+
shiftedRGB = overlayChannels(shiftedRGB, shiftedHue);
|
|
72
|
+
|
|
73
|
+
color = d.vec4f(std.mix(color.xyz, shiftedRGB, hueBlend), color.w);
|
|
74
|
+
const baseColor = color;
|
|
75
|
+
const blendColor = glow;
|
|
76
|
+
|
|
77
|
+
const combined = overlayChannels(baseColor.xyz, blendColor);
|
|
78
|
+
color = d.vec4f(std.mix(color.xyz, combined, glow), color.w);
|
|
79
|
+
|
|
80
|
+
return color;
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
export const newGlareFragment = tgpu['~unstable'].fragmentFn({
|
|
84
|
+
in: { uv: d.vec2f },
|
|
85
|
+
out: d.vec4f,
|
|
86
|
+
})((input) => {
|
|
87
|
+
const texcoord = d.vec2f(input.uv.x, 1.0 - input.uv.y);
|
|
88
|
+
const uv = d.vec2f(input.uv.x, 1.0 - input.uv.y);
|
|
89
|
+
const centeredCoords = std.sub(std.mul(uv, 2.0), 1.0);
|
|
90
|
+
|
|
91
|
+
const rot = rotationBindGroupLayout.$.vec;
|
|
92
|
+
const center = std.add(d.vec2f(0.0), d.vec2f(rot.x, rot.y)); // do not change
|
|
93
|
+
|
|
94
|
+
const opts = glareBindGroupLayout.$.glareOptions;
|
|
95
|
+
const glareIntensity = opts.glareIntensity; // [0..∞): bigger → wider/stronger area
|
|
96
|
+
const glowPower = opts.glowPower; // (0..∞): curve shaping; bigger → softer/wider glow
|
|
97
|
+
const hueBlendPower = opts.hueBlendPower; // [0..1+]: how much hue-shifted color blends in
|
|
98
|
+
const hueShiftAngleMin = opts.hueShiftAngleMin; // radians
|
|
99
|
+
const hueShiftAngleMax = opts.hueShiftAngleMax; // radians
|
|
100
|
+
const lightIntensity = opts.lightIntensity / 1.3; // [0..∞): brightness boost of the glare/bloom
|
|
101
|
+
|
|
102
|
+
let color = std.textureSample(
|
|
103
|
+
textureBindGroupLayout.$.texture,
|
|
104
|
+
textureBindGroupLayout.$.sampler,
|
|
105
|
+
texcoord
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
const dist = std.distance(center, centeredCoords);
|
|
109
|
+
const radial = std.exp(-dist); // (0,1], steeper near center
|
|
110
|
+
const radialScaled = std.mul(
|
|
111
|
+
radial,
|
|
112
|
+
std.add(1.0, std.max(0.0, glareIntensity))
|
|
113
|
+
);
|
|
114
|
+
const influenceRaw = std.smoothstep(0.0, 1.0, radialScaled); // 0..1
|
|
115
|
+
const curveExp = std.clamp(glowPower, 0.05, 64.0);
|
|
116
|
+
const glowMask = std.pow(influenceRaw, std.div(1.0, curveExp)); // 0..1
|
|
117
|
+
|
|
118
|
+
const maskedGlow = std.mul(glowMask, color.w); // 0..1
|
|
119
|
+
const boostedRGB = glareColorShift(color.xyz, maskedGlow);
|
|
120
|
+
|
|
121
|
+
const hueT = std.clamp(maskedGlow, 0.0, 1.0);
|
|
122
|
+
const hueAngle = std.mix(hueShiftAngleMin, hueShiftAngleMax, hueT);
|
|
123
|
+
const hueShifted = hueShift(boostedRGB, hueAngle);
|
|
124
|
+
|
|
125
|
+
const hueMixWeight = std.clamp(
|
|
126
|
+
std.mul(hueBlendPower / 5.0, maskedGlow),
|
|
127
|
+
0.0,
|
|
128
|
+
1.0
|
|
129
|
+
);
|
|
130
|
+
const chromaMixed = std.mix(color.xyz, hueShifted, hueMixWeight);
|
|
131
|
+
|
|
132
|
+
const glareStrength = std.clamp(lightIntensity, 0.0, 100.0);
|
|
133
|
+
const glareLayer = std.mul(d.vec3f(maskedGlow), glareStrength);
|
|
134
|
+
|
|
135
|
+
const overlaidRGB = overlayChannels(chromaMixed, glareLayer);
|
|
136
|
+
const finalRGB = std.mix(chromaMixed, overlaidRGB, d.vec3f(maskedGlow));
|
|
137
|
+
|
|
138
|
+
const outRGB = std.clamp(finalRGB, d.vec3f(0.0), d.vec3f(1.0));
|
|
139
|
+
|
|
140
|
+
// if (maskedGlow > 0.6) return d.vec4f(0.0, 0.0, 0.0, 0.0);
|
|
141
|
+
|
|
142
|
+
return d.vec4f(outRGB, color.w);
|
|
143
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import tgpu from 'typegpu';
|
|
2
|
+
import * as d from 'typegpu/data';
|
|
3
|
+
import * as std from 'typegpu/std';
|
|
4
|
+
import {
|
|
5
|
+
rotationBindGroupLayout,
|
|
6
|
+
textureBindGroupLayout,
|
|
7
|
+
} from '../bindGroupLayouts';
|
|
8
|
+
import { hueShift } from '../tgpuUtils';
|
|
9
|
+
import { waveCallbackSlot } from '../../enums/waveCallback';
|
|
10
|
+
|
|
11
|
+
export const holoFragment = tgpu['~unstable'].fragmentFn({
|
|
12
|
+
in: { uv: d.vec2f },
|
|
13
|
+
out: d.vec4f,
|
|
14
|
+
})((input) => {
|
|
15
|
+
const texcoord = d.vec2f(input.uv.x, 1.0 - input.uv.y);
|
|
16
|
+
const uv = texcoord;
|
|
17
|
+
const textureColor = std.textureSample(
|
|
18
|
+
textureBindGroupLayout.$.texture,
|
|
19
|
+
textureBindGroupLayout.$.sampler,
|
|
20
|
+
texcoord
|
|
21
|
+
);
|
|
22
|
+
const rot = rotationBindGroupLayout.$.vec;
|
|
23
|
+
|
|
24
|
+
const wave = waveCallbackSlot.$(rot.xy);
|
|
25
|
+
const waveX = wave.x;
|
|
26
|
+
const waveY = wave.y;
|
|
27
|
+
|
|
28
|
+
const band = std.add(0.2 * waveX * uv.x, 2 * waveY * uv.y);
|
|
29
|
+
|
|
30
|
+
const hueAngle = std.mul(std.abs(band), (10 * Math.PI * rot.x) / 3);
|
|
31
|
+
const rainbowColor = hueShift(d.vec3f(1.0, 1.0, 1.0), hueAngle);
|
|
32
|
+
const finalColor = std.mul(rainbowColor, 1.0);
|
|
33
|
+
|
|
34
|
+
return d.vec4f(finalColor, 0.7 * textureColor.w);
|
|
35
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import tgpu from 'typegpu';
|
|
2
|
+
import * as d from 'typegpu/data';
|
|
3
|
+
import * as std from 'typegpu/std';
|
|
4
|
+
import {
|
|
5
|
+
textureBindGroupLayout,
|
|
6
|
+
maskTextureBindGroupLayout,
|
|
7
|
+
} from '../bindGroupLayouts';
|
|
8
|
+
|
|
9
|
+
const maskFragment = tgpu['~unstable'].fragmentFn({
|
|
10
|
+
in: { uv: d.vec2f },
|
|
11
|
+
out: d.vec4f,
|
|
12
|
+
})((input) => {
|
|
13
|
+
const texcoord = d.vec2f(input.uv.x, 1.0 - input.uv.y);
|
|
14
|
+
|
|
15
|
+
const mask = std.textureSample(
|
|
16
|
+
maskTextureBindGroupLayout.$.texture,
|
|
17
|
+
maskTextureBindGroupLayout.$.sampler,
|
|
18
|
+
texcoord
|
|
19
|
+
);
|
|
20
|
+
const reversedMask = d.vec4f(std.sub(1.0, mask.xyz), mask.w);
|
|
21
|
+
|
|
22
|
+
let color = std.textureSample(
|
|
23
|
+
textureBindGroupLayout.$.texture,
|
|
24
|
+
textureBindGroupLayout.$.sampler,
|
|
25
|
+
texcoord
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return d.vec4f(color.xyz, reversedMask.x);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export default maskFragment;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import tgpu from 'typegpu';
|
|
2
|
+
import * as d from 'typegpu/data';
|
|
3
|
+
import * as std from 'typegpu/std';
|
|
4
|
+
import {
|
|
5
|
+
textureBindGroupLayout,
|
|
6
|
+
maskTextureBindGroupLayout,
|
|
7
|
+
rotationBindGroupLayout,
|
|
8
|
+
glareBindGroupLayout,
|
|
9
|
+
} from '../bindGroupLayouts';
|
|
10
|
+
import { hueShift } from '../tgpuUtils';
|
|
11
|
+
|
|
12
|
+
export const reverseHoloFragment = tgpu['~unstable'].fragmentFn({
|
|
13
|
+
in: { uv: d.vec2f },
|
|
14
|
+
out: d.vec4f,
|
|
15
|
+
})((input) => {
|
|
16
|
+
const texcoord = d.vec2f(input.uv.x, 1.0 - input.uv.y);
|
|
17
|
+
const uv = texcoord;
|
|
18
|
+
const centeredCoords = std.sub(std.mul(uv, 2.0), 1.0);
|
|
19
|
+
|
|
20
|
+
const rot = rotationBindGroupLayout.$.vec;
|
|
21
|
+
const center = std.add(d.vec2f(0.0), d.vec2f(rot.x, rot.y)); // center from device orientation/touch
|
|
22
|
+
|
|
23
|
+
const opts = glareBindGroupLayout.$.glareOptions;
|
|
24
|
+
const glareIntensity = opts.glareIntensity;
|
|
25
|
+
const glowPower = opts.glowPower;
|
|
26
|
+
const hueBlendPower = opts.hueBlendPower;
|
|
27
|
+
const hueShiftAngleMin = opts.hueShiftAngleMin;
|
|
28
|
+
const hueShiftAngleMax = opts.hueShiftAngleMax;
|
|
29
|
+
const lightIntensity = opts.lightIntensity;
|
|
30
|
+
|
|
31
|
+
const cardColor = std.textureSample(
|
|
32
|
+
textureBindGroupLayout.$.texture,
|
|
33
|
+
textureBindGroupLayout.$.sampler,
|
|
34
|
+
texcoord
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const holoMaskColor = std.textureSample(
|
|
38
|
+
maskTextureBindGroupLayout.$.texture,
|
|
39
|
+
maskTextureBindGroupLayout.$.sampler,
|
|
40
|
+
texcoord
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const dist = std.distance(centeredCoords, center);
|
|
44
|
+
const rFalloff = std.exp(-dist);
|
|
45
|
+
const scaledRadial = std.mul(
|
|
46
|
+
rFalloff,
|
|
47
|
+
std.add(1.0, std.max(0.0, glareIntensity))
|
|
48
|
+
);
|
|
49
|
+
const influence = std.smoothstep(0.0, 1.0, scaledRadial);
|
|
50
|
+
const curvePower = std.clamp(glowPower, 0.05, 64.0);
|
|
51
|
+
const glowMask = std.pow(influence, std.div(1.0, curvePower));
|
|
52
|
+
|
|
53
|
+
const holoFactor =
|
|
54
|
+
(1.0 - holoMaskColor.x) * holoMaskColor.w * std.pow(scaledRadial, 1.5);
|
|
55
|
+
|
|
56
|
+
const maskedGlow = std.mul(glowMask, holoFactor); // only affect masked areas
|
|
57
|
+
|
|
58
|
+
const hueAmount = std.mix(
|
|
59
|
+
hueShiftAngleMin,
|
|
60
|
+
hueShiftAngleMax,
|
|
61
|
+
std.clamp(maskedGlow, 0.0, 1.0)
|
|
62
|
+
);
|
|
63
|
+
const sparkleHue = hueShift(cardColor.xyz, hueAmount);
|
|
64
|
+
const hueMixAmt = std.clamp((hueBlendPower / 5.0) * maskedGlow, 0.0, 1.0);
|
|
65
|
+
const chromaMix = std.mix(cardColor.xyz, sparkleHue, hueMixAmt);
|
|
66
|
+
|
|
67
|
+
const shineStrength = std.clamp(lightIntensity, 1.0, 100.0);
|
|
68
|
+
const shineLayer = std.mul(chromaMix, 1.5 * shineStrength * maskedGlow);
|
|
69
|
+
|
|
70
|
+
return d.vec4f(shineLayer, 1 - maskedGlow);
|
|
71
|
+
});
|
|
@@ -1,34 +1,53 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
TgpuBindGroup,
|
|
3
|
+
TgpuRenderPipeline,
|
|
4
|
+
TgpuRoot,
|
|
5
|
+
TgpuTexture,
|
|
6
|
+
} from 'typegpu';
|
|
2
7
|
import type { BindGroupPair } from '../types/types';
|
|
8
|
+
import {
|
|
9
|
+
maskTextureBindGroupLayout,
|
|
10
|
+
textureBindGroupLayout,
|
|
11
|
+
} from './bindGroupLayouts';
|
|
12
|
+
import mainVertex from './vertexShaders/mainVertex';
|
|
13
|
+
import maskFragment from './fragmentShaders/maskFragment';
|
|
14
|
+
import { reverseHoloFragment } from './fragmentShaders/reverseHoloFragment';
|
|
15
|
+
import { holoFragment } from './fragmentShaders/holoFragment';
|
|
16
|
+
import {
|
|
17
|
+
WAVE_CALLBACKS,
|
|
18
|
+
waveCallbackFn,
|
|
19
|
+
waveCallbackSlot,
|
|
20
|
+
} from '../enums/waveCallback';
|
|
3
21
|
|
|
4
22
|
export const attachBindGroups = (
|
|
5
23
|
pipeline: TgpuRenderPipeline,
|
|
6
|
-
|
|
7
|
-
) =>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
24
|
+
bindGroups: TgpuBindGroup[]
|
|
25
|
+
) =>
|
|
26
|
+
bindGroups.reduce(
|
|
27
|
+
(acc, bindGroup) => acc.with(bindGroup.layout, bindGroup),
|
|
28
|
+
pipeline
|
|
29
|
+
);
|
|
11
30
|
|
|
12
|
-
|
|
31
|
+
export const blend: GPUBlendState = {
|
|
32
|
+
color: {
|
|
33
|
+
srcFactor: 'one-minus-src-alpha',
|
|
34
|
+
dstFactor: 'src-alpha',
|
|
35
|
+
operation: 'add',
|
|
36
|
+
} satisfies GPUBlendComponent,
|
|
37
|
+
alpha: {
|
|
38
|
+
srcFactor: 'one-minus-src-alpha',
|
|
39
|
+
dstFactor: 'dst-alpha',
|
|
40
|
+
operation: 'add',
|
|
41
|
+
} satisfies GPUBlendComponent,
|
|
13
42
|
};
|
|
14
43
|
|
|
15
44
|
export const getDefaultTarget = (
|
|
16
|
-
presentationFormat: GPUTextureFormat
|
|
45
|
+
presentationFormat: GPUTextureFormat,
|
|
46
|
+
blendMode?: GPUBlendState
|
|
17
47
|
): GPUColorTargetState => {
|
|
18
48
|
return {
|
|
19
49
|
format: presentationFormat,
|
|
20
|
-
blend:
|
|
21
|
-
color: {
|
|
22
|
-
srcFactor: 'src-alpha',
|
|
23
|
-
dstFactor: 'one-minus-src-alpha',
|
|
24
|
-
operation: 'add',
|
|
25
|
-
},
|
|
26
|
-
alpha: {
|
|
27
|
-
srcFactor: 'one',
|
|
28
|
-
dstFactor: 'one-minus-src-alpha',
|
|
29
|
-
operation: 'add',
|
|
30
|
-
},
|
|
31
|
-
},
|
|
50
|
+
blend: blendMode,
|
|
32
51
|
};
|
|
33
52
|
};
|
|
34
53
|
|
|
@@ -42,3 +61,116 @@ export const attachBindGroupsToPass = (
|
|
|
42
61
|
|
|
43
62
|
return pass;
|
|
44
63
|
};
|
|
64
|
+
|
|
65
|
+
export const createMaskPipeline = (
|
|
66
|
+
root: TgpuRoot,
|
|
67
|
+
maskTexture: TgpuTexture | undefined,
|
|
68
|
+
bindGroups: TgpuBindGroup[],
|
|
69
|
+
sampler: GPUSampler,
|
|
70
|
+
presentationFormat: GPUTextureFormat
|
|
71
|
+
): TgpuRenderPipeline | void => {
|
|
72
|
+
if (!maskTexture) return;
|
|
73
|
+
|
|
74
|
+
const maskTextureBindGroup = root.createBindGroup(
|
|
75
|
+
maskTextureBindGroupLayout,
|
|
76
|
+
{
|
|
77
|
+
texture: root.unwrap(maskTexture).createView(),
|
|
78
|
+
sampler,
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
const maskBGP: TgpuBindGroup[] = [maskTextureBindGroup];
|
|
82
|
+
for (let i = 0; i < bindGroups.length; i++) {
|
|
83
|
+
maskBGP.push(bindGroups[i]!);
|
|
84
|
+
}
|
|
85
|
+
let maskPipeline = root['~unstable']
|
|
86
|
+
.withVertex(mainVertex, {})
|
|
87
|
+
.withFragment(maskFragment, getDefaultTarget(presentationFormat, blend))
|
|
88
|
+
.createPipeline();
|
|
89
|
+
maskPipeline = attachBindGroups(maskPipeline, maskBGP);
|
|
90
|
+
|
|
91
|
+
return maskPipeline;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const createReverseHoloPipeline = (
|
|
95
|
+
root: TgpuRoot,
|
|
96
|
+
texture: TgpuTexture | undefined,
|
|
97
|
+
bindGroups: TgpuBindGroup[],
|
|
98
|
+
sampler: GPUSampler,
|
|
99
|
+
presentationFormat: GPUTextureFormat
|
|
100
|
+
): TgpuRenderPipeline | void => {
|
|
101
|
+
if (!texture) return;
|
|
102
|
+
|
|
103
|
+
const reverseHoloBindGroup = root.createBindGroup(
|
|
104
|
+
maskTextureBindGroupLayout,
|
|
105
|
+
{
|
|
106
|
+
texture: root.unwrap(texture).createView(),
|
|
107
|
+
sampler,
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
const reverseHoloBGP: TgpuBindGroup[] = [...bindGroups, reverseHoloBindGroup];
|
|
111
|
+
|
|
112
|
+
let reverseHoloPipeline = root['~unstable']
|
|
113
|
+
.withVertex(mainVertex, {})
|
|
114
|
+
.withFragment(
|
|
115
|
+
reverseHoloFragment,
|
|
116
|
+
getDefaultTarget(presentationFormat, blend)
|
|
117
|
+
)
|
|
118
|
+
.createPipeline();
|
|
119
|
+
reverseHoloPipeline = attachBindGroups(reverseHoloPipeline, reverseHoloBGP);
|
|
120
|
+
|
|
121
|
+
return reverseHoloPipeline;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export const createRainbowHoloPipeline = (
|
|
125
|
+
root: TgpuRoot,
|
|
126
|
+
texture: TgpuTexture | undefined,
|
|
127
|
+
bindGroups: TgpuBindGroup[],
|
|
128
|
+
sampler: GPUSampler,
|
|
129
|
+
presentationFormat: GPUTextureFormat
|
|
130
|
+
): TgpuRenderPipeline | void => {
|
|
131
|
+
if (!texture) return;
|
|
132
|
+
|
|
133
|
+
const imageTextureBindGroup = root.createBindGroup(textureBindGroupLayout, {
|
|
134
|
+
texture: root.unwrap(texture).createView(),
|
|
135
|
+
sampler,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
let rainbowHoloPipeline = root['~unstable']
|
|
139
|
+
.with(waveCallbackSlot, waveCallbackFn(WAVE_CALLBACKS.default))
|
|
140
|
+
.withVertex(mainVertex, {})
|
|
141
|
+
.withFragment(holoFragment, getDefaultTarget(presentationFormat, blend))
|
|
142
|
+
.createPipeline();
|
|
143
|
+
|
|
144
|
+
rainbowHoloPipeline = attachBindGroups(rainbowHoloPipeline, [
|
|
145
|
+
...bindGroups,
|
|
146
|
+
imageTextureBindGroup,
|
|
147
|
+
]);
|
|
148
|
+
return rainbowHoloPipeline;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export function renderPipelinesInSinglePass(
|
|
152
|
+
root: TgpuRoot,
|
|
153
|
+
pipelines: TgpuRenderPipeline[],
|
|
154
|
+
view: GPUTextureView
|
|
155
|
+
) {
|
|
156
|
+
const unstableRoot = root['~unstable'];
|
|
157
|
+
const attachment: GPURenderPassColorAttachment = {
|
|
158
|
+
view,
|
|
159
|
+
clearValue: [0, 0, 0, 0],
|
|
160
|
+
loadOp: 'clear',
|
|
161
|
+
storeOp: 'store',
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
unstableRoot.beginRenderPass(
|
|
165
|
+
{
|
|
166
|
+
colorAttachments: [attachment],
|
|
167
|
+
},
|
|
168
|
+
(pass) => {
|
|
169
|
+
for (const pipeline of pipelines) {
|
|
170
|
+
pass.setPipeline(pipeline);
|
|
171
|
+
pass.draw(6);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
unstableRoot.flush();
|
|
176
|
+
}
|
|
@@ -13,6 +13,7 @@ const getBitmapFromURI = async (uri: string): Promise<ImageBitmap> => {
|
|
|
13
13
|
const blob = await response.blob();
|
|
14
14
|
const imageBitmap = await createImageBitmap(blob);
|
|
15
15
|
|
|
16
|
+
console.log('bitmap size: ', imageBitmap);
|
|
16
17
|
uriToBitmapMap.set(uri, imageBitmap);
|
|
17
18
|
return imageBitmap;
|
|
18
19
|
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { TgpuRoot, TgpuBuffer, ValidateBufferSchema } from 'typegpu';
|
|
2
|
+
|
|
3
|
+
export type BufferUsageType = 'uniform' | 'storage' | 'vertex';
|
|
4
|
+
|
|
5
|
+
type BufferWithUsageFromEntry<
|
|
6
|
+
TEntry extends { schema: ValidateBufferSchema<any>; usage: BufferUsageType },
|
|
7
|
+
> = TEntry['usage'] extends 'uniform'
|
|
8
|
+
? TgpuBuffer<TEntry['schema']> & { usableAsUniform: true }
|
|
9
|
+
: TEntry['usage'] extends 'storage'
|
|
10
|
+
? TgpuBuffer<TEntry['schema']> & { usableAsStorage: true }
|
|
11
|
+
: TEntry['usage'] extends 'vertex'
|
|
12
|
+
? TgpuBuffer<TEntry['schema']> & { usableAsVertex: true }
|
|
13
|
+
: never;
|
|
14
|
+
|
|
15
|
+
export class TypedBufferMap<
|
|
16
|
+
TSchemas extends Record<
|
|
17
|
+
string,
|
|
18
|
+
{ schema: ValidateBufferSchema<any>; usage: BufferUsageType }
|
|
19
|
+
>,
|
|
20
|
+
> {
|
|
21
|
+
private buffers: {
|
|
22
|
+
[K in keyof TSchemas]?: BufferWithUsageFromEntry<TSchemas[K]>;
|
|
23
|
+
} = {};
|
|
24
|
+
|
|
25
|
+
constructor(private schemas: TSchemas) {}
|
|
26
|
+
|
|
27
|
+
set<K extends keyof TSchemas>(
|
|
28
|
+
key: K,
|
|
29
|
+
buffer: BufferWithUsageFromEntry<TSchemas[K]>
|
|
30
|
+
): void {
|
|
31
|
+
this.buffers[key] = buffer;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get<K extends keyof TSchemas>(
|
|
35
|
+
key: K
|
|
36
|
+
): BufferWithUsageFromEntry<TSchemas[K]> | undefined {
|
|
37
|
+
return this.buffers[key];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
addBuffer<K extends keyof TSchemas>(
|
|
41
|
+
root: TgpuRoot,
|
|
42
|
+
key: K,
|
|
43
|
+
initValues?: TSchemas[K]['schema']['_TSType']
|
|
44
|
+
): BufferWithUsageFromEntry<TSchemas[K]> {
|
|
45
|
+
const entry = this.schemas[key];
|
|
46
|
+
if (!entry) {
|
|
47
|
+
throw new Error(`No schema found for buffer key "${String(key)}"`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const { schema, usage } = entry;
|
|
51
|
+
if (this.buffers[key]) {
|
|
52
|
+
console.warn(`Buffer "${String(key)}" already exists. Skipping...`);
|
|
53
|
+
return this.buffers[key]!;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const buffer = initValues
|
|
57
|
+
? root.createBuffer(schema, initValues)
|
|
58
|
+
: root.createBuffer(schema);
|
|
59
|
+
|
|
60
|
+
const typedBuffer = buffer.$usage(usage) as BufferWithUsageFromEntry<
|
|
61
|
+
TSchemas[K]
|
|
62
|
+
>;
|
|
63
|
+
this.buffers[key] = typedBuffer;
|
|
64
|
+
return typedBuffer;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
keys(): (keyof TSchemas)[] {
|
|
68
|
+
return Object.keys(this.buffers) as (keyof TSchemas)[];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
has<K extends keyof TSchemas>(key: K): boolean {
|
|
72
|
+
return !!this.buffers[key];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
delete<K extends keyof TSchemas>(key: K): void {
|
|
76
|
+
const buf = this.buffers[key];
|
|
77
|
+
if (buf) {
|
|
78
|
+
buf.destroy?.();
|
|
79
|
+
delete this.buffers[key];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type TextureProps, type TgpuRoot, type TgpuTexture } from 'typegpu';
|
|
2
|
+
import getBitmapFromURI from './bitmaps';
|
|
3
|
+
|
|
4
|
+
export const createTexture = async (
|
|
5
|
+
root: TgpuRoot,
|
|
6
|
+
size: {
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
}
|
|
10
|
+
): Promise<TgpuTexture> => {
|
|
11
|
+
const texture = root['~unstable']
|
|
12
|
+
.createTexture({
|
|
13
|
+
size: [size.width, size.height],
|
|
14
|
+
format: 'rgba8unorm',
|
|
15
|
+
})
|
|
16
|
+
.$usage('sampled', 'render');
|
|
17
|
+
|
|
18
|
+
return texture;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const loadTexture = async (
|
|
22
|
+
root: TgpuRoot,
|
|
23
|
+
imageBitmap: ImageBitmap,
|
|
24
|
+
texture: TgpuTexture
|
|
25
|
+
) => {
|
|
26
|
+
root.device.queue.copyExternalImageToTexture(
|
|
27
|
+
{ source: imageBitmap },
|
|
28
|
+
{ texture: root.unwrap(texture) },
|
|
29
|
+
[imageBitmap.width, imageBitmap.height]
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export async function loadBitmap(
|
|
34
|
+
root: TgpuRoot,
|
|
35
|
+
imageURI: string,
|
|
36
|
+
setTexture: (texture: TgpuTexture<TextureProps>) => void
|
|
37
|
+
) {
|
|
38
|
+
const bitmap = await getBitmapFromURI(imageURI);
|
|
39
|
+
const texture = await createTexture(root, bitmap);
|
|
40
|
+
setTexture(texture);
|
|
41
|
+
await loadTexture(root, bitmap, texture);
|
|
42
|
+
}
|
package/src/shaders/tgpuUtils.ts
CHANGED
|
@@ -33,7 +33,7 @@ export const hueShift = tgpu.fn(
|
|
|
33
33
|
return d.vec3f(r, g, b);
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
export const
|
|
36
|
+
export const glareColorShift = tgpu.fn(
|
|
37
37
|
[d.vec3f, d.f32],
|
|
38
38
|
d.vec3f
|
|
39
39
|
)((color, power) => {
|
|
@@ -73,3 +73,38 @@ export const overlayChannels = tgpu.fn(
|
|
|
73
73
|
overlayChannel(base.z, blend.z)
|
|
74
74
|
);
|
|
75
75
|
});
|
|
76
|
+
|
|
77
|
+
/** Rec.601 luma */
|
|
78
|
+
export const luma601 = tgpu.fn(
|
|
79
|
+
[d.vec3f],
|
|
80
|
+
d.f32
|
|
81
|
+
)((rgb) => {
|
|
82
|
+
return std.add(
|
|
83
|
+
std.mul(rgb.x, 0.299),
|
|
84
|
+
std.add(std.mul(rgb.y, 0.587), std.mul(rgb.z, 0.114))
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export const tiltTowardsLighterNeighbor = tgpu.fn(
|
|
89
|
+
[d.vec3f, d.f32],
|
|
90
|
+
d.vec3f
|
|
91
|
+
)((rgb, t) => {
|
|
92
|
+
const toYellow = d.vec3f(std.max(rgb.x, rgb.y), std.max(rgb.x, rgb.y), rgb.z);
|
|
93
|
+
const toCyan = d.vec3f(rgb.x, std.max(rgb.y, rgb.z), std.max(rgb.y, rgb.z));
|
|
94
|
+
|
|
95
|
+
const yYellow = luma601(toYellow);
|
|
96
|
+
const yCyan = luma601(toCyan);
|
|
97
|
+
|
|
98
|
+
const toColor = std.select(toCyan, toYellow, yYellow >= yCyan);
|
|
99
|
+
|
|
100
|
+
const tClamped = std.clamp(t, 0.0, 1.0);
|
|
101
|
+
return std.mix(rgb, toColor, tClamped);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export const linearstep = tgpu.fn(
|
|
105
|
+
[d.f32, d.f32, d.f32],
|
|
106
|
+
d.f32
|
|
107
|
+
)((num1, num2, x) => {
|
|
108
|
+
const t = (x - num1) / (num2 - num1);
|
|
109
|
+
return std.clamp(t, 0, 1);
|
|
110
|
+
});
|