react-native-shine 0.2.2 → 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.
Files changed (111) hide show
  1. package/README.md +1 -1
  2. package/lib/module/components/Shine.js +269 -0
  3. package/lib/module/components/Shine.js.map +1 -0
  4. package/lib/module/components/ShineGroup.js +104 -0
  5. package/lib/module/components/ShineGroup.js.map +1 -0
  6. package/lib/module/enums/waveCallback.js +19 -0
  7. package/lib/module/enums/waveCallback.js.map +1 -0
  8. package/lib/module/hooks/useOrientation.js +16 -0
  9. package/lib/module/hooks/useOrientation.js.map +1 -0
  10. package/lib/module/index.js +5 -219
  11. package/lib/module/index.js.map +1 -1
  12. package/lib/module/shaders/bindGroupLayouts.js +40 -5
  13. package/lib/module/shaders/bindGroupLayouts.js.map +1 -1
  14. package/lib/module/shaders/bindGroupUtils.js +27 -12
  15. package/lib/module/shaders/bindGroupUtils.js.map +1 -1
  16. package/lib/module/shaders/fragmentShaders/colorMaskFragment.js +2 -2
  17. package/lib/module/shaders/fragmentShaders/colorMaskFragment.js.map +1 -1
  18. package/lib/module/shaders/fragmentShaders/glareFragment.js +114 -0
  19. package/lib/module/shaders/fragmentShaders/glareFragment.js.map +1 -0
  20. package/lib/module/shaders/fragmentShaders/holoFragment.js +33 -0
  21. package/lib/module/shaders/fragmentShaders/holoFragment.js.map +1 -0
  22. package/lib/module/shaders/fragmentShaders/maskFragment.js +20 -0
  23. package/lib/module/shaders/fragmentShaders/maskFragment.js.map +1 -0
  24. package/lib/module/shaders/fragmentShaders/reverseHoloFragment.js +46 -0
  25. package/lib/module/shaders/fragmentShaders/reverseHoloFragment.js.map +1 -0
  26. package/lib/module/shaders/pipelineSetups.js +82 -13
  27. package/lib/module/shaders/pipelineSetups.js.map +1 -1
  28. package/lib/module/shaders/{resourceManagement.js → resourceManagement/bitmaps.js} +2 -1
  29. package/lib/module/shaders/resourceManagement/bitmaps.js.map +1 -0
  30. package/lib/module/shaders/resourceManagement/bufferManager.js +46 -0
  31. package/lib/module/shaders/resourceManagement/bufferManager.js.map +1 -0
  32. package/lib/module/shaders/resourceManagement/textures.js +17 -0
  33. package/lib/module/shaders/resourceManagement/textures.js.map +1 -0
  34. package/lib/module/shaders/tgpuUtils.js +19 -1
  35. package/lib/module/shaders/tgpuUtils.js.map +1 -1
  36. package/lib/module/shaders/utils.js +0 -14
  37. package/lib/module/shaders/utils.js.map +1 -1
  38. package/lib/module/shaders/vertexShaders/mainRotationEffectVertex.js +47 -0
  39. package/lib/module/shaders/vertexShaders/mainRotationEffectVertex.js.map +1 -0
  40. package/lib/module/types/typeUtils.js +17 -5
  41. package/lib/module/types/typeUtils.js.map +1 -1
  42. package/lib/typescript/src/components/Shine.d.ts +17 -0
  43. package/lib/typescript/src/components/Shine.d.ts.map +1 -0
  44. package/lib/typescript/src/components/ShineGroup.d.ts +8 -0
  45. package/lib/typescript/src/components/ShineGroup.d.ts.map +1 -0
  46. package/lib/typescript/src/enums/waveCallback.d.ts +9 -0
  47. package/lib/typescript/src/enums/waveCallback.d.ts.map +1 -0
  48. package/lib/typescript/src/hooks/useOrientation.d.ts +2 -0
  49. package/lib/typescript/src/hooks/useOrientation.d.ts.map +1 -0
  50. package/lib/typescript/src/index.d.ts +6 -11
  51. package/lib/typescript/src/index.d.ts.map +1 -1
  52. package/lib/typescript/src/shaders/bindGroupLayouts.d.ts +44 -6
  53. package/lib/typescript/src/shaders/bindGroupLayouts.d.ts.map +1 -1
  54. package/lib/typescript/src/shaders/bindGroupUtils.d.ts +8 -8
  55. package/lib/typescript/src/shaders/bindGroupUtils.d.ts.map +1 -1
  56. package/lib/typescript/src/shaders/fragmentShaders/glareFragment.d.ts +8 -0
  57. package/lib/typescript/src/shaders/fragmentShaders/glareFragment.d.ts.map +1 -0
  58. package/lib/typescript/src/shaders/fragmentShaders/holoFragment.d.ts +5 -0
  59. package/lib/typescript/src/shaders/fragmentShaders/holoFragment.d.ts.map +1 -0
  60. package/lib/typescript/src/shaders/fragmentShaders/maskFragment.d.ts +6 -0
  61. package/lib/typescript/src/shaders/fragmentShaders/maskFragment.d.ts.map +1 -0
  62. package/lib/typescript/src/shaders/fragmentShaders/reverseHoloFragment.d.ts +5 -0
  63. package/lib/typescript/src/shaders/fragmentShaders/reverseHoloFragment.d.ts.map +1 -0
  64. package/lib/typescript/src/shaders/pipelineSetups.d.ts +9 -4
  65. package/lib/typescript/src/shaders/pipelineSetups.d.ts.map +1 -1
  66. package/lib/typescript/src/shaders/{resourceManagement.d.ts → resourceManagement/bitmaps.d.ts} +1 -1
  67. package/lib/typescript/src/shaders/resourceManagement/bitmaps.d.ts.map +1 -0
  68. package/lib/typescript/src/shaders/resourceManagement/bufferManager.d.ts +28 -0
  69. package/lib/typescript/src/shaders/resourceManagement/bufferManager.d.ts.map +1 -0
  70. package/lib/typescript/src/shaders/resourceManagement/textures.d.ts +7 -0
  71. package/lib/typescript/src/shaders/resourceManagement/textures.d.ts.map +1 -0
  72. package/lib/typescript/src/shaders/tgpuUtils.d.ts +5 -1
  73. package/lib/typescript/src/shaders/tgpuUtils.d.ts.map +1 -1
  74. package/lib/typescript/src/shaders/utils.d.ts +1 -7
  75. package/lib/typescript/src/shaders/utils.d.ts.map +1 -1
  76. package/lib/typescript/src/shaders/vertexShaders/mainRotationEffectVertex.d.ts +6 -0
  77. package/lib/typescript/src/shaders/vertexShaders/mainRotationEffectVertex.d.ts.map +1 -0
  78. package/lib/typescript/src/types/typeUtils.d.ts +3 -2
  79. package/lib/typescript/src/types/typeUtils.d.ts.map +1 -1
  80. package/lib/typescript/src/types/types.d.ts +7 -2
  81. package/lib/typescript/src/types/types.d.ts.map +1 -1
  82. package/package.json +4 -3
  83. package/scripts/postinstall.js +16 -17
  84. package/src/components/Shine.tsx +480 -0
  85. package/src/components/ShineGroup.tsx +107 -0
  86. package/src/enums/waveCallback.ts +22 -0
  87. package/src/hooks/useOrientation.ts +20 -0
  88. package/src/index.tsx +6 -322
  89. package/src/shaders/bindGroupLayouts.ts +43 -6
  90. package/src/shaders/bindGroupUtils.ts +34 -19
  91. package/src/shaders/fragmentShaders/colorMaskFragment.ts +2 -2
  92. package/src/shaders/fragmentShaders/glareFragment.ts +142 -0
  93. package/src/shaders/fragmentShaders/holoFragment.ts +43 -0
  94. package/src/shaders/fragmentShaders/maskFragment.ts +31 -0
  95. package/src/shaders/fragmentShaders/reverseHoloFragment.ts +71 -0
  96. package/src/shaders/pipelineSetups.ts +161 -14
  97. package/src/shaders/{resourceManagement.ts → resourceManagement/bitmaps.ts} +1 -0
  98. package/src/shaders/resourceManagement/bufferManager.ts +82 -0
  99. package/src/shaders/resourceManagement/textures.ts +30 -0
  100. package/src/shaders/tgpuUtils.ts +36 -1
  101. package/src/shaders/utils.ts +0 -30
  102. package/src/shaders/vertexShaders/mainRotationEffectVertex.ts +76 -0
  103. package/src/types/typeUtils.ts +22 -8
  104. package/src/types/types.ts +8 -2
  105. package/lib/module/shaders/fragmentShaders/bloomFragment.js +0 -66
  106. package/lib/module/shaders/fragmentShaders/bloomFragment.js.map +0 -1
  107. package/lib/module/shaders/resourceManagement.js.map +0 -1
  108. package/lib/typescript/src/shaders/fragmentShaders/bloomFragment.d.ts +0 -6
  109. package/lib/typescript/src/shaders/fragmentShaders/bloomFragment.d.ts.map +0 -1
  110. package/lib/typescript/src/shaders/resourceManagement.d.ts.map +0 -1
  111. package/src/shaders/fragmentShaders/bloomFragment.ts +0 -83
