@driftengine/core 4.8.2 → 4.8.3

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 (121) hide show
  1. package/CHANGELOG.json +56 -0
  2. package/README.md +1 -1
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.js +6 -0
  5. package/dist/render/backend/materialChanges.d.ts +7 -2
  6. package/dist/render/backend/materialChanges.js +8 -3
  7. package/dist/render/backend/webgl2/renderer.d.ts +23 -0
  8. package/dist/render/backend/webgl2/renderer.js +58 -17
  9. package/dist/render/backend/webgpu/causticsPass.js +2 -1
  10. package/dist/render/backend/webgpu/depthPass.d.ts +13 -3
  11. package/dist/render/backend/webgpu/depthPass.js +4 -3
  12. package/dist/render/backend/webgpu/filmPass.js +2 -1
  13. package/dist/render/backend/webgpu/flatPass.d.ts +5 -0
  14. package/dist/render/backend/webgpu/flatPass.js +2 -1
  15. package/dist/render/backend/webgpu/linePass.js +2 -1
  16. package/dist/render/backend/webgpu/panelPass.js +2 -1
  17. package/dist/render/backend/webgpu/particlePass.js +2 -1
  18. package/dist/render/backend/webgpu/plumePass.js +2 -1
  19. package/dist/render/backend/webgpu/postPass.d.ts +12 -2
  20. package/dist/render/backend/webgpu/postPass.js +19 -5
  21. package/dist/render/backend/webgpu/renderer.d.ts +10 -1
  22. package/dist/render/backend/webgpu/renderer.js +38 -12
  23. package/dist/render/backend/webgpu/sdfTextPass.js +2 -1
  24. package/dist/render/backend/webgpu/textPass.js +2 -1
  25. package/dist/render/backend/webgpu/waterPass.js +2 -1
  26. package/dist/render/backend/webgpu/windStreakPass.js +2 -1
  27. package/dist/render/boltBatch.js +2 -1
  28. package/dist/render/causticsRenderer.js +2 -1
  29. package/dist/render/cutoutCaster.d.ts +3 -1
  30. package/dist/render/cutoutCaster.js +4 -0
  31. package/dist/render/decalPass.js +2 -1
  32. package/dist/render/globalMediumPass.js +3 -2
  33. package/dist/render/lineBatch.js +5 -1
  34. package/dist/render/oitPass.js +2 -1
  35. package/dist/render/particleBatch.js +3 -2
  36. package/dist/render/particlePool.d.ts +6 -2
  37. package/dist/render/plumeRenderer.js +3 -2
  38. package/dist/render/renderQuality.d.ts +9 -2
  39. package/dist/render/sceneCoverage.d.ts +54 -0
  40. package/dist/render/sceneCoverage.js +72 -0
  41. package/dist/render/sdfTextRenderer.js +2 -1
  42. package/dist/render/shaders/depth.js +3 -2
  43. package/dist/render/shaders/flat/index.js +6 -1
  44. package/dist/render/shaders/generated/depth.wgsl.d.ts +32 -12
  45. package/dist/render/shaders/generated/depth.wgsl.js +32 -12
  46. package/dist/render/shaders/generated/flat.wgsl.d.ts +25 -0
  47. package/dist/render/shaders/generated/flat.wgsl.js +47 -22
  48. package/dist/render/shaders/generated/line.wgsl.d.ts +1 -1
  49. package/dist/render/shaders/generated/line.wgsl.js +1 -1
  50. package/dist/render/shaders/generated/particle.wgsl.d.ts +3 -3
  51. package/dist/render/shaders/generated/particle.wgsl.js +3 -3
  52. package/dist/render/shaders/generated/rush.wgsl.d.ts +1 -1
  53. package/dist/render/shaders/generated/rush.wgsl.js +1 -1
  54. package/dist/render/shaders/generated/sdfText.wgsl.d.ts +1 -1
  55. package/dist/render/shaders/generated/sdfText.wgsl.js +1 -1
  56. package/dist/render/shaders/generated/temporalResolve.wgsl.d.ts +1 -1
  57. package/dist/render/shaders/generated/temporalResolve.wgsl.js +1 -1
  58. package/dist/render/shaders/line.d.ts +1 -1
  59. package/dist/render/shaders/outputTransform.d.ts +14 -1
  60. package/dist/render/shaders/outputTransform.js +23 -1
  61. package/dist/render/shaders/particle.d.ts +3 -3
  62. package/dist/render/shaders/recon/resolve.wgsl.js +15 -1
  63. package/dist/render/shaders/rush.js +13 -2
  64. package/dist/render/shaders/sdfText.d.ts +1 -1
  65. package/dist/render/shaders/temporalResolve.js +12 -5
  66. package/dist/render/ssrPass.js +2 -1
  67. package/dist/render/surfaceTexture.d.ts +11 -0
  68. package/dist/render/textRenderer.js +2 -1
  69. package/dist/render/vertexDefaults.js +1 -0
  70. package/dist/render/waterRenderer.js +2 -1
  71. package/dist/render/windStreakRenderer.js +2 -1
  72. package/package.json +6 -6
  73. package/src/index.ts +13 -0
  74. package/src/render/backend/materialChanges.ts +8 -3
  75. package/src/render/backend/webgl2/renderer.ts +57 -16
  76. package/src/render/backend/webgpu/causticsPass.ts +2 -1
  77. package/src/render/backend/webgpu/depthPass.ts +4 -3
  78. package/src/render/backend/webgpu/filmPass.ts +2 -1
  79. package/src/render/backend/webgpu/flatPass.ts +2 -1
  80. package/src/render/backend/webgpu/linePass.ts +2 -1
  81. package/src/render/backend/webgpu/panelPass.ts +2 -1
  82. package/src/render/backend/webgpu/particlePass.ts +2 -1
  83. package/src/render/backend/webgpu/plumePass.ts +2 -1
  84. package/src/render/backend/webgpu/postPass.ts +20 -5
  85. package/src/render/backend/webgpu/renderer.ts +40 -11
  86. package/src/render/backend/webgpu/sdfTextPass.ts +2 -1
  87. package/src/render/backend/webgpu/textPass.ts +2 -1
  88. package/src/render/backend/webgpu/waterPass.ts +2 -1
  89. package/src/render/backend/webgpu/windStreakPass.ts +2 -1
  90. package/src/render/boltBatch.ts +2 -1
  91. package/src/render/causticsRenderer.ts +2 -1
  92. package/src/render/cutoutCaster.ts +15 -2
  93. package/src/render/decalPass.ts +2 -1
  94. package/src/render/globalMediumPass.ts +3 -2
  95. package/src/render/lineBatch.ts +3 -1
  96. package/src/render/oitPass.ts +2 -1
  97. package/src/render/particleBatch.ts +3 -2
  98. package/src/render/particlePool.ts +6 -2
  99. package/src/render/plumeRenderer.ts +3 -2
  100. package/src/render/renderQuality.ts +9 -2
  101. package/src/render/sceneCoverage.ts +78 -0
  102. package/src/render/sdfTextRenderer.ts +2 -1
  103. package/src/render/shaders/depth.ts +3 -2
  104. package/src/render/shaders/flat/index.ts +6 -1
  105. package/src/render/shaders/generated/depth.wgsl.ts +32 -12
  106. package/src/render/shaders/generated/flat.wgsl.ts +47 -22
  107. package/src/render/shaders/generated/line.wgsl.ts +1 -1
  108. package/src/render/shaders/generated/particle.wgsl.ts +3 -3
  109. package/src/render/shaders/generated/rush.wgsl.ts +1 -1
  110. package/src/render/shaders/generated/sdfText.wgsl.ts +1 -1
  111. package/src/render/shaders/generated/temporalResolve.wgsl.ts +1 -1
  112. package/src/render/shaders/outputTransform.ts +24 -1
  113. package/src/render/shaders/recon/resolve.wgsl.ts +15 -1
  114. package/src/render/shaders/rush.ts +13 -2
  115. package/src/render/shaders/temporalResolve.ts +12 -5
  116. package/src/render/ssrPass.ts +2 -1
  117. package/src/render/surfaceTexture.ts +11 -0
  118. package/src/render/textRenderer.ts +2 -1
  119. package/src/render/vertexDefaults.ts +1 -0
  120. package/src/render/waterRenderer.ts +2 -1
  121. package/src/render/windStreakRenderer.ts +2 -1
@@ -9,6 +9,7 @@ import type { UniformFields } from './scatterPass.ts';
9
9
  import { DEPTH_FORMAT } from './flatPass.ts';
10
10
  import type { PipelineCache } from './pipelineCache.ts';
11
11
  import { shaderModule } from './shaderModules.ts';
12
+ import { SCENE_ALPHA_COVERS } from '../../sceneCoverage.ts';
12
13
 
13
14
  /**
14
15
  * The wind-streak pass: a lattice of debris that follows the camera and wraps.
@@ -184,7 +185,7 @@ export function windStreakPipeline(
184
185
  dstFactor: 'one-minus-src-alpha',
185
186
  operation: 'add',
186
187
  },
187
- alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },
188
+ alpha: SCENE_ALPHA_COVERS,
188
189
  },
189
190
  },
190
191
  ],
@@ -2,6 +2,7 @@ import { compileProgram, uniformLocations } from './shader.ts';
2
2
  import { BOLT_FRAG, BOLT_VERT } from './shaders/bolt.ts';
3
3
  import { buildSegmentQuads, expandBoltSegments } from './segmentQuads.ts';
4
4
  import type { BoltSegments } from './boltPool.ts';
5
+ import { blendKeeping } from './sceneCoverage.ts';
5
6
 
6
7
  /**
7
8
  * One draw call for a pool of electrical arcs.
@@ -86,7 +87,7 @@ export class BoltBatch {
86
87
  drawTo(gl: WebGL2RenderingContext, segmentCount: number): void {
87
88
  if (segmentCount === 0) return;
88
89
  gl.enable(gl.BLEND);
89
- gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
90
+ blendKeeping(gl, gl.SRC_ALPHA, gl.ONE);
90
91
  gl.depthMask(false);
91
92
  gl.disable(gl.CULL_FACE);
92
93
 
@@ -7,6 +7,7 @@ import type { Atmosphere } from './atmosphere.ts';
7
7
  import { buildSheets } from './surfaceSheet.ts';
8
8
  import type { SheetSpan } from './surfaceSheet.ts';
9
9
  import { seaStateForWind } from './seaState.ts';
10
+ import { blendKeeping } from './sceneCoverage.ts';
10
11
 
11
12
  /**
12
13
  * A surface lit by nearby water: the floor of a pool, the bottom of a flooded
@@ -149,7 +150,7 @@ export class CausticsRenderer {
149
150
  bindAtmosphere(gl, u, atmosphere, camera.position[1] ?? 0, underwaterEnabled);
150
151
 
151
152
  gl.enable(gl.BLEND);
152
- gl.blendFunc(gl.ONE, gl.ONE);
153
+ blendKeeping(gl, gl.ONE, gl.ONE);
153
154
  /*
154
155
  * No depth write, but depth *testing* stays on: the sheet sits a couple of
155
156
  * centimetres under the surface it lights, so geometry in front of it — the
@@ -13,19 +13,30 @@
13
13
  */
