@woosh/meep-engine 3.14.6 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts +48 -0
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +246 -3
- package/src/shade/RENDERER_CONTRACT.md +584 -580
- package/src/shade/playground/avboit/README.md +117 -0
- package/src/shade/playground/avboit/index.html +215 -0
- package/src/shade/playground/avboit/main.d.ts +2 -0
- package/src/shade/playground/avboit/main.d.ts.map +1 -0
- package/src/shade/playground/avboit/main.js +875 -0
- package/src/shade/renderer/Renderer.d.ts +16 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +29 -28
- package/src/shade/renderer/ShadeTransparencyMode.d.ts +13 -0
- package/src/shade/renderer/ShadeTransparencyMode.d.ts.map +1 -0
- package/src/shade/renderer/ShadeTransparencyMode.js +30 -0
- package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts +9 -0
- package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js +26 -0
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts +7 -2
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +12 -1
- package/src/shade/renderer/rasterize/expand/shader_filter_triangle_by_material_side.js +1 -1
- package/src/shade/renderer/rasterize/forward/FORWARD_VERTEX_SHADER_STRUCT.d.ts +3 -0
- package/src/shade/renderer/rasterize/forward/FORWARD_VERTEX_SHADER_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/{native/oit → forward}/FORWARD_VERTEX_SHADER_STRUCT.js +4 -4
- package/src/shade/renderer/rasterize/forward/SHADING_SCENE_RESOURCE_GROUP.d.ts +3 -0
- package/src/shade/renderer/rasterize/forward/SHADING_SCENE_RESOURCE_GROUP.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/forward/SHADING_SCENE_RESOURCE_GROUP.js +17 -0
- package/src/shade/renderer/rasterize/{native/oit → forward}/chunk_forward_shade_standard_fragment_brick4.d.ts +1 -1
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_brick4.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/{native/oit → forward}/chunk_forward_shade_standard_fragment_brick4.js +16 -16
- package/src/shade/renderer/rasterize/{native/oit → forward}/chunk_forward_shade_standard_fragment_ibl.d.ts +1 -1
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_ibl.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/{native/oit → forward}/chunk_forward_shade_standard_fragment_ibl.js +17 -17
- package/src/shade/renderer/rasterize/{native/oit → forward}/chunk_material_side_should_draw.d.ts +1 -1
- package/src/shade/renderer/rasterize/forward/chunk_material_side_should_draw.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/{native/oit → forward}/chunk_material_side_should_draw.js +2 -2
- package/src/shade/renderer/rasterize/forward/vertex_shader_chunk.d.ts +3 -0
- package/src/shade/renderer/rasterize/forward/vertex_shader_chunk.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/{native/oit → forward}/vertex_shader_chunk.js +4 -4
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSettings.d.ts +27 -0
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSettings.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSettings.js +27 -0
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_CONSTANTS.d.ts +107 -0
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_CONSTANTS.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_CONSTANTS.js +120 -0
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_LEDGER.md +463 -0
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +509 -0
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_WARP_STRUCT.d.ts +15 -0
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_WARP_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_WARP_STRUCT.js +33 -0
- package/src/shade/renderer/rasterize/native/avboit/avboit_build_depth_curve.d.ts +20 -0
- package/src/shade/renderer/rasterize/native/avboit/avboit_build_depth_curve.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/avboit_build_depth_curve.js +38 -0
- package/src/shade/renderer/rasterize/native/avboit/avboit_draw_fragment_body.d.ts +38 -0
- package/src/shade/renderer/rasterize/native/avboit/avboit_draw_fragment_body.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/avboit_draw_fragment_body.js +130 -0
- package/src/shade/renderer/rasterize/native/avboit/avboit_spec_support.d.ts +37 -0
- package/src/shade/renderer/rasterize/native/avboit/avboit_spec_support.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/avboit_spec_support.js +73 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_counts_to_extinction.d.ts +9 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_counts_to_extinction.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_counts_to_extinction.js +17 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_dilate_word.d.ts +11 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_dilate_word.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_dilate_word.js +18 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_extinction_to_counts.d.ts +9 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_extinction_to_counts.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_extinction_to_counts.js +17 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_extinction_to_transmittance.d.ts +9 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_extinction_to_transmittance.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_extinction_to_transmittance.js +17 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_fold_pairs.d.ts +15 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_fold_pairs.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_fold_pairs.js +25 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_integral_depth_coordinate.d.ts +17 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_integral_depth_coordinate.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_integral_depth_coordinate.js +35 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_occupancy_range.d.ts +11 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_occupancy_range.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_occupancy_range.js +21 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_occupancy_word_mask.d.ts +9 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_occupancy_word_mask.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_occupancy_word_mask.js +26 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_overflows.d.ts +11 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_overflows.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_overflows.js +22 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_pack_counts.d.ts +10 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_pack_counts.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_pack_counts.js +21 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_sample_transmittance.d.ts +10 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_sample_transmittance.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_sample_transmittance.js +32 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_transmission_tint.d.ts +20 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_transmission_tint.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_transmission_tint.js +27 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_transmittance_to_extinction.d.ts +10 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_transmittance_to_extinction.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_transmittance_to_extinction.js +18 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_unpack_counts.d.ts +9 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_unpack_counts.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_unpack_counts.js +21 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_view_depth_to_physical.d.ts +9 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_view_depth_to_physical.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_view_depth_to_physical.js +23 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_view_depth_to_virtual.d.ts +13 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_view_depth_to_virtual.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_view_depth_to_virtual.js +27 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_warp.d.ts +22 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_warp.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_warp.js +38 -0
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts +117 -0
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +935 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_build_warp.d.ts +8 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_build_warp.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_build_warp.js +135 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_brick4.d.ts +3 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_brick4.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_brick4.js +101 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_ibl.d.ts +3 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_ibl.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_ibl.js +96 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_integrate.d.ts +3 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_integrate.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_integrate.js +83 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_occupancy.d.ts +9 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_occupancy.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_occupancy.js +119 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_resolve.d.ts +3 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_resolve.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_resolve.js +81 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.d.ts +15 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.js +237 -0
- package/src/shade/renderer/rasterize/native/material_draw_indirect.d.ts +22 -0
- package/src/shade/renderer/rasterize/native/material_draw_indirect.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/material_draw_indirect.js +69 -0
- package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +665 -722
- package/src/shade/renderer/rasterize/native/oit/shader_oit_generate_moments.js +3 -3
- package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments.js +4 -4
- package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +4 -4
- package/src/shade/renderer/rasterize/native/oit/FORWARD_VERTEX_SHADER_STRUCT.d.ts +0 -3
- package/src/shade/renderer/rasterize/native/oit/FORWARD_VERTEX_SHADER_STRUCT.d.ts.map +0 -1
- package/src/shade/renderer/rasterize/native/oit/SHADING_SCENE_RESOURCE_GROUP.d.ts +0 -3
- package/src/shade/renderer/rasterize/native/oit/SHADING_SCENE_RESOURCE_GROUP.d.ts.map +0 -1
- package/src/shade/renderer/rasterize/native/oit/SHADING_SCENE_RESOURCE_GROUP.js +0 -17
- package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_brick4.d.ts.map +0 -1
- package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_ibl.d.ts.map +0 -1
- package/src/shade/renderer/rasterize/native/oit/chunk_material_side_should_draw.d.ts.map +0 -1
- package/src/shade/renderer/rasterize/native/oit/vertex_shader_chunk.d.ts +0 -3
- package/src/shade/renderer/rasterize/native/oit/vertex_shader_chunk.d.ts.map +0 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { chunk_is_nan } from "../../../shader/chunk/math/chunk_is_nan.js";
|
|
2
|
+
import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
|
|
3
|
+
import { ImageShader } from "../../../shader/ImageShader.js";
|
|
4
|
+
import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
|
|
5
|
+
import { ShaderDescriptor } from "../../../shader/ShaderDescriptor.js";
|
|
6
|
+
|
|
7
|
+
const resources = new ShaderResourceSetDescriptor();
|
|
8
|
+
resources.createGroup()
|
|
9
|
+
.addTexture("tScene")
|
|
10
|
+
.addTexture("tColor")
|
|
11
|
+
.addTexture("tNorm")
|
|
12
|
+
.addTexture("tExtinction")
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* AVBOIT resolve: composites the three draw accumulators over the scene colour (plan §3.9).
|
|
16
|
+
*
|
|
17
|
+
* Per channel:
|
|
18
|
+
*
|
|
19
|
+
* ```
|
|
20
|
+
* T_total = exp(-Σ extinction)
|
|
21
|
+
* norm = Σ norm > ε ? (1 - T_total) / Σ norm : 0
|
|
22
|
+
* out = scene × T_total + Σ color × norm
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* The total transmittance is RGB, which fixed-function blending cannot apply to the destination
|
|
26
|
+
* without dual-source blending, so this reads the scene colour and writes a fresh target rather than
|
|
27
|
+
* blending in place. A NaN in any accumulator drops the transparency for that pixel and keeps the
|
|
28
|
+
* scene, the same backstop the MBOIT blend carries.
|
|
29
|
+
*/
|
|
30
|
+
const body = CodeChunk.from(
|
|
31
|
+
//language=WGSL
|
|
32
|
+
`
|
|
33
|
+
@fragment
|
|
34
|
+
fn main(
|
|
35
|
+
@builtin(position) coord: vec4<f32>
|
|
36
|
+
) -> @location(0) vec4<f32> {
|
|
37
|
+
|
|
38
|
+
let coord_u = vec2<u32>(coord.xy);
|
|
39
|
+
|
|
40
|
+
let scene = textureLoad(tScene, coord_u, 0);
|
|
41
|
+
|
|
42
|
+
let accum_color = textureLoad(tColor, coord_u, 0).rgb;
|
|
43
|
+
let accum_norm = textureLoad(tNorm, coord_u, 0).rgb;
|
|
44
|
+
let accum_extinction = textureLoad(tExtinction, coord_u, 0).rgb;
|
|
45
|
+
|
|
46
|
+
if (is_nan(accum_color.r) || is_nan(accum_norm.r) || is_nan(accum_extinction.r)) {
|
|
47
|
+
// one NaN fragment poisons the whole pixel of an additive accumulator; keeping the opaque
|
|
48
|
+
// scene beats smearing NaN into the frame
|
|
49
|
+
return scene;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let total_transmittance = exp(-accum_extinction);
|
|
53
|
+
|
|
54
|
+
// sum of (1 - T_self) * T at each fragment; zero where nothing transparent was drawn
|
|
55
|
+
let safe = accum_norm > vec3<f32>(1e-4);
|
|
56
|
+
let renormalization = select(
|
|
57
|
+
vec3<f32>(0.0),
|
|
58
|
+
(vec3<f32>(1.0) - total_transmittance) / max(accum_norm, vec3<f32>(1e-4)),
|
|
59
|
+
safe
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
let transparent = accum_color * renormalization;
|
|
63
|
+
|
|
64
|
+
return vec4<f32>(scene.rgb * total_transmittance + transparent, scene.a);
|
|
65
|
+
}
|
|
66
|
+
`, [
|
|
67
|
+
chunk_is_nan
|
|
68
|
+
]
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
export const shader_avboit_resolve = ImageShader.from({
|
|
72
|
+
descriptor: ShaderDescriptor.from({
|
|
73
|
+
label: "AVBOIT / resolve",
|
|
74
|
+
resources,
|
|
75
|
+
body,
|
|
76
|
+
}),
|
|
77
|
+
targets: [{
|
|
78
|
+
label: "AVBOIT composited",
|
|
79
|
+
format: "rgba16float",
|
|
80
|
+
}]
|
|
81
|
+
})
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bind group index of the atomics the splat writes; the three below it are the rasterization
|
|
3
|
+
* path's fixed material / scene / view slots.
|
|
4
|
+
* @type {number}
|
|
5
|
+
*/
|
|
6
|
+
export const AVBOIT_SPLAT_BIND_GROUP_VOLUME: number;
|
|
7
|
+
/**
|
|
8
|
+
* Format of the attachment the splat pass rasterizes against. It is never written (`writeMask: 0`);
|
|
9
|
+
* WebGPU requires at least one attachment and this is the cheapest one.
|
|
10
|
+
* @type {GPUTextureFormat}
|
|
11
|
+
*/
|
|
12
|
+
export const AVBOIT_SPLAT_DUMMY_FORMAT: GPUTextureFormat;
|
|
13
|
+
export const shader_avboit_splat: RenderPassDescriptor;
|
|
14
|
+
import { RenderPassDescriptor } from "../../../shader/pass/RenderPassDescriptor.js";
|
|
15
|
+
//# sourceMappingURL=shader_avboit_splat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shader_avboit_splat.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.js"],"names":[],"mappings":"AA4BA;;;;GAIG;AACH,6CAFU,MAAM,CAEgC;AAEhD;;;;GAIG;AACH,yDAAmD;AA6LnD,uDAA8D;qCAzNzB,8CAA8C"}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { PipelineLayoutDescriptor } from "../../../../descriptor/pipeline/PipelineLayoutDescriptor.js";
|
|
2
|
+
import { RenderPipelineDescriptor } from "../../../../descriptor/pipeline/render/RenderPipelineDescriptor.js";
|
|
3
|
+
import { atomic_u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
4
|
+
import { WebGPUArray } from "../../../shader/type/WebGPUArray.js";
|
|
5
|
+
import { CAMERA_UNIFORM_STRUCT } from "../../../camera/CAMERA_UNIFORM_STRUCT.js";
|
|
6
|
+
import { SHADING_MATERIAL_RESOURCE_GROUP } from "../../../material/standard/SHADING_MATERIAL_RESOURCE_GROUP.js";
|
|
7
|
+
import { chunk_F_Hauber } from "../../../shader/chunk/brdf/fresnel/chunk_F_Hauber.js";
|
|
8
|
+
import { chunk_get_view_space_depth } from "../../../shader/chunk/depth/chunk_get_view_space_depth.js";
|
|
9
|
+
import { chunk_mat4_extract_position } from "../../../shader/chunk/geometry/mat4/chunk_mat4_extract_position.js";
|
|
10
|
+
import { chunk_dielectric_specular_color } from "../../../shader/chunk/material/chunk_dielectric_specular_color.js";
|
|
11
|
+
import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
|
|
12
|
+
import { RenderPassColorAttachmentDescriptor } from "../../../shader/pass/RenderPassColorAttachmentDescriptor.js";
|
|
13
|
+
import { RenderPassDescriptor } from "../../../shader/pass/RenderPassDescriptor.js";
|
|
14
|
+
import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
|
|
15
|
+
import { ShaderDescriptor } from "../../../shader/ShaderDescriptor.js";
|
|
16
|
+
import { FORWARD_VERTEX_SHADER_STRUCT } from "../../forward/FORWARD_VERTEX_SHADER_STRUCT.js";
|
|
17
|
+
import { SHADING_SCENE_RESOURCE_GROUP } from "../../forward/SHADING_SCENE_RESOURCE_GROUP.js";
|
|
18
|
+
import { vertex_shader_chunk } from "../../forward/vertex_shader_chunk.js";
|
|
19
|
+
import { OIT_COVERAGE_MAX } from "../oit/OIT_CONSTANTS.js";
|
|
20
|
+
import { rasterization_primitive_state } from "../rasterization_primitive_state.js";
|
|
21
|
+
import { AVBOIT_WARP_STRUCT } from "./AVBOIT_WARP_STRUCT.js";
|
|
22
|
+
import { chunk_avboit_extinction_to_counts } from "./chunk_avboit_extinction_to_counts.js";
|
|
23
|
+
import { chunk_avboit_overflows } from "./chunk_avboit_overflows.js";
|
|
24
|
+
import { chunk_avboit_pack_counts } from "./chunk_avboit_pack_counts.js";
|
|
25
|
+
import { chunk_avboit_transmission_tint } from "./chunk_avboit_transmission_tint.js";
|
|
26
|
+
import { chunk_avboit_transmittance_to_extinction } from "./chunk_avboit_transmittance_to_extinction.js";
|
|
27
|
+
import { chunk_avboit_view_depth_to_physical } from "./chunk_avboit_view_depth_to_physical.js";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Bind group index of the atomics the splat writes; the three below it are the rasterization
|
|
31
|
+
* path's fixed material / scene / view slots.
|
|
32
|
+
* @type {number}
|
|
33
|
+
*/
|
|
34
|
+
export const AVBOIT_SPLAT_BIND_GROUP_VOLUME = 3;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Format of the attachment the splat pass rasterizes against. It is never written (`writeMask: 0`);
|
|
38
|
+
* WebGPU requires at least one attachment and this is the cheapest one.
|
|
39
|
+
* @type {GPUTextureFormat}
|
|
40
|
+
*/
|
|
41
|
+
export const AVBOIT_SPLAT_DUMMY_FORMAT = "r8unorm";
|
|
42
|
+
|
|
43
|
+
const resources = new ShaderResourceSetDescriptor();
|
|
44
|
+
|
|
45
|
+
resources.addGroup(SHADING_MATERIAL_RESOURCE_GROUP);
|
|
46
|
+
resources.addGroup(SHADING_SCENE_RESOURCE_GROUP);
|
|
47
|
+
|
|
48
|
+
resources.createGroup()
|
|
49
|
+
.addUniform("camera", CAMERA_UNIFORM_STRUCT)
|
|
50
|
+
.addStorageBuffer("warp", AVBOIT_WARP_STRUCT)
|
|
51
|
+
;
|
|
52
|
+
|
|
53
|
+
resources.createGroup()
|
|
54
|
+
.addStorageBuffer("extinction_volume", WebGPUArray.from(atomic_u32), true)
|
|
55
|
+
.addStorageBuffer("overflow_slice", WebGPUArray.from(atomic_u32), true)
|
|
56
|
+
;
|
|
57
|
+
|
|
58
|
+
const shader_vertex = ShaderDescriptor.from({
|
|
59
|
+
label: 'AVBOIT / splat vertex shader',
|
|
60
|
+
body: vertex_shader_chunk,
|
|
61
|
+
resources,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* AVBOIT splat: rasterizes the transparent buckets at 1/8 resolution and adds each fragment's RGB
|
|
66
|
+
* extinction into the voxel volume with atomics (plan §3.5).
|
|
67
|
+
*
|
|
68
|
+
* Coverage is computed the way `shader_oit_generate_moments` computes it — texture alpha, or the
|
|
69
|
+
* view-angle Fresnel when the material transmits — and then, new to this path, a per-channel
|
|
70
|
+
* self-transmittance: `(1 - coverage) × tint`, with `tint` the base colour weighted by
|
|
71
|
+
* `transmission_factor` — but only while `AVBOITSettings.transmission_tint_from_base_color` is on,
|
|
72
|
+
* which the warp header carries. A plain alpha-blended material lands exactly where it would under
|
|
73
|
+
* MBOIT (`tint = 1`), and so does glass unless the tint is opted into.
|
|
74
|
+
*
|
|
75
|
+
* Depth goes view-space → curve → warp → physical, and the extinction is linear-splat between the
|
|
76
|
+
* two physical slices around it (`c = p - 0.5`) so a surface crossing a slice boundary does not
|
|
77
|
+
* alias. A field that crosses 255 with this add records the slice in the per-channel overflow
|
|
78
|
+
* plane — stored as `P - slice` under `atomicMax`, so the buffer's zero clear reads as "none" and
|
|
79
|
+
* the nearest overflow wins.
|
|
80
|
+
*
|
|
81
|
+
* No depth attachment: a splat behind opaque geometry lies deeper than any visible transparent
|
|
82
|
+
* fragment and the integral at a depth only contains what is in front of it. No TAA un-jitter: the
|
|
83
|
+
* jitter is expressed in internal-resolution pixels and the derivative-based correction would be
|
|
84
|
+
* eight times too large here.
|
|
85
|
+
*/
|
|
86
|
+
const fragment_body = CodeChunk.from(
|
|
87
|
+
//language=WGSL
|
|
88
|
+
`
|
|
89
|
+
fn avboit_splat_slice(column: u32, slice: i32, extinction: vec3<f32>, texel: vec2<u32>) {
|
|
90
|
+
let physical = i32(warp.physical_count);
|
|
91
|
+
let s = clamp(slice, 0, physical - 1);
|
|
92
|
+
|
|
93
|
+
let counts = avboit_extinction_to_counts(extinction);
|
|
94
|
+
|
|
95
|
+
if (all(counts == vec3<u32>(0u))) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let previous = atomicAdd(&extinction_volume[column + u32(s)], avboit_pack_counts(counts));
|
|
100
|
+
|
|
101
|
+
let overflow = avboit_overflows(previous, counts);
|
|
102
|
+
|
|
103
|
+
if (any(overflow)) {
|
|
104
|
+
let base = (texel.y * warp.voxel_width + texel.x) * 3u;
|
|
105
|
+
// inverted so that the zero-cleared buffer means "no overflow" and max keeps the nearest
|
|
106
|
+
let mark = u32(physical - s);
|
|
107
|
+
if (overflow.x) {
|
|
108
|
+
atomicMax(&overflow_slice[base], mark);
|
|
109
|
+
}
|
|
110
|
+
if (overflow.y) {
|
|
111
|
+
atomicMax(&overflow_slice[base + 1u], mark);
|
|
112
|
+
}
|
|
113
|
+
if (overflow.z) {
|
|
114
|
+
atomicMax(&overflow_slice[base + 2u], mark);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@fragment
|
|
120
|
+
fn main(
|
|
121
|
+
@builtin(front_facing) front_facing : bool,
|
|
122
|
+
vert: ${FORWARD_VERTEX_SHADER_STRUCT.wgsl_ref},
|
|
123
|
+
) {
|
|
124
|
+
let uv = vert.uv;
|
|
125
|
+
|
|
126
|
+
let t_diffuse = textureSample(texture_diffuse, texture_diffuse_sampler, uv);
|
|
127
|
+
let surface_alpha = t_diffuse.a * material_info.albedo_color.a;
|
|
128
|
+
|
|
129
|
+
var opacity = surface_alpha;
|
|
130
|
+
var tint = vec3<f32>(1.0);
|
|
131
|
+
|
|
132
|
+
let f_transmission = material_info.transmission_factor;
|
|
133
|
+
if (f_transmission > 0.0) {
|
|
134
|
+
let t_pbr = textureSample(texture_orm, texture_orm_sampler, uv);
|
|
135
|
+
// undo premultiplication; vert.color already carries the material's albedo colour
|
|
136
|
+
let base_color = (t_diffuse.rgb / max(t_diffuse.a, 1e-7)) * vert.color;
|
|
137
|
+
let f_metalness = t_pbr.b * material_info.metallic_factor;
|
|
138
|
+
let specular_f0 = dielectric_specular_color(material_info.ior_factor, f_metalness, base_color);
|
|
139
|
+
|
|
140
|
+
let view_position = mat4_extract_position(camera.transform);
|
|
141
|
+
let view_direction = normalize(view_position - vert.position_ws);
|
|
142
|
+
let nov = saturate(abs(dot(normalize(vert.normal), view_direction)));
|
|
143
|
+
let f_view = F_Hauber(specular_f0, 1.0, nov);
|
|
144
|
+
let f_scalar = max(f_view.r, max(f_view.g, f_view.b));
|
|
145
|
+
|
|
146
|
+
opacity = mix(surface_alpha, f_scalar, f_transmission);
|
|
147
|
+
// what the surface lets through is coloured by what it is made of, when the renderer says
|
|
148
|
+
// so (AVBOITSettings.transmission_tint_from_base_color, carried in the warp header)
|
|
149
|
+
tint = avboit_transmission_tint(base_color, f_transmission * f32(warp.tint_from_base_color));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
let coverage = min(opacity, ${OIT_COVERAGE_MAX});
|
|
153
|
+
let transmittance = (1.0 - coverage) * tint;
|
|
154
|
+
let extinction = avboit_transmittance_to_extinction(transmittance);
|
|
155
|
+
|
|
156
|
+
// vert.position is @builtin(position): .z is device depth, .xy the low-resolution pixel
|
|
157
|
+
let z_view = get_view_space_depth(vert.position.z, camera);
|
|
158
|
+
let p = avboit_view_depth_to_physical(&warp, z_view);
|
|
159
|
+
|
|
160
|
+
let texel = vec2<u32>(vert.position.xy);
|
|
161
|
+
let column = (texel.y * warp.voxel_width + texel.x) * warp.physical_count;
|
|
162
|
+
|
|
163
|
+
// linear splat between the two slices around the fragment
|
|
164
|
+
let c = p - 0.5;
|
|
165
|
+
let slice = i32(floor(c));
|
|
166
|
+
let fraction = c - floor(c);
|
|
167
|
+
|
|
168
|
+
avboit_splat_slice(column, slice, extinction * (1.0 - fraction), texel);
|
|
169
|
+
avboit_splat_slice(column, slice + 1, extinction * fraction, texel);
|
|
170
|
+
}
|
|
171
|
+
`, [
|
|
172
|
+
FORWARD_VERTEX_SHADER_STRUCT.declaration_chunk,
|
|
173
|
+
chunk_get_view_space_depth,
|
|
174
|
+
chunk_mat4_extract_position,
|
|
175
|
+
chunk_dielectric_specular_color,
|
|
176
|
+
chunk_F_Hauber,
|
|
177
|
+
chunk_avboit_extinction_to_counts,
|
|
178
|
+
chunk_avboit_overflows,
|
|
179
|
+
chunk_avboit_pack_counts,
|
|
180
|
+
chunk_avboit_transmission_tint,
|
|
181
|
+
chunk_avboit_transmittance_to_extinction,
|
|
182
|
+
chunk_avboit_view_depth_to_physical,
|
|
183
|
+
]
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
const shader_fragment = ShaderDescriptor.from({
|
|
187
|
+
label: "AVBOIT / splat",
|
|
188
|
+
resources,
|
|
189
|
+
body: fragment_body
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
/*
|
|
193
|
+
The pipeline layout is built group by group rather than with `generatePipelineLayout(stage)`, which
|
|
194
|
+
gives every group the same visibility: WebGPU refuses a read-write storage buffer that is visible to
|
|
195
|
+
the vertex stage, and the atomics group is fragment-only. The first three groups keep the
|
|
196
|
+
rasterization path's `VERTEX | FRAGMENT`, which is what the bind groups the orchestrator builds
|
|
197
|
+
against `SHADING_*_RESOURCE_GROUP` are laid out for.
|
|
198
|
+
*/
|
|
199
|
+
const groups = resources.groups;
|
|
200
|
+
const layout = PipelineLayoutDescriptor.from([
|
|
201
|
+
groups[0].generateBindGroupLayoutDescriptor(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
|
|
202
|
+
groups[1].generateBindGroupLayoutDescriptor(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
|
|
203
|
+
groups[2].generateBindGroupLayoutDescriptor(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
|
|
204
|
+
groups[AVBOIT_SPLAT_BIND_GROUP_VOLUME].generateBindGroupLayoutDescriptor(GPUShaderStage.FRAGMENT),
|
|
205
|
+
], resources.immediateSize);
|
|
206
|
+
|
|
207
|
+
const pipeline = RenderPipelineDescriptor.from({
|
|
208
|
+
label: "AVBOIT / splat",
|
|
209
|
+
layout,
|
|
210
|
+
vertex: {
|
|
211
|
+
module: {
|
|
212
|
+
code: shader_vertex.source
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
fragment: {
|
|
216
|
+
module: {
|
|
217
|
+
code: shader_fragment.source
|
|
218
|
+
},
|
|
219
|
+
targets: [
|
|
220
|
+
// never written; see AVBOIT_SPLAT_DUMMY_FORMAT
|
|
221
|
+
{
|
|
222
|
+
format: AVBOIT_SPLAT_DUMMY_FORMAT,
|
|
223
|
+
writeMask: 0,
|
|
224
|
+
}
|
|
225
|
+
]
|
|
226
|
+
},
|
|
227
|
+
primitive: rasterization_primitive_state,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
export const shader_avboit_splat = new RenderPassDescriptor();
|
|
231
|
+
shader_avboit_splat.pipeline = pipeline;
|
|
232
|
+
shader_avboit_splat.resources = resources;
|
|
233
|
+
shader_avboit_splat.colorAttachments = [
|
|
234
|
+
RenderPassColorAttachmentDescriptor.from({
|
|
235
|
+
clearValue: [0, 0, 0, 0],
|
|
236
|
+
}),
|
|
237
|
+
];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One indirect draw per material out of a command buffer built by
|
|
3
|
+
* `graph_prepare_meshlet_draw_commands_by_material`, with the material's bind group at slot 0.
|
|
4
|
+
* Materials whose GPU side is not built yet are skipped. Shared by the MBOIT and AVBOIT
|
|
5
|
+
* orchestrators, which call it once per render pass they record.
|
|
6
|
+
*
|
|
7
|
+
* @param {GPUMaterialManager} material_manager
|
|
8
|
+
* @param {number} material_count
|
|
9
|
+
* @param {ShadeMaterial[]} materials
|
|
10
|
+
* @param {RenderPassDescriptor} render_pass_descriptor its group 0 is the material group
|
|
11
|
+
* @param {BindGroupManager} bind_manager
|
|
12
|
+
* @param {ShadeGPURenderPassEncoder} pass_encoder
|
|
13
|
+
* @param {GPUBuffer} command_buffer_draw one `STRUCT_UNINDEXED_DRAW_COMMAND` per material, in order
|
|
14
|
+
*/
|
|
15
|
+
export function material_draw_indirect(material_manager: GPUMaterialManager, material_count: number, materials: ShadeMaterial[], render_pass_descriptor: RenderPassDescriptor, bind_manager: BindGroupManager, pass_encoder: ShadeGPURenderPassEncoder, command_buffer_draw: GPUBuffer): void;
|
|
16
|
+
/**
|
|
17
|
+
* The material bind group layout every transparent draw binds at slot 0; hoisted so it is computed
|
|
18
|
+
* once and so the two transparency pipelines cannot disagree on it.
|
|
19
|
+
* @type {BindGroupLayoutDescriptor}
|
|
20
|
+
*/
|
|
21
|
+
export const BIND_GROUP_LAYOUT_MATERIAL: BindGroupLayoutDescriptor;
|
|
22
|
+
//# sourceMappingURL=material_draw_indirect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"material_draw_indirect.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/rasterize/native/material_draw_indirect.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;GAaG;AACH,6FAPW,MAAM,aACN,eAAe,+JA8CzB;AA7DD;;;;GAIG;AACH,mEAA6J"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
2
|
+
import { STRUCT_UNINDEXED_DRAW_COMMAND } from "../../gpu_primitive/indirect/STRUCT_UNINDEXED_DRAW_COMMAND.js";
|
|
3
|
+
import { BindGroupDescriptor } from "../../binding/BindGroupDescriptor.js";
|
|
4
|
+
import { SHADING_MATERIAL_RESOURCE_GROUP } from "../../material/standard/SHADING_MATERIAL_RESOURCE_GROUP.js";
|
|
5
|
+
|
|
6
|
+
const DRAW_COMMAND_BYTE_SIZE = STRUCT_UNINDEXED_DRAW_COMMAND.aligned_size;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The material bind group layout every transparent draw binds at slot 0; hoisted so it is computed
|
|
10
|
+
* once and so the two transparency pipelines cannot disagree on it.
|
|
11
|
+
* @type {BindGroupLayoutDescriptor}
|
|
12
|
+
*/
|
|
13
|
+
export const BIND_GROUP_LAYOUT_MATERIAL = SHADING_MATERIAL_RESOURCE_GROUP.generateBindGroupLayoutDescriptor(GPUShaderStage.FRAGMENT | GPUShaderStage.VERTEX);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* One indirect draw per material out of a command buffer built by
|
|
17
|
+
* `graph_prepare_meshlet_draw_commands_by_material`, with the material's bind group at slot 0.
|
|
18
|
+
* Materials whose GPU side is not built yet are skipped. Shared by the MBOIT and AVBOIT
|
|
19
|
+
* orchestrators, which call it once per render pass they record.
|
|
20
|
+
*
|
|
21
|
+
* @param {GPUMaterialManager} material_manager
|
|
22
|
+
* @param {number} material_count
|
|
23
|
+
* @param {ShadeMaterial[]} materials
|
|
24
|
+
* @param {RenderPassDescriptor} render_pass_descriptor its group 0 is the material group
|
|
25
|
+
* @param {BindGroupManager} bind_manager
|
|
26
|
+
* @param {ShadeGPURenderPassEncoder} pass_encoder
|
|
27
|
+
* @param {GPUBuffer} command_buffer_draw one `STRUCT_UNINDEXED_DRAW_COMMAND` per material, in order
|
|
28
|
+
*/
|
|
29
|
+
export function material_draw_indirect(
|
|
30
|
+
material_manager,
|
|
31
|
+
material_count,
|
|
32
|
+
materials,
|
|
33
|
+
render_pass_descriptor,
|
|
34
|
+
bind_manager,
|
|
35
|
+
pass_encoder,
|
|
36
|
+
command_buffer_draw
|
|
37
|
+
) {
|
|
38
|
+
|
|
39
|
+
assert.defined(material_manager, 'material_manager');
|
|
40
|
+
assert.isNonNegativeInteger(material_count, 'material_count');
|
|
41
|
+
assert.isArray(materials, 'materials');
|
|
42
|
+
|
|
43
|
+
for (let i = 0; i < material_count; i++) {
|
|
44
|
+
|
|
45
|
+
const material = materials[i];
|
|
46
|
+
const gpu_material = material_manager.obtain(material);
|
|
47
|
+
|
|
48
|
+
if (!gpu_material.is_built) {
|
|
49
|
+
// skip, not ready for rendering
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const material_resource_group = render_pass_descriptor.resources.groups[0];
|
|
54
|
+
const binding_entries = material_resource_group.generateBindings(gpu_material.binding_data);
|
|
55
|
+
const material_bindings = bind_manager.obtain(BindGroupDescriptor.from(
|
|
56
|
+
BIND_GROUP_LAYOUT_MATERIAL,
|
|
57
|
+
binding_entries
|
|
58
|
+
));
|
|
59
|
+
|
|
60
|
+
// set material-specific bind group at 0
|
|
61
|
+
pass_encoder.setBindGroup(0, material_bindings)
|
|
62
|
+
|
|
63
|
+
pass_encoder.drawIndirect(
|
|
64
|
+
command_buffer_draw,
|
|
65
|
+
i * DRAW_COMMAND_BYTE_SIZE,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
}
|
package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph_rasterize_meshes_transparent_oit.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"graph_rasterize_meshes_transparent_oit.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js"],"names":[],"mappings":"AAoaA;;;;;;;;;;;;;;;;GAgBG;AACH,uSAFa,MAAM,CAsOlB"}
|