@@ -0,0 +1,43 @@
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
+ } 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 centeredCoords = std.sub(std.mul(uv, 2.0), 1.0);
18
+
19
+ const textureColor = std.textureSample(
20
+ textureBindGroupLayout.$.texture,
21
+ textureBindGroupLayout.$.sampler,
22
+ texcoord
23
+ );
24
+
25
+ const rot = rotationValuesBindGroupLayout.$.vec;
26
+ const center = std.add(d.vec2f(0.0), d.vec2f(rot.x, rot.y));
27
+
28
+ const wave = waveCallbackSlot.$(rot.xy);
29
+ const waveX = wave.x;
30
+ const waveY = wave.y;
31
+
32
+ const band = std.add(waveX, waveY);
33
+
34
+ const dist = std.distance(centeredCoords, center);
35
+ const intensity = std.clamp(1.0 - dist, 0.0, 1.0);
36
+ const falloff = std.pow(std.exp(-dist), 1.0 / intensity);
37
+
38
+ const hueAngle = std.mul(std.abs(band), (10 * Math.PI * rot.x) / 3);
39
+ const rainbowColor = hueShift(d.vec3f(1.0, 1.0, 1.0), hueAngle);
40
+ const finalColor = std.mul(rainbowColor, falloff);
41
+
42
+ return d.vec4f(finalColor, 1 - falloff * dist * textureColor.w);
43
+ });
@@ -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
+ rotationValuesBindGroupLayout,
8
+ glareOptionsBindGroupLayout,
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 = rotationValuesBindGroupLayout.$.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 = glareOptionsBindGroupLayout.$.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,5 +1,19 @@
1
- import type { TgpuRenderPipeline } from 'typegpu';
1
+ import type { TgpuRenderPipeline, TgpuRoot, TgpuTexture } from 'typegpu';
2
2
  import type { BindGroupPair } from '../types/types';
