react-native-shine 0.2.1 → 0.3.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/README.md +1 -1
- package/lib/module/components/Shine.js +269 -0
- package/lib/module/components/Shine.js.map +1 -0
- package/lib/module/components/ShineGroup.js +104 -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/useOrientation.js +16 -0
- package/lib/module/hooks/useOrientation.js.map +1 -0
- package/lib/module/index.js +5 -219
- package/lib/module/index.js.map +1 -1
- package/lib/module/shaders/bindGroupLayouts.js +40 -5
- package/lib/module/shaders/bindGroupLayouts.js.map +1 -1
- package/lib/module/shaders/bindGroupUtils.js +27 -12
- 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 +114 -0
- package/lib/module/shaders/fragmentShaders/glareFragment.js.map +1 -0
- package/lib/module/shaders/fragmentShaders/holoFragment.js +33 -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 +82 -13
- 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 +17 -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 +0 -14
- 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/typeUtils.js +17 -5
- package/lib/module/types/typeUtils.js.map +1 -1
- package/lib/typescript/src/components/Shine.d.ts +17 -0
- package/lib/typescript/src/components/Shine.d.ts.map +1 -0
- package/lib/typescript/src/components/ShineGroup.d.ts +8 -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/useOrientation.d.ts +2 -0
- package/lib/typescript/src/hooks/useOrientation.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +6 -11
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/shaders/bindGroupLayouts.d.ts +44 -6
- package/lib/typescript/src/shaders/bindGroupLayouts.d.ts.map +1 -1
- package/lib/typescript/src/shaders/bindGroupUtils.d.ts +8 -8
- 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 +7 -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 +1 -7
- 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/typeUtils.d.ts +3 -2
- package/lib/typescript/src/types/typeUtils.d.ts.map +1 -1
- package/lib/typescript/src/types/types.d.ts +7 -2
- package/lib/typescript/src/types/types.d.ts.map +1 -1
- package/package.json +5 -3
- package/scripts/install-peers.js +21 -0
- package/scripts/postinstall.js +18 -0
- package/src/components/Shine.tsx +480 -0
- package/src/components/ShineGroup.tsx +107 -0
- package/src/enums/waveCallback.ts +22 -0
- package/src/hooks/useOrientation.ts +20 -0
- package/src/index.tsx +6 -322
- package/src/shaders/bindGroupLayouts.ts +43 -6
- package/src/shaders/bindGroupUtils.ts +34 -19
- package/src/shaders/fragmentShaders/colorMaskFragment.ts +2 -2
- package/src/shaders/fragmentShaders/glareFragment.ts +142 -0
- package/src/shaders/fragmentShaders/holoFragment.ts +43 -0
- package/src/shaders/fragmentShaders/maskFragment.ts +31 -0
- package/src/shaders/fragmentShaders/reverseHoloFragment.ts +71 -0
- package/src/shaders/pipelineSetups.ts +161 -14
- package/src/shaders/{resourceManagement.ts → resourceManagement/bitmaps.ts} +1 -0
- package/src/shaders/resourceManagement/bufferManager.ts +82 -0
- package/src/shaders/resourceManagement/textures.ts +30 -0
- package/src/shaders/tgpuUtils.ts +36 -1
- package/src/shaders/utils.ts +0 -30
- package/src/shaders/vertexShaders/mainRotationEffectVertex.ts +76 -0
- package/src/types/typeUtils.ts +22 -8
- package/src/types/types.ts +8 -2
- 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
package/src/index.tsx
CHANGED
|
@@ -1,326 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Canvas, useDevice, useGPUContext } from 'react-native-wgpu';
|
|
3
|
-
import { getOrInitRoot } from './roots';
|
|
4
|
-
import mainVertex from './shaders/vertexShaders/mainVertex';
|
|
5
|
-
import getBitmapFromURI from './shaders/resourceManagement';
|
|
1
|
+
import { useOrientation } from './hooks/useOrientation';
|
|
6
2
|
import {
|
|
7
|
-
createTexture,
|
|
8
|
-
loadTexture,
|
|
9
|
-
clamp,
|
|
10
|
-
rotate2D,
|
|
11
|
-
subscribeToOrientationChange,
|
|
12
3
|
getAngleFromDimensions,
|
|
4
|
+
subscribeToOrientationChange,
|
|
13
5
|
} from './shaders/utils';
|
|
14
|
-
import type { TgpuTexture } from 'typegpu';
|
|
15
|
-
import {
|
|
16
|
-
bloomOptionsBindGroupLayout,
|
|
17
|
-
colorMaskBindGroupLayout,
|
|
18
|
-
rotationValuesBindGroupLayout,
|
|
19
|
-
textureBindGroupLayout,
|
|
20
|
-
} from './shaders/bindGroupLayouts';
|
|
21
|
-
import {
|
|
22
|
-
SensorType,
|
|
23
|
-
useAnimatedSensor,
|
|
24
|
-
useDerivedValue,
|
|
25
|
-
useSharedValue,
|
|
26
|
-
} from 'react-native-reanimated';
|
|
27
|
-
import * as d from 'typegpu/data';
|
|
28
|
-
import { Platform } from 'react-native';
|
|
29
|
-
import bloomFragment from './shaders/fragmentShaders/bloomFragment';
|
|
30
|
-
import {
|
|
31
|
-
createBloomOptionsBindGroup,
|
|
32
|
-
createBloomOptionsBuffer,
|
|
33
|
-
createColorMaskBindGroup,
|
|
34
|
-
createColorMaskBuffer,
|
|
35
|
-
createRotationBuffer,
|
|
36
|
-
createRotationValuesBindGroup,
|
|
37
|
-
} from './shaders/bindGroupUtils';
|
|
38
|
-
import {
|
|
39
|
-
createBindGroupPairs,
|
|
40
|
-
createBloomOptions,
|
|
41
|
-
createColorMask,
|
|
42
|
-
} from './types/typeUtils';
|
|
43
|
-
import type {
|
|
44
|
-
BindGroupPair,
|
|
45
|
-
BloomOptions,
|
|
46
|
-
ColorMask,
|
|
47
|
-
DeepPartiallyOptional,
|
|
48
|
-
} from './types/types';
|
|
49
|
-
import { attachBindGroups, getDefaultTarget } from './shaders/pipelineSetups';
|
|
50
|
-
import colorMaskFragment from './shaders/fragmentShaders/colorMaskFragment';
|
|
51
|
-
interface ShineProps {
|
|
52
|
-
width: number;
|
|
53
|
-
height: number;
|
|
54
|
-
imageURI: string;
|
|
55
|
-
bloomOptions?: Partial<BloomOptions>;
|
|
56
|
-
colorMaskOptions?: DeepPartiallyOptional<ColorMask, 'baseColor'>;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function Shine({
|
|
60
|
-
width,
|
|
61
|
-
height,
|
|
62
|
-
imageURI,
|
|
63
|
-
bloomOptions,
|
|
64
|
-
colorMaskOptions,
|
|
65
|
-
}: ShineProps) {
|
|
66
|
-
const { device = null } = useDevice();
|
|
67
|
-
const root = device ? getOrInitRoot(device) : null;
|
|
68
|
-
const { ref, context } = useGPUContext();
|
|
69
|
-
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
|
|
70
|
-
const frameRef = useRef<number | null>(null);
|
|
71
|
-
|
|
72
|
-
const [imageTexture, setImageTexture] = useState<TgpuTexture | null>(null);
|
|
73
|
-
|
|
74
|
-
const orientationAngle = useSharedValue<number>(0); // degrees
|
|
75
|
-
const rotationShared = useSharedValue<[number, number, number]>([0, 0, 0]); // final GPU offsets
|
|
76
|
-
|
|
77
|
-
// Calibration shared values (UI thread)
|
|
78
|
-
const initialGravity = useSharedValue<[number, number, number]>([0, 0, 0]);
|
|
79
|
-
const calibSum = useSharedValue<[number, number, number]>([0, 0, 0]);
|
|
80
|
-
const calibCount = useSharedValue<number>(0);
|
|
81
|
-
const calibrated = useSharedValue<boolean>(false);
|
|
82
|
-
|
|
83
|
-
const gravitySensor = useAnimatedSensor(SensorType.GRAVITY, { interval: 20 });
|
|
84
|
-
|
|
85
|
-
console.log('render');
|
|
86
|
-
|
|
87
|
-
// Subscribe to orientation changes and reset calibration on change
|
|
88
|
-
useEffect(() => {
|
|
89
|
-
orientationAngle.value = getAngleFromDimensions();
|
|
90
|
-
const unsubscribe = subscribeToOrientationChange((angleDeg) => {
|
|
91
|
-
orientationAngle.value = angleDeg;
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
return () => unsubscribe();
|
|
95
|
-
}, [orientationAngle]);
|
|
96
|
-
|
|
97
|
-
// Calibration & mapping logic
|
|
98
|
-
useDerivedValue(() => {
|
|
99
|
-
'worklet';
|
|
100
|
-
|
|
101
|
-
// console.log(orientationAngle.value);
|
|
102
|
-
const v: any = gravitySensor.sensor?.value ??
|
|
103
|
-
gravitySensor.sensor.value ?? { x: 0, y: 0, z: 0 };
|
|
104
|
-
const gx = v.x ?? 0;
|
|
105
|
-
const gy = v.y ?? 0;
|
|
106
|
-
const gz = v.z ?? 0;
|
|
107
|
-
|
|
108
|
-
const CALIBRATION_SAMPLES = 40;
|
|
109
|
-
const alpha = 0.15; // smoothing
|
|
110
|
-
const scale = 0.6;
|
|
111
|
-
|
|
112
|
-
if (!calibrated.value) {
|
|
113
|
-
// accumulate baseline in device coordinates
|
|
114
|
-
const s = calibSum.value;
|
|
115
|
-
const c = calibCount.value + 1;
|
|
116
|
-
calibSum.value = [s[0] + gx, s[1] + gy, s[2] + gz];
|
|
117
|
-
calibCount.value = c;
|
|
118
|
-
|
|
119
|
-
if (c >= CALIBRATION_SAMPLES) {
|
|
120
|
-
const avg = calibSum.value;
|
|
121
|
-
initialGravity.value = [avg[0] / c, avg[1] / c, avg[2] / c];
|
|
122
|
-
calibrated.value = true;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
rotationShared.value = [0, 0, 0];
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const init = initialGravity.value;
|
|
130
|
-
const dx = gx - init[0];
|
|
131
|
-
const dy = gy - init[1];
|
|
132
|
-
const dz = gz - init[2];
|
|
133
|
-
|
|
134
|
-
// Rotate into screen coordinates so offsets auto-swap with orientation
|
|
135
|
-
const [mx, my] = rotate2D([dx, dy], -orientationAngle.value);
|
|
136
|
-
const screenX = mx;
|
|
137
|
-
const screenY = -my;
|
|
138
|
-
|
|
139
|
-
const prev = rotationShared.value;
|
|
140
|
-
const smoothX = prev[0] * (1 - alpha) + screenX * alpha;
|
|
141
|
-
const smoothY = prev[1] * (1 - alpha) + screenY * alpha;
|
|
142
|
-
const smoothZ = prev[2] * (1 - alpha) + dz * alpha;
|
|
143
|
-
|
|
144
|
-
if (orientationAngle.value === 90) {
|
|
145
|
-
rotationShared.value = [
|
|
146
|
-
clamp(smoothY * scale, -1, 1),
|
|
147
|
-
clamp(-smoothX * scale, -1, 1),
|
|
148
|
-
clamp(smoothZ * scale, -1, 1),
|
|
149
|
-
];
|
|
150
|
-
} else {
|
|
151
|
-
rotationShared.value = [
|
|
152
|
-
clamp(smoothX * scale, -1, 1),
|
|
153
|
-
clamp(smoothY * scale, -1, 1),
|
|
154
|
-
clamp(smoothZ * scale, -1, 1),
|
|
155
|
-
];
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
// Resource setup
|
|
160
|
-
useEffect(() => {
|
|
161
|
-
if (!root || !device || !context) return;
|
|
162
|
-
(async () => {
|
|
163
|
-
const bitmap = await getBitmapFromURI(imageURI);
|
|
164
|
-
const texture = await createTexture(root, bitmap);
|
|
165
|
-
setImageTexture(texture);
|
|
166
|
-
await loadTexture(root, bitmap, texture);
|
|
167
|
-
})();
|
|
168
|
-
}, [root, device, context, imageURI]);
|
|
169
|
-
|
|
170
|
-
// Render loop
|
|
171
|
-
useEffect(() => {
|
|
172
|
-
if (!root || !device || !context || !imageTexture) return;
|
|
173
|
-
|
|
174
|
-
context.configure({
|
|
175
|
-
device,
|
|
176
|
-
format: presentationFormat,
|
|
177
|
-
alphaMode: 'premultiplied',
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
const sampler = device.createSampler({
|
|
181
|
-
magFilter: 'linear',
|
|
182
|
-
minFilter: 'linear',
|
|
183
|
-
});
|
|
184
|
-
const textureBindGroup = root.createBindGroup(textureBindGroupLayout, {
|
|
185
|
-
texture: root.unwrap(imageTexture).createView(),
|
|
186
|
-
sampler,
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
const rotationBuffer = createRotationBuffer(root);
|
|
190
|
-
const rotationBindGroup = createRotationValuesBindGroup(
|
|
191
|
-
root,
|
|
192
|
-
rotationBuffer
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
const bloomOptionsBuffer = createBloomOptionsBuffer(
|
|
196
|
-
root,
|
|
197
|
-
createBloomOptions(bloomOptions ?? {})
|
|
198
|
-
);
|
|
199
|
-
const bloomOptionsBindGroup = createBloomOptionsBindGroup(
|
|
200
|
-
root,
|
|
201
|
-
bloomOptionsBuffer
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
const colorMaskBuffer = createColorMaskBuffer(
|
|
205
|
-
root,
|
|
206
|
-
createColorMask(colorMaskOptions ?? { baseColor: [-20, -20, -20] })
|
|
207
|
-
);
|
|
208
|
-
const colorMaskBindGroup = createColorMaskBindGroup(root, colorMaskBuffer);
|
|
209
|
-
|
|
210
|
-
const bloomBGP: BindGroupPair[] = createBindGroupPairs(
|
|
211
|
-
[
|
|
212
|
-
textureBindGroupLayout,
|
|
213
|
-
rotationValuesBindGroupLayout,
|
|
214
|
-
bloomOptionsBindGroupLayout,
|
|
215
|
-
colorMaskBindGroupLayout,
|
|
216
|
-
],
|
|
217
|
-
[
|
|
218
|
-
textureBindGroup,
|
|
219
|
-
rotationBindGroup,
|
|
220
|
-
bloomOptionsBindGroup,
|
|
221
|
-
colorMaskBindGroup,
|
|
222
|
-
]
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
const maskBGP: BindGroupPair[] = createBindGroupPairs(
|
|
226
|
-
[textureBindGroupLayout, colorMaskBindGroupLayout],
|
|
227
|
-
[textureBindGroup, colorMaskBindGroup]
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
let bloomPipeline = root['~unstable']
|
|
231
|
-
.withVertex(mainVertex, {})
|
|
232
|
-
.withFragment(bloomFragment, getDefaultTarget(presentationFormat))
|
|
233
|
-
.createPipeline();
|
|
234
|
-
bloomPipeline = attachBindGroups(bloomPipeline, bloomBGP);
|
|
235
|
-
|
|
236
|
-
let colorMaskPipeline = root['~unstable']
|
|
237
|
-
.withVertex(mainVertex, {})
|
|
238
|
-
.withFragment(colorMaskFragment, getDefaultTarget(presentationFormat))
|
|
239
|
-
.createPipeline();
|
|
240
|
-
colorMaskPipeline = attachBindGroups(colorMaskPipeline, maskBGP);
|
|
241
|
-
|
|
242
|
-
const rot = d.vec3f(0.0);
|
|
243
|
-
let view: GPUTextureView;
|
|
244
|
-
let bloomAttachment;
|
|
245
|
-
let colorMaskAttachment;
|
|
246
|
-
const render = () => {
|
|
247
|
-
rot[0] = rotationShared.value[0];
|
|
248
|
-
rot[1] = rotationShared.value[1];
|
|
249
|
-
rot[2] = rotationShared.value[2];
|
|
250
|
-
rotationBuffer.write(rot);
|
|
251
|
-
|
|
252
|
-
view = context.getCurrentTexture().createView();
|
|
253
|
-
bloomAttachment = {
|
|
254
|
-
view: view,
|
|
255
|
-
clearValue: [0, 0, 0, 0],
|
|
256
|
-
loadOp: 'clear' as GPULoadOp,
|
|
257
|
-
storeOp: 'store' as GPUStoreOp,
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
colorMaskAttachment = {
|
|
261
|
-
view: view,
|
|
262
|
-
loadOp: 'load' as GPULoadOp,
|
|
263
|
-
storeOp: 'store' as GPUStoreOp,
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
// root['~unstable'].beginRenderPass(
|
|
267
|
-
// {
|
|
268
|
-
// colorAttachments: [
|
|
269
|
-
// {
|
|
270
|
-
// view,
|
|
271
|
-
// clearValue: [0, 0, 0, 0],
|
|
272
|
-
// loadOp: 'clear',
|
|
273
|
-
// storeOp: 'store',
|
|
274
|
-
// },
|
|
275
|
-
// ],
|
|
276
|
-
// },
|
|
277
|
-
// (pass) => {
|
|
278
|
-
// pass.setPipeline(bloomPipeline);
|
|
279
|
-
// // pass = attachBindGroupsToPass(pass, bloomBGP);
|
|
280
|
-
// pass.setBindGroup(textureBindGroupLayout, textureBindGroup);
|
|
281
|
-
// pass.setBindGroup(rotationValuesBindGroupLayout, rotationBindGroup);
|
|
282
|
-
// pass.setBindGroup(bloomOptionsBindGroupLayout, bloomOptionsBindGroup);
|
|
283
|
-
// pass.setBindGroup(colorMaskBindGroupLayout, colorMaskBindGroup);
|
|
284
|
-
// pass.draw(6);
|
|
285
|
-
|
|
286
|
-
// // Mask draw
|
|
287
|
-
// pass.setPipeline(colorMaskPipeline);
|
|
288
|
-
// pass.setBindGroup(textureBindGroupLayout, textureBindGroup);
|
|
289
|
-
// pass.setBindGroup(colorMaskBindGroupLayout, colorMaskBindGroup);
|
|
290
|
-
// pass.draw(6);
|
|
291
|
-
// }
|
|
292
|
-
// );
|
|
293
|
-
// root['~unstable'].flush();
|
|
294
|
-
|
|
295
|
-
bloomPipeline.withColorAttachment(bloomAttachment).draw(6);
|
|
296
|
-
colorMaskPipeline.withColorAttachment(colorMaskAttachment).draw(6);
|
|
297
|
-
|
|
298
|
-
context.present();
|
|
299
|
-
frameRef.current = requestAnimationFrame(render);
|
|
300
|
-
};
|
|
301
|
-
frameRef.current = requestAnimationFrame(render);
|
|
302
|
-
|
|
303
|
-
return () => {
|
|
304
|
-
if (frameRef.current) cancelAnimationFrame(frameRef.current);
|
|
305
|
-
};
|
|
306
|
-
}, [
|
|
307
|
-
device,
|
|
308
|
-
context,
|
|
309
|
-
root,
|
|
310
|
-
presentationFormat,
|
|
311
|
-
imageTexture,
|
|
312
|
-
rotationShared,
|
|
313
|
-
bloomOptions,
|
|
314
|
-
colorMaskOptions,
|
|
315
|
-
]);
|
|
316
|
-
|
|
317
|
-
return (
|
|
318
|
-
<Canvas
|
|
319
|
-
ref={ref}
|
|
320
|
-
style={{ width, height, aspectRatio: width / height }}
|
|
321
|
-
transparent={Platform.OS === 'ios'}
|
|
322
|
-
/>
|
|
323
|
-
);
|
|
324
|
-
}
|
|
325
6
|
|
|
326
|
-
export { subscribeToOrientationChange, getAngleFromDimensions };
|
|
7
|
+
export { subscribeToOrientationChange, getAngleFromDimensions, useOrientation };
|
|
8
|
+
export { Shine } from './components/Shine';
|
|
9
|
+
export { ShineGroup } from './components/ShineGroup';
|
|
10
|
+
export type { ShineProps } from './components/Shine';
|
|
@@ -1,28 +1,34 @@
|
|
|
1
|
-
import tgpu from 'typegpu';
|
|
1
|
+
import tgpu, { type ValidateBufferSchema } from 'typegpu';
|
|
2
2
|
import * as d from 'typegpu/data';
|
|
3
|
+
import type { BufferUsageType } from './resourceManagement/bufferManager';
|
|
3
4
|
|
|
4
5
|
export const textureBindGroupLayout = tgpu.bindGroupLayout({
|
|
5
6
|
texture: { texture: 'float', dimension: '2d', sampleType: 'float' },
|
|
6
7
|
sampler: { sampler: 'filtering' },
|
|
7
8
|
});
|
|
8
9
|
|
|
10
|
+
export const maskTextureBindGroupLayout = tgpu.bindGroupLayout({
|
|
11
|
+
texture: { texture: 'float', dimension: '2d', sampleType: 'float' },
|
|
12
|
+
sampler: { sampler: 'filtering' },
|
|
13
|
+
});
|
|
14
|
+
|
|
9
15
|
export const rotationValuesBindGroupLayout = tgpu.bindGroupLayout({
|
|
10
16
|
vec: { uniform: d.vec3f },
|
|
11
17
|
});
|
|
12
18
|
|
|
13
|
-
export const
|
|
19
|
+
export const glareOptionsSchema = d.struct({
|
|
14
20
|
glowPower: d.f32,
|
|
15
21
|
hueShiftAngleMax: d.f32,
|
|
16
22
|
hueShiftAngleMin: d.f32,
|
|
17
23
|
hueBlendPower: d.f32,
|
|
18
24
|
lightIntensity: d.f32,
|
|
19
|
-
|
|
25
|
+
glareIntensity: d.f32,
|
|
20
26
|
});
|
|
21
27
|
|
|
22
|
-
export type
|
|
28
|
+
export type glareOptionsSchema = typeof glareOptionsSchema;
|
|
23
29
|
|
|
24
|
-
export const
|
|
25
|
-
|
|
30
|
+
export const glareOptionsBindGroupLayout = tgpu.bindGroupLayout({
|
|
31
|
+
glareOptions: { uniform: glareOptionsSchema },
|
|
26
32
|
});
|
|
27
33
|
|
|
28
34
|
export const colorMaskSchema = d.struct({
|
|
@@ -38,3 +44,34 @@ export type colorMaskSchema = typeof colorMaskSchema;
|
|
|
38
44
|
export const colorMaskBindGroupLayout = tgpu.bindGroupLayout({
|
|
39
45
|
mask: { uniform: colorMaskSchema },
|
|
40
46
|
});
|
|
47
|
+
|
|
48
|
+
export const bufferData = {
|
|
49
|
+
rotationBuffer: {
|
|
50
|
+
schema: d.vec3f,
|
|
51
|
+
usage: 'uniform',
|
|
52
|
+
},
|
|
53
|
+
glareBuffer: {
|
|
54
|
+
schema: glareOptionsSchema,
|
|
55
|
+
usage: 'uniform',
|
|
56
|
+
},
|
|
57
|
+
colorMaskBuffer: {
|
|
58
|
+
schema: colorMaskSchema,
|
|
59
|
+
usage: 'uniform',
|
|
60
|
+
},
|
|
61
|
+
} as const satisfies Record<
|
|
62
|
+
string,
|
|
63
|
+
{ schema: ValidateBufferSchema<any>; usage: BufferUsageType }
|
|
64
|
+
>;
|
|
65
|
+
|
|
66
|
+
export type BufferDataMap = typeof bufferData;
|
|
67
|
+
|
|
68
|
+
// export const holoSchema = d.struct({
|
|
69
|
+
// intensity: d.f32,
|
|
70
|
+
// waveCallback: WaveCallback, //TgpuFn<(uv: d.Vec2f) => d.Vec2f>,
|
|
71
|
+
// });
|
|
72
|
+
|
|
73
|
+
// export type holoSchema = typeof holoSchema;
|
|
74
|
+
|
|
75
|
+
// export const holoBindGroupLayout = tgpu.bindGroupLayout({
|
|
76
|
+
// holoOptions: { uniform: holoSchema },
|
|
77
|
+
// });
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { type TgpuBuffer, type TgpuRoot, type UniformFlag } from 'typegpu';
|
|
2
2
|
import * as d from 'typegpu/data';
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
glareOptionsBindGroupLayout,
|
|
5
|
+
glareOptionsSchema,
|
|
6
6
|
colorMaskBindGroupLayout,
|
|
7
7
|
colorMaskSchema,
|
|
8
8
|
rotationValuesBindGroupLayout,
|
|
9
9
|
} from './bindGroupLayouts';
|
|
10
10
|
import type {
|
|
11
|
-
|
|
11
|
+
GlareOptions,
|
|
12
12
|
ColorMask,
|
|
13
13
|
PartiallyOptional,
|
|
14
14
|
} from '../types/types';
|
|
15
15
|
import {
|
|
16
16
|
colorMaskToTyped,
|
|
17
|
-
|
|
17
|
+
createGlareOptions,
|
|
18
18
|
createColorMask,
|
|
19
19
|
mapToF32,
|
|
20
20
|
} from '../types/typeUtils';
|
|
@@ -35,44 +35,44 @@ export const createRotationBuffer = (
|
|
|
35
35
|
|
|
36
36
|
export const createRotationValuesBindGroup = (
|
|
37
37
|
root: TgpuRoot,
|
|
38
|
-
buffer: TgpuBuffer<d.Vec3f>
|
|
38
|
+
buffer: TgpuBuffer<d.Vec3f>
|
|
39
39
|
) => {
|
|
40
40
|
const rotationValuesBindGroup = root.createBindGroup(
|
|
41
41
|
rotationValuesBindGroupLayout,
|
|
42
42
|
{
|
|
43
|
-
vec: buffer,
|
|
43
|
+
vec: root.unwrap(buffer),
|
|
44
44
|
}
|
|
45
45
|
);
|
|
46
46
|
|
|
47
47
|
return rotationValuesBindGroup;
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
-
export const
|
|
50
|
+
export const createGlareOptionsBuffer = (
|
|
51
51
|
root: TgpuRoot,
|
|
52
|
-
initValues?: Partial<
|
|
52
|
+
initValues?: Partial<GlareOptions>
|
|
53
53
|
) => {
|
|
54
|
-
const
|
|
55
|
-
const
|
|
54
|
+
const glareOptions: GlareOptions = createGlareOptions({ ...initValues });
|
|
55
|
+
const glareOptionsTyped = mapToF32(glareOptions);
|
|
56
56
|
|
|
57
|
-
const
|
|
58
|
-
.createBuffer(
|
|
57
|
+
const glareOptionsBuffer = root
|
|
58
|
+
.createBuffer(glareOptionsSchema, glareOptionsTyped)
|
|
59
59
|
.$usage('uniform');
|
|
60
60
|
|
|
61
|
-
return
|
|
61
|
+
return glareOptionsBuffer;
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
export const
|
|
64
|
+
export const createGlareOptionsBindGroup = (
|
|
65
65
|
root: TgpuRoot,
|
|
66
|
-
buffer: TgpuBuffer<
|
|
66
|
+
buffer: TgpuBuffer<glareOptionsSchema> & UniformFlag
|
|
67
67
|
) => {
|
|
68
|
-
const
|
|
69
|
-
|
|
68
|
+
const glareOptionsBindGroup = root.createBindGroup(
|
|
69
|
+
glareOptionsBindGroupLayout,
|
|
70
70
|
{
|
|
71
|
-
|
|
71
|
+
glareOptions: buffer,
|
|
72
72
|
}
|
|
73
73
|
);
|
|
74
74
|
|
|
75
|
-
return
|
|
75
|
+
return glareOptionsBindGroup;
|
|
76
76
|
};
|
|
77
77
|
|
|
78
78
|
export const createColorMaskBuffer = (
|
|
@@ -99,3 +99,18 @@ export const createColorMaskBindGroup = (
|
|
|
99
99
|
|
|
100
100
|
return colorMaskBindGroup;
|
|
101
101
|
};
|
|
102
|
+
|
|
103
|
+
// export const crateHoloBuffer = (
|
|
104
|
+
// root: TgpuRoot,
|
|
105
|
+
// initValues: Partial<HoloOptions>
|
|
106
|
+
// ) => {
|
|
107
|
+
// const holoOptions: HoloOptions = createHoloOptions({ ...initValues });
|
|
108
|
+
// const holoOptionsTyped = {
|
|
109
|
+
// intensity: d.f32(holoOptions.intensity),
|
|
110
|
+
// waveCallback: holoOptions.waveCallback,
|
|
111
|
+
// };
|
|
112
|
+
|
|
113
|
+
// const holoBuffer = root
|
|
114
|
+
// .createBuffer(holoSchema, holoOptionsTyped)
|
|
115
|
+
// .$usage('uniform');
|
|
116
|
+
// };
|
|
@@ -27,9 +27,9 @@ const colorMaskFragment = tgpu['~unstable'].fragmentFn({
|
|
|
27
27
|
const upperCheck = std.all(std.le(color.xyz, maskedColorUpper));
|
|
28
28
|
const lowerCheck = std.all(std.ge(color.xyz, maskedColorLower));
|
|
29
29
|
if (upperCheck && lowerCheck) {
|
|
30
|
-
return color;
|
|
30
|
+
return d.vec4f(color.xyz, 0.0);
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
return d.vec4f(1.0);
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
export default colorMaskFragment;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import tgpu from 'typegpu';
|
|
2
|
+
import * as d from 'typegpu/data';
|
|
3
|
+
import * as std from 'typegpu/std';
|
|
4
|
+
import {
|
|
5
|
+
rotationValuesBindGroupLayout,
|
|
6
|
+
textureBindGroupLayout,
|
|
7
|
+
glareOptionsBindGroupLayout,
|
|
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 = rotationValuesBindGroupLayout.$.vec;
|
|
21
|
+
const center = std.add(d.vec2f(0.0), d.vec2f(rot.x, rot.y));
|
|
22
|
+
|
|
23
|
+
const glareOptions = glareOptionsBindGroupLayout.$.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 = rotationValuesBindGroupLayout.$.vec;
|
|
92
|
+
const center = std.add(d.vec2f(0.0), d.vec2f(rot.x, rot.y)); // do not change
|
|
93
|
+
|
|
94
|
+
const opts = glareOptionsBindGroupLayout.$.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
|
+
// Optional mild safety clamp to avoid NaNs/overflow artifacts.
|
|
139
|
+
const outRGB = std.clamp(finalRGB, d.vec3f(0.0), d.vec3f(1.0));
|
|
140
|
+
|
|
141
|
+
return d.vec4f(outRGB, color.w);
|
|
142
|
+
});
|