14
14
  import type { SurfaceMaterial } from './surfaceTexture.ts';
15
15
 
16
- /** A cutout caster's texture, its cutoff and its UV scale. */
16
+ /** A cutout caster's texture, its cutoff and its UV scale and offset. */
17
17
  export interface CutoutCaster<Texture> {
18
18
  readonly albedo: Texture;
19
19
  readonly cutoff: number;
20
20
  readonly u: number;
21
21
  readonly v: number;
22
+ readonly uOffset: number;
23
+ readonly vOffset: number;
22
24
  }
23
25
 
24
- const answer: { albedo: unknown; cutoff: number; u: number; v: number } = {
26
+ const answer: {
27
+ albedo: unknown;
28
+ cutoff: number;
29
+ u: number;
30
+ v: number;
31
+ uOffset: number;
32
+ vOffset: number;
33
+ } = {
25
34
  albedo: null,
26
35
  cutoff: 0,
27
36
  u: 1,
28
37
  v: 1,
38
+ uOffset: 0,
39
+ vOffset: 0,
29
40
  };
30
41
 
31
42
  /** The cutout `material` casts, or null for an ordinary caster. */
@@ -40,5 +51,7 @@ export function cutoutOf<Texture>(
40
51
  answer.cutoff = cutoff;
41
52
  answer.u = material.uScale ?? 1;
42
53
  answer.v = material.vScale ?? 1;
54
+ answer.uOffset = material.uOffset ?? 0;
55
+ answer.vOffset = material.vOffset ?? 0;
43
56
  return answer as CutoutCaster<Texture>;
44
57
  }
@@ -7,6 +7,7 @@ import { DEPTH_01_TO_CLIP } from './lightVolumeDraw.ts';
7
7
  import { compileProgram, uniformLocations } from './shader.ts';
8
8
  import { DECAL_PROJECT_FRAG } from './shaders/decalProject.ts';
9
9
  import { FULLSCREEN_VERT } from './shaders/fullscreen.ts';
10
+ import { blendKeeping } from './sceneCoverage.ts';
10
11
 
11
12
  /**
12
13
  * Drawn decals on WebGL2: one scissored triangle per mark, multiplied into the finished scene.
@@ -66,7 +67,7 @@ export class DecalPass {
66
67
  gl.depthMask(false);
67
68
  gl.disable(gl.CULL_FACE);
68
69
  gl.enable(gl.BLEND);
69
- gl.blendFunc(gl.ZERO, gl.SRC_COLOR);
70
+ blendKeeping(gl, gl.ZERO, gl.SRC_COLOR);
70
71
  gl.enable(gl.SCISSOR_TEST);
71
72
 
72
73
  /* Unit 0, chosen rather than inherited: `bindTexture` binds to whichever unit is active, and
@@ -7,6 +7,7 @@ import { DEPTH_01_TO_CLIP } from './lightVolumeDraw.ts';
7
7
  import { compileProgram, uniformLocations } from './shader.ts';
8
8
  import { FULLSCREEN_VERT } from './shaders/fullscreen.ts';
9
9
  import { MEDIUM_FRAG, MEDIUM_UPSAMPLE_FRAG } from './shaders/globalMedium.ts';
10
+ import { blendCovering, blendTransmitting } from './sceneCoverage.ts';
10
11
 
11
12
  /** What the march needs about the light, which is the sun and the sky and nothing else. */
12
13
  export interface MediumLight {
@@ -270,7 +271,7 @@ export class GlobalMediumPass {
270
271
  gl.depthMask(false);
271
272
  gl.disable(gl.CULL_FACE);
272
273
  gl.enable(gl.BLEND);
273
- gl.blendFuncSeparate(gl.ONE, gl.SRC_ALPHA, gl.ZERO, gl.ONE);
274
+ blendTransmitting(gl, gl.ONE, gl.SRC_ALPHA);
274
275
 
275
276
  gl.useProgram(this.upsample);
276
277
  gl.bindVertexArray(this.vao);
@@ -293,7 +294,7 @@ export class GlobalMediumPass {
293
294
  gl.activeTexture(gl.TEXTURE0);
294
295
  gl.bindTexture(gl.TEXTURE_2D, null);
295
296
  /* Back to the blend every other pass in this renderer assumes it inherits. */
296
- gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
297
+ blendCovering(gl, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
297
298
  gl.disable(gl.BLEND);
298
299
  gl.depthMask(true);
299
300
  gl.enable(gl.DEPTH_TEST);
@@ -2,6 +2,7 @@ import { compileProgram, uniformLocations } from './shader.ts';
2
2
  import { LINE_FRAG, LINE_VERT } from './shaders/line.ts';
3
3
  import { buildSegmentQuads, expandLineSegments } from './segmentQuads.ts';
4
4
  import type { LineSegments } from './linePoints.ts';
5
+ import { blendCovering, blendKeeping } from './sceneCoverage.ts';
5
6
 
6
7
  /**
7
8
  * One draw call for a polyline with a real width — an audio waveform, a trail, a plotted
@@ -102,7 +103,8 @@ export class LineBatch {
102
103
  drawTo(gl: WebGL2RenderingContext, segmentCount: number, additive = false): void {
103
104
  if (segmentCount === 0) return;
104
105
  gl.enable(gl.BLEND);
105
- gl.blendFunc(gl.SRC_ALPHA, additive ? gl.ONE : gl.ONE_MINUS_SRC_ALPHA);
106
+ if (additive) blendKeeping(gl, gl.SRC_ALPHA, gl.ONE);
107
+ else blendCovering(gl, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
106
108
  gl.depthMask(false);
107
109
  // The quad billboards toward the view direction the same way a bolt's does — see
108
110
  // `line.ts`'s own `cross(dir, view)` — so its winding can flip with the camera exactly
@@ -1,6 +1,7 @@
1
1
  import { compileProgram, uniformLocations } from './shader.ts';
2
2
  import { FULLSCREEN_VERT } from './shaders/fullscreen.ts';
3
3
  import { OIT_RESOLVE_FRAG } from './shaders/oitResolve.ts';
4
+ import { blendTransmitting } from './sceneCoverage.ts';
4
5
 
5
6
  /**
6
7
  * Order-independent transparency on WebGL2: two targets, two passes over the same geometry, and a
@@ -179,7 +180,7 @@ export class OitPass {
179
180
  gl.depthMask(false);
180
181
  gl.disable(gl.CULL_FACE);
181
182
  gl.enable(gl.BLEND);
182
- gl.blendFunc(gl.ONE_MINUS_SRC_ALPHA, gl.SRC_ALPHA);
183
+ blendTransmitting(gl, gl.ONE_MINUS_SRC_ALPHA, gl.SRC_ALPHA);
183
184
 
184
185
  gl.useProgram(this.program);
185
186
  gl.activeTexture(gl.TEXTURE0);
@@ -2,6 +2,7 @@ import { compileProgram, uniformLocations } from './shader.ts';
2
2
  import { particleShaders, type ParticleMaterial } from './particleMaterial.ts';
3
3
  import { PARTICLE_BLADES, PARTICLE_INDICES, PARTICLE_VERTS } from './shaders/particle.ts';
4
4
  import type { ParticleInstances } from './particlePool.ts';
5
+ import { blendCovering, blendKeeping } from './sceneCoverage.ts';
5
6
 
6
7
  /**
7
8
  * One draw call for a live particle pool: one camera-facing quad per particle, or a
@@ -239,8 +240,8 @@ export class ParticleBatch {
239
240
  drawTo(gl: WebGL2RenderingContext, count: number): void {
240
241
  if (count === 0) return;
241
242
  gl.enable(gl.BLEND);
242
- if (this.blend === 'additive') gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
243
- else gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
243
+ if (this.blend === 'additive') blendKeeping(gl, gl.SRC_ALPHA, gl.ONE);
244
+ else blendCovering(gl, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
244
245
  gl.depthMask(false);
245
246
  gl.disable(gl.CULL_FACE);
246
247
 
@@ -21,7 +21,11 @@ import type { Vec3 } from '../math/color.ts';
21
21
  export interface ParticleInstances {
22
22
  /** World position, three floats each. */
23
23
  positions: Float32Array;
24
- /** Metres across, and radians of roll about the particle's own axis. */
24
+ /**
25
+ * Metres from the centre to an edge, a half-width: the quad spans twice this. Then radians of
26
+ * roll about the particle's own axis. This said metres across until 4.8.3, and a caller who took
27
+ * it at its word drew every particle twice as wide as meant.
28
+ */
25
29
  sizes: Float32Array;
26
30
  spins: Float32Array;
27
31
  /** Linear colour, three floats each. */
@@ -72,7 +76,7 @@ export interface ParticlePoolOptions {
72
76
  capacity: number;
73
77
  /** Seconds a particle lives. */
74
78
  lifeSec: number;
75
- /** Size at birth and at death, metres. */
79
+ /** Size at birth and at death: metres from the centre to an edge, so the quad is twice as wide. */
76
80
  sizeStart: number;
77
81
  sizeEnd: number;
78
82
  /** Colour at birth and at death. */
@@ -6,6 +6,7 @@ import { plumeShaders, type PlumeMaterial } from './plumeMaterial.ts';
6
6
  import { buildPlumeGeometry } from './plumeGeometry.ts';
7
7
  import type { Atmosphere } from './atmosphere.ts';
8
8
  import type { Vec3 } from '../math/color.ts';
9
+ import { blendCovering, blendKeeping } from './sceneCoverage.ts';
9
10
 
10
11
  /**
11
12
  * Batched camera-facing quads for volumetric effects — flames, smoke, steam,
@@ -202,8 +203,8 @@ export class PlumeRenderer {
202
203
  bindAtmosphere(gl, u, atmosphere, atmosphereCameraY, underwaterEnabled);
203
204
 
204
205
  gl.enable(gl.BLEND);
205
- if (this.blend === 'additive') gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
206
- else gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
206
+ if (this.blend === 'additive') blendKeeping(gl, gl.SRC_ALPHA, gl.ONE);
207
+ else blendCovering(gl, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
207
208
  gl.depthMask(false);
208
209
  gl.disable(gl.CULL_FACE);
209
210
 
@@ -20,8 +20,14 @@ import { PREFILTER_SAMPLE_COUNTS } from './prefilterEnvMap.ts';
20
20
  * `aces` adds filmic tone mapping before that, rolling highlights off instead of
21
21
  * clipping them flat. Together they are what three.js does by default, which is why a
22
22
  * world ported from it looks wrong until this exists.
23
+ *
24
+ * `shoulder` keeps sRGB's midtones exactly and eases only the highlights: past 0.8 the brightest
25
+ * channel rolls toward 1 and the other two are scaled with it, so an overbright red spark stays
26
+ * red where `srgb` clips each channel and turns its core pink and wide. It is the curve a ported
27
+ * game's own resolve applied — for a port that has to match one — and it has none of ACES's toe or
28
+ * desaturation. See `HIGHLIGHT_SHOULDER_GLSL` for the arithmetic.
23
29
  */
24
- export type OutputTransform = 'none' | 'srgb' | 'aces';
30
+ export type OutputTransform = 'none' | 'srgb' | 'aces' | 'shoulder';
25
31
 
26
32
  /**
27
33
  * The three settings whose accepted values are a closed set, written as one.
@@ -69,7 +75,8 @@ export interface RenderQuality {
69
75
  * chooses is a look rather than a standard — three.js uses 1/0.6 and says so. This
70
76
  * engine holds no opinion and takes the number from whoever is authoring the world, so
71
77
  * that matching another renderer, or simply preferring a different grade, is a setting
72
- * rather than a patch. Ignored when `outputTransform` is not `aces`.
78
+ * rather than a patch. Scales into `aces` and into `shoulder`, the two curves; ignored by
79
+ * `none` and `srgb`, which have none.
73
80
  */
74
81
  readonly outputExposure: number;
75
82
  /**
@@ -0,0 +1,78 @@
1
+ /**
2
+ * What a blended draw into the scene does to its alpha, which holds how much of each pixel is still
3
+ * the opaque surface — the share ambient occlusion is allowed to darken.
4
+ *
5
+ * **Occlusion is applied in the composite, from the depth the opaque world left**, after every
6
+ * translucent draw has landed, and a particle or a pane writes no depth: so a puff of smoke in front
7
+ * of a wall was darkened by the corner behind it. Reported from a game as walls and two figures
8
+ * standing behind a cloud showing through it as outlines, and nothing at all with occlusion off.
9
+ *
10
+ * So the scene's alpha is a running share. The frame clears it to 1 and an opaque draw writes 1,
11
+ * which is the whole of the surface; then each draw blended in front of it says which of three
12
+ * things it is, and the composite darkens `share` of the pixel and leaves the rest:
13
+ *
14
+ * - **It covers**: glass, smoke, water, a line, text in the world, a panel. The share falls by what
15
+ * the draw lets through, `share * (1 - a)`.
16
+ * - **It transmits**: the medium, the order-independent composite. Its alpha already *is* what gets
17
+ * through, `share * a`.
18
+ * - **It keeps**: light added to the surface or a layer of the surface itself — caustics, a light
19
+ * volume, a bolt, a wet film, a decal, a reflection. The share is unchanged.
20
+ *
21
+ * **What it gives up** is added light in front of an occluded corner: a glow or a spark adds to the
22
+ * pixel and keeps the share, so the composite darkens what it added along with the surface — which
23
+ * is how every blended draw behaved before this, and one multiply cannot tell the two apart. **What
24
+ * would make it wrong** is an opaque pass writing an alpha below 1: its surface would then take less
25
+ * occlusion than it should, which is the safe direction, and is the lit shader's own case at a
26
+ * cutout's edge or under a per-vertex alpha lane.
27
+ *
28
+ * **It survives the temporal passes.** A temporal resolve passes the frame's alpha through, since
29
+ * it is a fact about this frame and takes no history; a reconstruction reads it from the scene it
30
+ * rebuilt into the picture it shows, and the blended draws that land after it cover that picture.
31
+ *
32
+ * **One pipeline does not take part**: the GPU-driven pass blends its own surfaces into a target
33
+ * whose alpha is the mask its blit reads to tell a drawn pixel from an undrawn one, and that blit
34
+ * writes the share back to 1. Its panes still take the occlusion of what they cover. What would
35
+ * close it is a channel for that mask other than alpha.
36
+ *
37
+ * A contributed pass drawing something blended into the scene states the same thing for its own
38
+ * pipeline with `SCENE_ALPHA_COVERS`, `SCENE_ALPHA_TRANSMITS` or `SCENE_ALPHA_KEEPS`.
39
+ */
40
+
41
+ /** A blended draw that covers the surface by its alpha: `share * (1 - a)`. */
42
+ export const SCENE_ALPHA_COVERS: GPUBlendComponent = {
43
+ srcFactor: 'zero',
44
+ dstFactor: 'one-minus-src-alpha',
45
+ operation: 'add',
46
+ };
47
+
48
+ /** A draw whose alpha is what gets through it, a transmittance or a revealage: `share * a`. */
49
+ export const SCENE_ALPHA_TRANSMITS: GPUBlendComponent = {
50
+ srcFactor: 'zero',
51
+ dstFactor: 'src-alpha',
52
+ operation: 'add',
53
+ };
54
+
55
+ /** Light added to the surface, or a layer of it: the share unchanged. */
56
+ export const SCENE_ALPHA_KEEPS: GPUBlendComponent = {
57
+ srcFactor: 'zero',
58
+ dstFactor: 'one',
59
+ operation: 'add',
60
+ };
61
+
62
+ /**
63
+ * The same three on WebGL2, as the alpha half of `blendFuncSeparate` beside the colour half a
64
+ * caller already had. `src` and `dst` are the colour factors.
65
+ */
66
+ export function blendCovering(gl: WebGL2RenderingContext, src: number, dst: number): void {
67
+ gl.blendFuncSeparate(src, dst, gl.ZERO, gl.ONE_MINUS_SRC_ALPHA);
68
+ }
69
+
70
+ /** `SCENE_ALPHA_TRANSMITS` on WebGL2, beside the colour factors `src` and `dst`. */
71
+ export function blendTransmitting(gl: WebGL2RenderingContext, src: number, dst: number): void {
72
+ gl.blendFuncSeparate(src, dst, gl.ZERO, gl.SRC_ALPHA);
73
+ }
74
+
75
+ /** `SCENE_ALPHA_KEEPS` on WebGL2, beside the colour factors `src` and `dst`. */
76
+ export function blendKeeping(gl: WebGL2RenderingContext, src: number, dst: number): void {
77
+ gl.blendFuncSeparate(src, dst, gl.ZERO, gl.ONE);
78
+ }
@@ -7,6 +7,7 @@ import { compileProgram, uniformLocations } from './shader.ts';
7
7
  import { SDF_TEXT_FRAG, SDF_TEXT_VERT } from './shaders/sdfText.ts';
8
8
  import type { SurfaceTexture } from './surfaceTexture.ts';
9
9
  import { SDF_TEXT_TEXTURE_UNIT } from './lightBudget.ts';
10
+ import { blendCovering } from './sceneCoverage.ts';
10
11
 
11
12
  /**
12
13
  * Text from a signed distance field, on WebGL2.
@@ -144,7 +145,7 @@ export class SdfTextRenderer {
144
145
  */
145
146
  gl.depthMask(false);
146
147
  gl.enable(gl.BLEND);
147
- gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
148
+ blendCovering(gl, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
148
149
 
149
150
  this.atlas.bind(gl, SDF_TEXT_TEXTURE_UNIT);
150
151
 
@@ -60,12 +60,13 @@ ${CHANNEL_BEND}
60
60
 
61
61
  #if CUTOUT
62
62
  /*
63
- * **What a cutout caster adds, and where.** The UV at location 5, where every mesh carries it; two
63
+ * **What a cutout caster adds, and where.** The UV at location 5, where every mesh carries it; three
64
64
  * uniforms declared after every other, so no field of the plain variant moves and a binder written
65
65
  * against it stays right for this one; and two outputs after vLightPosition, which keeps location 0.
66
66
  */
67
67
  layout(location = 5) in vec3 aUv;
68
68
  uniform vec2 uUvScale;
69
+ uniform vec2 uUvOffset;
69
70
  uniform float uAlphaCutout;
70
71
  #endif
71
72
 
@@ -104,7 +105,7 @@ void main() {
104
105
  vLightPosition = uLightViewProj * vec4(bent, world.w);
105
106
  gl_Position = vLightPosition;
106
107
  #if CUTOUT
107
- vUv = vec3(aUv.xy * uUvScale, aUv.z);
108
+ vUv = vec3(aUv.xy * uUvScale + uUvOffset, aUv.z);
108
109
  vAlphaCutout = uAlphaCutout;
109
110
  #endif
110
111
  #if GLASS
@@ -62,6 +62,11 @@ uniform mat4 uLightViewProj;
62
62
  * when no texture is bound.
63
63
  */
64
64
  uniform vec2 uUvScale;
65
+ /**
66
+ * Where the texture starts, per axis, added after the scale: \`uv * uUvScale + uUvOffset\`. What
67
+ * picks a cell of a flipbook or an atlas through the material. See \`SurfaceMaterial.uOffset\`.
68
+ */
69
+ uniform vec2 uUvOffset;
65
70
 
66
71
  /*
67
72
  * **Placement and tint are declared last of the shared uniforms, and the position is the
@@ -244,7 +249,7 @@ void main() {
244
249
  vColor = aColor * tint;
245
250
  vEmissive = aEmissive;
246
251
  vSpecular = aSpecular;
247
- vUv = vec3(aUv.xy * uUvScale, aUv.z);
252
+ vUv = vec3(aUv.xy * uUvScale + uUvOffset, aUv.z);
248
253
  vEmissiveColor = aEmissiveColor;
249
254
  vRoughness = aRoughness;
250
255
  vGrain = aGrain;
@@ -7,11 +7,11 @@
7
7
 
8
8
  export const DEPTH_CUTOUT_FRAG_WGSL = "struct Uniforms {\n uPeelShadowLayer: i32,\n}\n\nvar<private> vUv_1: vec3<f32>;\n@group(0) @binding(34) \nvar uCutoutMap_t: texture_2d_array<f32>;\n@group(0) @binding(35) \nvar uCutoutMap_s: sampler;\n@group(0) @binding(1) \nvar<uniform> unnamed: Uniforms;\nvar<private> vLightPosition_1: vec4<f32>;\n@group(0) @binding(32) \nvar uPreviousShadowMap_t: texture_2d_array<f32>;\n@group(0) @binding(33) \nvar uPreviousShadowMap_s: sampler;\nvar<private> gl_FragCoord_1: vec4<f32>;\nvar<private> vAlphaCutout_1: f32;\n\nfn cutoutAlpha_u0028_f1_u003b_vf2_u003b(alpha: ptr<function, f32>, texels: ptr<function, vec2<f32>>) -> f32 {\n var dx: vec2<f32>;\n var dy: vec2<f32>;\n var level: f32;\n\n let _e23 = (*texels);\n let _e24 = dpdx(_e23);\n dx = _e24;\n let _e25 = (*texels);\n let _e26 = dpdy(_e25);\n dy = _e26;\n let _e27 = dx;\n let _e28 = dx;\n let _e30 = dy;\n let _e31 = dy;\n level = max(0f, (0.5f * log2(max(dot(_e27, _e28), dot(_e30, _e31)))));\n let _e37 = (*alpha);\n let _e38 = level;\n return (_e37 * (1f + (_e38 * 0.25f)));\n}\n\nfn main_1() {\n var at: vec3<f32>;\n var alpha_1: f32;\n var param: f32;\n var param_1: vec2<f32>;\n var p: vec3<f32>;\n var uv: vec2<f32>;\n var previousDepth: f32;\n\n let _e25 = vUv_1;\n let _e26 = _e25.xy;\n let _e28 = vUv_1[2u];\n at = vec3<f32>(_e26.x, _e26.y, floor((_e28 + 0.5f)));\n let _e34 = at;\n let _e40 = textureSample(uCutoutMap_t, uCutoutMap_s, vec2<f32>(_e34.x, _e34.y), i32(_e34.z));\n let _e41 = vUv_1;\n let _e43 = textureDimensions(uCutoutMap_t, 0i);\n param = _e40.w;\n param_1 = (_e41.xy * vec2<f32>(vec2<i32>(_e43).xy));\n let _e49 = cutoutAlpha_u0028_f1_u003b_vf2_u003b((&param), (&param_1));\n alpha_1 = _e49;\n let _e51 = unnamed.uPeelShadowLayer;\n if (_e51 != 0i) {\n let _e53 = vLightPosition_1;\n let _e56 = vLightPosition_1[3u];\n p = (_e53.xyz / vec3(_e56));\n let _e59 = p;\n uv = ((_e59.xy * 0.5f) + vec2(0.5f));\n let _e64 = uv;\n let _e67 = vec3<f32>(_e64.x, _e64.y, 0f);\n let _e73 = textureSampleLevel(uPreviousShadowMap_t, uPreviousShadowMap_s, vec2<f32>(_e67.x, _e67.y), i32(_e67.z), 0f);\n previousDepth = _e73.x;\n let _e76 = gl_FragCoord_1[2u];\n let _e77 = previousDepth;\n if (_e76 <= (_e77 + 0.00001f)) {\n discard;\n }\n }\n let _e80 = alpha_1;\n let _e81 = vAlphaCutout_1;\n if (_e80 < _e81) {\n discard;\n }\n return;\n}\n\n@fragment \nfn main(@location(1) vUv: vec3<f32>, @location(0) vLightPosition: vec4<f32>, @builtin(position) gl_FragCoord: vec4<f32>, @location(2) @interpolate(flat) vAlphaCutout: f32) {\n vUv_1 = vUv;\n vLightPosition_1 = vLightPosition;\n gl_FragCoord_1 = gl_FragCoord;\n vAlphaCutout_1 = vAlphaCutout;\n main_1();\n}\n";
9
9
 
10
- export const DEPTH_CUTOUT_VERT_WGSL = "struct Uniforms {\n uLightViewProj: mat4x4<f32>,\n uModel: mat4x4<f32>,\n uWindDirection: vec2<f32>,\n uWindSpeed: f32,\n uWindGust: f32,\n uWindTime: f32,\n uWindSpatialPhase: vec2<f32>,\n uUvScale: vec2<f32>,\n uAlphaCutout: f32,\n}\n\nstruct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct VertexOutput {\n @location(0) member: vec4<f32>,\n @builtin(position) gl_Position: vec4<f32>,\n @location(1) member_1: vec3<f32>,\n @location(2) @interpolate(flat) member_2: f32,\n}\n\n@group(0) @binding(0) \nvar<uniform> unnamed: Uniforms;\nvar<private> aPosition_1: vec3<f32>;\nvar<private> aChannel_1: vec4<f32>;\nvar<private> vLightPosition: vec4<f32>;\nvar<private> unnamed_1: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\nvar<private> vUv: vec3<f32>;\nvar<private> aUv_1: vec3<f32>;\nvar<private> vAlphaCutout: f32;\n\nfn channelBend_u0028_vf3_u003b_f1_u003b(worldPos: ptr<function, vec3<f32>>, sway: ptr<function, f32>) -> vec3<f32> {\n var phase: f32;\n var bend: f32;\n\n let _e27 = (*sway);\n if (_e27 <= 0f) {\n let _e29 = (*worldPos);\n return _e29;\n }\n let _e30 = (*worldPos);\n let _e33 = unnamed.uWindSpatialPhase;\n let _e36 = unnamed.uWindTime;\n phase = (dot(_e30.xz, _e33) + _e36);\n let _e39 = unnamed.uWindSpeed;\n let _e41 = unnamed.uWindGust;\n let _e43 = phase;\n let _e46 = (*sway);\n bend = (((_e39 + _e41) * sin(_e43)) * _e46);\n let _e49 = (*worldPos)[0u];\n let _e52 = unnamed.uWindDirection[0u];\n let _e53 = bend;\n let _e57 = (*worldPos)[1u];\n let _e59 = (*worldPos)[2u];\n let _e62 = unnamed.uWindDirection[1u];\n let _e63 = bend;\n return vec3<f32>((_e49 + (_e52 * _e53)), _e57, (_e59 + (_e62 * _e63)));\n}\n\nfn main_1() {\n var local: vec4<f32>;\n var model: mat4x4<f32>;\n var world: vec4<f32>;\n var bent: vec3<f32>;\n var param: vec3<f32>;\n var param_1: f32;\n\n let _e29 = aPosition_1;\n local = vec4<f32>(_e29.x, _e29.y, _e29.z, 1f);\n let _e35 = unnamed.uModel;\n model = _e35;\n let _e36 = model;\n let _e37 = local;\n world = (_e36 * _e37);\n let _e39 = world;\n param = _e39.xyz;\n let _e42 = aChannel_1[0u];\n param_1 = _e42;\n let _e43 = channelBend_u0028_vf3_u003b_f1_u003b((&param), (&param_1));\n bent = _e43;\n let _e45 = unnamed.uLightViewProj;\n let _e46 = bent;\n let _e48 = world[3u];\n vLightPosition = (_e45 * vec4<f32>(_e46.x, _e46.y, _e46.z, _e48));\n let _e54 = vLightPosition;\n unnamed_1.gl_Position = _e54;\n let _e56 = aUv_1;\n let _e59 = unnamed.uUvScale;\n let _e60 = (_e56.xy * _e59);\n let _e62 = aUv_1[2u];\n vUv = vec3<f32>(_e60.x, _e60.y, _e62);\n let _e67 = unnamed.uAlphaCutout;\n vAlphaCutout = _e67;\n return;\n}\n\n@vertex \nfn main(@location(0) aPosition: vec3<f32>, @location(13) aChannel: vec4<f32>, @location(5) aUv: vec3<f32>) -> VertexOutput {\n aPosition_1 = aPosition;\n aChannel_1 = aChannel;\n aUv_1 = aUv;\n main_1();\n let _e12 = unnamed_1.gl_Position.y;\n unnamed_1.gl_Position.y = -(_e12);\n let _e14 = vLightPosition;\n let _e15 = unnamed_1.gl_Position;\n let _e16 = vUv;\n let _e17 = vAlphaCutout;\n return VertexOutput(_e14, _e15, _e16, _e17);\n}\n";
10
+ export const DEPTH_CUTOUT_VERT_WGSL = "struct Uniforms {\n uLightViewProj: mat4x4<f32>,\n uModel: mat4x4<f32>,\n uWindDirection: vec2<f32>,\n uWindSpeed: f32,\n uWindGust: f32,\n uWindTime: f32,\n uWindSpatialPhase: vec2<f32>,\n uUvScale: vec2<f32>,\n uUvOffset: vec2<f32>,\n uAlphaCutout: f32,\n}\n\nstruct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct VertexOutput {\n @location(0) member: vec4<f32>,\n @builtin(position) gl_Position: vec4<f32>,\n @location(1) member_1: vec3<f32>,\n @location(2) @interpolate(flat) member_2: f32,\n}\n\n@group(0) @binding(0) \nvar<uniform> unnamed: Uniforms;\nvar<private> aPosition_1: vec3<f32>;\nvar<private> aChannel_1: vec4<f32>;\nvar<private> vLightPosition: vec4<f32>;\nvar<private> unnamed_1: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\nvar<private> vUv: vec3<f32>;\nvar<private> aUv_1: vec3<f32>;\nvar<private> vAlphaCutout: f32;\n\nfn channelBend_u0028_vf3_u003b_f1_u003b(worldPos: ptr<function, vec3<f32>>, sway: ptr<function, f32>) -> vec3<f32> {\n var phase: f32;\n var bend: f32;\n\n let _e28 = (*sway);\n if (_e28 <= 0f) {\n let _e30 = (*worldPos);\n return _e30;\n }\n let _e31 = (*worldPos);\n let _e34 = unnamed.uWindSpatialPhase;\n let _e37 = unnamed.uWindTime;\n phase = (dot(_e31.xz, _e34) + _e37);\n let _e40 = unnamed.uWindSpeed;\n let _e42 = unnamed.uWindGust;\n let _e44 = phase;\n let _e47 = (*sway);\n bend = (((_e40 + _e42) * sin(_e44)) * _e47);\n let _e50 = (*worldPos)[0u];\n let _e53 = unnamed.uWindDirection[0u];\n let _e54 = bend;\n let _e58 = (*worldPos)[1u];\n let _e60 = (*worldPos)[2u];\n let _e63 = unnamed.uWindDirection[1u];\n let _e64 = bend;\n return vec3<f32>((_e50 + (_e53 * _e54)), _e58, (_e60 + (_e63 * _e64)));\n}\n\nfn main_1() {\n var local: vec4<f32>;\n var model: mat4x4<f32>;\n var world: vec4<f32>;\n var bent: vec3<f32>;\n var param: vec3<f32>;\n var param_1: f32;\n\n let _e30 = aPosition_1;\n local = vec4<f32>(_e30.x, _e30.y, _e30.z, 1f);\n let _e36 = unnamed.uModel;\n model = _e36;\n let _e37 = model;\n let _e38 = local;\n world = (_e37 * _e38);\n let _e40 = world;\n param = _e40.xyz;\n let _e43 = aChannel_1[0u];\n param_1 = _e43;\n let _e44 = channelBend_u0028_vf3_u003b_f1_u003b((&param), (&param_1));\n bent = _e44;\n let _e46 = unnamed.uLightViewProj;\n let _e47 = bent;\n let _e49 = world[3u];\n vLightPosition = (_e46 * vec4<f32>(_e47.x, _e47.y, _e47.z, _e49));\n let _e55 = vLightPosition;\n unnamed_1.gl_Position = _e55;\n let _e57 = aUv_1;\n let _e60 = unnamed.uUvScale;\n let _e63 = unnamed.uUvOffset;\n let _e64 = ((_e57.xy * _e60) + _e63);\n let _e66 = aUv_1[2u];\n vUv = vec3<f32>(_e64.x, _e64.y, _e66);\n let _e71 = unnamed.uAlphaCutout;\n vAlphaCutout = _e71;\n return;\n}\n\n@vertex \nfn main(@location(0) aPosition: vec3<f32>, @location(13) aChannel: vec4<f32>, @location(5) aUv: vec3<f32>) -> VertexOutput {\n aPosition_1 = aPosition;\n aChannel_1 = aChannel;\n aUv_1 = aUv;\n main_1();\n let _e12 = unnamed_1.gl_Position.y;\n unnamed_1.gl_Position.y = -(_e12);\n let _e14 = vLightPosition;\n let _e15 = unnamed_1.gl_Position;\n let _e16 = vUv;\n let _e17 = vAlphaCutout;\n return VertexOutput(_e14, _e15, _e16, _e17);\n}\n";
11
11
 
12
12
  export const DEPTH_FRAG_WGSL = "struct Uniforms {\n uPeelShadowLayer: i32,\n}\n\n@group(0) @binding(1) \nvar<uniform> unnamed: Uniforms;\nvar<private> vLightPosition_1: vec4<f32>;\n@group(0) @binding(32) \nvar uPreviousShadowMap_t: texture_2d_array<f32>;\n@group(0) @binding(33) \nvar uPreviousShadowMap_s: sampler;\nvar<private> gl_FragCoord_1: vec4<f32>;\n\nfn main_1() {\n var p: vec3<f32>;\n var uv: vec2<f32>;\n var previousDepth: f32;\n\n let _e16 = unnamed.uPeelShadowLayer;\n if (_e16 != 0i) {\n let _e18 = vLightPosition_1;\n let _e21 = vLightPosition_1[3u];\n p = (_e18.xyz / vec3(_e21));\n let _e24 = p;\n uv = ((_e24.xy * 0.5f) + vec2(0.5f));\n let _e29 = uv;\n let _e32 = vec3<f32>(_e29.x, _e29.y, 0f);\n let _e38 = textureSample(uPreviousShadowMap_t, uPreviousShadowMap_s, vec2<f32>(_e32.x, _e32.y), i32(_e32.z));\n previousDepth = _e38.x;\n let _e41 = gl_FragCoord_1[2u];\n let _e42 = previousDepth;\n if (_e41 <= (_e42 + 0.00001f)) {\n discard;\n }\n }\n return;\n}\n\n@fragment \nfn main(@location(0) vLightPosition: vec4<f32>, @builtin(position) gl_FragCoord: vec4<f32>) {\n vLightPosition_1 = vLightPosition;\n gl_FragCoord_1 = gl_FragCoord;\n main_1();\n}\n";
13
13
 
14
- export const DEPTH_INSTANCED_CUTOUT_VERT_WGSL = "struct Uniforms {\n uLightViewProj: mat4x4<f32>,\n uUvScale: vec2<f32>,\n uAlphaCutout: f32,\n}\n\nstruct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct VertexOutput {\n @location(0) member: vec4<f32>,\n @builtin(position) gl_Position: vec4<f32>,\n @location(1) member_1: vec3<f32>,\n @location(2) @interpolate(flat) member_2: f32,\n}\n\nvar<private> aPosition_1: vec3<f32>;\nvar<private> aInstanceModel0_1: vec4<f32>;\nvar<private> aInstanceModel1_1: vec4<f32>;\nvar<private> aInstanceModel2_1: vec4<f32>;\nvar<private> aInstanceModel3_1: vec4<f32>;\nvar<private> vLightPosition: vec4<f32>;\n@group(0) @binding(0) \nvar<uniform> unnamed: Uniforms;\nvar<private> unnamed_1: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\nvar<private> vUv: vec3<f32>;\nvar<private> aUv_1: vec3<f32>;\nvar<private> vAlphaCutout: f32;\n\nfn main_1() {\n var local: vec4<f32>;\n var model: mat4x4<f32>;\n var world: vec4<f32>;\n var bent: vec3<f32>;\n\n let _e22 = aPosition_1;\n local = vec4<f32>(_e22.x, _e22.y, _e22.z, 1f);\n let _e27 = aInstanceModel0_1;\n let _e28 = aInstanceModel1_1;\n let _e29 = aInstanceModel2_1;\n let _e30 = aInstanceModel3_1;\n model = mat4x4<f32>(vec4<f32>(_e27.x, _e27.y, _e27.z, _e27.w), vec4<f32>(_e28.x, _e28.y, _e28.z, _e28.w), vec4<f32>(_e29.x, _e29.y, _e29.z, _e29.w), vec4<f32>(_e30.x, _e30.y, _e30.z, _e30.w));\n let _e52 = model;\n let _e53 = local;\n world = (_e52 * _e53);\n let _e55 = world;\n bent = _e55.xyz;\n let _e58 = unnamed.uLightViewProj;\n let _e59 = bent;\n let _e61 = world[3u];\n vLightPosition = (_e58 * vec4<f32>(_e59.x, _e59.y, _e59.z, _e61));\n let _e67 = vLightPosition;\n unnamed_1.gl_Position = _e67;\n let _e69 = aUv_1;\n let _e72 = unnamed.uUvScale;\n let _e73 = (_e69.xy * _e72);\n let _e75 = aUv_1[2u];\n vUv = vec3<f32>(_e73.x, _e73.y, _e75);\n let _e80 = unnamed.uAlphaCutout;\n vAlphaCutout = _e80;\n return;\n}\n\n@vertex \nfn main(@location(0) aPosition: vec3<f32>, @location(11) aInstanceModel0_: vec4<f32>, @location(12) aInstanceModel1_: vec4<f32>, @location(13) aInstanceModel2_: vec4<f32>, @location(14) aInstanceModel3_: vec4<f32>, @location(5) aUv: vec3<f32>) -> VertexOutput {\n aPosition_1 = aPosition;\n aInstanceModel0_1 = aInstanceModel0_;\n aInstanceModel1_1 = aInstanceModel1_;\n aInstanceModel2_1 = aInstanceModel2_;\n aInstanceModel3_1 = aInstanceModel3_;\n aUv_1 = aUv;\n main_1();\n let _e18 = unnamed_1.gl_Position.y;\n unnamed_1.gl_Position.y = -(_e18);\n let _e20 = vLightPosition;\n let _e21 = unnamed_1.gl_Position;\n let _e22 = vUv;\n let _e23 = vAlphaCutout;\n return VertexOutput(_e20, _e21, _e22, _e23);\n}\n";
14
+ export const DEPTH_INSTANCED_CUTOUT_VERT_WGSL = "struct Uniforms {\n uLightViewProj: mat4x4<f32>,\n uUvScale: vec2<f32>,\n uUvOffset: vec2<f32>,\n uAlphaCutout: f32,\n}\n\nstruct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct VertexOutput {\n @location(0) member: vec4<f32>,\n @builtin(position) gl_Position: vec4<f32>,\n @location(1) member_1: vec3<f32>,\n @location(2) @interpolate(flat) member_2: f32,\n}\n\nvar<private> aPosition_1: vec3<f32>;\nvar<private> aInstanceModel0_1: vec4<f32>;\nvar<private> aInstanceModel1_1: vec4<f32>;\nvar<private> aInstanceModel2_1: vec4<f32>;\nvar<private> aInstanceModel3_1: vec4<f32>;\nvar<private> vLightPosition: vec4<f32>;\n@group(0) @binding(0) \nvar<uniform> unnamed: Uniforms;\nvar<private> unnamed_1: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\nvar<private> vUv: vec3<f32>;\nvar<private> aUv_1: vec3<f32>;\nvar<private> vAlphaCutout: f32;\n\nfn main_1() {\n var local: vec4<f32>;\n var model: mat4x4<f32>;\n var world: vec4<f32>;\n var bent: vec3<f32>;\n\n let _e23 = aPosition_1;\n local = vec4<f32>(_e23.x, _e23.y, _e23.z, 1f);\n let _e28 = aInstanceModel0_1;\n let _e29 = aInstanceModel1_1;\n let _e30 = aInstanceModel2_1;\n let _e31 = aInstanceModel3_1;\n model = mat4x4<f32>(vec4<f32>(_e28.x, _e28.y, _e28.z, _e28.w), vec4<f32>(_e29.x, _e29.y, _e29.z, _e29.w), vec4<f32>(_e30.x, _e30.y, _e30.z, _e30.w), vec4<f32>(_e31.x, _e31.y, _e31.z, _e31.w));\n let _e53 = model;\n let _e54 = local;\n world = (_e53 * _e54);\n let _e56 = world;\n bent = _e56.xyz;\n let _e59 = unnamed.uLightViewProj;\n let _e60 = bent;\n let _e62 = world[3u];\n vLightPosition = (_e59 * vec4<f32>(_e60.x, _e60.y, _e60.z, _e62));\n let _e68 = vLightPosition;\n unnamed_1.gl_Position = _e68;\n let _e70 = aUv_1;\n let _e73 = unnamed.uUvScale;\n let _e76 = unnamed.uUvOffset;\n let _e77 = ((_e70.xy * _e73) + _e76);\n let _e79 = aUv_1[2u];\n vUv = vec3<f32>(_e77.x, _e77.y, _e79);\n let _e84 = unnamed.uAlphaCutout;\n vAlphaCutout = _e84;\n return;\n}\n\n@vertex \nfn main(@location(0) aPosition: vec3<f32>, @location(11) aInstanceModel0_: vec4<f32>, @location(12) aInstanceModel1_: vec4<f32>, @location(13) aInstanceModel2_: vec4<f32>, @location(14) aInstanceModel3_: vec4<f32>, @location(5) aUv: vec3<f32>) -> VertexOutput {\n aPosition_1 = aPosition;\n aInstanceModel0_1 = aInstanceModel0_;\n aInstanceModel1_1 = aInstanceModel1_;\n aInstanceModel2_1 = aInstanceModel2_;\n aInstanceModel3_1 = aInstanceModel3_;\n aUv_1 = aUv;\n main_1();\n let _e18 = unnamed_1.gl_Position.y;\n unnamed_1.gl_Position.y = -(_e18);\n let _e20 = vLightPosition;\n let _e21 = unnamed_1.gl_Position;\n let _e22 = vUv;\n let _e23 = vAlphaCutout;\n return VertexOutput(_e20, _e21, _e22, _e23);\n}\n";
15
15
 
16
16
  export const DEPTH_INSTANCED_VERT_WGSL = "struct Uniforms {\n uLightViewProj: mat4x4<f32>,\n}\n\nstruct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct VertexOutput {\n @location(0) member: vec4<f32>,\n @builtin(position) gl_Position: vec4<f32>,\n}\n\nvar<private> aPosition_1: vec3<f32>;\nvar<private> aInstanceModel0_1: vec4<f32>;\nvar<private> aInstanceModel1_1: vec4<f32>;\nvar<private> aInstanceModel2_1: vec4<f32>;\nvar<private> aInstanceModel3_1: vec4<f32>;\nvar<private> vLightPosition: vec4<f32>;\n@group(0) @binding(0) \nvar<uniform> unnamed: Uniforms;\nvar<private> unnamed_1: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\n\nfn main_1() {\n var local: vec4<f32>;\n var model: mat4x4<f32>;\n var world: vec4<f32>;\n var bent: vec3<f32>;\n\n let _e16 = aPosition_1;\n local = vec4<f32>(_e16.x, _e16.y, _e16.z, 1f);\n let _e21 = aInstanceModel0_1;\n let _e22 = aInstanceModel1_1;\n let _e23 = aInstanceModel2_1;\n let _e24 = aInstanceModel3_1;\n model = mat4x4<f32>(vec4<f32>(_e21.x, _e21.y, _e21.z, _e21.w), vec4<f32>(_e22.x, _e22.y, _e22.z, _e22.w), vec4<f32>(_e23.x, _e23.y, _e23.z, _e23.w), vec4<f32>(_e24.x, _e24.y, _e24.z, _e24.w));\n let _e46 = model;\n let _e47 = local;\n world = (_e46 * _e47);\n let _e49 = world;\n bent = _e49.xyz;\n let _e52 = unnamed.uLightViewProj;\n let _e53 = bent;\n let _e55 = world[3u];\n vLightPosition = (_e52 * vec4<f32>(_e53.x, _e53.y, _e53.z, _e55));\n let _e61 = vLightPosition;\n unnamed_1.gl_Position = _e61;\n return;\n}\n\n@vertex \nfn main(@location(0) aPosition: vec3<f32>, @location(11) aInstanceModel0_: vec4<f32>, @location(12) aInstanceModel1_: vec4<f32>, @location(13) aInstanceModel2_: vec4<f32>, @location(14) aInstanceModel3_: vec4<f32>) -> VertexOutput {\n aPosition_1 = aPosition;\n aInstanceModel0_1 = aInstanceModel0_;\n aInstanceModel1_1 = aInstanceModel1_;\n aInstanceModel2_1 = aInstanceModel2_;\n aInstanceModel3_1 = aInstanceModel3_;\n main_1();\n let _e14 = unnamed_1.gl_Position.y;\n unnamed_1.gl_Position.y = -(_e14);\n let _e16 = vLightPosition;\n let _e17 = unnamed_1.gl_Position;\n return VertexOutput(_e16, _e17);\n}\n";
17
17
 
@@ -21,11 +21,11 @@ export const DEPTH_VERT_WGSL = "struct Uniforms {\n uLightViewProj: mat4x4<f3
21
21
 
22
22
  export const GLASS_TINT_CUTOUT_FRAG_WGSL = "struct Uniforms {\n uGlassPane: vec4<f32>,\n uGlassLight: vec4<f32>,\n}\n\nvar<private> vUv_1: vec3<f32>;\n@group(0) @binding(32) \nvar uCutoutMap_t: texture_2d_array<f32>;\n@group(0) @binding(33) \nvar uCutoutMap_s: sampler;\nvar<private> vGlassWorld_1: vec3<f32>;\n@group(0) @binding(1) \nvar<uniform> unnamed: Uniforms;\nvar<private> outTint: vec4<f32>;\nvar<private> vAlphaCutout_1: f32;\nvar<private> vLightPosition_1: vec4<f32>;\n\nfn cutoutAlpha_u0028_f1_u003b_vf2_u003b(alpha: ptr<function, f32>, texels: ptr<function, vec2<f32>>) -> f32 {\n var dx: vec2<f32>;\n var dy: vec2<f32>;\n var level: f32;\n\n let _e24 = (*texels);\n let _e25 = dpdx(_e24);\n dx = _e25;\n let _e26 = (*texels);\n let _e27 = dpdy(_e26);\n dy = _e27;\n let _e28 = dx;\n let _e29 = dx;\n let _e31 = dy;\n let _e32 = dy;\n level = max(0f, (0.5f * log2(max(dot(_e28, _e29), dot(_e31, _e32)))));\n let _e38 = (*alpha);\n let _e39 = level;\n return (_e38 * (1f + (_e39 * 0.25f)));\n}\n\nfn main_1() {\n var at: vec3<f32>;\n var alpha_1: f32;\n var param: f32;\n var param_1: vec2<f32>;\n var n: vec3<f32>;\n var toLight: vec3<f32>;\n var local: vec3<f32>;\n var cosLight: f32;\n var reflected: f32;\n\n let _e28 = vUv_1;\n let _e29 = _e28.xy;\n let _e31 = vUv_1[2u];\n at = vec3<f32>(_e29.x, _e29.y, floor((_e31 + 0.5f)));\n let _e37 = at;\n let _e43 = textureSample(uCutoutMap_t, uCutoutMap_s, vec2<f32>(_e37.x, _e37.y), i32(_e37.z));\n let _e44 = vUv_1;\n let _e46 = textureDimensions(uCutoutMap_t, 0i);\n param = _e43.w;\n param_1 = (_e44.xy * vec2<f32>(vec2<i32>(_e46).xy));\n let _e52 = cutoutAlpha_u0028_f1_u003b_vf2_u003b((&param), (&param_1));\n alpha_1 = _e52;\n let _e53 = vGlassWorld_1;\n let _e54 = dpdx(_e53);\n let _e55 = vGlassWorld_1;\n let _e56 = dpdy(_e55);\n n = normalize(cross(_e54, _e56));\n let _e61 = unnamed.uGlassLight[3u];\n if (_e61 > 0.5f) {\n let _e64 = unnamed.uGlassLight;\n let _e66 = vGlassWorld_1;\n local = normalize((_e64.xyz - _e66));\n } else {\n let _e70 = unnamed.uGlassLight;\n local = _e70.xyz;\n }\n let _e72 = local;\n toLight = _e72;\n let _e73 = n;\n let _e74 = toLight;\n cosLight = abs(dot(_e73, _e74));\n let _e77 = cosLight;\n reflected = (0.04f + (0.96f * pow((1f - _e77), 5f)));\n let _e83 = unnamed.uGlassPane;\n let _e85 = reflected;\n let _e87 = (_e83.xyz * (1f - _e85));\n let _e90 = unnamed.uGlassPane[3u];\n outTint = vec4<f32>(_e87.x, _e87.y, _e87.z, _e90);\n let _e95 = alpha_1;\n let _e96 = vAlphaCutout_1;\n if (_e95 < _e96) {\n discard;\n }\n return;\n}\n\n@fragment \nfn main(@location(1) vUv: vec3<f32>, @location(3) vGlassWorld: vec3<f32>, @location(2) @interpolate(flat) vAlphaCutout: f32, @location(0) vLightPosition: vec4<f32>) -> @location(0) vec4<f32> {\n vUv_1 = vUv;\n vGlassWorld_1 = vGlassWorld;\n vAlphaCutout_1 = vAlphaCutout;\n vLightPosition_1 = vLightPosition;\n main_1();\n let _e9 = outTint;\n return _e9;\n}\n";
23
23
 
24
- export const GLASS_TINT_CUTOUT_VERT_WGSL = "struct Uniforms {\n uLightViewProj: mat4x4<f32>,\n uModel: mat4x4<f32>,\n uWindDirection: vec2<f32>,\n uWindSpeed: f32,\n uWindGust: f32,\n uWindTime: f32,\n uWindSpatialPhase: vec2<f32>,\n uUvScale: vec2<f32>,\n uAlphaCutout: f32,\n}\n\nstruct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct VertexOutput {\n @location(0) member: vec4<f32>,\n @builtin(position) gl_Position: vec4<f32>,\n @location(1) member_1: vec3<f32>,\n @location(2) @interpolate(flat) member_2: f32,\n @location(3) member_3: vec3<f32>,\n}\n\n@group(0) @binding(0) \nvar<uniform> unnamed: Uniforms;\nvar<private> aPosition_1: vec3<f32>;\nvar<private> aChannel_1: vec4<f32>;\nvar<private> vLightPosition: vec4<f32>;\nvar<private> unnamed_1: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\nvar<private> vUv: vec3<f32>;\nvar<private> aUv_1: vec3<f32>;\nvar<private> vAlphaCutout: f32;\nvar<private> vGlassWorld: vec3<f32>;\n\nfn channelBend_u0028_vf3_u003b_f1_u003b(worldPos: ptr<function, vec3<f32>>, sway: ptr<function, f32>) -> vec3<f32> {\n var phase: f32;\n var bend: f32;\n\n let _e28 = (*sway);\n if (_e28 <= 0f) {\n let _e30 = (*worldPos);\n return _e30;\n }\n let _e31 = (*worldPos);\n let _e34 = unnamed.uWindSpatialPhase;\n let _e37 = unnamed.uWindTime;\n phase = (dot(_e31.xz, _e34) + _e37);\n let _e40 = unnamed.uWindSpeed;\n let _e42 = unnamed.uWindGust;\n let _e44 = phase;\n let _e47 = (*sway);\n bend = (((_e40 + _e42) * sin(_e44)) * _e47);\n let _e50 = (*worldPos)[0u];\n let _e53 = unnamed.uWindDirection[0u];\n let _e54 = bend;\n let _e58 = (*worldPos)[1u];\n let _e60 = (*worldPos)[2u];\n let _e63 = unnamed.uWindDirection[1u];\n let _e64 = bend;\n return vec3<f32>((_e50 + (_e53 * _e54)), _e58, (_e60 + (_e63 * _e64)));\n}\n\nfn main_1() {\n var local: vec4<f32>;\n var model: mat4x4<f32>;\n var world: vec4<f32>;\n var bent: vec3<f32>;\n var param: vec3<f32>;\n var param_1: f32;\n\n let _e30 = aPosition_1;\n local = vec4<f32>(_e30.x, _e30.y, _e30.z, 1f);\n let _e36 = unnamed.uModel;\n model = _e36;\n let _e37 = model;\n let _e38 = local;\n world = (_e37 * _e38);\n let _e40 = world;\n param = _e40.xyz;\n let _e43 = aChannel_1[0u];\n param_1 = _e43;\n let _e44 = channelBend_u0028_vf3_u003b_f1_u003b((&param), (&param_1));\n bent = _e44;\n let _e46 = unnamed.uLightViewProj;\n let _e47 = bent;\n let _e49 = world[3u];\n vLightPosition = (_e46 * vec4<f32>(_e47.x, _e47.y, _e47.z, _e49));\n let _e55 = vLightPosition;\n unnamed_1.gl_Position = _e55;\n let _e57 = aUv_1;\n let _e60 = unnamed.uUvScale;\n let _e61 = (_e57.xy * _e60);\n let _e63 = aUv_1[2u];\n vUv = vec3<f32>(_e61.x, _e61.y, _e63);\n let _e68 = unnamed.uAlphaCutout;\n vAlphaCutout = _e68;\n let _e69 = bent;\n vGlassWorld = _e69;\n return;\n}\n\n@vertex \nfn main(@location(0) aPosition: vec3<f32>, @location(13) aChannel: vec4<f32>, @location(5) aUv: vec3<f32>) -> VertexOutput {\n aPosition_1 = aPosition;\n aChannel_1 = aChannel;\n aUv_1 = aUv;\n main_1();\n let _e13 = unnamed_1.gl_Position.y;\n unnamed_1.gl_Position.y = -(_e13);\n let _e15 = vLightPosition;\n let _e16 = unnamed_1.gl_Position;\n let _e17 = vUv;\n let _e18 = vAlphaCutout;\n let _e19 = vGlassWorld;\n return VertexOutput(_e15, _e16, _e17, _e18, _e19);\n}\n";
24
+ export const GLASS_TINT_CUTOUT_VERT_WGSL = "struct Uniforms {\n uLightViewProj: mat4x4<f32>,\n uModel: mat4x4<f32>,\n uWindDirection: vec2<f32>,\n uWindSpeed: f32,\n uWindGust: f32,\n uWindTime: f32,\n uWindSpatialPhase: vec2<f32>,\n uUvScale: vec2<f32>,\n uUvOffset: vec2<f32>,\n uAlphaCutout: f32,\n}\n\nstruct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct VertexOutput {\n @location(0) member: vec4<f32>,\n @builtin(position) gl_Position: vec4<f32>,\n @location(1) member_1: vec3<f32>,\n @location(2) @interpolate(flat) member_2: f32,\n @location(3) member_3: vec3<f32>,\n}\n\n@group(0) @binding(0) \nvar<uniform> unnamed: Uniforms;\nvar<private> aPosition_1: vec3<f32>;\nvar<private> aChannel_1: vec4<f32>;\nvar<private> vLightPosition: vec4<f32>;\nvar<private> unnamed_1: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\nvar<private> vUv: vec3<f32>;\nvar<private> aUv_1: vec3<f32>;\nvar<private> vAlphaCutout: f32;\nvar<private> vGlassWorld: vec3<f32>;\n\nfn channelBend_u0028_vf3_u003b_f1_u003b(worldPos: ptr<function, vec3<f32>>, sway: ptr<function, f32>) -> vec3<f32> {\n var phase: f32;\n var bend: f32;\n\n let _e29 = (*sway);\n if (_e29 <= 0f) {\n let _e31 = (*worldPos);\n return _e31;\n }\n let _e32 = (*worldPos);\n let _e35 = unnamed.uWindSpatialPhase;\n let _e38 = unnamed.uWindTime;\n phase = (dot(_e32.xz, _e35) + _e38);\n let _e41 = unnamed.uWindSpeed;\n let _e43 = unnamed.uWindGust;\n let _e45 = phase;\n let _e48 = (*sway);\n bend = (((_e41 + _e43) * sin(_e45)) * _e48);\n let _e51 = (*worldPos)[0u];\n let _e54 = unnamed.uWindDirection[0u];\n let _e55 = bend;\n let _e59 = (*worldPos)[1u];\n let _e61 = (*worldPos)[2u];\n let _e64 = unnamed.uWindDirection[1u];\n let _e65 = bend;\n return vec3<f32>((_e51 + (_e54 * _e55)), _e59, (_e61 + (_e64 * _e65)));\n}\n\nfn main_1() {\n var local: vec4<f32>;\n var model: mat4x4<f32>;\n var world: vec4<f32>;\n var bent: vec3<f32>;\n var param: vec3<f32>;\n var param_1: f32;\n\n let _e31 = aPosition_1;\n local = vec4<f32>(_e31.x, _e31.y, _e31.z, 1f);\n let _e37 = unnamed.uModel;\n model = _e37;\n let _e38 = model;\n let _e39 = local;\n world = (_e38 * _e39);\n let _e41 = world;\n param = _e41.xyz;\n let _e44 = aChannel_1[0u];\n param_1 = _e44;\n let _e45 = channelBend_u0028_vf3_u003b_f1_u003b((&param), (&param_1));\n bent = _e45;\n let _e47 = unnamed.uLightViewProj;\n let _e48 = bent;\n let _e50 = world[3u];\n vLightPosition = (_e47 * vec4<f32>(_e48.x, _e48.y, _e48.z, _e50));\n let _e56 = vLightPosition;\n unnamed_1.gl_Position = _e56;\n let _e58 = aUv_1;\n let _e61 = unnamed.uUvScale;\n let _e64 = unnamed.uUvOffset;\n let _e65 = ((_e58.xy * _e61) + _e64);\n let _e67 = aUv_1[2u];\n vUv = vec3<f32>(_e65.x, _e65.y, _e67);\n let _e72 = unnamed.uAlphaCutout;\n vAlphaCutout = _e72;\n let _e73 = bent;\n vGlassWorld = _e73;\n return;\n}\n\n@vertex \nfn main(@location(0) aPosition: vec3<f32>, @location(13) aChannel: vec4<f32>, @location(5) aUv: vec3<f32>) -> VertexOutput {\n aPosition_1 = aPosition;\n aChannel_1 = aChannel;\n aUv_1 = aUv;\n main_1();\n let _e13 = unnamed_1.gl_Position.y;\n unnamed_1.gl_Position.y = -(_e13);\n let _e15 = vLightPosition;\n let _e16 = unnamed_1.gl_Position;\n let _e17 = vUv;\n let _e18 = vAlphaCutout;\n let _e19 = vGlassWorld;\n return VertexOutput(_e15, _e16, _e17, _e18, _e19);\n}\n";
25
25
 
26
26
  export const GLASS_TINT_FRAG_WGSL = "struct Uniforms {\n uGlassPane: vec4<f32>,\n uGlassLight: vec4<f32>,\n}\n\nvar<private> vGlassWorld_1: vec3<f32>;\n@group(0) @binding(1) \nvar<uniform> unnamed: Uniforms;\nvar<private> outTint: vec4<f32>;\nvar<private> vLightPosition_1: vec4<f32>;\n\nfn main_1() {\n var n: vec3<f32>;\n var toLight: vec3<f32>;\n var local: vec3<f32>;\n var cosLight: f32;\n var reflected: f32;\n\n let _e17 = vGlassWorld_1;\n let _e18 = dpdx(_e17);\n let _e19 = vGlassWorld_1;\n let _e20 = dpdy(_e19);\n n = normalize(cross(_e18, _e20));\n let _e25 = unnamed.uGlassLight[3u];\n if (_e25 > 0.5f) {\n let _e28 = unnamed.uGlassLight;\n let _e30 = vGlassWorld_1;\n local = normalize((_e28.xyz - _e30));\n } else {\n let _e34 = unnamed.uGlassLight;\n local = _e34.xyz;\n }\n let _e36 = local;\n toLight = _e36;\n let _e37 = n;\n let _e38 = toLight;\n cosLight = abs(dot(_e37, _e38));\n let _e41 = cosLight;\n reflected = (0.04f + (0.96f * pow((1f - _e41), 5f)));\n let _e47 = unnamed.uGlassPane;\n let _e49 = reflected;\n let _e51 = (_e47.xyz * (1f - _e49));\n let _e54 = unnamed.uGlassPane[3u];\n outTint = vec4<f32>(_e51.x, _e51.y, _e51.z, _e54);\n return;\n}\n\n@fragment \nfn main(@location(1) vGlassWorld: vec3<f32>, @location(0) vLightPosition: vec4<f32>) -> @location(0) vec4<f32> {\n vGlassWorld_1 = vGlassWorld;\n vLightPosition_1 = vLightPosition;\n main_1();\n let _e5 = outTint;\n return _e5;\n}\n";
27
27
 
28
- export const GLASS_TINT_INSTANCED_CUTOUT_VERT_WGSL = "struct Uniforms {\n uLightViewProj: mat4x4<f32>,\n uUvScale: vec2<f32>,\n uAlphaCutout: f32,\n}\n\nstruct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct VertexOutput {\n @location(0) member: vec4<f32>,\n @builtin(position) gl_Position: vec4<f32>,\n @location(1) member_1: vec3<f32>,\n @location(2) @interpolate(flat) member_2: f32,\n @location(3) member_3: vec3<f32>,\n}\n\nvar<private> aPosition_1: vec3<f32>;\nvar<private> aInstanceModel0_1: vec4<f32>;\nvar<private> aInstanceModel1_1: vec4<f32>;\nvar<private> aInstanceModel2_1: vec4<f32>;\nvar<private> aInstanceModel3_1: vec4<f32>;\nvar<private> vLightPosition: vec4<f32>;\n@group(0) @binding(0) \nvar<uniform> unnamed: Uniforms;\nvar<private> unnamed_1: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\nvar<private> vUv: vec3<f32>;\nvar<private> aUv_1: vec3<f32>;\nvar<private> vAlphaCutout: f32;\nvar<private> vGlassWorld: vec3<f32>;\n\nfn main_1() {\n var local: vec4<f32>;\n var model: mat4x4<f32>;\n var world: vec4<f32>;\n var bent: vec3<f32>;\n\n let _e23 = aPosition_1;\n local = vec4<f32>(_e23.x, _e23.y, _e23.z, 1f);\n let _e28 = aInstanceModel0_1;\n let _e29 = aInstanceModel1_1;\n let _e30 = aInstanceModel2_1;\n let _e31 = aInstanceModel3_1;\n model = mat4x4<f32>(vec4<f32>(_e28.x, _e28.y, _e28.z, _e28.w), vec4<f32>(_e29.x, _e29.y, _e29.z, _e29.w), vec4<f32>(_e30.x, _e30.y, _e30.z, _e30.w), vec4<f32>(_e31.x, _e31.y, _e31.z, _e31.w));\n let _e53 = model;\n let _e54 = local;\n world = (_e53 * _e54);\n let _e56 = world;\n bent = _e56.xyz;\n let _e59 = unnamed.uLightViewProj;\n let _e60 = bent;\n let _e62 = world[3u];\n vLightPosition = (_e59 * vec4<f32>(_e60.x, _e60.y, _e60.z, _e62));\n let _e68 = vLightPosition;\n unnamed_1.gl_Position = _e68;\n let _e70 = aUv_1;\n let _e73 = unnamed.uUvScale;\n let _e74 = (_e70.xy * _e73);\n let _e76 = aUv_1[2u];\n vUv = vec3<f32>(_e74.x, _e74.y, _e76);\n let _e81 = unnamed.uAlphaCutout;\n vAlphaCutout = _e81;\n let _e82 = bent;\n vGlassWorld = _e82;\n return;\n}\n\n@vertex \nfn main(@location(0) aPosition: vec3<f32>, @location(11) aInstanceModel0_: vec4<f32>, @location(12) aInstanceModel1_: vec4<f32>, @location(13) aInstanceModel2_: vec4<f32>, @location(14) aInstanceModel3_: vec4<f32>, @location(5) aUv: vec3<f32>) -> VertexOutput {\n aPosition_1 = aPosition;\n aInstanceModel0_1 = aInstanceModel0_;\n aInstanceModel1_1 = aInstanceModel1_;\n aInstanceModel2_1 = aInstanceModel2_;\n aInstanceModel3_1 = aInstanceModel3_;\n aUv_1 = aUv;\n main_1();\n let _e19 = unnamed_1.gl_Position.y;\n unnamed_1.gl_Position.y = -(_e19);\n let _e21 = vLightPosition;\n let _e22 = unnamed_1.gl_Position;\n let _e23 = vUv;\n let _e24 = vAlphaCutout;\n let _e25 = vGlassWorld;\n return VertexOutput(_e21, _e22, _e23, _e24, _e25);\n}\n";
28
+ export const GLASS_TINT_INSTANCED_CUTOUT_VERT_WGSL = "struct Uniforms {\n uLightViewProj: mat4x4<f32>,\n uUvScale: vec2<f32>,\n uUvOffset: vec2<f32>,\n uAlphaCutout: f32,\n}\n\nstruct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct VertexOutput {\n @location(0) member: vec4<f32>,\n @builtin(position) gl_Position: vec4<f32>,\n @location(1) member_1: vec3<f32>,\n @location(2) @interpolate(flat) member_2: f32,\n @location(3) member_3: vec3<f32>,\n}\n\nvar<private> aPosition_1: vec3<f32>;\nvar<private> aInstanceModel0_1: vec4<f32>;\nvar<private> aInstanceModel1_1: vec4<f32>;\nvar<private> aInstanceModel2_1: vec4<f32>;\nvar<private> aInstanceModel3_1: vec4<f32>;\nvar<private> vLightPosition: vec4<f32>;\n@group(0) @binding(0) \nvar<uniform> unnamed: Uniforms;\nvar<private> unnamed_1: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\nvar<private> vUv: vec3<f32>;\nvar<private> aUv_1: vec3<f32>;\nvar<private> vAlphaCutout: f32;\nvar<private> vGlassWorld: vec3<f32>;\n\nfn main_1() {\n var local: vec4<f32>;\n var model: mat4x4<f32>;\n var world: vec4<f32>;\n var bent: vec3<f32>;\n\n let _e24 = aPosition_1;\n local = vec4<f32>(_e24.x, _e24.y, _e24.z, 1f);\n let _e29 = aInstanceModel0_1;\n let _e30 = aInstanceModel1_1;\n let _e31 = aInstanceModel2_1;\n let _e32 = aInstanceModel3_1;\n model = mat4x4<f32>(vec4<f32>(_e29.x, _e29.y, _e29.z, _e29.w), vec4<f32>(_e30.x, _e30.y, _e30.z, _e30.w), vec4<f32>(_e31.x, _e31.y, _e31.z, _e31.w), vec4<f32>(_e32.x, _e32.y, _e32.z, _e32.w));\n let _e54 = model;\n let _e55 = local;\n world = (_e54 * _e55);\n let _e57 = world;\n bent = _e57.xyz;\n let _e60 = unnamed.uLightViewProj;\n let _e61 = bent;\n let _e63 = world[3u];\n vLightPosition = (_e60 * vec4<f32>(_e61.x, _e61.y, _e61.z, _e63));\n let _e69 = vLightPosition;\n unnamed_1.gl_Position = _e69;\n let _e71 = aUv_1;\n let _e74 = unnamed.uUvScale;\n let _e77 = unnamed.uUvOffset;\n let _e78 = ((_e71.xy * _e74) + _e77);\n let _e80 = aUv_1[2u];\n vUv = vec3<f32>(_e78.x, _e78.y, _e80);\n let _e85 = unnamed.uAlphaCutout;\n vAlphaCutout = _e85;\n let _e86 = bent;\n vGlassWorld = _e86;\n return;\n}\n\n@vertex \nfn main(@location(0) aPosition: vec3<f32>, @location(11) aInstanceModel0_: vec4<f32>, @location(12) aInstanceModel1_: vec4<f32>, @location(13) aInstanceModel2_: vec4<f32>, @location(14) aInstanceModel3_: vec4<f32>, @location(5) aUv: vec3<f32>) -> VertexOutput {\n aPosition_1 = aPosition;\n aInstanceModel0_1 = aInstanceModel0_;\n aInstanceModel1_1 = aInstanceModel1_;\n aInstanceModel2_1 = aInstanceModel2_;\n aInstanceModel3_1 = aInstanceModel3_;\n aUv_1 = aUv;\n main_1();\n let _e19 = unnamed_1.gl_Position.y;\n unnamed_1.gl_Position.y = -(_e19);\n let _e21 = vLightPosition;\n let _e22 = unnamed_1.gl_Position;\n let _e23 = vUv;\n let _e24 = vAlphaCutout;\n let _e25 = vGlassWorld;\n return VertexOutput(_e21, _e22, _e23, _e24, _e25);\n}\n";
29
29
 
30
30
  export const GLASS_TINT_INSTANCED_VERT_WGSL = "struct Uniforms {\n uLightViewProj: mat4x4<f32>,\n}\n\nstruct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct VertexOutput {\n @location(0) member: vec4<f32>,\n @builtin(position) gl_Position: vec4<f32>,\n @location(1) member_1: vec3<f32>,\n}\n\nvar<private> aPosition_1: vec3<f32>;\nvar<private> aInstanceModel0_1: vec4<f32>;\nvar<private> aInstanceModel1_1: vec4<f32>;\nvar<private> aInstanceModel2_1: vec4<f32>;\nvar<private> aInstanceModel3_1: vec4<f32>;\nvar<private> vLightPosition: vec4<f32>;\n@group(0) @binding(0) \nvar<uniform> unnamed: Uniforms;\nvar<private> unnamed_1: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\nvar<private> vGlassWorld: vec3<f32>;\n\nfn main_1() {\n var local: vec4<f32>;\n var model: mat4x4<f32>;\n var world: vec4<f32>;\n var bent: vec3<f32>;\n\n let _e17 = aPosition_1;\n local = vec4<f32>(_e17.x, _e17.y, _e17.z, 1f);\n let _e22 = aInstanceModel0_1;\n let _e23 = aInstanceModel1_1;\n let _e24 = aInstanceModel2_1;\n let _e25 = aInstanceModel3_1;\n model = mat4x4<f32>(vec4<f32>(_e22.x, _e22.y, _e22.z, _e22.w), vec4<f32>(_e23.x, _e23.y, _e23.z, _e23.w), vec4<f32>(_e24.x, _e24.y, _e24.z, _e24.w), vec4<f32>(_e25.x, _e25.y, _e25.z, _e25.w));\n let _e47 = model;\n let _e48 = local;\n world = (_e47 * _e48);\n let _e50 = world;\n bent = _e50.xyz;\n let _e53 = unnamed.uLightViewProj;\n let _e54 = bent;\n let _e56 = world[3u];\n vLightPosition = (_e53 * vec4<f32>(_e54.x, _e54.y, _e54.z, _e56));\n let _e62 = vLightPosition;\n unnamed_1.gl_Position = _e62;\n let _e64 = bent;\n vGlassWorld = _e64;\n return;\n}\n\n@vertex \nfn main(@location(0) aPosition: vec3<f32>, @location(11) aInstanceModel0_: vec4<f32>, @location(12) aInstanceModel1_: vec4<f32>, @location(13) aInstanceModel2_: vec4<f32>, @location(14) aInstanceModel3_: vec4<f32>) -> VertexOutput {\n aPosition_1 = aPosition;\n aInstanceModel0_1 = aInstanceModel0_;\n aInstanceModel1_1 = aInstanceModel1_;\n aInstanceModel2_1 = aInstanceModel2_;\n aInstanceModel3_1 = aInstanceModel3_;\n main_1();\n let _e15 = unnamed_1.gl_Position.y;\n unnamed_1.gl_Position.y = -(_e15);\n let _e17 = vLightPosition;\n let _e18 = unnamed_1.gl_Position;\n let _e19 = vGlassWorld;\n return VertexOutput(_e17, _e18, _e19);\n}\n";
31
31
 
@@ -64,7 +64,7 @@ export const DEPTH_BINDINGS = {
64
64
  },
65
65
  "DEPTH_CUTOUT_VERT": {
66
66
  "uniforms": 0,
67
- "uniformSize": 176,
67
+ "uniformSize": 192,
68
68
  "fields": {
69
69
  "uLightViewProj": {
70
70
  "offset": 0,
@@ -106,8 +106,13 @@ export const DEPTH_BINDINGS = {
106
106
  "size": 8,
107
107
  "type": "vec2"
108
108
  },
109
- "uAlphaCutout": {
109
+ "uUvOffset": {
110
110
  "offset": 168,
111
+ "size": 8,
112
+ "type": "vec2"
113
+ },
114
+ "uAlphaCutout": {
115
+ "offset": 176,
111
116
  "size": 4,
112
117
  "type": "float"
113
118
  }
@@ -134,7 +139,7 @@ export const DEPTH_BINDINGS = {
134
139
  },
135
140
  "DEPTH_INSTANCED_CUTOUT_VERT": {
136
141
  "uniforms": 0,
137
- "uniformSize": 80,
142
+ "uniformSize": 96,
138
143
  "fields": {
139
144
  "uLightViewProj": {
140
145
  "offset": 0,
@@ -146,8 +151,13 @@ export const DEPTH_BINDINGS = {
146
151
  "size": 8,
147
152
  "type": "vec2"
148
153
  },
149
- "uAlphaCutout": {
154
+ "uUvOffset": {
150
155
  "offset": 72,
156
+ "size": 8,
157
+ "type": "vec2"
158
+ },
159
+ "uAlphaCutout": {
160
+ "offset": 80,
151
161
  "size": 4,
152
162
  "type": "float"
153
163
  }
@@ -281,7 +291,7 @@ export const DEPTH_BINDINGS = {
281
291
  },
282
292
  "GLASS_TINT_CUTOUT_VERT": {
283
293
  "uniforms": 0,
284
- "uniformSize": 176,
294
+ "uniformSize": 192,
285
295
  "fields": {
286
296
  "uLightViewProj": {
287
297
  "offset": 0,
@@ -323,8 +333,13 @@ export const DEPTH_BINDINGS = {
323
333
  "size": 8,
324
334
  "type": "vec2"
325
335
  },
326
- "uAlphaCutout": {
336
+ "uUvOffset": {
327
337
  "offset": 168,
338
+ "size": 8,
339
+ "type": "vec2"
340
+ },
341
+ "uAlphaCutout": {
342
+ "offset": 176,
328
343
  "size": 4,
329
344
  "type": "float"
330
345
  }
@@ -350,7 +365,7 @@ export const DEPTH_BINDINGS = {
350
365
  },
351
366
  "GLASS_TINT_INSTANCED_CUTOUT_VERT": {
352
367
  "uniforms": 0,
353
- "uniformSize": 80,
368
+ "uniformSize": 96,
354
369
  "fields": {
355
370
  "uLightViewProj": {
356
371
  "offset": 0,
@@ -362,8 +377,13 @@ export const DEPTH_BINDINGS = {
362
377
  "size": 8,
363
378
  "type": "vec2"
364
379
  },
365
- "uAlphaCutout": {
380
+ "uUvOffset": {
366
381
  "offset": 72,
382
+ "size": 8,
383
+ "type": "vec2"
384
+ },
385
+ "uAlphaCutout": {
386
+ "offset": 80,
367
387
  "size": 4,
368
388
  "type": "float"
369
389
  }