@bornengine/engine 0.4.16
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/LICENSE +21 -0
- package/README.md +231 -0
- package/native/android/Cargo.lock +1848 -0
- package/native/android/Cargo.toml +24 -0
- package/native/android/src/lib.rs +702 -0
- package/native/ios/Cargo.lock +1690 -0
- package/native/ios/Cargo.toml +32 -0
- package/native/ios/src/lib.rs +1267 -0
- package/native/linux/Cargo.lock +3279 -0
- package/native/linux/Cargo.toml +29 -0
- package/native/linux/src/lib.rs +1331 -0
- package/native/macos/Cargo.lock +3310 -0
- package/native/macos/Cargo.toml +46 -0
- package/native/macos/src/lib.rs +1302 -0
- package/native/shared/Cargo.lock +1899 -0
- package/native/shared/Cargo.toml +62 -0
- package/native/shared/assets/default_font.ttf +0 -0
- package/native/shared/build.rs +270 -0
- package/native/shared/shaders/common/clouds.wgsl +122 -0
- package/native/shared/shaders/common/fog.wgsl +16 -0
- package/native/shared/shaders/common/foliage_wind.wgsl +98 -0
- package/native/shared/shaders/common/imposter.wgsl +112 -0
- package/native/shared/shaders/common/pbr.wgsl +186 -0
- package/native/shared/shaders/common/shadows.wgsl +186 -0
- package/native/shared/shaders/common/sky.wgsl +8 -0
- package/native/shared/shaders/common/tonemap.wgsl +25 -0
- package/native/shared/shaders/impulse_field.wgsl +57 -0
- package/native/shared/shaders/material_abi.wgsl +383 -0
- package/native/shared/shaders/materials/test_minimal.wgsl +42 -0
- package/native/shared/src/anim_mixer.rs +61 -0
- package/native/shared/src/attach.rs +263 -0
- package/native/shared/src/audio/decode.rs +123 -0
- package/native/shared/src/audio/mod.rs +863 -0
- package/native/shared/src/audio/render.rs +892 -0
- package/native/shared/src/audio/spsc.rs +156 -0
- package/native/shared/src/audio/stream.rs +226 -0
- package/native/shared/src/custom_shaders.rs +104 -0
- package/native/shared/src/decals.rs +245 -0
- package/native/shared/src/drs.rs +211 -0
- package/native/shared/src/engine.rs +261 -0
- package/native/shared/src/ffi.rs +116 -0
- package/native/shared/src/ffi_core/assets.rs +388 -0
- package/native/shared/src/ffi_core/audio_ffi.rs +184 -0
- package/native/shared/src/ffi_core/draw.rs +334 -0
- package/native/shared/src/ffi_core/game_loop.rs +577 -0
- package/native/shared/src/ffi_core/input.rs +234 -0
- package/native/shared/src/ffi_core/mod.rs +127 -0
- package/native/shared/src/ffi_core/models.rs +1154 -0
- package/native/shared/src/ffi_core/ragdoll_ffi.rs +261 -0
- package/native/shared/src/ffi_core/scene.rs +626 -0
- package/native/shared/src/ffi_core/vfx.rs +212 -0
- package/native/shared/src/ffi_core/visual.rs +691 -0
- package/native/shared/src/frame_callbacks.rs +122 -0
- package/native/shared/src/geometry.rs +236 -0
- package/native/shared/src/handles.rs +182 -0
- package/native/shared/src/input.rs +448 -0
- package/native/shared/src/jolt_sys.rs +822 -0
- package/native/shared/src/lib.rs +55 -0
- package/native/shared/src/models.rs +1093 -0
- package/native/shared/src/models_gltf.rs +1280 -0
- package/native/shared/src/particles.rs +391 -0
- package/native/shared/src/physics_jolt.rs +1908 -0
- package/native/shared/src/picking.rs +298 -0
- package/native/shared/src/postfx.rs +345 -0
- package/native/shared/src/profiler.rs +492 -0
- package/native/shared/src/ragdoll.rs +474 -0
- package/native/shared/src/renderer/atmosphere_lut.rs +573 -0
- package/native/shared/src/renderer/brdf_lut.rs +154 -0
- package/native/shared/src/renderer/draw2d.rs +143 -0
- package/native/shared/src/renderer/formats.rs +822 -0
- package/native/shared/src/renderer/froxel.rs +421 -0
- package/native/shared/src/renderer/gi_bake.rs +653 -0
- package/native/shared/src/renderer/graph.rs +462 -0
- package/native/shared/src/renderer/hiz.rs +269 -0
- package/native/shared/src/renderer/hot_reload.rs +390 -0
- package/native/shared/src/renderer/impulse_field.rs +456 -0
- package/native/shared/src/renderer/lighting.rs +154 -0
- package/native/shared/src/renderer/material_instancing.rs +171 -0
- package/native/shared/src/renderer/material_pipeline.rs +700 -0
- package/native/shared/src/renderer/material_system.rs +1996 -0
- package/native/shared/src/renderer/material_system_tests.rs +601 -0
- package/native/shared/src/renderer/material_system_wasm.rs +41 -0
- package/native/shared/src/renderer/mod.rs +12556 -0
- package/native/shared/src/renderer/model_draw.rs +641 -0
- package/native/shared/src/renderer/occlusion.rs +429 -0
- package/native/shared/src/renderer/planar_pass.rs +593 -0
- package/native/shared/src/renderer/planar_reflection.rs +499 -0
- package/native/shared/src/renderer/post_pass.rs +249 -0
- package/native/shared/src/renderer/postfx_chain.rs +728 -0
- package/native/shared/src/renderer/pt_pass.rs +577 -0
- package/native/shared/src/renderer/scene_pass.rs +607 -0
- package/native/shared/src/renderer/shader_include.rs +205 -0
- package/native/shared/src/renderer/shader_library.rs +135 -0
- package/native/shared/src/renderer/shaders/ao.rs +570 -0
- package/native/shared/src/renderer/shaders/core.rs +1243 -0
- package/native/shared/src/renderer/shaders/env.rs +907 -0
- package/native/shared/src/renderer/shaders/gi.rs +810 -0
- package/native/shared/src/renderer/shaders/mod.rs +19 -0
- package/native/shared/src/renderer/shaders/post.rs +1558 -0
- package/native/shared/src/renderer/shaders/pt.rs +1859 -0
- package/native/shared/src/renderer/shaders/ssgi.rs +1586 -0
- package/native/shared/src/renderer/shadow_pass.rs +731 -0
- package/native/shared/src/renderer/ssgi_pass.rs +392 -0
- package/native/shared/src/renderer/ssr_pass.rs +188 -0
- package/native/shared/src/renderer/texture_store.rs +473 -0
- package/native/shared/src/renderer/transient.rs +591 -0
- package/native/shared/src/renderer/types.rs +941 -0
- package/native/shared/src/renderer/util.rs +152 -0
- package/native/shared/src/scene.rs +1362 -0
- package/native/shared/src/sdf_cache.rs +274 -0
- package/native/shared/src/shadows.rs +1036 -0
- package/native/shared/src/staging.rs +102 -0
- package/native/shared/src/string_header.rs +266 -0
- package/native/shared/src/text_renderer.rs +502 -0
- package/native/shared/src/textures.rs +197 -0
- package/native/tvos/Cargo.lock +1693 -0
- package/native/tvos/Cargo.toml +36 -0
- package/native/tvos/metal-patched/Cargo.toml +178 -0
- package/native/tvos/metal-patched/LICENSE-APACHE +201 -0
- package/native/tvos/metal-patched/LICENSE-MIT +25 -0
- package/native/tvos/metal-patched/src/acceleration_structure.rs +667 -0
- package/native/tvos/metal-patched/src/acceleration_structure_pass.rs +108 -0
- package/native/tvos/metal-patched/src/argument.rs +366 -0
- package/native/tvos/metal-patched/src/blitpass.rs +102 -0
- package/native/tvos/metal-patched/src/buffer.rs +71 -0
- package/native/tvos/metal-patched/src/capturedescriptor.rs +76 -0
- package/native/tvos/metal-patched/src/capturemanager.rs +113 -0
- package/native/tvos/metal-patched/src/commandbuffer.rs +192 -0
- package/native/tvos/metal-patched/src/commandqueue.rs +44 -0
- package/native/tvos/metal-patched/src/computepass.rs +107 -0
- package/native/tvos/metal-patched/src/constants.rs +152 -0
- package/native/tvos/metal-patched/src/counters.rs +119 -0
- package/native/tvos/metal-patched/src/depthstencil.rs +190 -0
- package/native/tvos/metal-patched/src/device.rs +2134 -0
- package/native/tvos/metal-patched/src/drawable.rs +39 -0
- package/native/tvos/metal-patched/src/encoder.rs +2041 -0
- package/native/tvos/metal-patched/src/heap.rs +281 -0
- package/native/tvos/metal-patched/src/indirect_encoder.rs +344 -0
- package/native/tvos/metal-patched/src/lib.rs +657 -0
- package/native/tvos/metal-patched/src/library.rs +902 -0
- package/native/tvos/metal-patched/src/mps.rs +575 -0
- package/native/tvos/metal-patched/src/pipeline/compute.rs +475 -0
- package/native/tvos/metal-patched/src/pipeline/mod.rs +71 -0
- package/native/tvos/metal-patched/src/pipeline/render.rs +762 -0
- package/native/tvos/metal-patched/src/renderpass.rs +443 -0
- package/native/tvos/metal-patched/src/resource.rs +182 -0
- package/native/tvos/metal-patched/src/sampler.rs +165 -0
- package/native/tvos/metal-patched/src/sync.rs +178 -0
- package/native/tvos/metal-patched/src/texture.rs +352 -0
- package/native/tvos/metal-patched/src/types.rs +90 -0
- package/native/tvos/metal-patched/src/vertexdescriptor.rs +250 -0
- package/native/tvos/src/audio_backend.rs +197 -0
- package/native/tvos/src/lib.rs +1891 -0
- package/native/visionos/Cargo.lock +1693 -0
- package/native/visionos/Cargo.toml +40 -0
- package/native/visionos/src/audio_backend.rs +197 -0
- package/native/visionos/src/lib.rs +1887 -0
- package/native/watchos/Cargo.lock +16 -0
- package/native/watchos/Cargo.toml +19 -0
- package/native/watchos/shaders/bloom_postfx.metal +99 -0
- package/native/watchos/src/BloomWatchApp.swift +1267 -0
- package/native/watchos/src/BloomWatchAudio.swift +179 -0
- package/native/watchos/src/audio.rs +55 -0
- package/native/watchos/src/draw_list.rs +229 -0
- package/native/watchos/src/ffi_stubs.rs +915 -0
- package/native/watchos/src/ffi_stubs_manual.rs +35 -0
- package/native/watchos/src/lib.rs +1124 -0
- package/native/watchos/src/models.rs +746 -0
- package/native/watchos/src/postfx.rs +95 -0
- package/native/watchos/src/scene.rs +534 -0
- package/native/watchos/src/textures.rs +184 -0
- package/native/web/Cargo.lock +1657 -0
- package/native/web/Cargo.toml +43 -0
- package/native/web/bloom_glue.js +695 -0
- package/native/web/build.sh +131 -0
- package/native/web/index.html +35 -0
- package/native/web/jolt_bridge.js +1519 -0
- package/native/web/src/input_ffi.rs +286 -0
- package/native/web/src/lib.rs +1796 -0
- package/native/web/src/material_ffi.rs +710 -0
- package/native/web/src/parity_ffi.rs +343 -0
- package/native/web/src/physics_ffi.rs +643 -0
- package/native/web/src/ragdoll_ffi.rs +250 -0
- package/native/web/src/render_settings.rs +98 -0
- package/native/windows/Cargo.lock +1815 -0
- package/native/windows/Cargo.toml +68 -0
- package/native/windows/src/lib.rs +1486 -0
- package/package.json +4279 -0
- package/src/audio/index.ts +315 -0
- package/src/core/colors.ts +63 -0
- package/src/core/index.ts +1206 -0
- package/src/core/keys.ts +63 -0
- package/src/core/types.ts +104 -0
- package/src/index.ts +171 -0
- package/src/math/index.ts +516 -0
- package/src/mobile/index.ts +294 -0
- package/src/models/index.ts +1258 -0
- package/src/physics/index.ts +1134 -0
- package/src/scene/index.ts +698 -0
- package/src/shapes/index.ts +120 -0
- package/src/text/index.ts +48 -0
- package/src/textures/index.ts +187 -0
- package/src/vfx/index.ts +191 -0
- package/src/world/index.ts +24 -0
- package/src/world/loader.ts +423 -0
- package/src/world/prefab.ts +217 -0
- package/src/world/render.ts +172 -0
- package/src/world/saver.ts +108 -0
- package/src/world/serialize.ts +301 -0
- package/src/world/terrain.ts +355 -0
- package/src/world/types.ts +160 -0
- package/src/world/validate.ts +319 -0
- package/src/world/version.ts +114 -0
|
@@ -0,0 +1,941 @@
|
|
|
1
|
+
//! Uniform + vertex types used throughout the renderer.
|
|
2
|
+
//!
|
|
3
|
+
//! Pure POD data (`bytemuck::Pod`-derived structs) — no Renderer state,
|
|
4
|
+
//! no wgpu resource ownership, no behavior beyond tiny constructors /
|
|
5
|
+
//! VertexBufferLayout descriptors. Split out of the 11 500-line
|
|
6
|
+
//! renderer monolith so the wiring and the data types are separable.
|
|
7
|
+
//!
|
|
8
|
+
//! `pub` items that external modules import (`Vertex3D`,
|
|
9
|
+
//! `SceneMaterialUniforms`) are re-exported from `renderer/mod.rs`
|
|
10
|
+
//! with `pub use types::*;` so their public paths
|
|
11
|
+
//! (`crate::renderer::Vertex3D`, etc.) stay stable.
|
|
12
|
+
|
|
13
|
+
use crate::renderer::IDENTITY_MAT4;
|
|
14
|
+
|
|
15
|
+
// ============================================================
|
|
16
|
+
// Constants
|
|
17
|
+
// ============================================================
|
|
18
|
+
|
|
19
|
+
pub(super) const MAX_UNIFORM_SLOTS: usize = 8;
|
|
20
|
+
|
|
21
|
+
// ============================================================
|
|
22
|
+
// Vertex and Uniform types
|
|
23
|
+
// ============================================================
|
|
24
|
+
|
|
25
|
+
#[repr(C)]
|
|
26
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
27
|
+
pub(super) struct Uniforms2D {
|
|
28
|
+
pub(super) screen_size: [f32; 2],
|
|
29
|
+
pub(super) _pad: [f32; 2],
|
|
30
|
+
pub(super) view_proj: [[f32; 4]; 4],
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
#[repr(C)]
|
|
34
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
35
|
+
pub(super) struct Uniforms3D {
|
|
36
|
+
pub(super) mvp: [[f32; 4]; 4],
|
|
37
|
+
pub(super) model: [[f32; 4]; 4],
|
|
38
|
+
pub(super) prev_mvp: [[f32; 4]; 4],
|
|
39
|
+
pub(super) model_tint: [f32; 4],
|
|
40
|
+
/// x = joint-buffer base offset for this draw (added to vertex joint
|
|
41
|
+
/// indices by the scene VS), y = 1.0 for skinned cached draws else
|
|
42
|
+
/// 0.0, zw unused. Lets GPU-resident skinned models share the static
|
|
43
|
+
/// cached-model path: the VB keeps RAW joint indices and the per-draw
|
|
44
|
+
/// uniform carries the frame's pose offset instead.
|
|
45
|
+
pub(super) misc: [f32; 4],
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/// Scene-pipeline per-material factors — the scalar parts of a glTF
|
|
49
|
+
/// PBR material that get multiplied onto the corresponding texture
|
|
50
|
+
/// samples. Sized to a multiple of 16 bytes for UBO alignment.
|
|
51
|
+
#[repr(C)]
|
|
52
|
+
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
|
|
53
|
+
pub struct SceneMaterialUniforms {
|
|
54
|
+
/// x = metallic_factor, y = roughness_factor,
|
|
55
|
+
/// z = has_mr_texture (1.0 = sample mr_tex and multiply, 0.0 = ignore
|
|
56
|
+
/// mr_tex and use factors directly),
|
|
57
|
+
/// w = alpha_cutoff (0.0 = OPAQUE mode, >0 = MASK/BLEND — fragments
|
|
58
|
+
/// whose base-colour alpha is below this are discarded).
|
|
59
|
+
pub metal_rough: [f32; 4],
|
|
60
|
+
/// rgb = emissive_factor, w = padding
|
|
61
|
+
pub emissive: [f32; 4],
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
impl SceneMaterialUniforms {
|
|
65
|
+
pub fn new(
|
|
66
|
+
metallic: f32,
|
|
67
|
+
roughness: f32,
|
|
68
|
+
emissive: [f32; 3],
|
|
69
|
+
has_mr_texture: bool,
|
|
70
|
+
alpha_cutoff: f32,
|
|
71
|
+
) -> Self {
|
|
72
|
+
Self {
|
|
73
|
+
metal_rough: [
|
|
74
|
+
metallic,
|
|
75
|
+
roughness,
|
|
76
|
+
if has_mr_texture { 1.0 } else { 0.0 },
|
|
77
|
+
alpha_cutoff,
|
|
78
|
+
],
|
|
79
|
+
emissive: [emissive[0], emissive[1], emissive[2], 0.0],
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Raised from 4/16: scenes were hard-capped at 16 point lights, the
|
|
85
|
+
// audit's top graphics blocker. Arrays stay in a uniform buffer so the
|
|
86
|
+
// cap raise works on every backend including WebGL2 (whose 16KB minimum
|
|
87
|
+
// UBO size this still fits: 256*32B + 8*32B + header < 9KB). Shaders
|
|
88
|
+
// loop only over the live count, so small scenes pay nothing. Per-pixel
|
|
89
|
+
// cost for genuinely large light counts is the follow-up (froxel
|
|
90
|
+
// clustering); this change removes the capability ceiling.
|
|
91
|
+
pub(crate) const MAX_DIR_LIGHTS: usize = 8;
|
|
92
|
+
pub(crate) const MAX_POINT_LIGHTS: usize = 256;
|
|
93
|
+
|
|
94
|
+
#[repr(C)]
|
|
95
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
96
|
+
pub(super) struct DirLight {
|
|
97
|
+
pub(super) direction: [f32; 4], // xyz + intensity
|
|
98
|
+
pub(super) color: [f32; 4], // rgb + _pad
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
#[repr(C)]
|
|
102
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
103
|
+
pub(super) struct PointLight {
|
|
104
|
+
pub(super) position: [f32; 4], // xyz + range
|
|
105
|
+
pub(super) color: [f32; 4], // rgb + intensity
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
#[repr(C)]
|
|
109
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
110
|
+
pub(super) struct LightingUniforms {
|
|
111
|
+
pub(super) ambient: [f32; 4], // rgb + intensity
|
|
112
|
+
pub(super) light_dir: [f32; 4], // xyz + intensity (legacy, kept for compat)
|
|
113
|
+
pub(super) light_color: [f32; 4], // rgb + _pad (legacy)
|
|
114
|
+
pub(super) dir_light_count: [f32; 4], // [count, 0, 0, 0]
|
|
115
|
+
pub(super) dir_lights: [DirLight; MAX_DIR_LIGHTS], // additional directional lights
|
|
116
|
+
pub(super) point_light_count: [f32; 4], // [count, 0, 0, 0]
|
|
117
|
+
pub(super) point_lights: [PointLight; MAX_POINT_LIGHTS], // point lights
|
|
118
|
+
/// Camera world-space position (xyz) + env intensity multiplier
|
|
119
|
+
/// (w). Scene shader uses xyz to compute V = normalize(camera_pos
|
|
120
|
+
/// - world_pos) for GGX specular, and multiplies w into every env
|
|
121
|
+
/// sample so IBL stays in sync with the sky pass when the user
|
|
122
|
+
/// scales their HDR. Written once per frame before the main pass.
|
|
123
|
+
pub(super) camera_pos: [f32; 4],
|
|
124
|
+
/// Cascaded shadow map: 3 light view-projection matrices (one per
|
|
125
|
+
/// cascade). Scene shader selects the tightest cascade based on
|
|
126
|
+
/// the fragment's view-space depth and projects through the
|
|
127
|
+
/// corresponding matrix for shadow-map UV.
|
|
128
|
+
pub(super) shadow_cascade_vps: [[[f32; 4]; 4]; 3],
|
|
129
|
+
/// View-space Z split distances for cascade selection (xyz = split
|
|
130
|
+
/// distances for cascades 0/1/2, w = unused). Fragment at depth z
|
|
131
|
+
/// uses cascade i where z <= cascade_splits[i].
|
|
132
|
+
pub(super) shadow_cascade_splits: [f32; 4],
|
|
133
|
+
/// Camera view matrix — passed to the shader so the fragment shader
|
|
134
|
+
/// can compute view-space Z for cascade selection without an extra
|
|
135
|
+
/// buffer binding.
|
|
136
|
+
pub(super) shadow_view_matrix: [[f32; 4]; 4],
|
|
137
|
+
/// Wind for foliage sway in the built-in scene vertex shader:
|
|
138
|
+
/// xy = wind direction in the XZ plane (magnitude scales sway),
|
|
139
|
+
/// z = amplitude, w = elapsed time (seconds) for the sway phase.
|
|
140
|
+
/// Appended last so existing field offsets stay stable.
|
|
141
|
+
pub(super) wind: [f32; 4],
|
|
142
|
+
/// Cloud deck for the built-in scene shader: x = shadow strength,
|
|
143
|
+
/// y = deck height (m), z = feature scale, w = drift speed (m/s).
|
|
144
|
+
/// Strength 0 = the scene ignores the clouds. Appended last so existing
|
|
145
|
+
/// field offsets stay stable.
|
|
146
|
+
pub(super) cloud: [f32; 4],
|
|
147
|
+
/// x = delta_time (seconds). The scene VS needs LAST frame's wind offset to
|
|
148
|
+
/// emit a correct motion vector for swaying foliage — without it TAA sees
|
|
149
|
+
/// velocity 0 on every moving leaf and ghosts them. Appended last so existing
|
|
150
|
+
/// field offsets stay stable.
|
|
151
|
+
pub(super) frame_misc: [f32; 4],
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
impl LightingUniforms {
|
|
155
|
+
pub(super) fn defaults() -> Self {
|
|
156
|
+
Self {
|
|
157
|
+
ambient: [1.0, 1.0, 1.0, 0.3],
|
|
158
|
+
light_dir: [0.5, 1.0, 0.3, 0.7],
|
|
159
|
+
light_color: [1.0, 1.0, 1.0, 0.0],
|
|
160
|
+
dir_light_count: [0.0; 4],
|
|
161
|
+
dir_lights: [DirLight { direction: [0.0; 4], color: [0.0; 4] }; MAX_DIR_LIGHTS],
|
|
162
|
+
point_light_count: [0.0; 4],
|
|
163
|
+
point_lights: [PointLight { position: [0.0; 4], color: [0.0; 4] }; MAX_POINT_LIGHTS],
|
|
164
|
+
// w = env_intensity multiplier for IBL + sky. 1.0 matches
|
|
165
|
+
// the path-traced reference; apps with bright HDR envs
|
|
166
|
+
// typically dial to 0.2–0.5 via set_env_intensity.
|
|
167
|
+
camera_pos: [0.0, 0.0, 0.0, 1.0],
|
|
168
|
+
shadow_cascade_vps: [IDENTITY_MAT4; 3],
|
|
169
|
+
shadow_cascade_splits: [8.0, 25.0, 80.0, 0.0],
|
|
170
|
+
shadow_view_matrix: IDENTITY_MAT4,
|
|
171
|
+
wind: [0.0, 0.0, 0.0, 0.0],
|
|
172
|
+
cloud: [0.0, 420.0, 0.0035, 8.0],
|
|
173
|
+
frame_misc: [0.0; 4],
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
#[repr(C)]
|
|
179
|
+
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
|
|
180
|
+
pub struct Vertex2D {
|
|
181
|
+
pub position: [f32; 2],
|
|
182
|
+
pub uv: [f32; 2],
|
|
183
|
+
pub color: [f32; 4],
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
impl Vertex2D {
|
|
187
|
+
pub fn desc() -> wgpu::VertexBufferLayout<'static> {
|
|
188
|
+
wgpu::VertexBufferLayout {
|
|
189
|
+
array_stride: std::mem::size_of::<Self>() as wgpu::BufferAddress,
|
|
190
|
+
step_mode: wgpu::VertexStepMode::Vertex,
|
|
191
|
+
attributes: &[
|
|
192
|
+
wgpu::VertexAttribute { offset: 0, shader_location: 0, format: wgpu::VertexFormat::Float32x2 },
|
|
193
|
+
wgpu::VertexAttribute { offset: 8, shader_location: 1, format: wgpu::VertexFormat::Float32x2 },
|
|
194
|
+
wgpu::VertexAttribute { offset: 16, shader_location: 2, format: wgpu::VertexFormat::Float32x4 },
|
|
195
|
+
],
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
#[repr(C)]
|
|
201
|
+
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
|
|
202
|
+
pub struct Vertex3D {
|
|
203
|
+
pub position: [f32; 3],
|
|
204
|
+
pub normal: [f32; 3],
|
|
205
|
+
pub color: [f32; 4],
|
|
206
|
+
pub uv: [f32; 2],
|
|
207
|
+
pub joints: [f32; 4], // bone indices (as floats for simplicity)
|
|
208
|
+
pub weights: [f32; 4], // bone weights (sum to 1.0, or all 0.0 for unskinned)
|
|
209
|
+
pub tangent: [f32; 4], // xyz = tangent direction, w = bitangent sign (±1). All zero = no tangent data; scene shader then skips normal mapping.
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
impl Default for Vertex3D {
|
|
213
|
+
fn default() -> Self {
|
|
214
|
+
bytemuck::Zeroable::zeroed()
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
impl Vertex3D {
|
|
219
|
+
pub fn desc() -> wgpu::VertexBufferLayout<'static> {
|
|
220
|
+
wgpu::VertexBufferLayout {
|
|
221
|
+
array_stride: std::mem::size_of::<Self>() as wgpu::BufferAddress,
|
|
222
|
+
step_mode: wgpu::VertexStepMode::Vertex,
|
|
223
|
+
attributes: &[
|
|
224
|
+
wgpu::VertexAttribute { offset: 0, shader_location: 0, format: wgpu::VertexFormat::Float32x3 }, // position
|
|
225
|
+
wgpu::VertexAttribute { offset: 12, shader_location: 1, format: wgpu::VertexFormat::Float32x3 }, // normal
|
|
226
|
+
wgpu::VertexAttribute { offset: 24, shader_location: 2, format: wgpu::VertexFormat::Float32x4 }, // color
|
|
227
|
+
wgpu::VertexAttribute { offset: 40, shader_location: 3, format: wgpu::VertexFormat::Float32x2 }, // uv
|
|
228
|
+
wgpu::VertexAttribute { offset: 48, shader_location: 4, format: wgpu::VertexFormat::Float32x4 }, // joints
|
|
229
|
+
wgpu::VertexAttribute { offset: 64, shader_location: 5, format: wgpu::VertexFormat::Float32x4 }, // weights
|
|
230
|
+
wgpu::VertexAttribute { offset: 80, shader_location: 6, format: wgpu::VertexFormat::Float32x4 }, // tangent
|
|
231
|
+
],
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/// Per-instance data for materials compiled with `wants_instancing = true`.
|
|
237
|
+
/// Bound at vertex buffer slot 1, step_mode = Instance. Layout is fixed
|
|
238
|
+
/// at engine V1; future extensions can parameterise from a material desc.
|
|
239
|
+
///
|
|
240
|
+
/// Per-vertex attributes use shader_location 0..6. Per-instance
|
|
241
|
+
/// attributes start at shader_location 7. The TS-side flat layout is 9
|
|
242
|
+
/// floats per instance (pos.xyz, rot_y, scale, tint.rgba); the Rust
|
|
243
|
+
/// side pads each instance to 12 floats so the GPU stride matches the
|
|
244
|
+
/// 48-byte vec4-aligned layout.
|
|
245
|
+
#[repr(C)]
|
|
246
|
+
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
|
|
247
|
+
pub struct InstanceData3D {
|
|
248
|
+
pub position: [f32; 3], // world-space position
|
|
249
|
+
pub rot_y: f32, // Y-axis rotation in radians
|
|
250
|
+
pub scale: f32, // uniform scale multiplier (1.0 = no scale)
|
|
251
|
+
pub tint: [f32; 4], // RGBA tint multiplier (1,1,1,1 = no tint)
|
|
252
|
+
/// EN-026 — was pure padding to the 16-byte boundary; now carried to the
|
|
253
|
+
/// shader as `@location(11) instance_extra: vec3<f32>`. The three floats
|
|
254
|
+
/// were already being uploaded, so exposing them costs nothing: no stride
|
|
255
|
+
/// change, no extra bandwidth. Particles use them for (atlas frame,
|
|
256
|
+
/// velocity-stretch length, random seed); anything else can leave them 0
|
|
257
|
+
/// and simply not declare location 11 — a vertex buffer may carry
|
|
258
|
+
/// attributes the shader does not consume.
|
|
259
|
+
pub extra: [f32; 3],
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
impl InstanceData3D {
|
|
263
|
+
pub fn desc() -> wgpu::VertexBufferLayout<'static> {
|
|
264
|
+
wgpu::VertexBufferLayout {
|
|
265
|
+
array_stride: std::mem::size_of::<Self>() as wgpu::BufferAddress,
|
|
266
|
+
step_mode: wgpu::VertexStepMode::Instance,
|
|
267
|
+
attributes: &[
|
|
268
|
+
wgpu::VertexAttribute { offset: 0, shader_location: 7, format: wgpu::VertexFormat::Float32x3 }, // position
|
|
269
|
+
wgpu::VertexAttribute { offset: 12, shader_location: 8, format: wgpu::VertexFormat::Float32 }, // rot_y
|
|
270
|
+
wgpu::VertexAttribute { offset: 16, shader_location: 9, format: wgpu::VertexFormat::Float32 }, // scale
|
|
271
|
+
wgpu::VertexAttribute { offset: 20, shader_location: 10, format: wgpu::VertexFormat::Float32x4 }, // tint
|
|
272
|
+
wgpu::VertexAttribute { offset: 36, shader_location: 11, format: wgpu::VertexFormat::Float32x3 }, // extra (EN-026)
|
|
273
|
+
],
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// ============================================================
|
|
279
|
+
// Draw call tracking
|
|
280
|
+
// ============================================================
|
|
281
|
+
|
|
282
|
+
pub(super) struct DrawCall2D {
|
|
283
|
+
pub(super) texture_idx: u32,
|
|
284
|
+
pub(super) uniform_idx: u32,
|
|
285
|
+
pub(super) index_start: u32,
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
pub(super) struct DrawCall3D {
|
|
289
|
+
pub(super) texture_idx: u32,
|
|
290
|
+
pub(super) index_start: u32,
|
|
291
|
+
/// First vertex of this segment in `vertices_3d` — lets the shadow
|
|
292
|
+
/// pass lazily scan primitive-only segments for bounds.
|
|
293
|
+
pub(super) vertex_start: u32,
|
|
294
|
+
/// World AABB of the segment's content. Non-skinned verts contribute
|
|
295
|
+
/// their (already world-space) positions; skinned model draws
|
|
296
|
+
/// contribute the union of their joint-transformed rest AABBs (a
|
|
297
|
+
/// rigorous conservative bound: a skinned vertex is a convex blend
|
|
298
|
+
/// of per-joint transforms of the same rest position).
|
|
299
|
+
/// `wmin[0] > wmax[0]` = not yet computed.
|
|
300
|
+
pub(super) wmin: [f32; 3],
|
|
301
|
+
pub(super) wmax: [f32; 3],
|
|
302
|
+
/// Segment contains skinned (animated) vertices → its rendered
|
|
303
|
+
/// output changes every frame, so shadow caching must treat it as
|
|
304
|
+
/// always-dirty for the cascades it touches.
|
|
305
|
+
pub(super) has_skinned: bool,
|
|
306
|
+
/// FNV-1a over the non-skinned vertex positions appended to this
|
|
307
|
+
/// segment — a cheap content identity so static immediate geometry
|
|
308
|
+
/// (e.g. pickups re-submitted identically every frame) doesn't
|
|
309
|
+
/// dirty the shadow cascades it sits in.
|
|
310
|
+
pub(super) content_hash: u64,
|
|
311
|
+
/// True when bounds/hash were maintained inline (model draws).
|
|
312
|
+
/// False → primitive-only segment, scanned on demand.
|
|
313
|
+
pub(super) bounded: bool,
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
pub(super) const FNV_OFFSET: u64 = 0xcbf29ce484222325;
|
|
317
|
+
|
|
318
|
+
#[inline]
|
|
319
|
+
pub(super) fn fnv1a_bytes(mut h: u64, bytes: &[u8]) -> u64 {
|
|
320
|
+
for &b in bytes {
|
|
321
|
+
h ^= b as u64;
|
|
322
|
+
h = h.wrapping_mul(0x100000001b3);
|
|
323
|
+
}
|
|
324
|
+
h
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
#[derive(PartialEq, Clone, Copy)]
|
|
328
|
+
pub enum RenderMode {
|
|
329
|
+
ScreenSpace,
|
|
330
|
+
Mode2D,
|
|
331
|
+
Mode3D,
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// ============================================================
|
|
335
|
+
// Pass / compute uniform params (moved out of mod.rs, EN-052)
|
|
336
|
+
// ============================================================
|
|
337
|
+
// Pure POD uniform structs for the sky, GI, SSR, post, and PT
|
|
338
|
+
// passes plus the card-ortho helper. Fields are pub(super) so the
|
|
339
|
+
// renderer and its pass submodules can build them by literal.
|
|
340
|
+
|
|
341
|
+
#[repr(C)]
|
|
342
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
343
|
+
pub(super) struct PrefilterUniforms {
|
|
344
|
+
/// x = roughness (∈ [0, 1]), y = sample count, zw = mip resolution
|
|
345
|
+
pub(super) params: [f32; 4],
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// ============================================================
|
|
349
|
+
// Sky / equirectangular HDR background shader
|
|
350
|
+
// ============================================================
|
|
351
|
+
//
|
|
352
|
+
// Renders a fullscreen triangle with z=1 (far plane) and samples the
|
|
353
|
+
// environment map by the world-space view direction reconstructed from
|
|
354
|
+
// inverse VP. Tone-maps with the same ACES curve the rest of the
|
|
355
|
+
// renderer uses so the background blends seamlessly with lit
|
|
356
|
+
// geometry. Always overwrites depth — the 3D opaque pass drawn after
|
|
357
|
+
// will occlude wherever it has actual geometry.
|
|
358
|
+
|
|
359
|
+
#[repr(C)]
|
|
360
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
361
|
+
pub(super) struct SkyUniforms {
|
|
362
|
+
/// Camera right vector × tan(fovy/2) × aspect — pre-scaled so the
|
|
363
|
+
/// fragment shader just multiplies by NDC.x to get the horizontal
|
|
364
|
+
/// offset from the forward direction.
|
|
365
|
+
/// `.w` = camera world position X (see below).
|
|
366
|
+
pub(super) right: [f32; 4],
|
|
367
|
+
/// Camera up vector × tan(fovy/2). `.w` = camera world position Y.
|
|
368
|
+
pub(super) up: [f32; 4],
|
|
369
|
+
/// Camera forward unit vector. `.w` = camera world position Z.
|
|
370
|
+
///
|
|
371
|
+
/// The camera POSITION rides in the spare `.w` lanes of the three basis
|
|
372
|
+
/// vectors. The sky pass never needed it — a sky at infinity only cares
|
|
373
|
+
/// which way you are looking — but the cloud deck is anchored in world
|
|
374
|
+
/// space so that its shadow lands under it, and that makes the camera's
|
|
375
|
+
/// position load-bearing. Packing it here keeps the bind group unchanged.
|
|
376
|
+
pub(super) forward: [f32; 4],
|
|
377
|
+
/// x = intensity multiplier, y = elapsed seconds (the cloud deck's clock);
|
|
378
|
+
/// zw padding.
|
|
379
|
+
pub(super) intensity: [f32; 4],
|
|
380
|
+
/// Cloud deck: x = shadow strength, y = deck height (m), z = feature scale
|
|
381
|
+
/// (noise units per metre), w = drift speed (m/s). Same vec4 the world
|
|
382
|
+
/// materials get, so the sky and the ground cannot disagree.
|
|
383
|
+
pub(super) cloud: [f32; 4],
|
|
384
|
+
/// xy = wind direction in the XZ plane — the clouds drift downwind, the
|
|
385
|
+
/// same way the grass is leaning.
|
|
386
|
+
pub(super) wind: [f32; 4],
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// EN-005 Phase 2 — uniforms for the procedural sky path.
|
|
390
|
+
//
|
|
391
|
+
// `SkyViewParams` drives the sky-view LUT compute shader (recomputed
|
|
392
|
+
// when the sun moves). `SunUniforms` drives the per-frame sun-disk
|
|
393
|
+
// composite in the procedural sky fragment shader.
|
|
394
|
+
|
|
395
|
+
#[repr(C)]
|
|
396
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
397
|
+
pub(super) struct SkyViewParams {
|
|
398
|
+
/// xyz = sun direction (world space, unit), w = sun intensity scale.
|
|
399
|
+
pub(super) sun: [f32; 4],
|
|
400
|
+
/// x = rayleigh density mult, y = mie density mult, z = ground albedo, w unused.
|
|
401
|
+
pub(super) knobs: [f32; 4],
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
#[repr(C)]
|
|
405
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
406
|
+
pub(super) struct SunUniforms {
|
|
407
|
+
/// xyz = sun direction (unit), w = sun intensity.
|
|
408
|
+
pub(super) sun: [f32; 4],
|
|
409
|
+
/// x = sun angular radius (rad), y = limb darkening (0..1), zw unused.
|
|
410
|
+
pub(super) params: [f32; 4],
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// EN-005 V2 — aerial-perspective compute uniforms.
|
|
414
|
+
//
|
|
415
|
+
// Driven each frame from the renderer (camera + sun + atmosphere
|
|
416
|
+
// knobs). Layout must mirror `AerialParams` in
|
|
417
|
+
// AERIAL_PERSPECTIVE_SHADER_WGSL exactly.
|
|
418
|
+
#[repr(C)]
|
|
419
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
420
|
+
pub(super) struct AerialParams {
|
|
421
|
+
/// xyz = camera world position (engine units, metres assumed),
|
|
422
|
+
/// w = max distance the LUT covers (km).
|
|
423
|
+
pub(super) cam_pos: [f32; 4],
|
|
424
|
+
/// World→clip inverse, used per-voxel to reconstruct view rays
|
|
425
|
+
/// from NDC.
|
|
426
|
+
pub(super) inv_vp: [[f32; 4]; 4],
|
|
427
|
+
/// xyz = sun direction (unit), w = sun intensity scalar.
|
|
428
|
+
pub(super) sun: [f32; 4],
|
|
429
|
+
/// x = rayleigh density mult, y = mie density mult, zw unused.
|
|
430
|
+
pub(super) knobs: [f32; 4],
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
#[repr(C)]
|
|
435
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
436
|
+
pub(super) struct HizLinearizeParams {
|
|
437
|
+
/// xy = inv_size, z = proj[2][2], w = proj[3][2]
|
|
438
|
+
pub(super) params: [f32; 4],
|
|
439
|
+
/// xy = mip-0 size, zw unused
|
|
440
|
+
pub(super) size: [u32; 4],
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
#[repr(C)]
|
|
444
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
445
|
+
pub(super) struct HizDownsampleParams {
|
|
446
|
+
/// xy = dst-mip size, zw unused
|
|
447
|
+
pub(super) size: [u32; 4],
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
#[repr(C)]
|
|
451
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
452
|
+
pub(super) struct SsaoParams {
|
|
453
|
+
/// xy = inv_size (1/half_w, 1/half_h), z = radius (world units),
|
|
454
|
+
/// w = strength
|
|
455
|
+
pub(super) params: [f32; 4],
|
|
456
|
+
/// x = proj[0][0], y = proj[1][1], z = proj[2][0] (TAA jitter),
|
|
457
|
+
/// w = proj[2][1] (TAA jitter). Column-major: proj[col][row].
|
|
458
|
+
pub(super) proj_row01: [f32; 4],
|
|
459
|
+
/// x = proj[2][2], y = proj[3][2], z = 1/proj[0][0], w = 1/proj[1][1]
|
|
460
|
+
pub(super) proj_z: [f32; 4],
|
|
461
|
+
/// Light direction in view space (xyz, w unused). For contact shadows.
|
|
462
|
+
pub(super) light_dir_vs: [f32; 4],
|
|
463
|
+
/// x = half-res width, y = half-res height, z = frame phase
|
|
464
|
+
/// (`frame_index % 4`), w = "force-refresh" flag (non-zero on
|
|
465
|
+
/// first few frames, resize, or any host-side history invalidation).
|
|
466
|
+
pub(super) size: [u32; 4],
|
|
467
|
+
/// x = temporal blend alpha (≈0.25 steady, 4-frame EMA).
|
|
468
|
+
/// y = per-frame Halton-5 rotation of the direction basis
|
|
469
|
+
/// (uncorrelated with TAA's Halton-2/3 pixel jitter).
|
|
470
|
+
/// zw unused.
|
|
471
|
+
pub(super) temporal: [f32; 4],
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// ============================================================
|
|
475
|
+
// SSAO Bilateral Blur post-process
|
|
476
|
+
// ============================================================
|
|
477
|
+
|
|
478
|
+
#[repr(C)]
|
|
479
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
480
|
+
pub(super) struct SsaoBlurParams {
|
|
481
|
+
/// xy = texel_size (of the half-res SSAO RT), z = depth_sigma, w = unused.
|
|
482
|
+
pub(super) params: [f32; 4],
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// ============================================================
|
|
486
|
+
// Depth of Field (DoF) post-process
|
|
487
|
+
// ============================================================
|
|
488
|
+
|
|
489
|
+
#[repr(C)]
|
|
490
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
491
|
+
pub(super) struct DofParams {
|
|
492
|
+
/// x = focus_distance, y = aperture, z = max_blur_radius (UV), w = unused
|
|
493
|
+
pub(super) params: [f32; 4],
|
|
494
|
+
/// Inverse projection matrix — used to linearize depth.
|
|
495
|
+
pub(super) inv_proj: [[f32; 4]; 4],
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// ============================================================
|
|
499
|
+
// Motion Blur post-process
|
|
500
|
+
// ============================================================
|
|
501
|
+
//
|
|
502
|
+
// Reads the TAA/DoF output (color) and the per-pixel velocity buffer.
|
|
503
|
+
// For each pixel, samples 8 taps along the velocity direction with a
|
|
504
|
+
// tent (linear) weight, blending them into a directionally-blurred
|
|
505
|
+
// result. Default OFF — no perf cost when disabled.
|
|
506
|
+
|
|
507
|
+
#[repr(C)]
|
|
508
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
509
|
+
pub(super) struct MotionBlurParams {
|
|
510
|
+
/// x = strength, y = max_blur (UV), zw = unused.
|
|
511
|
+
pub(super) params: [f32; 4],
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// ============================================================
|
|
515
|
+
// Screen-Space Subsurface Scattering (SSS) post-process
|
|
516
|
+
// ============================================================
|
|
517
|
+
//
|
|
518
|
+
// Single-pass 9-tap disc blur applied after the motion blur pass
|
|
519
|
+
// (pre-composite). Uses a chromatic diffusion profile where red
|
|
520
|
+
// scatters furthest (kernel width 1×), green 0.5×, blue 0.25×,
|
|
521
|
+
// simulating the spectral absorption of skin/wax/leaves.
|
|
522
|
+
// Depth-guided bilateral weighting prevents color bleeding across
|
|
523
|
+
// depth discontinuities (hard edges stay sharp). Default OFF.
|
|
524
|
+
|
|
525
|
+
#[repr(C)]
|
|
526
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
527
|
+
pub(super) struct SssParams {
|
|
528
|
+
/// x = strength, y = width, z = falloff, w = unused.
|
|
529
|
+
pub(super) params: [f32; 4],
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// ============================================================
|
|
533
|
+
// SSGI (Screen-Space Global Illumination) post-process
|
|
534
|
+
// ============================================================
|
|
535
|
+
|
|
536
|
+
// Ticket 007a: per-pass uniform params for the screen-probe SSGI chain.
|
|
537
|
+
|
|
538
|
+
#[repr(C)]
|
|
539
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
540
|
+
pub(super) struct ProbePlaceParams {
|
|
541
|
+
pub(super) inv_view: [[f32; 4]; 4],
|
|
542
|
+
/// x = proj[0][0], y = proj[1][1], z = proj[2][0], w = proj[2][1]
|
|
543
|
+
pub(super) proj_row01: [f32; 4],
|
|
544
|
+
/// x = half_w, y = half_h, z = grid_w, w = grid_h
|
|
545
|
+
pub(super) size: [u32; 4],
|
|
546
|
+
/// x = frame_index, y = tile_size (16.0), zw unused
|
|
547
|
+
pub(super) params: [f32; 4],
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
#[repr(C)]
|
|
551
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
552
|
+
pub(super) struct ProbeTraceParams {
|
|
553
|
+
pub(super) view: [[f32; 4]; 4],
|
|
554
|
+
pub(super) proj: [[f32; 4]; 4],
|
|
555
|
+
pub(super) inv_view: [[f32; 4]; 4],
|
|
556
|
+
pub(super) proj_row01: [f32; 4],
|
|
557
|
+
pub(super) size: [u32; 4],
|
|
558
|
+
/// x = frame_index, y = intensity, z = max_march_t (world units),
|
|
559
|
+
/// w = firefly luma cap.
|
|
560
|
+
pub(super) params: [f32; 4],
|
|
561
|
+
/// Ticket 007b HW path — sun direction in world space (xyz) +
|
|
562
|
+
/// intensity (w). Ignored by the SW-HiZ shader, consumed by HW + SDF.
|
|
563
|
+
pub(super) sun_dir: [f32; 4],
|
|
564
|
+
/// Sun colour (xyz), reserved (w). Used for analytical NdotL at hit.
|
|
565
|
+
pub(super) sun_color: [f32; 4],
|
|
566
|
+
/// Sky dome colour (xyz), reserved (w). Flat analytic sky for
|
|
567
|
+
/// up-facing hits where the ray hits a surface with an up normal.
|
|
568
|
+
pub(super) sky_color: [f32; 4],
|
|
569
|
+
/// Ticket 014 V3 — clipmap origin (xyz) + full extent (w). Used
|
|
570
|
+
/// by the SDF sphere-trace variant to map world-space march
|
|
571
|
+
/// positions into clipmap sample UVs.
|
|
572
|
+
pub(super) clipmap: [f32; 4],
|
|
573
|
+
/// Ticket 014 V6/V13 — WSRC cascade cubes. Each entry is
|
|
574
|
+
/// (origin xyz, extent w). Cascades are ordered near→far; miss
|
|
575
|
+
/// paths pick the smallest cascade whose cube contains the
|
|
576
|
+
/// ray-terminal position. `extent = 0.0` marks an unbaked
|
|
577
|
+
/// cascade (shader falls through to the next one). HW + Hi-Z
|
|
578
|
+
/// carry these for uniform-buffer size parity; Hi-Z ignores
|
|
579
|
+
/// them.
|
|
580
|
+
pub(super) wsrc_cascades: [[f32; 4]; 3],
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/// PT-2 — fixed size of the kernel's texture binding array. Real texture
|
|
584
|
+
/// indices at or above this clamp to 0 (white); unused tail slots are
|
|
585
|
+
/// padded with the white texture so no PARTIALLY_BOUND feature is needed.
|
|
586
|
+
pub(super) const PT_MAX_TEXTURES: usize = 256;
|
|
587
|
+
|
|
588
|
+
/// Uniform for the path-tracing megakernel — WGSL mirror `PtParams` in
|
|
589
|
+
/// shaders/pt.rs. Field-for-field, 16-byte aligned, 672 bytes.
|
|
590
|
+
#[repr(C)]
|
|
591
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
592
|
+
pub(super) struct PtParamsCpu {
|
|
593
|
+
pub(super) inv_vp: [[f32; 4]; 4],
|
|
594
|
+
/// PT-3 — previous frame's unjittered VP (transposed like inv_vp)
|
|
595
|
+
/// for temporal history reprojection in realtime mode.
|
|
596
|
+
pub(super) prev_vp: [[f32; 4]; 4],
|
|
597
|
+
/// xyz camera world pos, w unused.
|
|
598
|
+
pub(super) cam_pos: [f32; 4],
|
|
599
|
+
/// xyz unit vector toward the sun, w unused.
|
|
600
|
+
pub(super) sun_dir: [f32; 4],
|
|
601
|
+
/// rgb premultiplied by intensity, w unused.
|
|
602
|
+
pub(super) sun_color: [f32; 4],
|
|
603
|
+
/// rgb ambient-derived sky tint, w unused.
|
|
604
|
+
pub(super) sky_color: [f32; 4],
|
|
605
|
+
/// x/y = TRACE grid dims (half in realtime mode), z=frame_index,
|
|
606
|
+
/// w=accum_count.
|
|
607
|
+
pub(super) size: [u32; 4],
|
|
608
|
+
/// x=mode (1 progressive / 2 realtime), y=max_bounces,
|
|
609
|
+
/// z=point_light_count (≤16), w=debug view (BLOOM_PT_DEBUG).
|
|
610
|
+
pub(super) cfg: [f32; 4],
|
|
611
|
+
/// PT-3 half-res: x/y = full G-buffer dims. z = 1 → hybrid sun
|
|
612
|
+
/// (shadow cascades instead of traced sun rays). w unused.
|
|
613
|
+
pub(super) ext: [u32; 4],
|
|
614
|
+
/// Raster shadow cascade VPs, transposed at upload like inv_vp.
|
|
615
|
+
pub(super) shadow_vps: [[[f32; 4]; 4]; 3],
|
|
616
|
+
/// 16 lights × (pos_range vec4, color_int vec4).
|
|
617
|
+
pub(super) lights: [[f32; 4]; 32],
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
#[repr(C)]
|
|
621
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
622
|
+
pub(super) struct ProbeTemporalParams {
|
|
623
|
+
/// x = alpha (EMA), y = force_refresh (1→alpha=1), z = grid_w (f32), w = grid_h (f32)
|
|
624
|
+
pub(super) params: [f32; 4],
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
#[repr(C)]
|
|
628
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
629
|
+
pub(super) struct ProbeResolveParams {
|
|
630
|
+
pub(super) inv_view: [[f32; 4]; 4],
|
|
631
|
+
pub(super) proj_row01: [f32; 4],
|
|
632
|
+
/// x = half_w, y = half_h, z = grid_w, w = grid_h
|
|
633
|
+
pub(super) size: [u32; 4],
|
|
634
|
+
/// x = tile_size (16.0), y = intensity, zw unused
|
|
635
|
+
pub(super) params: [f32; 4],
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/// On-GPU `ProbeHeader` layout (must match PROBE_HELPERS_WGSL's struct).
|
|
639
|
+
/// 32 bytes per probe.
|
|
640
|
+
#[repr(C)]
|
|
641
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
642
|
+
pub(super) struct ProbeHeaderCpu {
|
|
643
|
+
pub(super) world_pos: [f32; 4],
|
|
644
|
+
pub(super) normal: [f32; 4],
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/// Ticket 013 V3 — CardCaptureParams. ortho_vp + base_color + emissive.
|
|
648
|
+
/// 96 bytes; we allocate 128 for uniform-alignment headroom.
|
|
649
|
+
#[repr(C)]
|
|
650
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
651
|
+
pub(super) struct CardCaptureParams {
|
|
652
|
+
pub(super) ortho_vp: [[f32; 4]; 4],
|
|
653
|
+
pub(super) base_color: [f32; 4], // rgb = factor, w = has_base_texture (0/1)
|
|
654
|
+
pub(super) emissive: [f32; 4], // rgb = emissive_factor, w = has_emissive_texture (0/1)
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/// Ticket 013 V2 — orthographic projection for the 6 signed axes.
|
|
658
|
+
/// `face_axis` encoding:
|
|
659
|
+
/// 0 → +X, 1 → -X, 2 → +Y, 3 → -Y, 4 → +Z, 5 → -Z.
|
|
660
|
+
/// For each face we pick the two orthogonal AABB axes and map them
|
|
661
|
+
/// to clip-space [-1, +1]. The ±pair for each axis differ only in
|
|
662
|
+
/// the sign of the "u" clip axis so that when the HW shader picks
|
|
663
|
+
/// axis N at hit and projects the hit into card UV, the UV lines up
|
|
664
|
+
/// with the mesh geometry as seen FROM that face.
|
|
665
|
+
pub(super) fn build_card_ortho_v2(face_axis: u32, bmin: [f32; 3], bmax: [f32; 3]) -> [[f32; 4]; 4] {
|
|
666
|
+
let wx = (bmax[0] - bmin[0]).max(1e-4);
|
|
667
|
+
let wy = (bmax[1] - bmin[1]).max(1e-4);
|
|
668
|
+
let wz = (bmax[2] - bmin[2]).max(1e-4);
|
|
669
|
+
let cx = bmin[0] + bmax[0];
|
|
670
|
+
let cy = bmin[1] + bmax[1];
|
|
671
|
+
let cz = bmin[2] + bmax[2];
|
|
672
|
+
match face_axis {
|
|
673
|
+
// +X → project onto YZ; clip.x = y, clip.y = z.
|
|
674
|
+
0 => [
|
|
675
|
+
[0.0, 0.0, 0.0, 0.0],
|
|
676
|
+
[2.0/wy, 0.0, 0.0, 0.0],
|
|
677
|
+
[0.0, 2.0/wz, 0.0, 0.0],
|
|
678
|
+
[-cy/wy, -cz/wz, 0.0, 1.0],
|
|
679
|
+
],
|
|
680
|
+
// -X → flip u so the -X view is the mirror of +X. clip.x = -y, clip.y = z.
|
|
681
|
+
1 => [
|
|
682
|
+
[0.0, 0.0, 0.0, 0.0],
|
|
683
|
+
[-2.0/wy, 0.0, 0.0, 0.0],
|
|
684
|
+
[0.0, 2.0/wz, 0.0, 0.0],
|
|
685
|
+
[cy/wy, -cz/wz, 0.0, 1.0],
|
|
686
|
+
],
|
|
687
|
+
// +Y → project onto XZ; clip.x = x, clip.y = z.
|
|
688
|
+
2 => [
|
|
689
|
+
[2.0/wx, 0.0, 0.0, 0.0],
|
|
690
|
+
[0.0, 0.0, 0.0, 0.0],
|
|
691
|
+
[0.0, 2.0/wz, 0.0, 0.0],
|
|
692
|
+
[-cx/wx, -cz/wz, 0.0, 1.0],
|
|
693
|
+
],
|
|
694
|
+
// -Y → flip u; clip.x = -x, clip.y = z.
|
|
695
|
+
3 => [
|
|
696
|
+
[-2.0/wx, 0.0, 0.0, 0.0],
|
|
697
|
+
[0.0, 0.0, 0.0, 0.0],
|
|
698
|
+
[0.0, 2.0/wz, 0.0, 0.0],
|
|
699
|
+
[cx/wx, -cz/wz, 0.0, 1.0],
|
|
700
|
+
],
|
|
701
|
+
// +Z → project onto XY; clip.x = x, clip.y = y.
|
|
702
|
+
4 => [
|
|
703
|
+
[2.0/wx, 0.0, 0.0, 0.0],
|
|
704
|
+
[0.0, 2.0/wy, 0.0, 0.0],
|
|
705
|
+
[0.0, 0.0, 0.0, 0.0],
|
|
706
|
+
[-cx/wx, -cy/wy, 0.0, 1.0],
|
|
707
|
+
],
|
|
708
|
+
// -Z → flip u; clip.x = -x, clip.y = y.
|
|
709
|
+
_ => [
|
|
710
|
+
[-2.0/wx, 0.0, 0.0, 0.0],
|
|
711
|
+
[0.0, 2.0/wy, 0.0, 0.0],
|
|
712
|
+
[0.0, 0.0, 0.0, 0.0],
|
|
713
|
+
[cx/wx, -cy/wy, 0.0, 1.0],
|
|
714
|
+
],
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
/// Ticket 014 — per-mesh SDF bake uniform.
|
|
719
|
+
#[repr(C)]
|
|
720
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
721
|
+
pub(super) struct SdfBakeParams {
|
|
722
|
+
pub(super) aabb_min: [f32; 4],
|
|
723
|
+
pub(super) aabb_max: [f32; 4],
|
|
724
|
+
/// x = triangle_count, y = sdf_resolution (32), zw unused
|
|
725
|
+
pub(super) counts: [u32; 4],
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/// Fullscreen-lag fix — an in-flight amortized scene-SDF-clipmap bake.
|
|
729
|
+
/// A job bakes `SCENE_SDF_CLIPMAP_LAYERS_PER_FRAME` voxel Z-layers per
|
|
730
|
+
/// frame into the staging texture; when the last slice lands the staging
|
|
731
|
+
/// contents are copied over the live clipmap and the origin flips
|
|
732
|
+
/// atomically, so traces never observe a half-baked field. The bind
|
|
733
|
+
/// group keeps the job's transient buffers alive.
|
|
734
|
+
pub(super) struct SdfClipmapBakeJob {
|
|
735
|
+
pub(super) origin: [f32; 3],
|
|
736
|
+
pub(super) aabb_min: [f32; 4],
|
|
737
|
+
pub(super) aabb_max: [f32; 4],
|
|
738
|
+
pub(super) uniform: wgpu::Buffer,
|
|
739
|
+
pub(super) bind_group: wgpu::BindGroup,
|
|
740
|
+
pub(super) next_z: u32,
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
/// Ticket 014 V6 — uniform for `WSRC_BAKE_WGSL`. Analytic sun × shadow
|
|
744
|
+
/// + analytic sky computed per probe-octel. Shadow VPs + splits +
|
|
745
|
+
/// flags mirror CARD_LIGHT_WGSL so the shader can re-use the same
|
|
746
|
+
/// cascade-sampling helper.
|
|
747
|
+
#[repr(C)]
|
|
748
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
749
|
+
pub(super) struct WsrcBakeParams {
|
|
750
|
+
pub(super) sun_dir: [f32; 4],
|
|
751
|
+
pub(super) sun_color: [f32; 4],
|
|
752
|
+
pub(super) sky_color: [f32; 4],
|
|
753
|
+
/// xyz = WSRC cube origin, w = full extent.
|
|
754
|
+
pub(super) grid: [f32; 4],
|
|
755
|
+
/// Cascade 0..2 VPs. Only cascade 2 is actually sampled by V6
|
|
756
|
+
/// (widest cascade covers the whole 120 m cube), but we carry
|
|
757
|
+
/// all three to keep the uniform layout identical to the card-
|
|
758
|
+
/// lighting params.
|
|
759
|
+
pub(super) shadow_vps: [[[f32; 4]; 4]; 3],
|
|
760
|
+
/// xyz = view-space split distances (unused by V6 because it
|
|
761
|
+
/// always samples cascade 2), w = 0.
|
|
762
|
+
pub(super) shadow_splits: [f32; 4],
|
|
763
|
+
/// x = shadow bias, y = shadows_enabled (0/1), zw unused.
|
|
764
|
+
pub(super) flags: [f32; 4],
|
|
765
|
+
/// EN-023 — xyz = scene-average albedo (mean of card-instance flat
|
|
766
|
+
/// albedos) for the SW bake's ground-bounce term; w unused. The HW
|
|
767
|
+
/// bake ignores it (it traces real geometry).
|
|
768
|
+
pub(super) ground_albedo: [f32; 4],
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/// Uniform struct for the card-lighting compute pass. Matches
|
|
772
|
+
/// CARD_LIGHT_WGSL.
|
|
773
|
+
#[repr(C)]
|
|
774
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
775
|
+
pub(super) struct CardLightParams {
|
|
776
|
+
pub(super) sun_dir: [f32; 4],
|
|
777
|
+
pub(super) sun_color: [f32; 4],
|
|
778
|
+
pub(super) sky_color: [f32; 4],
|
|
779
|
+
/// [atlas_size, slot_size, slots_per_row, active_slot_count]
|
|
780
|
+
pub(super) atlas_info: [u32; 4],
|
|
781
|
+
/// Shadow cascade VPs (3× mat4) — identity when shadows disabled.
|
|
782
|
+
pub(super) shadow_vps: [[[f32; 4]; 4]; 3],
|
|
783
|
+
/// xyz = view-space split distances for cascades 0/1/2, w = 0.
|
|
784
|
+
pub(super) shadow_splits: [f32; 4],
|
|
785
|
+
/// Camera view matrix — needed to convert card-texel world pos
|
|
786
|
+
/// into view-space Z for cascade selection.
|
|
787
|
+
pub(super) view_matrix: [[f32; 4]; 4],
|
|
788
|
+
/// x = shadow bias, y = shadows_enabled (0/1), zw unused.
|
|
789
|
+
pub(super) flags: [f32; 4],
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
/// Ticket 013 V3 — per-slot metadata consumed by `card_light_pass`.
|
|
793
|
+
/// Baked at capture time; carries enough state for the lighting
|
|
794
|
+
/// shader to reconstruct each texel's world-space position and query
|
|
795
|
+
/// the shadow cascade at that point. 128 bytes per slot × 4096 slots
|
|
796
|
+
/// = 512 KB — fits comfortably.
|
|
797
|
+
#[repr(C)]
|
|
798
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
799
|
+
pub(super) struct CardSlotMetaCpu {
|
|
800
|
+
/// xyz = world-space card-face normal, w = signed axis (0..6 as f32).
|
|
801
|
+
pub(super) normal_ws: [f32; 4],
|
|
802
|
+
/// Object-space AABB min (xyz) + padding (w).
|
|
803
|
+
pub(super) aabb_min: [f32; 4],
|
|
804
|
+
/// Object-space AABB max (xyz) + padding (w).
|
|
805
|
+
pub(super) aabb_max: [f32; 4],
|
|
806
|
+
/// Mesh's world transform. Multiplied into the object-space
|
|
807
|
+
/// card-plane position to land in world space for shadow lookup.
|
|
808
|
+
pub(super) transform: [[f32; 4]; 4],
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/// Ticket 007b — per-TLAS-instance GI shading input. Indexed by the
|
|
812
|
+
/// hit's `instance_custom_data` in the HW trace shader. Layout must
|
|
813
|
+
/// match the `InstanceGIData` struct in SSGI_PROBE_TRACE_HW_WGSL.
|
|
814
|
+
#[repr(C)]
|
|
815
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
816
|
+
pub(super) struct InstanceGiDataCpu {
|
|
817
|
+
/// Flat albedo (per-mesh, pre-baked from material base-color).
|
|
818
|
+
/// Used as a fallback when `card_slot.w < 0` (no card captured).
|
|
819
|
+
pub(super) albedo: [f32; 3],
|
|
820
|
+
/// Scalar emissive luminance — multiplied by `albedo` at the hit.
|
|
821
|
+
pub(super) emissive_luma: f32,
|
|
822
|
+
/// Flat world-space mesh normal. Rough — averaged over vertex
|
|
823
|
+
/// normals at BLAS build time. Used when the card atlas is
|
|
824
|
+
/// unavailable; ticket 013's textured path still drives lighting
|
|
825
|
+
/// from this flat normal but multiplies the sampled albedo in.
|
|
826
|
+
pub(super) normal_ws: [f32; 3],
|
|
827
|
+
pub(super) _pad0: f32,
|
|
828
|
+
/// Ticket 013 — card slot for textured hit shading.
|
|
829
|
+
/// `card_slot.xy` = atlas slot coord (0..CARD_SLOTS_PER_ROW).
|
|
830
|
+
/// `card_slot.z` = dominant axis (0=X, 1=Y, 2=Z).
|
|
831
|
+
/// `card_slot.w` = flag (1.0 = card captured, 0.0 = no card → fall
|
|
832
|
+
/// back to `albedo` flat value).
|
|
833
|
+
pub(super) card_slot: [f32; 4],
|
|
834
|
+
/// Object-space AABB min (xyz) + unused pad (w). The HW paths
|
|
835
|
+
/// transform hits into object space (hit.world_to_object) and
|
|
836
|
+
/// compare against THESE — do not world-ify them.
|
|
837
|
+
pub(super) card_aabb_min: [f32; 4],
|
|
838
|
+
/// Object-space AABB max (xyz) + unused pad (w).
|
|
839
|
+
pub(super) card_aabb_max: [f32; 4],
|
|
840
|
+
/// EN-023 — WORLD-space AABB min/max. The SDF trace has no
|
|
841
|
+
/// world_to_object (it marches a world-space clipmap), so its
|
|
842
|
+
/// broad-phase compares the world hit against these. With the old
|
|
843
|
+
/// object-space-only bounds, every transformed instance fell
|
|
844
|
+
/// through to the flat-gray analytic fallback — zero colored
|
|
845
|
+
/// bounce on non-RT adapters (round-2 audit F4).
|
|
846
|
+
pub(super) world_aabb_min: [f32; 4],
|
|
847
|
+
pub(super) world_aabb_max: [f32; 4],
|
|
848
|
+
/// PT-2 — geometry window into the PT megabuffers + texture id.
|
|
849
|
+
/// x = first vertex (Vertex3D-stride slot) in pt_geo_vertices,
|
|
850
|
+
/// y = first index in pt_geo_indices, z = index count,
|
|
851
|
+
/// w = albedo texture index (renderer texture store; 0 = white).
|
|
852
|
+
/// z == 0 marks "no geometry window" (kernel falls back to the
|
|
853
|
+
/// flat normal + card albedo, i.e. PT-1 behaviour).
|
|
854
|
+
pub(super) geo: [u32; 4],
|
|
855
|
+
/// PT-2 — x = roughness, y = metalness, z/w unused.
|
|
856
|
+
pub(super) mat_params: [f32; 4],
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
#[repr(C)]
|
|
860
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
861
|
+
pub(super) struct SsrTemporalParams {
|
|
862
|
+
/// x = blend_alpha (0.1), yzw unused
|
|
863
|
+
pub(super) params: [f32; 4],
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
#[repr(C)]
|
|
867
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
868
|
+
pub(super) struct SsrParams {
|
|
869
|
+
pub(super) inv_proj: [[f32; 4]; 4],
|
|
870
|
+
pub(super) proj: [[f32; 4]; 4],
|
|
871
|
+
/// x=strength, y=max_dist, z=n_steps, w=frame index
|
|
872
|
+
pub(super) params: [f32; 4],
|
|
873
|
+
/// EN-021 — view→world rotation (transpose of the view 3×3) for the
|
|
874
|
+
/// env-miss fallback's direction lookup.
|
|
875
|
+
pub(super) inv_view_rot: [[f32; 4]; 4],
|
|
876
|
+
/// EN-021 — x = env max LOD, y = env intensity, zw unused.
|
|
877
|
+
pub(super) params2: [f32; 4],
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
#[repr(C)]
|
|
881
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
882
|
+
pub(super) struct SceneComposeParams {
|
|
883
|
+
pub(super) misc: [f32; 4],
|
|
884
|
+
pub(super) inv_vp: [[f32; 4]; 4],
|
|
885
|
+
pub(super) fog_color_density: [f32; 4],
|
|
886
|
+
pub(super) fog_params: [f32; 4],
|
|
887
|
+
pub(super) sun_shaft_uv_strength: [f32; 4],
|
|
888
|
+
pub(super) sun_shaft_color: [f32; 4],
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
#[repr(C)]
|
|
892
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
893
|
+
pub(super) struct TaaParams {
|
|
894
|
+
/// x = blend factor (current-frame weight), yzw padding.
|
|
895
|
+
pub(super) params: [f32; 4],
|
|
896
|
+
pub(super) inv_vp: [[f32; 4]; 4],
|
|
897
|
+
pub(super) prev_vp: [[f32; 4]; 4],
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
#[repr(C)]
|
|
901
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
902
|
+
pub(super) struct UpscaleParams {
|
|
903
|
+
/// x = mode (0 = bilinear, 1 = Catmull-Rom), yzw padding.
|
|
904
|
+
pub(super) params: [f32; 4],
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
#[repr(C)]
|
|
908
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
909
|
+
pub(super) struct RcasParams {
|
|
910
|
+
/// x = sharpen strength (0 off, 1 max), yzw padding.
|
|
911
|
+
pub(super) params: [f32; 4],
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
#[repr(C)]
|
|
915
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
916
|
+
pub(super) struct ExposureParams {
|
|
917
|
+
pub(super) params: [f32; 4],
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
#[repr(C)]
|
|
921
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
922
|
+
pub(super) struct BloomParams {
|
|
923
|
+
/// xy = source texel size, z = filter radius (upsample),
|
|
924
|
+
/// w = HDR threshold (downsample-threshold variant).
|
|
925
|
+
pub(super) params: [f32; 4],
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
#[repr(C)]
|
|
929
|
+
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
930
|
+
pub(super) struct CompositeParams {
|
|
931
|
+
/// x = tonemap kind (0 ACES / 1 AgX), y = auto-exposure toggle,
|
|
932
|
+
/// z = manual exposure, w = auto-exposure target key.
|
|
933
|
+
pub(super) params: [f32; 4],
|
|
934
|
+
/// Filmic-look knobs — see WGSL comment.
|
|
935
|
+
/// x = chromatic-aberration strength, y = vignette strength,
|
|
936
|
+
/// z = vignette softness, w = grain strength.
|
|
937
|
+
pub(super) filmic: [f32; 4],
|
|
938
|
+
/// x = grain seed (frame index, animates the noise),
|
|
939
|
+
/// y = sharpen strength, zw padding.
|
|
940
|
+
pub(super) misc: [f32; 4],
|
|
941
|
+
}
|