@forgeax/engine-vfx-render 0.1.7 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgeax/engine-vfx-render",
3
- "version": "0.1.7",
3
+ "version": "0.1.20",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -22,13 +22,13 @@
22
22
  "LICENSE"
23
23
  ],
24
24
  "dependencies": {
25
- "@forgeax/engine-assets-runtime": "0.1.7",
26
- "@forgeax/engine-ecs": "0.1.7",
27
- "@forgeax/engine-math": "0.1.7",
28
- "@forgeax/engine-render": "0.1.7",
29
- "@forgeax/engine-scene": "0.1.7",
30
- "@forgeax/engine-types": "0.1.7",
31
- "@forgeax/engine-vfx": "0.1.7"
25
+ "@forgeax/engine-assets-runtime": "0.1.20",
26
+ "@forgeax/engine-ecs": "0.1.20",
27
+ "@forgeax/engine-math": "0.1.20",
28
+ "@forgeax/engine-render": "0.1.20",
29
+ "@forgeax/engine-scene": "0.1.20",
30
+ "@forgeax/engine-types": "0.1.20",
31
+ "@forgeax/engine-vfx": "0.1.20"
32
32
  },
33
33
  "devDependencies": {},
34
34
  "forgeax": {
@@ -8,23 +8,11 @@ function shaderSource(name: (typeof shaderNames)[number]): string {
8
8
  return readFileSync(fileURLToPath(new URL(`../shaders/${name}.wgsl`, import.meta.url)), 'utf8');
9
9
  }
10
10
 
11
- function count(source: string, pattern: RegExp): number {
12
- return source.match(pattern)?.length ?? 0;
13
- }
14
-
15
- describe('VFX Fog producer contract', () => {
16
- it('requires one shared Fog call with a world-space ray for every topology', () => {
11
+ describe('VFX volumetric-fog boundary contract', () => {
12
+ it('keeps analytic fog out of every particle topology', () => {
17
13
  for (const name of shaderNames) {
18
14
  const source = shaderSource(name);
19
- expect(source, name).toMatch(
20
- /#import\s+forgeax_view::common::\{[^}]*\bFogViewParams\b[^}]*\bFogRay\b[^}]*\}/,
21
- );
22
- expect(source, name).toMatch(/#import\s+forgeax_view::fog::\{[^}]*\bapply_fog\b[^}]*\}/);
23
- expect(count(source, /\bapply_fog\s*\(/g), name).toBe(1);
24
- expect(count(source, /\bFogRay\s*\(/g), name).toBe(1);
25
- expect(source, name).toMatch(/world[_A-Za-z]*position|worldPosition/);
26
- expect(source, name).toMatch(/ray[_A-Za-z]*distance|distance/);
27
- expect(source, name).toMatch(/\.a\b|alpha/);
15
+ expect(source, name).not.toMatch(/\bFogViewParams\b|\bFogRay\b|\bapply_fog\s*\(/);
28
16
  expect(source, name).not.toMatch(/texture_3d|raymarch/i);
29
17
  }
30
18
  });
@@ -46,15 +34,16 @@ describe('VFX Fog producer contract', () => {
46
34
  expect(camera).toContain('viewProjection');
47
35
  });
48
36
 
49
- it('keeps billboard scene-depth soft-particle alpha before Fog mixing', () => {
37
+ it('keeps billboard scene-depth soft-particle alpha in the final color', () => {
50
38
  const billboard = shaderSource('billboard');
51
39
  const depthLoad = billboard.indexOf('textureLoad(scene_depth');
52
40
  const softParticleCall = billboard.indexOf('softParticle(input.position');
53
- const fogCall = billboard.indexOf('apply_fog(');
41
+ const finalColor = billboard.indexOf('return vec4<f32>(rgb * alpha, alpha);');
54
42
 
55
43
  expect(depthLoad).toBeGreaterThanOrEqual(0);
56
44
  expect(softParticleCall).toBeGreaterThan(depthLoad);
57
- expect(fogCall).toBeGreaterThan(softParticleCall);
45
+ expect(finalColor).toBeGreaterThan(softParticleCall);
58
46
  expect(billboard).toContain('input.color.a * edge, input.fade_distance');
47
+ expect(billboard).not.toContain('apply_fog(');
59
48
  });
60
49
  });
@@ -50,7 +50,10 @@ describe('GPU VFX public host', () => {
50
50
  const world = new World();
51
51
  const lookups: string[] = [];
52
52
  class StatefulAssets {
53
- readonly material: MaterialAsset = { kind: 'material', values: {} };
53
+ readonly material: MaterialAsset = {
54
+ kind: 'material',
55
+ passes: [{ name: 'particle-billboard', program: { module: 'custom-depth' } }],
56
+ };
54
57
  readonly loaders = { registerPackLoader: () => {} };
55
58
 
56
59
  lookup<T extends Asset = Asset>(guid: string): T | undefined {
@@ -118,14 +121,29 @@ describe('GPU VFX public host', () => {
118
121
  frameNumber: 1,
119
122
  } as never,
120
123
  {
121
- targets: [],
124
+ targets: [
125
+ { name: 'scene-color', kind: 'color', format: 'rgba8unorm-srgb', sampleCount: 1 },
126
+ { name: 'scene-depth', kind: 'depth', format: 'depth24plus', sampleCount: 1 },
127
+ ],
122
128
  caps: {},
123
129
  frame: { frameNumber: 1 },
124
130
  generation: 1,
131
+ materialShaderBindingContract: () => 'group-0-resource',
125
132
  } as never,
126
133
  );
127
134
  expect(planned.ok).toBe(true);
128
135
  expect(lookups).toEqual(['material-guid']);
136
+ if (planned.ok) {
137
+ expect(planned.value.resources).toEqual(
138
+ expect.arrayContaining([
139
+ expect.objectContaining({
140
+ kind: 'graphics-bindings',
141
+ values: expect.objectContaining({ sceneDepthBinding: 0 }),
142
+ logicalTargets: { sceneDepth: 'scene-depth' },
143
+ }),
144
+ ]),
145
+ );
146
+ }
129
147
  await host.detachWorld({ world });
130
148
  });
131
149
 
@@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest';
3
3
  import {
4
4
  canonicalMeshVertices,
5
5
  particleMaterialPass,
6
+ particleMaterialSceneDepthBinding,
6
7
  particleMaterialUsesBindings,
7
8
  } from '../feature/particle-resources.js';
8
9
 
@@ -53,6 +54,14 @@ describe('particle material pass', () => {
53
54
  });
54
55
  });
55
56
 
57
+ it('maps renderer shader contracts to their scene-depth binding slots', () => {
58
+ expect(particleMaterialSceneDepthBinding('group-0-resource')).toBe(0);
59
+ expect(particleMaterialSceneDepthBinding('view-and-scene-depth')).toBe(1);
60
+ expect(particleMaterialSceneDepthBinding('group-0')).toBeUndefined();
61
+ expect(particleMaterialSceneDepthBinding('view-only')).toBeUndefined();
62
+ expect(particleMaterialSceneDepthBinding('render-material')).toBeUndefined();
63
+ });
64
+
56
65
  it('does not mistake an ordinary Forward pass for a particle shader', () => {
57
66
  const material: MaterialAsset = {
58
67
  kind: 'material',
@@ -1,6 +1,6 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { resolve } from 'node:path';
3
- import type { RenderFeaturePlan } from '@forgeax/engine-render';
3
+ import { createSceneDataCatalog, type RenderFeaturePlan } from '@forgeax/engine-render';
4
4
  import type { VfxGpuTickIntent } from '@forgeax/engine-vfx';
5
5
  import { describe, expect, it } from 'vitest';
6
6
  import { freezeRenderFeaturePlan } from '../../../render/src/features/plan';
@@ -108,6 +108,12 @@ describe('VFX managed stage execution seam', () => {
108
108
  { name: 'scene-color', kind: 'color', format: 'rgba16float', sampleCount: 1 },
109
109
  { name: 'scene-depth', kind: 'depth', format: 'depth24plus', sampleCount: 1 },
110
110
  ],
111
+ sceneData: createSceneDataCatalog({
112
+ featureIdentity: feature.identity,
113
+ generation: 1,
114
+ planIdentity: `${feature.identity}:1`,
115
+ rgba16floatRenderable: true,
116
+ }),
111
117
  },
112
118
  );
113
119
 
@@ -25,6 +25,7 @@ import {
25
25
  createTopologyResourcePlan,
26
26
  PARTICLE_SHADER_IDENTIFIERS,
27
27
  particleMaterialPass,
28
+ particleMaterialSceneDepthBinding,
28
29
  particleMaterialUsesBindings,
29
30
  } from './particle-resources.js';
30
31
  import type { VfxStagePlanObservation, VfxValidatedStagePlan } from './stage-plan.js';
@@ -346,6 +347,11 @@ export function gpuParticleRenderFeature(
346
347
  return {
347
348
  identity: IDENTITY,
348
349
  requiredCapabilities: ['compute', 'indirectDrawing'],
350
+ // Generated emitter programs are first-use assets. They must hand a
351
+ // WebGPU module to the prepared feature pipeline without waiting for the
352
+ // diagnostic-only getCompilationInfo() round trip; pipeline creation still
353
+ // validates the module before the pass is submitted.
354
+ shaderModuleMode: 'immediate',
349
355
  requiredMaterialShaders: Object.values(PARTICLE_SHADER_IDENTIFIERS),
350
356
  extract: (context) => {
351
357
  const extracted: ExtractedWorld[] = [];
@@ -552,6 +558,14 @@ export function gpuParticleRenderFeature(
552
558
  const submesh =
553
559
  renderer.kind === 'mesh' ? mesh?.submeshes[renderer.submesh ?? 0] : undefined;
554
560
  const indexFormat = mesh?.indices instanceof Uint32Array ? 'uint32' : 'uint16';
561
+ const sceneDepthBinding = isBillboard
562
+ ? particleMaterialSceneDepthBinding(
563
+ context.materialShaderBindingContract?.(materialPass.shader) ??
564
+ (materialPass.shader === PARTICLE_SHADER_IDENTIFIERS.billboard
565
+ ? 'view-and-scene-depth'
566
+ : undefined),
567
+ )
568
+ : undefined;
555
569
  const instances = `${rendererPrefix}.instances`;
556
570
  const history = `${rendererPrefix}.history`;
557
571
  const projectionRuntime = `${rendererPrefix}.runtime`;
@@ -690,9 +704,9 @@ export function gpuParticleRenderFeature(
690
704
  group: 0,
691
705
  runtime: projectionRuntime,
692
706
  instances,
693
- ...(isBillboard ? { sceneDepthBinding: 1 } : {}),
707
+ ...(sceneDepthBinding === undefined ? {} : { sceneDepthBinding }),
694
708
  },
695
- ...(isBillboard && depthTarget !== undefined
709
+ ...(sceneDepthBinding !== undefined && depthTarget !== undefined
696
710
  ? { logicalTargets: { sceneDepth: depthTarget.name } }
697
711
  : {}),
698
712
  },
@@ -784,7 +798,7 @@ export function gpuParticleRenderFeature(
784
798
  depthStoreOp: 'store',
785
799
  },
786
800
  }),
787
- ...(isBillboard && depthTarget !== undefined
801
+ ...(sceneDepthBinding !== undefined && depthTarget !== undefined
788
802
  ? { sampledTargets: [depthTarget.name] }
789
803
  : {}),
790
804
  draws: [
@@ -1,3 +1,4 @@
1
+ import type { RenderFeatureMaterialShaderBindingContract } from '@forgeax/engine-render';
1
2
  import {
2
3
  err,
3
4
  type MaterialAsset,
@@ -161,6 +162,23 @@ export function particleMaterialUsesBindings(material: MaterialAsset | undefined
161
162
  return (material?.parameters?.length ?? 0) > 0;
162
163
  }
163
164
 
165
+ /**
166
+ * Return the scene-depth binding slot required by a particle material shader.
167
+ *
168
+ * Custom particle shaders historically bind only the sampled depth resource at
169
+ * group(0)/binding(0), while the renderer-owned billboard shader also consumes
170
+ * the view UBO at binding(0) and therefore uses depth at binding(1). Keep this
171
+ * choice derived from the renderer contract instead of assuming every
172
+ * billboard has the built-in layout.
173
+ */
174
+ export function particleMaterialSceneDepthBinding(
175
+ contract: RenderFeatureMaterialShaderBindingContract | undefined,
176
+ ): 0 | 1 | undefined {
177
+ if (contract === 'group-0-resource') return 0;
178
+ if (contract === 'view-and-scene-depth') return 1;
179
+ return undefined;
180
+ }
181
+
164
182
  function floatAttribute(value: ArrayBuffer | Float32Array | Uint16Array | undefined): Float32Array {
165
183
  if (value instanceof Float32Array) return value;
166
184
  if (value instanceof Uint16Array) return Float32Array.from(value);
@@ -1,6 +1,4 @@
1
1
  #define_import_path forgeax::vfx-render.particles.beam
2
- #import forgeax_view::common::{View, FogViewParams, FogRay, view}
3
- #import forgeax_view::fog::{apply_fog}
4
2
 
5
3
  struct BeamInput {
6
4
  @location(0) start: vec3<f32>,
@@ -15,29 +13,6 @@ struct VertexOutput {
15
13
  @location(1) clip_position: vec3<f32>,
16
14
  }
17
15
 
18
- fn fogWorldPoint(ndc: vec3<f32>) -> vec3<f32> {
19
- let homogeneous = view.inverseViewProj * vec4<f32>(ndc, 1.0);
20
- let divisor = select(1.0, homogeneous.w, abs(homogeneous.w) > 0.000001);
21
- return homogeneous.xyz / divisor;
22
- }
23
-
24
- fn fogRayFromNdc(ndc: vec3<f32>) -> FogRay {
25
- let worldPosition = fogWorldPoint(ndc);
26
- let nearPosition = fogWorldPoint(vec3<f32>(ndc.xy, 0.0));
27
- let farPosition = fogWorldPoint(vec3<f32>(ndc.xy, 1.0));
28
- let perspective = view.temporalProjection.z < 0.5;
29
- let perspectiveVector = worldPosition - view.cameraPos;
30
- let orthographicVector = farPosition - nearPosition;
31
- let direction = normalize(select(orthographicVector, perspectiveVector, perspective));
32
- let origin = select(nearPosition, view.cameraPos, perspective);
33
- let ray_distance = select(
34
- max(dot(worldPosition - nearPosition, direction), 0.0),
35
- length(perspectiveVector),
36
- perspective,
37
- );
38
- return FogRay(origin, direction, ray_distance);
39
- }
40
-
41
16
  @vertex
42
17
  fn vs_main(input: BeamInput, @builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
43
18
  let corners = array<vec2<f32>, 6>(
@@ -60,10 +35,5 @@ fn vs_main(input: BeamInput, @builtin(vertex_index) vertexIndex: u32) -> VertexO
60
35
  fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
61
36
  let base = vec4<f32>(0.7, 0.2, 1.0, 1.0);
62
37
  let alpha = base.a * input.color.a;
63
- let fogged = apply_fog(
64
- view.fog,
65
- fogRayFromNdc(input.clip_position),
66
- vec4<f32>(base.rgb * input.color.rgb, alpha),
67
- );
68
- return vec4<f32>(fogged.rgb * fogged.a, fogged.a);
38
+ return vec4<f32>(base.rgb * input.color.rgb * alpha, alpha);
69
39
  }
@@ -1,8 +1,8 @@
1
1
  #define_import_path forgeax::vfx-render.particles.billboard
2
- #import forgeax_view::common::{View, FogViewParams, FogRay, view}
3
- #import forgeax_view::fog::{apply_fog}
4
-
5
- @group(0) @binding(1) var scene_depth: texture_depth_2d;
2
+ // The analytic fog producer was removed from this shader. Billboard
3
+ // soft-particle depth is therefore the sole group-0 resource again, matching
4
+ // the prepared group-0-resource layout and its binding resolver.
5
+ @group(0) @binding(0) var scene_depth: texture_depth_2d;
6
6
 
7
7
  struct VertexOutput {
8
8
  @builtin(position) position: vec4<f32>,
@@ -51,29 +51,6 @@ fn softParticle(position: vec4<f32>, alpha: f32, fadeDistance: f32) -> f32 {
51
51
  return alpha * softParticleFactor(position.z, sceneDepth, fadeDistance);
52
52
  }
53
53
 
54
- fn fogWorldPoint(ndc: vec3<f32>) -> vec3<f32> {
55
- let homogeneous = view.inverseViewProj * vec4<f32>(ndc, 1.0);
56
- let divisor = select(1.0, homogeneous.w, abs(homogeneous.w) > 0.000001);
57
- return homogeneous.xyz / divisor;
58
- }
59
-
60
- fn fogRayFromNdc(ndc: vec3<f32>) -> FogRay {
61
- let worldPosition = fogWorldPoint(ndc);
62
- let nearPosition = fogWorldPoint(vec3<f32>(ndc.xy, 0.0));
63
- let farPosition = fogWorldPoint(vec3<f32>(ndc.xy, 1.0));
64
- let perspective = view.temporalProjection.z < 0.5;
65
- let perspectiveVector = worldPosition - view.cameraPos;
66
- let orthographicVector = farPosition - nearPosition;
67
- let direction = normalize(select(orthographicVector, perspectiveVector, perspective));
68
- let origin = select(nearPosition, view.cameraPos, perspective);
69
- let ray_distance = select(
70
- max(dot(worldPosition - nearPosition, direction), 0.0),
71
- length(perspectiveVector),
72
- perspective,
73
- );
74
- return FogRay(origin, direction, ray_distance);
75
- }
76
-
77
54
  struct VertexInput {
78
55
  @location(0) position: vec3<f32>,
79
56
  @location(1) right: vec2<f32>,
@@ -127,6 +104,5 @@ fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
127
104
  let alpha = softParticle(input.position, input.color.a * edge, input.fade_distance);
128
105
  let sheetPulse = 0.82 + 0.18 * fract(input.sheet_frame * 0.618 + input.sheet_uv.x + input.sheet_uv.y);
129
106
  let rgb = (input.color.rgb + emissive * (0.35 + core * 0.65) + vec3<f32>(highlight)) * sheetPulse;
130
- let fogged = apply_fog(view.fog, fogRayFromNdc(input.clip_position), vec4<f32>(rgb, alpha));
131
- return vec4<f32>(fogged.rgb * fogged.a, fogged.a);
107
+ return vec4<f32>(rgb * alpha, alpha);
132
108
  }
@@ -1,6 +1,4 @@
1
1
  #define_import_path forgeax::vfx-render.particles.mesh
2
- #import forgeax_view::common::{View, FogViewParams, FogRay, view}
3
- #import forgeax_view::fog::{apply_fog}
4
2
 
5
3
  struct VertexOutput {
6
4
  @builtin(position) position: vec4<f32>,
@@ -26,29 +24,6 @@ struct VertexInput {
26
24
  @location(11) surface: vec4<f32>,
27
25
  };
28
26
 
29
- fn fogWorldPoint(ndc: vec3<f32>) -> vec3<f32> {
30
- let homogeneous = view.inverseViewProj * vec4<f32>(ndc, 1.0);
31
- let divisor = select(1.0, homogeneous.w, abs(homogeneous.w) > 0.000001);
32
- return homogeneous.xyz / divisor;
33
- }
34
-
35
- fn fogRayFromNdc(ndc: vec3<f32>) -> FogRay {
36
- let worldPosition = fogWorldPoint(ndc);
37
- let nearPosition = fogWorldPoint(vec3<f32>(ndc.xy, 0.0));
38
- let farPosition = fogWorldPoint(vec3<f32>(ndc.xy, 1.0));
39
- let perspective = view.temporalProjection.z < 0.5;
40
- let perspectiveVector = worldPosition - view.cameraPos;
41
- let orthographicVector = farPosition - nearPosition;
42
- let direction = normalize(select(orthographicVector, perspectiveVector, perspective));
43
- let origin = select(nearPosition, view.cameraPos, perspective);
44
- let ray_distance = select(
45
- max(dot(worldPosition - nearPosition, direction), 0.0),
46
- length(perspectiveVector),
47
- perspective,
48
- );
49
- return FogRay(origin, direction, ray_distance);
50
- }
51
-
52
27
  @vertex
53
28
  fn vs_main(input: VertexInput) -> VertexOutput {
54
29
  var output: VertexOutput;
@@ -89,10 +64,6 @@ fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
89
64
  let specular_color = mix(dielectric, input.color.rgb, metallic);
90
65
  let lit = input.color.rgb * diffuse * (1.0 - metallic * 0.55);
91
66
  let emissive = input.emissive_intensity.rgb * input.emissive_intensity.a;
92
- let fogged = apply_fog(
93
- view.fog,
94
- fogRayFromNdc(input.clip_position),
95
- vec4<f32>(lit + specular_color * specular + vec3<f32>(coat) + emissive, input.color.a),
96
- );
97
- return vec4<f32>(fogged.rgb * fogged.a, fogged.a);
67
+ let rgb = lit + specular_color * specular + vec3<f32>(coat) + emissive;
68
+ return vec4<f32>(rgb * input.color.a, input.color.a);
98
69
  }
@@ -1,6 +1,4 @@
1
1
  #define_import_path forgeax::vfx-render.particles.ribbon
2
- #import forgeax_view::common::{View, FogViewParams, FogRay, view}
3
- #import forgeax_view::fog::{apply_fog}
4
2
 
5
3
  struct SegmentInput {
6
4
  @location(0) start: vec3<f32>,
@@ -15,29 +13,6 @@ struct VertexOutput {
15
13
  @location(1) clip_position: vec3<f32>,
16
14
  }
17
15
 
18
- fn fogWorldPoint(ndc: vec3<f32>) -> vec3<f32> {
19
- let homogeneous = view.inverseViewProj * vec4<f32>(ndc, 1.0);
20
- let divisor = select(1.0, homogeneous.w, abs(homogeneous.w) > 0.000001);
21
- return homogeneous.xyz / divisor;
22
- }
23
-
24
- fn fogRayFromNdc(ndc: vec3<f32>) -> FogRay {
25
- let worldPosition = fogWorldPoint(ndc);
26
- let nearPosition = fogWorldPoint(vec3<f32>(ndc.xy, 0.0));
27
- let farPosition = fogWorldPoint(vec3<f32>(ndc.xy, 1.0));
28
- let perspective = view.temporalProjection.z < 0.5;
29
- let perspectiveVector = worldPosition - view.cameraPos;
30
- let orthographicVector = farPosition - nearPosition;
31
- let direction = normalize(select(orthographicVector, perspectiveVector, perspective));
32
- let origin = select(nearPosition, view.cameraPos, perspective);
33
- let ray_distance = select(
34
- max(dot(worldPosition - nearPosition, direction), 0.0),
35
- length(perspectiveVector),
36
- perspective,
37
- );
38
- return FogRay(origin, direction, ray_distance);
39
- }
40
-
41
16
  @vertex
42
17
  fn vs_main(input: SegmentInput, @builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
43
18
  let corners = array<vec2<f32>, 6>(
@@ -60,10 +35,5 @@ fn vs_main(input: SegmentInput, @builtin(vertex_index) vertexIndex: u32) -> Vert
60
35
  fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
61
36
  let base = vec4<f32>(0.2, 0.7, 1.0, 0.9);
62
37
  let alpha = base.a * input.color.a;
63
- let fogged = apply_fog(
64
- view.fog,
65
- fogRayFromNdc(input.clip_position),
66
- vec4<f32>(base.rgb * input.color.rgb, alpha),
67
- );
68
- return fogged;
38
+ return vec4<f32>(base.rgb * input.color.rgb * alpha, alpha);
69
39
  }
@@ -1,6 +1,4 @@
1
1
  #define_import_path forgeax::vfx-render.particles.trail
2
- #import forgeax_view::common::{View, FogViewParams, FogRay, view}
3
- #import forgeax_view::fog::{apply_fog}
4
2
 
5
3
  struct SegmentInput {
6
4
  @location(0) start: vec3<f32>,
@@ -15,29 +13,6 @@ struct VertexOutput {
15
13
  @location(1) clip_position: vec3<f32>,
16
14
  }
17
15
 
18
- fn fogWorldPoint(ndc: vec3<f32>) -> vec3<f32> {
19
- let homogeneous = view.inverseViewProj * vec4<f32>(ndc, 1.0);
20
- let divisor = select(1.0, homogeneous.w, abs(homogeneous.w) > 0.000001);
21
- return homogeneous.xyz / divisor;
22
- }
23
-
24
- fn fogRayFromNdc(ndc: vec3<f32>) -> FogRay {
25
- let worldPosition = fogWorldPoint(ndc);
26
- let nearPosition = fogWorldPoint(vec3<f32>(ndc.xy, 0.0));
27
- let farPosition = fogWorldPoint(vec3<f32>(ndc.xy, 1.0));
28
- let perspective = view.temporalProjection.z < 0.5;
29
- let perspectiveVector = worldPosition - view.cameraPos;
30
- let orthographicVector = farPosition - nearPosition;
31
- let direction = normalize(select(orthographicVector, perspectiveVector, perspective));
32
- let origin = select(nearPosition, view.cameraPos, perspective);
33
- let ray_distance = select(
34
- max(dot(worldPosition - nearPosition, direction), 0.0),
35
- length(perspectiveVector),
36
- perspective,
37
- );
38
- return FogRay(origin, direction, ray_distance);
39
- }
40
-
41
16
  @vertex
42
17
  fn vs_main(input: SegmentInput, @builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
43
18
  let corners = array<vec2<f32>, 6>(
@@ -68,10 +43,5 @@ fn vs_main(input: SegmentInput, @builtin(vertex_index) vertexIndex: u32) -> Vert
68
43
  fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
69
44
  let base = vec4<f32>(0.8, 0.35, 0.1, 1.0);
70
45
  let alpha = base.a * input.color.a;
71
- let fogged = apply_fog(
72
- view.fog,
73
- fogRayFromNdc(input.clip_position),
74
- vec4<f32>(base.rgb * input.color.rgb, alpha),
75
- );
76
- return vec4<f32>(fogged.rgb * fogged.a, fogged.a);
46
+ return vec4<f32>(base.rgb * input.color.rgb * alpha, alpha);
77
47
  }