3
+ import {
4
+ maskTextureBindGroupLayout,
5
+ textureBindGroupLayout,
6
+ } from './bindGroupLayouts';
7
+ import { createBindGroupPair, createBindGroupPairs } from '../types/typeUtils';
8
+ import mainVertex from './vertexShaders/mainVertex';
9
+ import maskFragment from './fragmentShaders/maskFragment';
10
+ import { reverseHoloFragment } from './fragmentShaders/reverseHoloFragment';
11
+ import { holoFragment } from './fragmentShaders/holoFragment';
12
+ import {
13
+ WAVE_CALLBACKS,
14
+ waveCallbackFn,
15
+ waveCallbackSlot,
16
+ } from '../enums/waveCallback';
3
17
 
4
18
  export const attachBindGroups = (
5
19
  pipeline: TgpuRenderPipeline,
@@ -12,23 +26,26 @@ export const attachBindGroups = (
12
26
  return pipeline;
13
27
  };
14
28
 
29
+ export const blend: GPUBlendState = {
30
+ color: {
31
+ srcFactor: 'one-minus-src-alpha',
32
+ dstFactor: 'src-alpha',
33
+ operation: 'add',
34
+ } satisfies GPUBlendComponent,
35
+ alpha: {
36
+ srcFactor: 'one-minus-src-alpha',
37
+ dstFactor: 'dst-alpha',
38
+ operation: 'add',
39
+ } satisfies GPUBlendComponent,
40
+ };
41
+
15
42
  export const getDefaultTarget = (
16
- presentationFormat: GPUTextureFormat
43
+ presentationFormat: GPUTextureFormat,
44
+ blendMode?: GPUBlendState
17
45
  ): GPUColorTargetState => {
18
46
  return {
19
47
  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
- },
48
+ blend: blendMode,
32
49
  };
33
50
  };
34
51
 
@@ -42,3 +59,133 @@ export const attachBindGroupsToPass = (
42
59
 
43
60
  return pass;
44
61
  };
