@forgeax/engine-shader 0.1.7 → 0.1.19

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 (99) hide show
  1. package/README.md +34 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/ShaderRegistry.d.ts.map +1 -1
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.mjs +53 -2
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/material-schemas.d.ts.map +1 -1
  9. package/package.json +6 -3
  10. package/src/ShaderRegistry.ts +50 -0
  11. package/src/__tests__/bloom-fxaa-tonemap.unit.test.ts +86 -12
  12. package/src/__tests__/default-standard-pbr-transmission.unit.test.ts +181 -0
  13. package/src/__tests__/lighting-punctual.unit.test.ts +1 -1
  14. package/src/__tests__/material-builtins.unit.test.ts +38 -1
  15. package/src/__tests__/material-contract.unit.test.ts +123 -0
  16. package/src/__tests__/motion-blur.unit.test.ts +44 -0
  17. package/src/__tests__/scene-temporal.unit.test.ts +23 -5
  18. package/src/__tests__/shader-manifest-transmission.unit.test.ts +75 -0
  19. package/src/__tests__/shader.unit.test.ts +43 -3
  20. package/src/__tests__/sprite-variants.unit.test.ts +19 -0
  21. package/src/__tests__/taa-resolve.unit.test.ts +75 -3
  22. package/src/__tests__/transmission-thickness-scale.unit.test.ts +19 -0
  23. package/src/common.wgsl +30 -30
  24. package/src/default-standard-pbr-skin.wgsl +27 -9
  25. package/src/default-standard-pbr.wgsl +209 -28
  26. package/src/fxaa.wgsl +5 -6
  27. package/src/index.ts +3 -0
  28. package/src/material-schemas.ts +7 -0
  29. package/src/motion-blur.wgsl +77 -0
  30. package/src/pbr-temporal.wgsl +15 -2
  31. package/src/scene-temporal.wgsl +54 -0
  32. package/src/shadow_caster.wgsl +27 -2
  33. package/src/sprite-lit.wgsl +5 -4
  34. package/src/sprite.wgsl +5 -4
  35. package/src/taa-resolve.wgsl +76 -81
  36. package/src/tonemap.wgsl +7 -9
  37. package/src/unlit.wgsl +6 -5
  38. package/dist/__tests__/atmosphere-background.test.d.ts +0 -2
  39. package/dist/__tests__/atmosphere-background.test.d.ts.map +0 -1
  40. package/dist/__tests__/atmosphere-cubemap-orientation.test.d.ts +0 -2
  41. package/dist/__tests__/atmosphere-cubemap-orientation.test.d.ts.map +0 -1
  42. package/dist/__tests__/atmosphere-preetham-numeric.test.d.ts +0 -2
  43. package/dist/__tests__/atmosphere-preetham-numeric.test.d.ts.map +0 -1
  44. package/dist/__tests__/atmosphere-preetham-red.test.d.ts +0 -2
  45. package/dist/__tests__/atmosphere-preetham-red.test.d.ts.map +0 -1
  46. package/dist/__tests__/atmosphere-preetham.test.d.ts +0 -2
  47. package/dist/__tests__/atmosphere-preetham.test.d.ts.map +0 -1
  48. package/dist/__tests__/atmosphere-three-r184-reference.test.d.ts +0 -2
  49. package/dist/__tests__/atmosphere-three-r184-reference.test.d.ts.map +0 -1
  50. package/dist/__tests__/bloom-fxaa-tonemap.unit.test.d.ts +0 -2
  51. package/dist/__tests__/bloom-fxaa-tonemap.unit.test.d.ts.map +0 -1
  52. package/dist/__tests__/builtin-texture-sampling-contract.test.d.ts +0 -2
  53. package/dist/__tests__/builtin-texture-sampling-contract.test.d.ts.map +0 -1
  54. package/dist/__tests__/default-standard-pbr-alpha.unit.test.d.ts +0 -2
  55. package/dist/__tests__/default-standard-pbr-alpha.unit.test.d.ts.map +0 -1
  56. package/dist/__tests__/deferred-lighting-ssao.test.d.ts +0 -2
  57. package/dist/__tests__/deferred-lighting-ssao.test.d.ts.map +0 -1
  58. package/dist/__tests__/fog-oracle.unit.test.d.ts +0 -2
  59. package/dist/__tests__/fog-oracle.unit.test.d.ts.map +0 -1
  60. package/dist/__tests__/fog-orthographic-ray.unit.test.d.ts +0 -2
  61. package/dist/__tests__/fog-orthographic-ray.unit.test.d.ts.map +0 -1
  62. package/dist/__tests__/fog-producer-matrix.integration.test.d.ts +0 -2
  63. package/dist/__tests__/fog-producer-matrix.integration.test.d.ts.map +0 -1
  64. package/dist/__tests__/hdrp-ssao-compile.test.d.ts +0 -2
  65. package/dist/__tests__/hdrp-ssao-compile.test.d.ts.map +0 -1
  66. package/dist/__tests__/ibl-irradiance.unit.test.d.ts +0 -2
  67. package/dist/__tests__/ibl-irradiance.unit.test.d.ts.map +0 -1
  68. package/dist/__tests__/ibl-sampling.unit.test.d.ts +0 -2
  69. package/dist/__tests__/ibl-sampling.unit.test.d.ts.map +0 -1
  70. package/dist/__tests__/lighting-punctual.unit.test.d.ts +0 -2
  71. package/dist/__tests__/lighting-punctual.unit.test.d.ts.map +0 -1
  72. package/dist/__tests__/material-artifact-dedup.unit.test.d.ts +0 -2
  73. package/dist/__tests__/material-artifact-dedup.unit.test.d.ts.map +0 -1
  74. package/dist/__tests__/material-builtins.unit.test.d.ts +0 -2
  75. package/dist/__tests__/material-builtins.unit.test.d.ts.map +0 -1
  76. package/dist/__tests__/material-contract.unit.test.d.ts +0 -2
  77. package/dist/__tests__/material-contract.unit.test.d.ts.map +0 -1
  78. package/dist/__tests__/material-derived-builtins.integration.test.d.ts +0 -2
  79. package/dist/__tests__/material-derived-builtins.integration.test.d.ts.map +0 -1
  80. package/dist/__tests__/points-lines-shader.unit.test.d.ts +0 -2
  81. package/dist/__tests__/points-lines-shader.unit.test.d.ts.map +0 -1
  82. package/dist/__tests__/public-surface.unit.test.d.ts +0 -2
  83. package/dist/__tests__/public-surface.unit.test.d.ts.map +0 -1
  84. package/dist/__tests__/scene-temporal.unit.test.d.ts +0 -2
  85. package/dist/__tests__/scene-temporal.unit.test.d.ts.map +0 -1
  86. package/dist/__tests__/shader-registry-transaction.unit.test.d.ts +0 -2
  87. package/dist/__tests__/shader-registry-transaction.unit.test.d.ts.map +0 -1
  88. package/dist/__tests__/shader.unit.test.d.ts +0 -2
  89. package/dist/__tests__/shader.unit.test.d.ts.map +0 -1
  90. package/dist/__tests__/sprite-lit-shader.test.d.ts +0 -2
  91. package/dist/__tests__/sprite-lit-shader.test.d.ts.map +0 -1
  92. package/dist/__tests__/sprite-variants.unit.test.d.ts +0 -2
  93. package/dist/__tests__/sprite-variants.unit.test.d.ts.map +0 -1
  94. package/dist/__tests__/taa-resolve.unit.test.d.ts +0 -2
  95. package/dist/__tests__/taa-resolve.unit.test.d.ts.map +0 -1
  96. package/dist/__tests__/transparent-pbr.unit.test.d.ts +0 -2
  97. package/dist/__tests__/transparent-pbr.unit.test.d.ts.map +0 -1
  98. package/dist/__tests__/vertex-color-variant.unit.test.d.ts +0 -2
  99. package/dist/__tests__/vertex-color-variant.unit.test.d.ts.map +0 -1
