@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
package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js
ADDED
|
@@ -0,0 +1,935 @@
|
|
|
1
|
+
import { assert } from "../../../../../core/assert.js";
|
|
2
|
+
import { SamplerDescriptor } from "../../../../descriptor/texture/SamplerDescriptor.js";
|
|
3
|
+
import { BufferResourceDescriptor } from "../../../../device/graph/BufferResourceDescriptor.js";
|
|
4
|
+
import { TextureResourceDescriptor } from "../../../../device/graph/TextureResourceDescriptor.js";
|
|
5
|
+
import { rp_rewrite_for_primitive_state } from "../../../../device/pipeline/rp_rewrite_for_primitive_state.js";
|
|
6
|
+
import { BindGroupDescriptor } from "../../../binding/BindGroupDescriptor.js";
|
|
7
|
+
import { SHADING_LIGHT_RESOURCE_GROUP } from "../../../deferred/SHADING_LIGHT_RESOURCE_GROUP.js";
|
|
8
|
+
import { ShadeDrawMode } from "../../../material/ShadeDrawMode.js";
|
|
9
|
+
import { ShadeDrawSide } from "../../../material/ShadeDrawSide.js";
|
|
10
|
+
import { TransparencyMode } from "../../../material/TransparencyMode.js";
|
|
11
|
+
import { ShadeIndirectLightingMode } from "../../../ShadeIndirectLightingMode.js";
|
|
12
|
+
import { graph_compute_pass } from "../../../shader/graph/compute/graph_compute_pass.js";
|
|
13
|
+
import { graph_image_pass } from "../../../shader/graph/graph_image_pass.js";
|
|
14
|
+
import { graph_import_buffer } from "../../../shader/graph/graph_import_buffer.js";
|
|
15
|
+
import { graph_import_texture } from "../../../shader/graph/graph_import_texture.js";
|
|
16
|
+
import {
|
|
17
|
+
SHADOWMAP_COMPARE_SAMPLER_DESCRIPTOR
|
|
18
|
+
} from "../../../shadow/map/SHADOWMAP_COMPARE_SAMPLER_DESCRIPTOR.js";
|
|
19
|
+
import { STATIC_GRAPHICS_ENGINE_ASSETS } from "../../../STATIC_GRAPHICS_ENGINE_ASSETS.js";
|
|
20
|
+
import { rasterization_material_bucket } from "../../expand/bucket/chunk_rasterization_material_bucket.js";
|
|
21
|
+
import { construct_primitive_state } from "../../bucket/construct_primitive_state.js";
|
|
22
|
+
import { filter_materials_by_bucket } from "../../bucket/filter_materials_by_bucket.js";
|
|
23
|
+
import {
|
|
24
|
+
graph_prepare_meshlet_draw_commands_by_material
|
|
25
|
+
} from "../../bucket/prepare_meshlet_draw_commands_by_material.js";
|
|
26
|
+
import { SHADING_SCENE_RESOURCE_GROUP } from "../../forward/SHADING_SCENE_RESOURCE_GROUP.js";
|
|
27
|
+
import {
|
|
28
|
+
RASTERIZATION_SHADER_BIND_GROUP_SCENE,
|
|
29
|
+
RASTERIZATION_SHADER_BIND_GROUP_VIEW
|
|
30
|
+
} from "../alpha_tested_pass_resources.js";
|
|
31
|
+
import { material_draw_indirect } from "../material_draw_indirect.js";
|
|
32
|
+
import {
|
|
33
|
+
AVBOIT_INTEGRAL_FORMAT,
|
|
34
|
+
AVBOIT_INTEGRATE_WORKGROUP_SIZE,
|
|
35
|
+
AVBOIT_OCCUPANCY_WORDS,
|
|
36
|
+
AVBOIT_PHYSICAL_SLICES,
|
|
37
|
+
AVBOIT_VOXEL_DOWNSCALE
|
|
38
|
+
} from "./AVBOIT_CONSTANTS.js";
|
|
39
|
+
import { avboit_build_depth_curve } from "./avboit_build_depth_curve.js";
|
|
40
|
+
import { AVBOITSettings } from "./AVBOITSettings.js";
|
|
41
|
+
import { AVBOIT_WARP_STRUCT } from "./AVBOIT_WARP_STRUCT.js";
|
|
42
|
+
import { AVBOIT_BUILD_WARP_SETTINGS_STRUCT, shader_avboit_build_warp } from "./shader_avboit_build_warp.js";
|
|
43
|
+
import { shader_avboit_draw_brick4 } from "./shader_avboit_draw_brick4.js";
|
|
44
|
+
import { shader_avboit_draw_ibl } from "./shader_avboit_draw_ibl.js";
|
|
45
|
+
import { shader_avboit_integrate } from "./shader_avboit_integrate.js";
|
|
46
|
+
import { AVBOIT_OCCUPANCY_SETTINGS_STRUCT, shader_avboit_occupancy } from "./shader_avboit_occupancy.js";
|
|
47
|
+
import { shader_avboit_resolve } from "./shader_avboit_resolve.js";
|
|
48
|
+
import {
|
|
49
|
+
AVBOIT_SPLAT_BIND_GROUP_VOLUME,
|
|
50
|
+
AVBOIT_SPLAT_DUMMY_FORMAT,
|
|
51
|
+
shader_avboit_splat
|
|
52
|
+
} from "./shader_avboit_splat.js";
|
|
53
|
+
|
|
54
|
+
const BIND_GROUP_LAYOUT_SCENE = SHADING_SCENE_RESOURCE_GROUP.generateBindGroupLayoutDescriptor(GPUShaderStage.FRAGMENT | GPUShaderStage.VERTEX);
|
|
55
|
+
const BIND_GROUP_LAYOUT_LIGHT = SHADING_LIGHT_RESOURCE_GROUP.generateBindGroupLayoutDescriptor(GPUShaderStage.FRAGMENT | GPUShaderStage.VERTEX);
|
|
56
|
+
|
|
57
|
+
const WARP_BUFFER_SIZE = AVBOIT_WARP_STRUCT.size;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* What a caller that passes no settings gets: every switch at its documented default.
|
|
61
|
+
* @type {AVBOITSettings}
|
|
62
|
+
*/
|
|
63
|
+
const DEFAULT_SETTINGS = new AVBOITSettings();
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Extinction volume XY resolution for an internal resolution.
|
|
67
|
+
*
|
|
68
|
+
* @param {ArrayLike<number>} resolution
|
|
69
|
+
* @returns {number[]}
|
|
70
|
+
*/
|
|
71
|
+
export function avboit_voxel_resolution(resolution) {
|
|
72
|
+
return [
|
|
73
|
+
Math.max(1, Math.ceil(resolution[0] / AVBOIT_VOXEL_DOWNSCALE)),
|
|
74
|
+
Math.max(1, Math.ceil(resolution[1] / AVBOIT_VOXEL_DOWNSCALE)),
|
|
75
|
+
];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Occupancy prepass over one bucket's HZB-filtered meshlets (plan §3.3).
|
|
80
|
+
*
|
|
81
|
+
* @param {FrameGraph} graph
|
|
82
|
+
* @param {GPUSceneContext} scene
|
|
83
|
+
* @param {number} camera resource ID
|
|
84
|
+
* @param {ArrayLike<number>} cluster_parameters the depth curve, see avboit_build_depth_curve
|
|
85
|
+
* @param {number} meshlet_collection resource ID, `MESHLET_COLLECTION_STRUCT` with its count header
|
|
86
|
+
* @param {number} meshlet_iterator_command resource ID, indirect dispatch over the collection
|
|
87
|
+
* @param {number} [occupancy] resource ID of an existing occupancy buffer to add to; created when -1
|
|
88
|
+
* @returns {number} resource ID of the occupancy bits
|
|
89
|
+
*/
|
|
90
|
+
export function graph_avboit_occupancy({
|
|
91
|
+
graph,
|
|
92
|
+
scene,
|
|
93
|
+
camera,
|
|
94
|
+
cluster_parameters,
|
|
95
|
+
meshlet_collection,
|
|
96
|
+
meshlet_iterator_command,
|
|
97
|
+
occupancy = -1,
|
|
98
|
+
}) {
|
|
99
|
+
|
|
100
|
+
assert.isNonNegativeInteger(camera, 'camera');
|
|
101
|
+
assert.isArrayLike(cluster_parameters, 'cluster_parameters');
|
|
102
|
+
assert.isNonNegativeInteger(meshlet_collection, 'meshlet_collection');
|
|
103
|
+
assert.isNonNegativeInteger(meshlet_iterator_command, 'meshlet_iterator_command');
|
|
104
|
+
|
|
105
|
+
const settings = { cluster_parameters };
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
*
|
|
109
|
+
* @param data
|
|
110
|
+
* @param {FramePassResources} resources
|
|
111
|
+
* @param {GraphicsExecutionContext} context
|
|
112
|
+
*/
|
|
113
|
+
function execute(data, resources, context) {
|
|
114
|
+
const encoder = context.encoder;
|
|
115
|
+
|
|
116
|
+
shader_avboit_occupancy.dispatchIndirect({
|
|
117
|
+
encoder,
|
|
118
|
+
command: resources.get(data.command),
|
|
119
|
+
bindings: {
|
|
120
|
+
camera: resources.get(data.camera),
|
|
121
|
+
settings: encoder.allocateTransientValueBuffer(AVBOIT_OCCUPANCY_SETTINGS_STRUCT, settings, GPUBufferUsage.UNIFORM),
|
|
122
|
+
scene_database: scene.scene_database_buffer,
|
|
123
|
+
meshlet_metadata: scene.geometries.meshlets.buffer_metadata,
|
|
124
|
+
input: resources.get(data.input),
|
|
125
|
+
occupancy: resources.get(data.occupancy),
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const pass_data = {};
|
|
131
|
+
const pass = graph.add("AVBOIT/occupancy", pass_data, execute);
|
|
132
|
+
|
|
133
|
+
pass_data.camera = pass.read(camera);
|
|
134
|
+
pass_data.input = pass.read(meshlet_collection);
|
|
135
|
+
pass_data.command = pass.read(meshlet_iterator_command);
|
|
136
|
+
|
|
137
|
+
if (occupancy !== -1) {
|
|
138
|
+
pass.read(occupancy);
|
|
139
|
+
pass_data.occupancy = pass.write(occupancy);
|
|
140
|
+
} else {
|
|
141
|
+
pass_data.occupancy = pass.create("AVBOIT occupancy", BufferResourceDescriptor.empty(
|
|
142
|
+
AVBOIT_OCCUPANCY_WORDS * 4,
|
|
143
|
+
GPUBufferUsage.STORAGE
|
|
144
|
+
));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return pass_data.occupancy;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* The depth-warp LUT from the occupancy bits (plan §3.4).
|
|
152
|
+
*
|
|
153
|
+
* @param {FrameGraph} graph
|
|
154
|
+
* @param {number} occupancy resource ID
|
|
155
|
+
* @param {number[]} voxel_resolution
|
|
156
|
+
* @param {ArrayLike<number>} cluster_parameters the depth curve, see avboit_build_depth_curve
|
|
157
|
+
* @param {AVBOITSettings} [avboit] the renderer's switches, carried into the header
|
|
158
|
+
* @returns {number} resource ID of the `AVBOIT_WARP_STRUCT` buffer
|
|
159
|
+
*/
|
|
160
|
+
export function graph_avboit_build_warp({
|
|
161
|
+
graph,
|
|
162
|
+
occupancy,
|
|
163
|
+
voxel_resolution,
|
|
164
|
+
cluster_parameters,
|
|
165
|
+
avboit = DEFAULT_SETTINGS,
|
|
166
|
+
}) {
|
|
167
|
+
|
|
168
|
+
assert.isNonNegativeInteger(occupancy, 'occupancy');
|
|
169
|
+
assert.isArrayLike(cluster_parameters, 'cluster_parameters');
|
|
170
|
+
|
|
171
|
+
const settings = {
|
|
172
|
+
physical_count: AVBOIT_PHYSICAL_SLICES,
|
|
173
|
+
voxel_width: voxel_resolution[0],
|
|
174
|
+
voxel_height: voxel_resolution[1],
|
|
175
|
+
tint_from_base_color: avboit.transmission_tint_from_base_color ? 1 : 0,
|
|
176
|
+
cluster_parameters,
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
*
|
|
181
|
+
* @param data
|
|
182
|
+
* @param {FramePassResources} resources
|
|
183
|
+
* @param {GraphicsExecutionContext} context
|
|
184
|
+
*/
|
|
185
|
+
function execute(data, resources, context) {
|
|
186
|
+
const encoder = context.encoder;
|
|
187
|
+
|
|
188
|
+
shader_avboit_build_warp.dispatch({
|
|
189
|
+
encoder,
|
|
190
|
+
bindings: {
|
|
191
|
+
// a few words per frame: a transient uniform, serialized from the plain object
|
|
192
|
+
settings: encoder.allocateTransientValueBuffer(AVBOIT_BUILD_WARP_SETTINGS_STRUCT, settings, GPUBufferUsage.UNIFORM),
|
|
193
|
+
occupancy: resources.get(data.occupancy),
|
|
194
|
+
warp: resources.get(data.warp),
|
|
195
|
+
},
|
|
196
|
+
group_count_x: 1,
|
|
197
|
+
group_count_y: 1,
|
|
198
|
+
group_count_z: 1,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Recorded by hand rather than through graph_compute_pass: the warp is a read_write storage
|
|
203
|
+
// buffer, which that helper treats as a managed input and will not create from a descriptor.
|
|
204
|
+
const pass_data = {};
|
|
205
|
+
const pass = graph.add("AVBOIT/build warp", pass_data, execute);
|
|
206
|
+
|
|
207
|
+
pass_data.occupancy = pass.read(occupancy);
|
|
208
|
+
// every entry that can be read is written; no clear
|
|
209
|
+
pass_data.warp = pass.create("AVBOIT warp", BufferResourceDescriptor.from(WARP_BUFFER_SIZE, GPUBufferUsage.STORAGE));
|
|
210
|
+
|
|
211
|
+
return pass_data.warp;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Splat one bucket's transparent draws into the extinction volume (plan §3.5).
|
|
216
|
+
*
|
|
217
|
+
* @param {FrameGraph} graph
|
|
218
|
+
* @param {GPUViewContext} view_ctx
|
|
219
|
+
* @param {number} material_count
|
|
220
|
+
* @param {ShadeMaterial[]} materials
|
|
221
|
+
* @param {number} draw_commands resource ID
|
|
222
|
+
* @param {number} meshlets resource ID
|
|
223
|
+
* @param {number} camera resource ID
|
|
224
|
+
* @param {number} warp resource ID
|
|
225
|
+
* @param {number[]} voxel_resolution
|
|
226
|
+
* @param {PrimitiveState} primitive
|
|
227
|
+
* @param {{extinction: number, overflow: number, dummy: number}} [volume] existing resources to add to
|
|
228
|
+
* @returns {{extinction: number, overflow: number, dummy: number}}
|
|
229
|
+
*/
|
|
230
|
+
export function graph_avboit_splat({
|
|
231
|
+
graph,
|
|
232
|
+
view_ctx,
|
|
233
|
+
material_count,
|
|
234
|
+
materials,
|
|
235
|
+
draw_commands,
|
|
236
|
+
meshlets,
|
|
237
|
+
camera,
|
|
238
|
+
warp,
|
|
239
|
+
voxel_resolution,
|
|
240
|
+
primitive,
|
|
241
|
+
volume,
|
|
242
|
+
}) {
|
|
243
|
+
|
|
244
|
+
assert.isNonNegativeInteger(material_count, 'material_count');
|
|
245
|
+
assert.isNonNegativeInteger(draw_commands, 'draw_commands');
|
|
246
|
+
assert.isNonNegativeInteger(meshlets, 'meshlets');
|
|
247
|
+
assert.isNonNegativeInteger(warp, 'warp');
|
|
248
|
+
|
|
249
|
+
const scene_ctx = view_ctx.scene;
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
*
|
|
253
|
+
* @param data
|
|
254
|
+
* @param {FramePassResources} resources
|
|
255
|
+
* @param {GraphicsExecutionContext} context
|
|
256
|
+
*/
|
|
257
|
+
function execute(data, resources, context) {
|
|
258
|
+
|
|
259
|
+
assert.ok(context.graphics.device.features.has("indirect-first-instance"), '"indirect-first-instance" feature needs to be enabled for non-zero firstInstance values to be used.')
|
|
260
|
+
|
|
261
|
+
const command_buffer_draw = resources.get(data.draw_commands);
|
|
262
|
+
const meshlet_buffer = resources.get(data.meshlets);
|
|
263
|
+
|
|
264
|
+
const camera_buffer = resources.get(data.camera);
|
|
265
|
+
const warp_buffer = resources.get(data.warp);
|
|
266
|
+
const extinction_buffer = resources.get(data.extinction);
|
|
267
|
+
const overflow_buffer = resources.get(data.overflow);
|
|
268
|
+
const t_dummy = resources.get(data.dummy);
|
|
269
|
+
|
|
270
|
+
const encoder = context.encoder;
|
|
271
|
+
const graphics = context.graphics;
|
|
272
|
+
const bind_manager = graphics.bind_groups;
|
|
273
|
+
|
|
274
|
+
const scene_bindings = bind_manager.obtain(BindGroupDescriptor.from(
|
|
275
|
+
BIND_GROUP_LAYOUT_SCENE,
|
|
276
|
+
[
|
|
277
|
+
{ buffer: meshlet_buffer },
|
|
278
|
+
{ buffer: scene_ctx.geometries.meshlets.buffer_metadata },
|
|
279
|
+
{ buffer: scene_ctx.geometries.meshlets.buffer_data },
|
|
280
|
+
{ buffer: scene_ctx.scene_database_buffer },
|
|
281
|
+
{ buffer: scene_ctx.geometries.buffer_metadata },
|
|
282
|
+
]
|
|
283
|
+
));
|
|
284
|
+
|
|
285
|
+
const render_pass_descriptor = shader_avboit_splat;
|
|
286
|
+
const layouts = render_pass_descriptor.pipeline.layout.bindGroupLayouts;
|
|
287
|
+
|
|
288
|
+
const view_bindings = bind_manager.obtain(BindGroupDescriptor.from(
|
|
289
|
+
layouts[RASTERIZATION_SHADER_BIND_GROUP_VIEW],
|
|
290
|
+
[
|
|
291
|
+
{ buffer: camera_buffer },
|
|
292
|
+
{ buffer: warp_buffer },
|
|
293
|
+
]
|
|
294
|
+
));
|
|
295
|
+
|
|
296
|
+
const volume_bindings = bind_manager.obtain(BindGroupDescriptor.from(
|
|
297
|
+
layouts[AVBOIT_SPLAT_BIND_GROUP_VOLUME],
|
|
298
|
+
[
|
|
299
|
+
{ buffer: extinction_buffer },
|
|
300
|
+
{ buffer: overflow_buffer },
|
|
301
|
+
]
|
|
302
|
+
));
|
|
303
|
+
|
|
304
|
+
// the dummy target is never written; it only sizes the raster
|
|
305
|
+
const pass_encoder = encoder.beginRenderPass(render_pass_descriptor.toGPU({
|
|
306
|
+
colorTargets: [t_dummy],
|
|
307
|
+
colorLoadOp: "clear",
|
|
308
|
+
colorStoreOp: "discard",
|
|
309
|
+
}));
|
|
310
|
+
|
|
311
|
+
const pipeline_descriptor = rp_rewrite_for_primitive_state(render_pass_descriptor.pipeline, primitive);
|
|
312
|
+
const pipeline = graphics.render_pipelines.obtain(pipeline_descriptor);
|
|
313
|
+
pass_encoder.setPipeline(pipeline);
|
|
314
|
+
|
|
315
|
+
pass_encoder.setBindGroup(RASTERIZATION_SHADER_BIND_GROUP_SCENE, scene_bindings);
|
|
316
|
+
pass_encoder.setBindGroup(RASTERIZATION_SHADER_BIND_GROUP_VIEW, view_bindings);
|
|
317
|
+
pass_encoder.setBindGroup(AVBOIT_SPLAT_BIND_GROUP_VOLUME, volume_bindings);
|
|
318
|
+
|
|
319
|
+
material_draw_indirect(
|
|
320
|
+
scene_ctx.materials,
|
|
321
|
+
material_count,
|
|
322
|
+
materials,
|
|
323
|
+
render_pass_descriptor,
|
|
324
|
+
bind_manager,
|
|
325
|
+
pass_encoder,
|
|
326
|
+
command_buffer_draw
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
pass_encoder.end();
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const pass_data = {};
|
|
333
|
+
const pass = graph.add("AVBOIT/splat", pass_data, execute);
|
|
334
|
+
|
|
335
|
+
pass_data.draw_commands = pass.read(draw_commands);
|
|
336
|
+
pass_data.meshlets = pass.read(meshlets);
|
|
337
|
+
pass_data.camera = pass.read(camera);
|
|
338
|
+
pass_data.warp = pass.read(warp);
|
|
339
|
+
|
|
340
|
+
if (volume !== undefined) {
|
|
341
|
+
pass.read(volume.extinction);
|
|
342
|
+
pass_data.extinction = pass.write(volume.extinction);
|
|
343
|
+
pass.read(volume.overflow);
|
|
344
|
+
pass_data.overflow = pass.write(volume.overflow);
|
|
345
|
+
pass.read(volume.dummy);
|
|
346
|
+
pass_data.dummy = pass.write(volume.dummy);
|
|
347
|
+
} else {
|
|
348
|
+
const texel_count = voxel_resolution[0] * voxel_resolution[1];
|
|
349
|
+
|
|
350
|
+
// one packed u32 per voxel, column-major with the slice fastest; zeroed every frame
|
|
351
|
+
pass_data.extinction = pass.create("AVBOIT extinction", BufferResourceDescriptor.empty(
|
|
352
|
+
texel_count * AVBOIT_PHYSICAL_SLICES * 4,
|
|
353
|
+
GPUBufferUsage.STORAGE
|
|
354
|
+
));
|
|
355
|
+
|
|
356
|
+
// three inverted first-overflow marks per texel; zero is "none"
|
|
357
|
+
pass_data.overflow = pass.create("AVBOIT overflow", BufferResourceDescriptor.empty(
|
|
358
|
+
texel_count * 3 * 4,
|
|
359
|
+
GPUBufferUsage.STORAGE
|
|
360
|
+
));
|
|
361
|
+
|
|
362
|
+
pass_data.dummy = pass.create("AVBOIT splat target", TextureResourceDescriptor.from({
|
|
363
|
+
resolution: voxel_resolution,
|
|
364
|
+
format: AVBOIT_SPLAT_DUMMY_FORMAT,
|
|
365
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT
|
|
366
|
+
}));
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return {
|
|
370
|
+
extinction: pass_data.extinction,
|
|
371
|
+
overflow: pass_data.overflow,
|
|
372
|
+
dummy: pass_data.dummy,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Integrate the extinction volume into the 3D transmittance-integral texture (plan §3.6).
|
|
378
|
+
*
|
|
379
|
+
* @param {FrameGraph} graph
|
|
380
|
+
* @param {number} warp resource ID
|
|
381
|
+
* @param {number} extinction resource ID
|
|
382
|
+
* @param {number} overflow resource ID
|
|
383
|
+
* @param {number[]} voxel_resolution
|
|
384
|
+
* @returns {number} resource ID of the integral texture, `P + 1` slices deep
|
|
385
|
+
*/
|
|
386
|
+
export function graph_avboit_integrate({
|
|
387
|
+
graph,
|
|
388
|
+
warp,
|
|
389
|
+
extinction,
|
|
390
|
+
overflow,
|
|
391
|
+
voxel_resolution,
|
|
392
|
+
}) {
|
|
393
|
+
|
|
394
|
+
assert.isNonNegativeInteger(warp, 'warp');
|
|
395
|
+
assert.isNonNegativeInteger(extinction, 'extinction');
|
|
396
|
+
assert.isNonNegativeInteger(overflow, 'overflow');
|
|
397
|
+
|
|
398
|
+
const { integral } = graph_compute_pass({
|
|
399
|
+
graph,
|
|
400
|
+
shader: shader_avboit_integrate,
|
|
401
|
+
bindings: {
|
|
402
|
+
warp,
|
|
403
|
+
extinction_volume: extinction,
|
|
404
|
+
overflow_slice: overflow,
|
|
405
|
+
integral: TextureResourceDescriptor.from({
|
|
406
|
+
resolution: [voxel_resolution[0], voxel_resolution[1], AVBOIT_PHYSICAL_SLICES + 1],
|
|
407
|
+
dimension: "3d",
|
|
408
|
+
format: AVBOIT_INTEGRAL_FORMAT,
|
|
409
|
+
usage: GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING
|
|
410
|
+
}),
|
|
411
|
+
},
|
|
412
|
+
group_count: [
|
|
413
|
+
Math.ceil(voxel_resolution[0] / AVBOIT_INTEGRATE_WORKGROUP_SIZE),
|
|
414
|
+
Math.ceil(voxel_resolution[1] / AVBOIT_INTEGRATE_WORKGROUP_SIZE),
|
|
415
|
+
1,
|
|
416
|
+
],
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
return integral;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Draw one bucket's transparent materials with full shading into the three accumulators (plan §3.8).
|
|
424
|
+
*
|
|
425
|
+
* @param {FrameGraph} graph
|
|
426
|
+
* @param {GPUViewContext} view_ctx
|
|
427
|
+
* @param {number} material_count
|
|
428
|
+
* @param {ShadeMaterial[]} materials
|
|
429
|
+
* @param {number} draw_commands resource ID
|
|
430
|
+
* @param {number} meshlets resource ID
|
|
431
|
+
* @param {number} depth_texture resource ID
|
|
432
|
+
* @param {number} warp resource ID
|
|
433
|
+
* @param {number} integral resource ID
|
|
434
|
+
* @param {PrimitiveState} primitive
|
|
435
|
+
* @param {number} light_cluster_parameters
|
|
436
|
+
* @param {number} light_cluster_lookup
|
|
437
|
+
* @param {number} light_cluster_data
|
|
438
|
+
* @param {number} shadowmap_atlas
|
|
439
|
+
* @param {number} volumetrics_lut
|
|
440
|
+
* @param {number} volumetrics_metadata
|
|
441
|
+
* @param {{color: number, norm: number, extinction: number}} [accumulators] existing targets to add to
|
|
442
|
+
* @param {ShadeIndirectLightingMode} indirect_lighting_mode
|
|
443
|
+
* @returns {{color: number, norm: number, extinction: number}}
|
|
444
|
+
*/
|
|
445
|
+
export function graph_avboit_draw({
|
|
446
|
+
graph,
|
|
447
|
+
view_ctx,
|
|
448
|
+
material_count,
|
|
449
|
+
materials,
|
|
450
|
+
draw_commands,
|
|
451
|
+
meshlets,
|
|
452
|
+
depth_texture,
|
|
453
|
+
warp,
|
|
454
|
+
integral,
|
|
455
|
+
primitive,
|
|
456
|
+
light_cluster_parameters,
|
|
457
|
+
light_cluster_lookup,
|
|
458
|
+
light_cluster_data,
|
|
459
|
+
shadowmap_atlas,
|
|
460
|
+
volumetrics_lut,
|
|
461
|
+
volumetrics_metadata,
|
|
462
|
+
accumulators,
|
|
463
|
+
indirect_lighting_mode = ShadeIndirectLightingMode.IBL,
|
|
464
|
+
}) {
|
|
465
|
+
|
|
466
|
+
assert.isNonNegativeInteger(material_count, 'material_count');
|
|
467
|
+
assert.isNonNegativeInteger(draw_commands, 'draw_commands');
|
|
468
|
+
assert.isNonNegativeInteger(meshlets, 'meshlets');
|
|
469
|
+
assert.isNonNegativeInteger(warp, 'warp');
|
|
470
|
+
assert.isNonNegativeInteger(integral, 'integral');
|
|
471
|
+
|
|
472
|
+
const scene_ctx = view_ctx.scene;
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
*
|
|
476
|
+
* @param data
|
|
477
|
+
* @param {FramePassResources} resources
|
|
478
|
+
* @param {GraphicsExecutionContext} context
|
|
479
|
+
*/
|
|
480
|
+
function execute(data, resources, context) {
|
|
481
|
+
|
|
482
|
+
assert.ok(context.graphics.device.features.has("indirect-first-instance"), '"indirect-first-instance" feature needs to be enabled for non-zero firstInstance values to be used.')
|
|
483
|
+
|
|
484
|
+
const command_buffer_draw = resources.get(data.draw_commands);
|
|
485
|
+
const meshlet_buffer = resources.get(data.meshlets);
|
|
486
|
+
|
|
487
|
+
const t_depth = resources.get(data.depth);
|
|
488
|
+
const t_color = resources.get(data.color);
|
|
489
|
+
const t_norm = resources.get(data.norm);
|
|
490
|
+
const t_extinction = resources.get(data.extinction);
|
|
491
|
+
|
|
492
|
+
const warp_buffer = resources.get(data.warp);
|
|
493
|
+
const t_integral = resources.get(data.integral);
|
|
494
|
+
|
|
495
|
+
const light_cluster_parameters = resources.get(data.light_cluster_parameters);
|
|
496
|
+
const light_cluster_lookup = resources.get(data.light_cluster_lookup);
|
|
497
|
+
const light_cluster_data = resources.get(data.light_cluster_data);
|
|
498
|
+
|
|
499
|
+
const shadowmap_atlas = resources.get(data.shadowmap_atlas);
|
|
500
|
+
|
|
501
|
+
const t_volumetrics_lut = resources.get(data.volumetrics_lut);
|
|
502
|
+
const volumetrics_metadata = resources.get(data.volumetrics_metadata);
|
|
503
|
+
|
|
504
|
+
const encoder = context.encoder;
|
|
505
|
+
const graphics = context.graphics;
|
|
506
|
+
const bind_manager = graphics.bind_groups;
|
|
507
|
+
|
|
508
|
+
const scene_bindings = bind_manager.obtain(BindGroupDescriptor.from(
|
|
509
|
+
BIND_GROUP_LAYOUT_SCENE,
|
|
510
|
+
[
|
|
511
|
+
{ buffer: meshlet_buffer },
|
|
512
|
+
{ buffer: scene_ctx.geometries.meshlets.buffer_metadata },
|
|
513
|
+
{ buffer: scene_ctx.geometries.meshlets.buffer_data },
|
|
514
|
+
{ buffer: scene_ctx.scene_database_buffer },
|
|
515
|
+
{ buffer: scene_ctx.geometries.buffer_metadata },
|
|
516
|
+
]
|
|
517
|
+
));
|
|
518
|
+
|
|
519
|
+
const sampler_shadowmap = graphics.samplers.obtain(SHADOWMAP_COMPARE_SAMPLER_DESCRIPTOR);
|
|
520
|
+
|
|
521
|
+
const light_bindings = bind_manager.obtain(BindGroupDescriptor.from(
|
|
522
|
+
BIND_GROUP_LAYOUT_LIGHT,
|
|
523
|
+
[
|
|
524
|
+
{ buffer: view_ctx.scene.lights.buffer_data },
|
|
525
|
+
view_ctx.scene.lights.environment.obtainView(),
|
|
526
|
+
//
|
|
527
|
+
{ buffer: light_cluster_parameters },
|
|
528
|
+
{ buffer: light_cluster_lookup },
|
|
529
|
+
{ buffer: light_cluster_data },
|
|
530
|
+
//
|
|
531
|
+
shadowmap_atlas.obtainView(),
|
|
532
|
+
sampler_shadowmap,
|
|
533
|
+
]
|
|
534
|
+
));
|
|
535
|
+
|
|
536
|
+
const use_brick4 = data.indirect_lighting_mode === ShadeIndirectLightingMode.Brick4;
|
|
537
|
+
const render_pass_descriptor = use_brick4
|
|
538
|
+
? shader_avboit_draw_brick4
|
|
539
|
+
: shader_avboit_draw_ibl;
|
|
540
|
+
|
|
541
|
+
const pass_encoder = encoder.beginRenderPass(render_pass_descriptor.toGPU({
|
|
542
|
+
colorTargets: [t_color, t_norm, t_extinction],
|
|
543
|
+
depthTarget: t_depth,
|
|
544
|
+
colorLoadOp: data.clear_targets ? "clear" : "load",
|
|
545
|
+
// depth is only tested, never written
|
|
546
|
+
depthLoadOp: "load",
|
|
547
|
+
storeOp: "store",
|
|
548
|
+
}));
|
|
549
|
+
|
|
550
|
+
const pipeline_descriptor = rp_rewrite_for_primitive_state(render_pass_descriptor.pipeline, primitive);
|
|
551
|
+
const pipeline = graphics.render_pipelines.obtain(pipeline_descriptor);
|
|
552
|
+
pass_encoder.setPipeline(pipeline);
|
|
553
|
+
|
|
554
|
+
pass_encoder.setBindGroup(RASTERIZATION_SHADER_BIND_GROUP_SCENE, scene_bindings);
|
|
555
|
+
pass_encoder.setBindGroup(3, light_bindings);
|
|
556
|
+
|
|
557
|
+
// linear and clamped on every axis: serves the split-sum LUT and the integral texture alike
|
|
558
|
+
const sampler_linear = graphics.samplers.obtain(SamplerDescriptor.from({
|
|
559
|
+
magFilter: "linear",
|
|
560
|
+
}));
|
|
561
|
+
|
|
562
|
+
const t_split_sum_lut = graphics.textures.obtain(STATIC_GRAPHICS_ENGINE_ASSETS.split_sum);
|
|
563
|
+
const stbn_vec3 = graphics.textures.obtain(STATIC_GRAPHICS_ENGINE_ASSETS.stbn_vec3);
|
|
564
|
+
|
|
565
|
+
// Entry order matches the view group declared in shader_avboit_draw_ibl / _brick4; the
|
|
566
|
+
// Brick4 variant carries its lightmap buffer right after the integral texture.
|
|
567
|
+
const view_bind_entries = use_brick4
|
|
568
|
+
? [
|
|
569
|
+
{ buffer: view_ctx.camera.buffer.buffer },
|
|
570
|
+
{ buffer: view_ctx.uniform_buffer.buffer },
|
|
571
|
+
{ buffer: warp_buffer },
|
|
572
|
+
t_integral.obtainView(),
|
|
573
|
+
{ buffer: view_ctx.scene.volumetric_light_map.buffer },
|
|
574
|
+
t_split_sum_lut.obtainView(),
|
|
575
|
+
sampler_linear,
|
|
576
|
+
// volumetrics
|
|
577
|
+
{ buffer: volumetrics_metadata },
|
|
578
|
+
t_volumetrics_lut.obtainView(),
|
|
579
|
+
stbn_vec3.obtainView(),
|
|
580
|
+
]
|
|
581
|
+
: [
|
|
582
|
+
{ buffer: view_ctx.camera.buffer.buffer },
|
|
583
|
+
{ buffer: view_ctx.uniform_buffer.buffer },
|
|
584
|
+
{ buffer: warp_buffer },
|
|
585
|
+
t_integral.obtainView(),
|
|
586
|
+
t_split_sum_lut.obtainView(),
|
|
587
|
+
sampler_linear,
|
|
588
|
+
// volumetrics
|
|
589
|
+
{ buffer: volumetrics_metadata },
|
|
590
|
+
t_volumetrics_lut.obtainView(),
|
|
591
|
+
stbn_vec3.obtainView(),
|
|
592
|
+
];
|
|
593
|
+
|
|
594
|
+
const view_bindings = bind_manager.obtain(BindGroupDescriptor.from(
|
|
595
|
+
render_pass_descriptor.pipeline.layout.bindGroupLayouts[RASTERIZATION_SHADER_BIND_GROUP_VIEW],
|
|
596
|
+
view_bind_entries
|
|
597
|
+
));
|
|
598
|
+
|
|
599
|
+
pass_encoder.setBindGroup(RASTERIZATION_SHADER_BIND_GROUP_VIEW, view_bindings);
|
|
600
|
+
|
|
601
|
+
material_draw_indirect(
|
|
602
|
+
scene_ctx.materials,
|
|
603
|
+
material_count,
|
|
604
|
+
materials,
|
|
605
|
+
render_pass_descriptor,
|
|
606
|
+
bind_manager,
|
|
607
|
+
pass_encoder,
|
|
608
|
+
command_buffer_draw
|
|
609
|
+
);
|
|
610
|
+
|
|
611
|
+
pass_encoder.end();
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
const pass_data = {
|
|
615
|
+
indirect_lighting_mode,
|
|
616
|
+
clear_targets: accumulators === undefined,
|
|
617
|
+
};
|
|
618
|
+
const pass = graph.add("AVBOIT/draw", pass_data, execute);
|
|
619
|
+
|
|
620
|
+
pass_data.draw_commands = pass.read(draw_commands);
|
|
621
|
+
pass_data.meshlets = pass.read(meshlets);
|
|
622
|
+
pass_data.depth = pass.read(depth_texture);
|
|
623
|
+
pass_data.warp = pass.read(warp);
|
|
624
|
+
pass_data.integral = pass.read(integral);
|
|
625
|
+
|
|
626
|
+
if (accumulators !== undefined) {
|
|
627
|
+
pass.read(accumulators.color);
|
|
628
|
+
pass_data.color = pass.write(accumulators.color);
|
|
629
|
+
pass.read(accumulators.norm);
|
|
630
|
+
pass_data.norm = pass.write(accumulators.norm);
|
|
631
|
+
pass.read(accumulators.extinction);
|
|
632
|
+
pass_data.extinction = pass.write(accumulators.extinction);
|
|
633
|
+
} else {
|
|
634
|
+
const make = label => pass.create(label, TextureResourceDescriptor.from({
|
|
635
|
+
resolution: view_ctx.resolution,
|
|
636
|
+
format: 'rgba16float',
|
|
637
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
|
|
638
|
+
}));
|
|
639
|
+
|
|
640
|
+
pass_data.color = make("AVBOIT accumulated color");
|
|
641
|
+
pass_data.norm = make("AVBOIT accumulated normalization");
|
|
642
|
+
pass_data.extinction = make("AVBOIT accumulated extinction");
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
pass_data.light_cluster_parameters = pass.read(light_cluster_parameters);
|
|
646
|
+
pass_data.light_cluster_lookup = pass.read(light_cluster_lookup);
|
|
647
|
+
pass_data.light_cluster_data = pass.read(light_cluster_data);
|
|
648
|
+
|
|
649
|
+
pass_data.shadowmap_atlas = pass.read(shadowmap_atlas);
|
|
650
|
+
|
|
651
|
+
pass_data.volumetrics_lut = pass.read(volumetrics_lut);
|
|
652
|
+
pass_data.volumetrics_metadata = pass.read(volumetrics_metadata);
|
|
653
|
+
|
|
654
|
+
return {
|
|
655
|
+
color: pass_data.color,
|
|
656
|
+
norm: pass_data.norm,
|
|
657
|
+
extinction: pass_data.extinction,
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Adaptive voxel-based order-independent transparency (Drobot, SIGGRAPH 2025). Does not write depth.
|
|
663
|
+
*
|
|
664
|
+
* Same argument object and same return as `graph_rasterize_meshes_transparent_oit`, so `Renderer`
|
|
665
|
+
* selects between the two with `transparency_mode` alone. The passes it records are listed in
|
|
666
|
+
* `AVBOIT_PLAN_2026_09_03.md` §3.1.
|
|
667
|
+
*
|
|
668
|
+
* @param {FrameGraph} graph
|
|
669
|
+
* @param {number} buckets
|
|
670
|
+
* @param {GPUViewContext} view_ctx
|
|
671
|
+
* @param {number[]} viewport
|
|
672
|
+
* @param {number} color_texture resource ID
|
|
673
|
+
* @param {number} depth_texture resource ID
|
|
674
|
+
* @param {GPUCollectionLimits} limits
|
|
675
|
+
* @param {number} light_cluster_parameters
|
|
676
|
+
* @param {number} light_cluster_lookup
|
|
677
|
+
* @param {number} light_cluster_data
|
|
678
|
+
* @param {number} shadowmap_atlas
|
|
679
|
+
* @param {number} volumetrics_lut
|
|
680
|
+
* @param {number} volumetrics_metadata
|
|
681
|
+
* @param {ShadeIndirectLightingMode} indirect_lighting_mode
|
|
682
|
+
* @param {AVBOITSettings} [avboit] `Renderer.avboit`; the MBOIT orchestrator ignores it
|
|
683
|
+
* @returns {number} resource ID of the composited color texture
|
|
684
|
+
*/
|
|
685
|
+
export function graph_rasterize_meshes_transparent_avboit({
|
|
686
|
+
graph,
|
|
687
|
+
buckets,
|
|
688
|
+
view_ctx,
|
|
689
|
+
viewport,
|
|
690
|
+
depth_texture,
|
|
691
|
+
color_texture,
|
|
692
|
+
limits,
|
|
693
|
+
light_cluster_parameters,
|
|
694
|
+
light_cluster_lookup,
|
|
695
|
+
light_cluster_data,
|
|
696
|
+
|
|
697
|
+
shadowmap_atlas,
|
|
698
|
+
|
|
699
|
+
volumetrics_lut,
|
|
700
|
+
volumetrics_metadata,
|
|
701
|
+
|
|
702
|
+
indirect_lighting_mode = ShadeIndirectLightingMode.IBL,
|
|
703
|
+
avboit = DEFAULT_SETTINGS,
|
|
704
|
+
}) {
|
|
705
|
+
|
|
706
|
+
assert.isNonNegativeInteger(buckets, 'buckets');
|
|
707
|
+
assert.isNonNegativeInteger(color_texture, 'color_texture');
|
|
708
|
+
assert.isNonNegativeInteger(depth_texture, 'depth_texture');
|
|
709
|
+
|
|
710
|
+
assert.isNonNegativeInteger(light_cluster_parameters, 'light_cluster_parameters');
|
|
711
|
+
assert.isNonNegativeInteger(light_cluster_lookup, 'light_cluster_lookup');
|
|
712
|
+
assert.isNonNegativeInteger(light_cluster_data, 'light_cluster_data');
|
|
713
|
+
|
|
714
|
+
assert.isNonNegativeInteger(shadowmap_atlas, 'shadowmap_atlas');
|
|
715
|
+
|
|
716
|
+
assert.equal(view_ctx.isGPUViewContext, true, 'view_ctx.isGPUViewContext !== true');
|
|
717
|
+
|
|
718
|
+
const scene_ctx = view_ctx.scene;
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* @type {ShadeMaterial[]}
|
|
722
|
+
*/
|
|
723
|
+
const materials_front = [];
|
|
724
|
+
/**
|
|
725
|
+
* @type {ShadeMaterial[]}
|
|
726
|
+
*/
|
|
727
|
+
const materials_double = [];
|
|
728
|
+
|
|
729
|
+
const scene_materials = scene_ctx.scene.instances.materials;
|
|
730
|
+
|
|
731
|
+
// Front-sided and double-sided materials need different pipeline states, so every raster pass
|
|
732
|
+
// below runs twice. `ShadeDrawSide.Back` is not drawn, the same as under MBOIT (plan §7).
|
|
733
|
+
const material_count_front = filter_materials_by_bucket(
|
|
734
|
+
materials_front, 0,
|
|
735
|
+
TransparencyMode.Transparent,
|
|
736
|
+
ShadeDrawMode.Triangles,
|
|
737
|
+
ShadeDrawSide.Front,
|
|
738
|
+
scene_materials,
|
|
739
|
+
scene_materials.length
|
|
740
|
+
);
|
|
741
|
+
|
|
742
|
+
const material_count_double = filter_materials_by_bucket(
|
|
743
|
+
materials_double, 0,
|
|
744
|
+
TransparencyMode.Transparent,
|
|
745
|
+
ShadeDrawMode.Triangles,
|
|
746
|
+
ShadeDrawSide.Double,
|
|
747
|
+
scene_materials,
|
|
748
|
+
scene_materials.length
|
|
749
|
+
);
|
|
750
|
+
|
|
751
|
+
if ((material_count_front + material_count_double) === 0) {
|
|
752
|
+
// nothing to do
|
|
753
|
+
return color_texture;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
const bucket_index_front = rasterization_material_bucket(
|
|
757
|
+
TransparencyMode.Transparent, ShadeDrawMode.Triangles, ShadeDrawSide.Front
|
|
758
|
+
);
|
|
759
|
+
|
|
760
|
+
const bucket_index_double = rasterization_material_bucket(
|
|
761
|
+
TransparencyMode.Transparent, ShadeDrawMode.Triangles, ShadeDrawSide.Double
|
|
762
|
+
);
|
|
763
|
+
|
|
764
|
+
const primitive_front = construct_primitive_state(ShadeDrawMode.Triangles, ShadeDrawSide.Front);
|
|
765
|
+
const primitive_double = construct_primitive_state(ShadeDrawMode.Triangles, ShadeDrawSide.Double);
|
|
766
|
+
|
|
767
|
+
const gr_hzb = graph_import_texture(graph, view_ctx.hierarchical_z_buffer.texture);
|
|
768
|
+
const gr_camera = graph_import_buffer(graph, view_ctx.camera.buffer.buffer);
|
|
769
|
+
|
|
770
|
+
const voxel_resolution = avboit_voxel_resolution(view_ctx.resolution);
|
|
771
|
+
|
|
772
|
+
// the depth curve for this camera, shared by the occupancy prepass and, through the warp
|
|
773
|
+
// header, by every pass after it
|
|
774
|
+
const camera = view_ctx.camera.camera;
|
|
775
|
+
const cluster_parameters = avboit_build_depth_curve(camera.near, camera.far);
|
|
776
|
+
|
|
777
|
+
// Draw artifacts (shared with MBOIT)
|
|
778
|
+
// ======
|
|
779
|
+
|
|
780
|
+
const prep_front = graph_prepare_meshlet_draw_commands_by_material({
|
|
781
|
+
graph,
|
|
782
|
+
materials: materials_front,
|
|
783
|
+
bucket_id: bucket_index_front,
|
|
784
|
+
limits,
|
|
785
|
+
buckets,
|
|
786
|
+
scene: scene_ctx,
|
|
787
|
+
camera: gr_camera,
|
|
788
|
+
hzb: gr_hzb,
|
|
789
|
+
resolution: [viewport[2], viewport[3]],
|
|
790
|
+
label: `${view_ctx.label}/AVBOIT-front`,
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
const prep_double = graph_prepare_meshlet_draw_commands_by_material({
|
|
794
|
+
graph,
|
|
795
|
+
materials: materials_double,
|
|
796
|
+
bucket_id: bucket_index_double,
|
|
797
|
+
limits,
|
|
798
|
+
buckets,
|
|
799
|
+
scene: scene_ctx,
|
|
800
|
+
camera: gr_camera,
|
|
801
|
+
hzb: gr_hzb,
|
|
802
|
+
resolution: [viewport[2], viewport[3]],
|
|
803
|
+
label: `${view_ctx.label}/AVBOIT-double`,
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
// Occupancy and warp
|
|
807
|
+
// ======
|
|
808
|
+
|
|
809
|
+
let occupancy = graph_avboit_occupancy({
|
|
810
|
+
graph,
|
|
811
|
+
scene: scene_ctx,
|
|
812
|
+
camera: gr_camera,
|
|
813
|
+
cluster_parameters,
|
|
814
|
+
meshlet_collection: prep_front.meshlet_collection,
|
|
815
|
+
meshlet_iterator_command: prep_front.meshlet_iterator_command,
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
occupancy = graph_avboit_occupancy({
|
|
819
|
+
graph,
|
|
820
|
+
scene: scene_ctx,
|
|
821
|
+
camera: gr_camera,
|
|
822
|
+
cluster_parameters,
|
|
823
|
+
meshlet_collection: prep_double.meshlet_collection,
|
|
824
|
+
meshlet_iterator_command: prep_double.meshlet_iterator_command,
|
|
825
|
+
occupancy,
|
|
826
|
+
});
|
|
827
|
+
|
|
828
|
+
const warp = graph_avboit_build_warp({
|
|
829
|
+
graph,
|
|
830
|
+
occupancy,
|
|
831
|
+
voxel_resolution,
|
|
832
|
+
cluster_parameters,
|
|
833
|
+
avboit,
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
// Splat
|
|
837
|
+
// ======
|
|
838
|
+
|
|
839
|
+
let volume = graph_avboit_splat({
|
|
840
|
+
graph,
|
|
841
|
+
view_ctx,
|
|
842
|
+
material_count: material_count_front,
|
|
843
|
+
materials: materials_front,
|
|
844
|
+
draw_commands: prep_front.draw_commands,
|
|
845
|
+
meshlets: prep_front.meshlets,
|
|
846
|
+
camera: gr_camera,
|
|
847
|
+
warp,
|
|
848
|
+
voxel_resolution,
|
|
849
|
+
primitive: primitive_front,
|
|
850
|
+
});
|
|
851
|
+
|
|
852
|
+
volume = graph_avboit_splat({
|
|
853
|
+
graph,
|
|
854
|
+
view_ctx,
|
|
855
|
+
material_count: material_count_double,
|
|
856
|
+
materials: materials_double,
|
|
857
|
+
draw_commands: prep_double.draw_commands,
|
|
858
|
+
meshlets: prep_double.meshlets,
|
|
859
|
+
camera: gr_camera,
|
|
860
|
+
warp,
|
|
861
|
+
voxel_resolution,
|
|
862
|
+
primitive: primitive_double,
|
|
863
|
+
volume,
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
// Integrate
|
|
867
|
+
// ======
|
|
868
|
+
|
|
869
|
+
const integral = graph_avboit_integrate({
|
|
870
|
+
graph,
|
|
871
|
+
warp,
|
|
872
|
+
extinction: volume.extinction,
|
|
873
|
+
overflow: volume.overflow,
|
|
874
|
+
voxel_resolution,
|
|
875
|
+
});
|
|
876
|
+
|
|
877
|
+
// Draw
|
|
878
|
+
// ======
|
|
879
|
+
|
|
880
|
+
const lighting = {
|
|
881
|
+
light_cluster_parameters,
|
|
882
|
+
light_cluster_lookup,
|
|
883
|
+
light_cluster_data,
|
|
884
|
+
shadowmap_atlas,
|
|
885
|
+
volumetrics_lut,
|
|
886
|
+
volumetrics_metadata,
|
|
887
|
+
indirect_lighting_mode,
|
|
888
|
+
};
|
|
889
|
+
|
|
890
|
+
let accumulators = graph_avboit_draw({
|
|
891
|
+
graph,
|
|
892
|
+
view_ctx,
|
|
893
|
+
material_count: material_count_front,
|
|
894
|
+
materials: materials_front,
|
|
895
|
+
draw_commands: prep_front.draw_commands,
|
|
896
|
+
meshlets: prep_front.meshlets,
|
|
897
|
+
depth_texture,
|
|
898
|
+
warp,
|
|
899
|
+
integral,
|
|
900
|
+
primitive: primitive_front,
|
|
901
|
+
...lighting,
|
|
902
|
+
});
|
|
903
|
+
|
|
904
|
+
accumulators = graph_avboit_draw({
|
|
905
|
+
graph,
|
|
906
|
+
view_ctx,
|
|
907
|
+
material_count: material_count_double,
|
|
908
|
+
materials: materials_double,
|
|
909
|
+
draw_commands: prep_double.draw_commands,
|
|
910
|
+
meshlets: prep_double.meshlets,
|
|
911
|
+
depth_texture,
|
|
912
|
+
warp,
|
|
913
|
+
integral,
|
|
914
|
+
primitive: primitive_double,
|
|
915
|
+
accumulators,
|
|
916
|
+
...lighting,
|
|
917
|
+
});
|
|
918
|
+
|
|
919
|
+
// Resolve
|
|
920
|
+
// ======
|
|
921
|
+
|
|
922
|
+
const [composited] = graph_image_pass({
|
|
923
|
+
graph,
|
|
924
|
+
shader: shader_avboit_resolve,
|
|
925
|
+
output_resolution: view_ctx.resolution,
|
|
926
|
+
inputs: {
|
|
927
|
+
tScene: color_texture,
|
|
928
|
+
tColor: accumulators.color,
|
|
929
|
+
tNorm: accumulators.norm,
|
|
930
|
+
tExtinction: accumulators.extinction,
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
|
|
934
|
+
return composited;
|
|
935
|
+
}
|