62
+
63
+ export const createMaskPipeline = (
64
+ root: TgpuRoot,
65
+ maskTexture: TgpuTexture | null,
66
+ BGP: BindGroupPair[],
67
+ sampler: GPUSampler,
68
+ presentationFormat: GPUTextureFormat
69
+ ): TgpuRenderPipeline | null => {
70
+ if (!maskTexture) return null;
71
+
72
+ const maskTextureBindGroup = root.createBindGroup(
73
+ maskTextureBindGroupLayout,
74
+ {
75
+ texture: root.unwrap(maskTexture).createView(),
76
+ sampler,
77
+ }
78
+ );
79
+ const maskBGP: BindGroupPair[] = createBindGroupPairs(
80
+ [maskTextureBindGroupLayout],
81
+ [maskTextureBindGroup]
82
+ );
83
+ for (let i = 0; i < BGP.length; i++) {
84
+ maskBGP.push(BGP[i]!);
85
+ }
86
+ let maskPipeline = root['~unstable']
87
+ .withVertex(mainVertex, {})
88
+ .withFragment(maskFragment, getDefaultTarget(presentationFormat, blend))
89
+ .createPipeline();
90
+ maskPipeline = attachBindGroups(maskPipeline, maskBGP);
91
+
92
+ return maskPipeline;
93
+ };
94
+
95
+ export const createReverseHoloPipeline = (
96
+ root: TgpuRoot,
97
+ texture: TgpuTexture | null,
98
+ BGP: BindGroupPair[],
99
+ sampler: GPUSampler,
100
+ presentationFormat: GPUTextureFormat
101
+ ): TgpuRenderPipeline | null => {
102
+ if (!texture) return null;
103
+
104
+ const reverseHoloBindGroup = root.createBindGroup(
105
+ maskTextureBindGroupLayout,
106
+ {
107
+ texture: root.unwrap(texture).createView(),
108
+ sampler,
109
+ }
110
+ );
111
+ const reverseHoloBGP: BindGroupPair[] = BGP;
112
+ reverseHoloBGP.push(
113
+ createBindGroupPair(maskTextureBindGroupLayout, reverseHoloBindGroup)
114
+ );
115
+
116
+ let reverseHoloPipeline = root['~unstable']
117
+ .withVertex(mainVertex, {})
118
+ .withFragment(
119
+ reverseHoloFragment,
120
+ getDefaultTarget(presentationFormat, blend)
121
+ )
122
+ .createPipeline();
123
+ reverseHoloPipeline = attachBindGroups(reverseHoloPipeline, reverseHoloBGP);
124
+
125
+ return reverseHoloPipeline;
126
+ };
127
+
128
+ export const createRainbowHoloPipeline = (
129
+ root: TgpuRoot,
130
+ texture: TgpuTexture | null,
131
+ BGP: BindGroupPair[],
132
+ sampler: GPUSampler,
133
+ presentationFormat: GPUTextureFormat
134
+ ): TgpuRenderPipeline | null => {
135
+ if (!texture) return null;
136
+
137
+ const imageTextureBindGroup = root.createBindGroup(textureBindGroupLayout, {
138
+ texture: root.unwrap(texture).createView(),
139
+ sampler,
140
+ });
141
+
142
+ const texBGP = createBindGroupPair(
143
+ textureBindGroupLayout,
144
+ imageTextureBindGroup
145
+ );
146
+
147
+ let rainbowHoloPipeline = root['~unstable']
148
+ .with(waveCallbackSlot, waveCallbackFn(WAVE_CALLBACKS.default))
149
+ .withVertex(mainVertex, {})
150
+ .withFragment(holoFragment, getDefaultTarget(presentationFormat, blend))
151
+ .createPipeline();
152
+
153
+ rainbowHoloPipeline = attachBindGroups(rainbowHoloPipeline, [...BGP, texBGP]);
154
+ return rainbowHoloPipeline;
155
+ };
156
+
157
+ export const pipelineRenderFunction = (
158
+ root: TgpuRoot,
159
+ pipelines: TgpuRenderPipeline[],
160
+ attachments: any[],
161
+ view: GPUTextureView,
162
+ isInSinglePass: boolean
163
+ ) => {
164
+ if (isInSinglePass) {
165
+ root['~unstable'].beginRenderPass(
166
+ {
167
+ colorAttachments: [
168
+ {
169
+ view: view,
170
+ clearValue: [0, 0, 0, 0],
171
+ loadOp: 'clear',
172
+ storeOp: 'store',
173
+ },
174
+ ],
175
+ },
176
+ (pass) => {
177
+ for (let i = 0; i < pipelines.length; i++) {
178
+ pass.setPipeline(pipelines[i]!);
179
+ pass.draw(6);
180
+ }
181
+ }
182
+ );
183
+ root['~unstable'].flush();
184
+ } else {
185
+ for (let i = 0; i < pipelines.length; i++) {
186
+ const attachment = attachments[i];
187
+ if (!attachment) return;
188
+ pipelines[i]!.withColorAttachment(attachment).draw(6);
189
+ }
190
+ }
191
+ };
@@ -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,30 @@
1
+ import { type TgpuRoot, type TgpuTexture } from 'typegpu';
2
+
3
+ export const createTexture = async (
4
+ root: TgpuRoot,
5
+ size: {
6
+ width: number;
7
+ height: number;
8
+ }
9
+ ): Promise<TgpuTexture> => {
10
+ const texture = root['~unstable']
11
+ .createTexture({
12
+ size: [size.width, size.height],
13
+ format: 'rgba8unorm',
14
+ })
15
+ .$usage('sampled', 'render');
16
+
17
+ return texture;
18
+ };
19
+
20
+ export const loadTexture = async (
21
+ root: TgpuRoot,
22
+ imageBitmap: ImageBitmap,
23
+ texture: TgpuTexture
24
+ ) => {
25
+ root.device.queue.copyExternalImageToTexture(
26
+ { source: imageBitmap },
27
+ { texture: root.unwrap(texture) },
28
+ [imageBitmap.width, imageBitmap.height]
29
+ );
30
+ };
@@ -33,7 +33,7 @@ export const hueShift = tgpu.fn(
33
33
  return d.vec3f(r, g, b);
34
34
  });