@@ -3,24 +3,29 @@ import { resolve } from 'node:path';
3
3
  import { describe, expect, it } from 'vitest';
4
4
 
5
5
  const source = readFileSync(resolve(import.meta.dirname, '../taa-resolve.wgsl'), 'utf8');
6
+ const pbrTemporal = readFileSync(resolve(import.meta.dirname, '../pbr-temporal.wgsl'), 'utf8');
7
+ const sceneTemporal = readFileSync(resolve(import.meta.dirname, '../scene-temporal.wgsl'), 'utf8');
6
8
 
7
9
  describe('taa-resolve.wgsl', () => {
8
10
  it('keeps the fixed packed temporal and two-attachment ABI', () => {
9
11
  expect(source).toContain('struct TaaResolveParams');
10
12
  expect(source).toContain('@location(0) color');
11
13
  expect(source).toContain('@location(1) temporal');
12
- expect(source).toContain('output.temporal = temporal');
14
+ expect(source).toContain('return TaaResolveOutput(');
15
+ expect(source).toContain('temporal,');
13
16
  expect(source).toContain('current.a');
17
+ expect(source).toContain('1.0 - clamp(temporal.w');
18
+ expect(source).not.toContain('1.0 - clamp(current.a');
14
19
  });
15
20
 
16
21
  it('contains every v1 rejection and adaptive weighting term', () => {
17
- expect(source).toContain('uv + params.currentJitterUv');
22
+ expect(source).toContain('in.uv + params.currentJitterUv');
18
23
  expect(source).toContain('in.uv - temporal.xy');
19
24
  expect(source).toContain('closestCurrentTemporal(pixel, dimensions)');
20
25
  expect(source).toContain('historyInBounds');
21
26
  expect(source).toContain('depthDelta > depthThreshold');
22
27
  expect(source).toContain('neighborhoodSquareMean');
23
- expect(source).toContain('clamp(rgbToYCoCg(sampledHistory.rgb), clipMin, clipMax)');
28
+ expect(source).toContain('clamp(rgbToYCoCg(history.rgb), clipMin, clipMax)');
24
29
  expect(source).toContain('reactiveFactor');
25
30
  expect(source).toContain('velocityFactor');
26
31
  expect(source).toContain('depthFactor');
@@ -28,5 +33,72 @@ describe('taa-resolve.wgsl', () => {
28
33
  expect(source).toContain('mix(0.88, 0.97, lumaFactor)');
29
34
  expect(source).toContain('params.temporalFrameIndex < 8u');
30
35
  expect(source).toContain('progressiveWeight');
36
+ expect(source).toContain('let dimensions = vec2<i32>(textureDimensions(currentColor, 0));');
37
+ expect(source).toContain('closestCurrentTemporal(pixel, dimensions)');
38
+ expect(source).toContain('vec2<f32>(dimensions)');
39
+ });
40
+
41
+ it('compiles the PBR temporal seam with coverage-aware reactive output', async () => {
42
+ const compilerPath = resolve(import.meta.dirname, '../../../shader-compiler/dist/index.mjs');
43
+ const { compileShader } = await import(/* @vite-ignore */ compilerPath);
44
+ const common = `
45
+ fn sampleMaterialTexture(
46
+ texture : texture_2d<f32>,
47
+ textureSampler : sampler,
48
+ uv : vec2<f32>,
49
+ uvScale : vec2<f32>,
50
+ ) -> vec4<f32> {
51
+ return textureSample(texture, textureSampler, uv * uvScale);
52
+ }
53
+
54
+ `;
55
+ const sceneTemporalBody = sceneTemporal
56
+ .replace(/^#define_import_path.*$/gm, '')
57
+ .replace(/^#import.*$/gm, '');
58
+ const entry = `${common}
59
+ ${sceneTemporalBody}
60
+ ${pbrTemporal.replace(/^#define_import_path.*$/gm, '').replace(/^#import.*$/gm, '')}
61
+ @group(0) @binding(0) var colorTexture : texture_2d<f32>;
62
+ @group(0) @binding(1) var colorSampler : sampler;
63
+ @fragment
64
+ fn fs_temporal_probe() -> @location(0) vec4<f32> {
65
+ return projectPbrSceneTemporal(
66
+ 0.75, 0.5, colorTexture, colorSampler,
67
+ vec4<f32>(0.0, 0.0, 1.0, 1.0), vec4<f32>(0.0),
68
+ vec4<f32>(0.0, 0.0, 1.0, 1.0), vec4<f32>(0.0),
69
+ vec4<f32>(0.0, 0.0, 0.0, 0.0), 0.0,
70
+ vec2<f32>(0.5), vec2<f32>(0.5), vec2<f32>(0.5), vec2<f32>(0.5),
71
+ vec2<f32>(0.5), vec2<f32>(0.5), vec2<f32>(0.5), vec2<f32>(0.5),
72
+ );
73
+ }
74
+ `;
75
+ const compiled = await compileShader(entry, {
76
+ id: 'test::pbr-temporal-reactive',
77
+ defines: { PER_INSTANCE_REGION: false, STORAGE_BUFFER_AVAILABLE: true },
78
+ });
79
+ expect(compiled.ok, compiled.ok ? undefined : String(compiled.error)).toBe(true);
80
+ if (!compiled.ok) return;
81
+ expect(compiled.value.wgsl).toContain('resolvePbrTemporalReactive');
82
+ expect(compiled.value.wgsl).toContain('max(clamp(reactive');
83
+ const discardIndex = pbrTemporal.indexOf('discard;');
84
+ const reactiveIndex = pbrTemporal.indexOf('let reactiveCoverage');
85
+ expect(discardIndex).toBeGreaterThanOrEqual(0);
86
+ expect(discardIndex).toBeLessThan(reactiveIndex);
87
+ });
88
+
89
+ it('rejects a dev-only forced-reactive-zero falsifier', () => {
90
+ const reactiveCoverageLine =
91
+ 'let reactiveCoverage = resolvePbrTemporalReactive(reactive, baseColorAlpha, baseSample.a);';
92
+ const falsified = pbrTemporal.replace(reactiveCoverageLine, 'let reactiveCoverage = 0.0;');
93
+ expect(() => {
94
+ expect(falsified).toContain(reactiveCoverageLine);
95
+ expect(falsified).toContain('let reactiveCoverage = 0.0;');
96
+ }).toThrow();
97
+ });
98
+
99
+ it('keeps the reactive coverage contract explicit', () => {
100
+ expect(pbrTemporal).toContain('resolvePbrTemporalReactive');
101
+ expect(pbrTemporal).toContain('coverageReactive');
102
+ expect(pbrTemporal).not.toContain('return packSceneTemporal(currentClip, previousClip, 0.0)');
31
103
  });
32
104
  });
@@ -0,0 +1,19 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { describe, expect, it } from 'vitest';
4
+
5
+ const shader = readFileSync(resolve(import.meta.dirname, '../default-standard-pbr.wgsl'), 'utf8');
6
+
7
+ describe('standard transmission thickness scale contract', () => {
8
+ it('converts local authored thickness through the combined local-to-world basis', () => {
9
+ expect(shader).toContain('let localToWorld = entityWorld * instanceLocal;');
10
+ expect(shader).toContain(
11
+ 'let localToWorld = meshes[0].worldFromLocal * instances[in.instanceIdx].localFromInstance;',
12
+ );
13
+ expect(shader).toContain('let worldToLocal0 = vec3<f32>(');
14
+ expect(shader).toContain('let worldRefractedDirection =');
15
+ expect(shader).toMatch(
16
+ /finiteScalar\(material\.thickness, 0\.0\) \* length\(worldRefractedDirection\) \*\s+finiteScalar\(thicknessSample, 1\.0\)/,
17
+ );
18
+ });
19
+ });
package/src/common.wgsl CHANGED
@@ -24,6 +24,9 @@ fn sampleMaterialTexture(
24
24
  }
25
25
 
26
26
  // Shared linear-LDR -> display-sRGB OETF for raw swap-chain storage writes.
27
+ // The high branch deliberately locks Three.js r184's reference literal
28
+ // (`0.41666`) instead of spelling the mathematically exact `1.0 / 2.4`.
29
+ // That literal is part of the byte-level parity contract at 8-bit boundaries.
27
30
  // sRGB texture views perform this conversion on attachment writes, but the
28
31
  // native output and FXAA passes intentionally target the non-sRGB storage view.
29
32
  fn linearToSrgbOetf(color : vec3<f32>) -> vec3<f32> {
@@ -278,6 +281,33 @@ struct SpotLightsArray {
278
281
  };
279
282
 
280
283
  @group(0) @binding(0) var<uniform> view : View;
284
+
285
+ // Shared screen-space ray reconstruction for scene Fog producers. Keeping the
286
+ // inverse-view and projection branch here prevents each producer from growing
287
+ // a second Fog formula or drifting from the View ABI.
288
+ fn fogWorldPoint(ndc : vec3<f32>) -> vec3<f32> {
289
+ let homogeneous = view.inverseViewProj * vec4<f32>(ndc, 1.0);
290
+ let divisor = select(1.0, homogeneous.w, abs(homogeneous.w) > 0.000001);
291
+ return homogeneous.xyz / divisor;
292
+ }
293
+
294
+ fn fogRayFromNdc(ndc : vec3<f32>) -> FogRay {
295
+ let worldPosition = fogWorldPoint(ndc);
296
+ let nearPosition = fogWorldPoint(vec3<f32>(ndc.xy, 0.0));
297
+ let farPosition = fogWorldPoint(vec3<f32>(ndc.xy, 1.0));
298
+ let perspective = view.temporalProjection.z < 0.5;
299
+ let perspectiveVector = worldPosition - view.cameraPos;
300
+ let orthographicVector = farPosition - nearPosition;
301
+ let direction = normalize(select(orthographicVector, perspectiveVector, perspective));
302
+ let origin = select(nearPosition, view.cameraPos, perspective);
303
+ let rayDistance = select(
304
+ max(dot(worldPosition - nearPosition, direction), 0.0),
305
+ length(perspectiveVector),
306
+ perspective,
307
+ );
308
+ return FogRay(origin, direction, rayDistance);
309
+ }
310
+
281
311
  #if STORAGE_BUFFER_AVAILABLE == true
282
312
  @group(0) @binding(1) var<storage, read> pointLightsBuffer : PointLightsArray;
283
313
  @group(0) @binding(2) var<storage, read> spotLightsBuffer : SpotLightsArray;
@@ -445,36 +475,6 @@ struct InstanceData {
445
475
  #endif
446
476
  };
447
477
 
448
- fn sceneTemporalUv(clip : vec4<f32>) -> vec2<f32> {
449
- let safeW = select(1e-6, clip.w, abs(clip.w) >= 1e-6);
450
- let ndc = clip.xy / safeW;
451
- return vec2<f32>(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5);
452
- }
453
-
454
- fn sceneTemporalViewDepth(clip : vec4<f32>) -> f32 {
455
- let perspectiveDepth = max(clip.w, 0.0);
456
- let ndcDepth = clip.z / max(abs(clip.w), 1e-6);
457
- let orthographicDepth = view.temporalProjection.x +
458
- ndcDepth * (view.temporalProjection.y - view.temporalProjection.x);
459
- let viewDepth = select(
460
- perspectiveDepth,
461
- max(orthographicDepth, 0.0),
462
- view.temporalProjection.z >= 0.5,
463
- );
464
- return log2(1.0 + viewDepth);
465
- }
466
-
467
- fn packSceneTemporal(
468
- currentClip : vec4<f32>,
469
- previousClip : vec4<f32>,
470
- reactive : f32,
471
- ) -> vec4<f32> {
472
- return vec4<f32>(
473
- sceneTemporalUv(currentClip) - sceneTemporalUv(previousClip),
474
- sceneTemporalViewDepth(currentClip),
475
- clamp(reactive, 0.0, 1.0),
476
- );
477
- }
478
478
  #if STORAGE_BUFFER_AVAILABLE == true
479
479
  @group(3) @binding(0) var<storage, read> instances : array<InstanceData>;
480
480
  #else
@@ -88,6 +88,11 @@ struct Material {
88
88
  clearcoatRoughness : f32,
89
89
  specularTint : vec3<f32>,
90
90
  normalScale : f32,
91
+ transmission : f32,
92
+ ior : f32,
93
+ thickness : f32,
94
+ attenuationColor : vec3<f32>,
95
+ attenuationDistance : f32,
91
96
  baseColorTextureCoordinatesTransform : vec4<f32>,
92
97
  baseColorTextureCoordinatesMetadata : vec4<f32>,
93
98
  metallicRoughnessTextureCoordinatesTransform : vec4<f32>,
@@ -100,6 +105,10 @@ struct Material {
100
105
  emissiveTextureCoordinatesMetadata : vec4<f32>,
101
106
  occlusionTextureCoordinatesTransform : vec4<f32>,
102
107
  occlusionTextureCoordinatesMetadata : vec4<f32>,
108
+ transmissionTextureCoordinatesTransform : vec4<f32>,
109
+ transmissionTextureCoordinatesMetadata : vec4<f32>,
110
+ thicknessTextureCoordinatesTransform : vec4<f32>,
111
+ thicknessTextureCoordinatesMetadata : vec4<f32>,
103
112
  };
104
113
 
105
114
  @group(1) @binding(0) var<uniform> material : Material;
@@ -115,6 +124,10 @@ struct Material {
115
124
  @group(1) @binding(10) var emissiveTexture : texture_2d<f32>;
116
125
  @group(1) @binding(11) var occlusionSampler : sampler;
117
126
  @group(1) @binding(12) var occlusionTexture : texture_2d<f32>;
127
+ @group(1) @binding(13) var transmissionSampler : sampler;
128
+ @group(1) @binding(14) var transmissionTexture : texture_2d<f32>;
129
+ @group(1) @binding(15) var thicknessSampler : sampler;
130
+ @group(1) @binding(16) var thicknessTexture : texture_2d<f32>;
118
131
 
119
132
  // Preserve filtering reflection for resources passed to the shared sampler.
120
133
  fn materialTextureFilteringWitness() {
@@ -124,12 +137,16 @@ fn materialTextureFilteringWitness() {
124
137
  let specularTint = specularTintTexture;
125
138
  let emissive = emissiveTexture;
126
139
  let occlusion = occlusionTexture;
140
+ let transmission = transmissionTexture;
141
+ let thickness = thicknessTexture;
127
142
  let baseWitness = textureSample(base, baseColorSampler, vec2<f32>(0.0));
128
143
  let metallicRoughnessWitness = textureSample(metallicRoughness, metallicRoughnessSampler, vec2<f32>(0.0));
129
144
  let normalWitness = textureSample(normal, normalSampler, vec2<f32>(0.0));
130
145
  let specularTintWitness = textureSample(specularTint, specularTintSampler, vec2<f32>(0.0));
131
146
  let emissiveWitness = textureSample(emissive, emissiveSampler, vec2<f32>(0.0));
132
147
  let occlusionWitness = textureSample(occlusion, occlusionSampler, vec2<f32>(0.0));
148
+ let transmissionWitness = textureSample(transmission, transmissionSampler, vec2<f32>(0.0));
149
+ let thicknessWitness = textureSample(thickness, thicknessSampler, vec2<f32>(0.0));
133
150
  }
134
151
 
135
152
  struct SkylightUniforms {
@@ -146,13 +163,13 @@ struct SkylightUniforms {
146
163
  colorB : f32,
147
164
  rotation : vec4<f32>,
148
165
  };
149
- @group(1) @binding(13) var irradianceMap : texture_cube<f32>;
150
- @group(1) @binding(14) var irradianceSampler : sampler;
151
- @group(1) @binding(15) var prefilterMap : texture_cube<f32>;
152
- @group(1) @binding(16) var prefilterSampler : sampler;
153
- @group(1) @binding(17) var brdfLut : texture_2d<f32>;
154
- @group(1) @binding(18) var brdfLutSampler : sampler;
155
- @group(1) @binding(19) var<uniform> skylight : SkylightUniforms;
166
+ @group(1) @binding(17) var irradianceMap : texture_cube<f32>;
167
+ @group(1) @binding(18) var irradianceSampler : sampler;
168
+ @group(1) @binding(19) var prefilterMap : texture_cube<f32>;
169
+ @group(1) @binding(20) var prefilterSampler : sampler;
170
+ @group(1) @binding(21) var brdfLut : texture_2d<f32>;
171
+ @group(1) @binding(22) var brdfLutSampler : sampler;
172
+ @group(1) @binding(23) var<uniform> skylight : SkylightUniforms;
156
173
 
157
174
  #if STORAGE_BUFFER_AVAILABLE == true
158
175
  @group(2) @binding(1) var<storage, read> palette : array<mat4x4<f32>>;
@@ -469,8 +486,8 @@ struct TemporalVsOut {
469
486
  @location(5) uv5 : vec2<f32>,
470
487
  @location(6) uv6 : vec2<f32>,
471
488
  @location(7) uv7 : vec2<f32>,
472
- @location(8) @interpolate(linear) currentClip : vec4<f32>,
473
- @location(9) @interpolate(linear) previousClip : vec4<f32>,
489
+ @location(8) @interpolate(perspective) currentClip : vec4<f32>,
490
+ @location(9) @interpolate(perspective) previousClip : vec4<f32>,
474
491
  #ifdef VERTEX_COLOR_AVAILABLE
475
492
  @location(14) color : vec4<f32>,
476
493
  #endif
@@ -531,6 +548,7 @@ fn fs_temporal(in : TemporalVsOut) -> @location(0) vec4<f32> {
531
548
  material.baseColorTextureCoordinatesMetadata,
532
549
  in.currentClip,
533
550
  in.previousClip,
551
+ view.temporalProjection,
534
552
  reactive,
535
553
  in.uv, in.uv1, in.uv2, in.uv3,
536
554
  in.uv4, in.uv5, in.uv6, in.uv7,