35
35
 
36
- export const bloomColorShift = tgpu.fn(
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
+ });
@@ -1,36 +1,6 @@
1
- import { type TgpuRoot, type TgpuTexture } from 'typegpu';
2
1
  import type { quaternion, vec3 } from '../types/types';
3
2
  import { Dimensions } from 'react-native';
4
3
 
5
- export const createTexture = async (
6
- root: TgpuRoot,
7
- size: {
8
- width: number;
9
- height: number;
10
- }
11
- ): Promise<TgpuTexture> => {
12
- const texture = root['~unstable']
13
- .createTexture({
14
- size: [size.width, size.height],
15
- format: 'rgba8unorm',
16
- })
17
- .$usage('sampled', 'render');
18
-
19
- return texture;
20
- };
21
-
22
- export const loadTexture = async (
23
- root: TgpuRoot,
24
- imageBitmap: ImageBitmap,
25
- texture: TgpuTexture
26
- ) => {
27
- root.device.queue.copyExternalImageToTexture(
28
- { source: imageBitmap },
29
- { texture: root.unwrap(texture) },
30
- [imageBitmap.width, imageBitmap.height]
31
- );
32
- };
33
-
34
4
  export const rotateVectorByQuaternion = (
35
5
  vec: vec3,
36
6
  quaternion: quaternion
@@ -0,0 +1,76 @@
1
+ import tgpu from 'typegpu';
2
+ import * as std from 'typegpu/std';
3
+ import * as d from 'typegpu/data';
4
+ import { rotationValuesBindGroupLayout } from '../bindGroupLayouts';
5
+
6
+ const mainRotationEffectVertex = tgpu['~unstable'].vertexFn({
7
+ in: { vertexIndex: d.builtin.vertexIndex },
8
+ out: { position: d.builtin.position, uv: d.vec2f },
9
+ })((input) => {
10
+ const rot = rotationValuesBindGroupLayout.$.vec;
11
+
12
+ // Maximum rotation angles in radians
13
+ const maxAngle = d.f32((25.0 * Math.PI) / 180.0);
14
+ const ax = d.f32(-rot.y * maxAngle); // rotateX depends on vertical touch
15
+ const ay = d.f32(-rot.x * 1.0); // rotateY depends on horizontal touch
16
+
17
+ const positions: d.v2f[] = [
18
+ d.vec2f(-1.0, -1.0),
19
+ d.vec2f(1.0, 1.0),
20
+ d.vec2f(1.0, -1.0),
21
+ d.vec2f(-1.0, -1.0),
22
+ d.vec2f(-1.0, 1.0),
23
+ d.vec2f(1.0, 1.0),
24
+ ];
25
+
26
+ const uvs: d.v2f[] = [
27
+ d.vec2f(0.0, 0.0),
28
+ d.vec2f(1.0, 1.0),
29
+ d.vec2f(1.0, 0.0),
30
+ d.vec2f(0.0, 0.0),
31
+ d.vec2f(0.0, 1.0),
32
+ d.vec2f(1.0, 1.0),
33
+ ];
34
+
35
+ const index = input.vertexIndex;
36
+ const pos = d.vec3f(positions[index] as d.v2f, 0.0);
37
+
38
+ const pivot = d.vec3f(rot.x, rot.y, 0.0);
39
+
40
+ const relative = std.sub(pos, pivot);
41
+ const cosX = std.cos(ax);
42
+ const sinX = std.sin(ax);
43
+ const rotatedX = d.vec3f(
44
+ relative.x,
45
+ cosX * relative.y - sinX * relative.z,
46
+ sinX * relative.y + cosX * relative.z
47
+ );
48
+
49
+ const cosY = std.cos(ay);
50
+ const sinY = std.sin(ay);
51
+ const rotatedXY = d.vec3f(
52
+ cosY * rotatedX.x + sinY * rotatedX.z,
53
+ rotatedX.y,
54
+ -sinY * rotatedX.x + cosY * rotatedX.z
55
+ );
56
+
57
+ const finalPos3D = std.add(rotatedXY, pivot);
58
+ const perspective = 100.0;
59
+ const zOffset = 2.5;
60
+ const z = finalPos3D.z + zOffset;
61
+ const persp = perspective / (perspective + z);
62
+
63
+ const finalPos = d.vec4f(
64
+ finalPos3D.x * persp,
65
+ finalPos3D.y * persp,
66
+ 0.0,
67
+ 1.0
68
+ );
69
+
70
+ return {
71
+ position: finalPos,
72
+ uv: uvs[index] as d.v2f,
73
+ };
74
+ });
75
+
76
+ export default mainRotationEffectVertex;
@@ -1,36 +1,38 @@
1
1
  import { f32, vec2f, vec3f, vec4f } from 'typegpu/data';
2
2
  import type {
3
3
  BindGroupPair,
4
- BloomOptions,
4
+ GlareOptions,
5
5
  ColorMask,
6
6
  DeepPartiallyOptional,
7
7
  vec3,
8
+ HoloOptions,
8
9
  } from './types';
9
10
  import { div } from 'typegpu/std';
10
11
  import type { TgpuBindGroup, TgpuBindGroupLayout } from 'typegpu';
12
+ import { WAVE_CALLBACKS } from '../enums/waveCallback';
11
13
 
12
- export const createBloomOptions = (
13
- options: Partial<BloomOptions>
14
- ): BloomOptions => {
14
+ export const createGlareOptions = (
15
+ options: Partial<GlareOptions>
16
+ ): GlareOptions => {
15
17
  const {
16
18
  glowPower,
17
19
  hueShiftAngleMax,
18
20
  hueShiftAngleMin,
19
21
  hueBlendPower,
20
22
  lightIntensity,
21
- bloomIntensity,
23
+ glareIntensity,
22
24
  } = options;
23
25
 
24
- const bloomOp = {
26
+ const glareOp = {
25
27
  glowPower: glowPower ?? 1.0,
26
28
  hueShiftAngleMax: hueShiftAngleMax ?? 1.0,
27
29
  hueShiftAngleMin: hueShiftAngleMin ?? 0.0,
28
30
  hueBlendPower: hueBlendPower ?? 1.0,
29
31
  lightIntensity: lightIntensity ?? 1.0,
30
- bloomIntensity: bloomIntensity ?? 1.0,
32
+ glareIntensity: glareIntensity ?? 1.0,
31
33
  };
32
34
 
33
- return bloomOp;
35
+ return glareOp;
34
36
  };
35
37
 
36
38
  export const mapToF32 = <T extends Record<string, number>>(
@@ -75,6 +77,18 @@ export const colorMaskToTyped = (colorMask: ColorMask) => {
75
77
  return result;
76
78
  };
77
79
 
80
+ export const createHoloOptions = (
81
+ options: Partial<HoloOptions>
82
+ ): HoloOptions => {
83
+ const { intensity, waveCallback } = options;
84
+ const holoOpt = {
85
+ intensity: intensity ?? 0.7,
86
+ waveCallback: waveCallback ?? WAVE_CALLBACKS.default,
87
+ };
88
+
89
+ return holoOpt;
90
+ };
91
+
78
92
  export const numberArrToTyped = (vec: number[]) => {
79
93
  let convFn: ((...args: number[]) => any) | null = null;
80
94
  switch (vec.length) {