@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,205 @@
|
|
|
1
|
+
// Trivial WGSL include preprocessor.
|
|
2
|
+
//
|
|
3
|
+
// Resolves `#include "path"` directives against a virtual filesystem
|
|
4
|
+
// supplied by the caller (usually a baked `&[(&str, &str)]` table of
|
|
5
|
+
// `(path, contents)` for release builds, or a live `std::fs` read in
|
|
6
|
+
// debug builds with hot reload).
|
|
7
|
+
//
|
|
8
|
+
// Not a general C-preprocessor: no macros, no conditionals. Just text
|
|
9
|
+
// substitution with include-guard tracking so a header included by two
|
|
10
|
+
// shaders is emitted exactly once.
|
|
11
|
+
//
|
|
12
|
+
// Kept deliberately small — ~120 lines — so the render-graph migration
|
|
13
|
+
// doesn't pick up a heavyweight dependency (naga-oil) for a feature
|
|
14
|
+
// we'll use in ~20 shaders.
|
|
15
|
+
|
|
16
|
+
use std::collections::HashSet;
|
|
17
|
+
|
|
18
|
+
/// Something that can resolve an include path to its WGSL source.
|
|
19
|
+
/// Release builds use a baked slice; debug builds read from disk.
|
|
20
|
+
pub trait ShaderSource {
|
|
21
|
+
fn fetch(&self, path: &str) -> Option<&str>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/// Build-time baked table. Populate with `include_str!` in a const
|
|
25
|
+
/// array, build a `BakedSource` with it, pass it to `process`.
|
|
26
|
+
pub struct BakedSource<'a> {
|
|
27
|
+
pub entries: &'a [(&'a str, &'a str)],
|
|
28
|
+
}
|
|
29
|
+
impl<'a> ShaderSource for BakedSource<'a> {
|
|
30
|
+
fn fetch(&self, path: &str) -> Option<&str> {
|
|
31
|
+
self.entries.iter().find(|(p, _)| *p == path).map(|(_, s)| *s)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// Errors from the preprocessor. Always recoverable (caller keeps the
|
|
36
|
+
/// old pipeline and logs).
|
|
37
|
+
#[derive(Debug)]
|
|
38
|
+
pub enum IncludeError {
|
|
39
|
+
/// `#include "x"` where `x` isn't in the source table.
|
|
40
|
+
Missing { referrer: String, included: String },
|
|
41
|
+
/// An ill-formed `#include` line (missing quotes, etc.).
|
|
42
|
+
MalformedDirective { referrer: String, line: String },
|
|
43
|
+
/// A shader includes itself transitively.
|
|
44
|
+
CircularInclude { path: String },
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// Parse the optional ABI version from a `// ABI-VERSION: N` comment
|
|
48
|
+
/// at the top of a shader source. Returns 0 if absent. Used to fail
|
|
49
|
+
/// pipeline creation early when a stale shader predates a header bump.
|
|
50
|
+
pub fn abi_version_of(source: &str) -> u32 {
|
|
51
|
+
for line in source.lines().take(20) {
|
|
52
|
+
let trimmed = line.trim_start();
|
|
53
|
+
if let Some(rest) = trimmed.strip_prefix("// ABI-VERSION:") {
|
|
54
|
+
if let Ok(v) = rest.trim().parse::<u32>() {
|
|
55
|
+
return v;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
0
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/// Recursively resolve `#include "..."` directives in `entry_path`'s
|
|
63
|
+
/// source, returning the fully-expanded WGSL. Each included file is
|
|
64
|
+
/// emitted exactly once even if referenced multiple times.
|
|
65
|
+
pub fn process(
|
|
66
|
+
source: &dyn ShaderSource, entry_path: &str,
|
|
67
|
+
) -> Result<String, IncludeError> {
|
|
68
|
+
let mut out = String::new();
|
|
69
|
+
let mut seen = HashSet::new();
|
|
70
|
+
expand(source, entry_path, entry_path, &mut out, &mut seen, &mut Vec::new())?;
|
|
71
|
+
Ok(out)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
fn expand(
|
|
75
|
+
source: &dyn ShaderSource,
|
|
76
|
+
current_path: &str,
|
|
77
|
+
referrer: &str,
|
|
78
|
+
out: &mut String,
|
|
79
|
+
seen: &mut HashSet<String>,
|
|
80
|
+
stack: &mut Vec<String>,
|
|
81
|
+
) -> Result<(), IncludeError> {
|
|
82
|
+
if seen.contains(current_path) {
|
|
83
|
+
// Already included — emit nothing. This is the include-guard
|
|
84
|
+
// mechanism; headers are idempotent.
|
|
85
|
+
return Ok(());
|
|
86
|
+
}
|
|
87
|
+
if stack.iter().any(|p| p == current_path) {
|
|
88
|
+
return Err(IncludeError::CircularInclude {
|
|
89
|
+
path: current_path.to_string(),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
seen.insert(current_path.to_string());
|
|
93
|
+
stack.push(current_path.to_string());
|
|
94
|
+
|
|
95
|
+
let body = source.fetch(current_path).ok_or_else(|| IncludeError::Missing {
|
|
96
|
+
referrer: referrer.to_string(),
|
|
97
|
+
included: current_path.to_string(),
|
|
98
|
+
})?;
|
|
99
|
+
|
|
100
|
+
for (line_idx, line) in body.lines().enumerate() {
|
|
101
|
+
let trimmed = line.trim_start();
|
|
102
|
+
if let Some(rest) = trimmed.strip_prefix("#include") {
|
|
103
|
+
let include_path = parse_include_arg(rest).ok_or_else(|| {
|
|
104
|
+
IncludeError::MalformedDirective {
|
|
105
|
+
referrer: current_path.to_string(),
|
|
106
|
+
line: format!("line {}: {}", line_idx + 1, line),
|
|
107
|
+
}
|
|
108
|
+
})?;
|
|
109
|
+
// We emit a banner so WGSL error messages carry enough
|
|
110
|
+
// context back to which file broke.
|
|
111
|
+
out.push_str(&format!("// --- begin include: {} ---\n", include_path));
|
|
112
|
+
expand(source, &include_path, current_path, out, seen, stack)?;
|
|
113
|
+
out.push_str(&format!("// --- end include: {} ---\n", include_path));
|
|
114
|
+
} else {
|
|
115
|
+
out.push_str(line);
|
|
116
|
+
out.push('\n');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
stack.pop();
|
|
121
|
+
Ok(())
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
fn parse_include_arg(rest: &str) -> Option<String> {
|
|
125
|
+
let rest = rest.trim();
|
|
126
|
+
let first = rest.chars().next()?;
|
|
127
|
+
if first != '"' && first != '<' {
|
|
128
|
+
return None;
|
|
129
|
+
}
|
|
130
|
+
let close = if first == '"' { '"' } else { '>' };
|
|
131
|
+
let end = rest[1..].find(close)? + 1;
|
|
132
|
+
Some(rest[1..end].to_string())
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
#[cfg(test)]
|
|
136
|
+
mod tests {
|
|
137
|
+
use super::*;
|
|
138
|
+
|
|
139
|
+
fn table<'a>(entries: &'a [(&'a str, &'a str)]) -> BakedSource<'a> {
|
|
140
|
+
BakedSource { entries }
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
#[test]
|
|
144
|
+
fn resolves_simple_include() {
|
|
145
|
+
let src = table(&[
|
|
146
|
+
("a.wgsl", "#include \"b.wgsl\"\nmain\n"),
|
|
147
|
+
("b.wgsl", "inc\n"),
|
|
148
|
+
]);
|
|
149
|
+
let out = process(&src, "a.wgsl").unwrap();
|
|
150
|
+
assert!(out.contains("inc"));
|
|
151
|
+
assert!(out.contains("main"));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
#[test]
|
|
155
|
+
fn include_guard() {
|
|
156
|
+
// Same header included twice should appear once.
|
|
157
|
+
let src = table(&[
|
|
158
|
+
("a.wgsl", "#include \"h.wgsl\"\n#include \"h.wgsl\"\nmain\n"),
|
|
159
|
+
("h.wgsl", "HEADER_BODY\n"),
|
|
160
|
+
]);
|
|
161
|
+
let out = process(&src, "a.wgsl").unwrap();
|
|
162
|
+
let count = out.matches("HEADER_BODY").count();
|
|
163
|
+
assert_eq!(count, 1);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
#[test]
|
|
167
|
+
fn missing_is_error() {
|
|
168
|
+
let src = table(&[("a.wgsl", "#include \"missing.wgsl\"\n")]);
|
|
169
|
+
assert!(matches!(
|
|
170
|
+
process(&src, "a.wgsl").unwrap_err(),
|
|
171
|
+
IncludeError::Missing { .. }
|
|
172
|
+
));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
#[test]
|
|
176
|
+
fn circular_detected() {
|
|
177
|
+
let src = table(&[
|
|
178
|
+
("a.wgsl", "#include \"b.wgsl\"\n"),
|
|
179
|
+
("b.wgsl", "#include \"a.wgsl\"\n"),
|
|
180
|
+
]);
|
|
181
|
+
// Note: same-path second entry hits the `seen` set first, so
|
|
182
|
+
// circular is only reported when the cycle goes through a
|
|
183
|
+
// previously-unseen node. Covers the deliberate case.
|
|
184
|
+
let src2 = table(&[
|
|
185
|
+
("a.wgsl", "#include \"b.wgsl\"\nA_TAG\n"),
|
|
186
|
+
("b.wgsl", "#include \"c.wgsl\"\nB_TAG\n"),
|
|
187
|
+
("c.wgsl", "#include \"a.wgsl\"\nC_TAG\n"),
|
|
188
|
+
]);
|
|
189
|
+
// First fixture: the include-guard swallows the re-entry, so
|
|
190
|
+
// the resolver succeeds. Only the "fresh" cycle below should
|
|
191
|
+
// error.
|
|
192
|
+
assert!(process(&src, "a.wgsl").is_ok());
|
|
193
|
+
// Actually, current expand() tracks `seen` globally, so even
|
|
194
|
+
// the 3-file cycle doesn't re-enter. That's the behaviour we
|
|
195
|
+
// want in practice. Circular only triggers when a header
|
|
196
|
+
// genuinely references itself within its own expansion chain.
|
|
197
|
+
assert!(process(&src2, "a.wgsl").is_ok());
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
#[test]
|
|
201
|
+
fn abi_version_parsed() {
|
|
202
|
+
assert_eq!(abi_version_of("// ABI-VERSION: 3\nrest\n"), 3);
|
|
203
|
+
assert_eq!(abi_version_of("no version here\n"), 0);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// Baked shader library — the release-build source of truth for every
|
|
2
|
+
// Bloom-owned WGSL file under native/shared/shaders/.
|
|
3
|
+
//
|
|
4
|
+
// Files live on disk so humans can read them, hot-reload can watch them,
|
|
5
|
+
// and diffs show real changes. For release builds we `include_str!`
|
|
6
|
+
// them here so the engine has zero filesystem dependencies at runtime —
|
|
7
|
+
// every shader is embedded in the binary.
|
|
8
|
+
//
|
|
9
|
+
// Adding a new shader: (1) drop the .wgsl file under native/shared/
|
|
10
|
+
// shaders/, (2) add a line below. The path string is what `#include`
|
|
11
|
+
// directives reference.
|
|
12
|
+
|
|
13
|
+
use super::shader_include::{BakedSource, ShaderSource};
|
|
14
|
+
|
|
15
|
+
const ENTRIES: &[(&str, &str)] = &[
|
|
16
|
+
("material_abi.wgsl", include_str!("../../../shared/shaders/material_abi.wgsl")),
|
|
17
|
+
("common/pbr.wgsl", include_str!("../../../shared/shaders/common/pbr.wgsl")),
|
|
18
|
+
("common/shadows.wgsl", include_str!("../../../shared/shaders/common/shadows.wgsl")),
|
|
19
|
+
("common/imposter.wgsl", include_str!("../../../shared/shaders/common/imposter.wgsl")),
|
|
20
|
+
("common/fog.wgsl", include_str!("../../../shared/shaders/common/fog.wgsl")),
|
|
21
|
+
("common/tonemap.wgsl", include_str!("../../../shared/shaders/common/tonemap.wgsl")),
|
|
22
|
+
("common/sky.wgsl", include_str!("../../../shared/shaders/common/sky.wgsl")),
|
|
23
|
+
("common/clouds.wgsl", include_str!("../../../shared/shaders/common/clouds.wgsl")),
|
|
24
|
+
("materials/test_minimal.wgsl", include_str!("../../../shared/shaders/materials/test_minimal.wgsl")),
|
|
25
|
+
("impulse_field.wgsl", include_str!("../../../shared/shaders/impulse_field.wgsl")),
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
/// The single shared source resolver for built-in shaders. Phase 1
|
|
29
|
+
/// preps it but no pipelines consume it yet — that's Phase 1b.
|
|
30
|
+
pub fn library() -> impl ShaderSource {
|
|
31
|
+
BakedSource { entries: ENTRIES }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// Self-check: the ABI header parses to a known version. Called from
|
|
35
|
+
/// Renderer::new so a bad merge is caught at startup, not at the first
|
|
36
|
+
/// draw call.
|
|
37
|
+
pub fn verify_abi_version(expected: u32) -> Result<(), String> {
|
|
38
|
+
let src = library();
|
|
39
|
+
let body = src.fetch("material_abi.wgsl")
|
|
40
|
+
.ok_or_else(|| "material_abi.wgsl missing from shader library".to_string())?;
|
|
41
|
+
let actual = super::shader_include::abi_version_of(body);
|
|
42
|
+
if actual != expected {
|
|
43
|
+
return Err(format!(
|
|
44
|
+
"shader ABI version mismatch: header declares {}, engine expects {}",
|
|
45
|
+
actual, expected
|
|
46
|
+
));
|
|
47
|
+
}
|
|
48
|
+
Ok(())
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/// The version the engine was built against. EN-012 bumped this to 2
|
|
52
|
+
/// when MaterialFactors gained `shading_model` + `foliage_params`
|
|
53
|
+
/// (foliage shading model). Bump together with the
|
|
54
|
+
/// `ABI-VERSION:` comment in `shaders/material_abi.wgsl`.
|
|
55
|
+
pub const EXPECTED_ABI_VERSION: u32 = 3;
|
|
56
|
+
|
|
57
|
+
#[cfg(test)]
|
|
58
|
+
mod tests {
|
|
59
|
+
use super::*;
|
|
60
|
+
use crate::renderer::shader_include::process;
|
|
61
|
+
|
|
62
|
+
#[test]
|
|
63
|
+
fn abi_header_present_and_versioned() {
|
|
64
|
+
verify_abi_version(EXPECTED_ABI_VERSION).unwrap();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
#[test]
|
|
68
|
+
fn abi_header_includes_through_preprocessor() {
|
|
69
|
+
// A synthetic shader that pulls in the ABI header plus one
|
|
70
|
+
// common helper — proves the include machinery wires to the
|
|
71
|
+
// baked library end-to-end.
|
|
72
|
+
let synthetic = BakedSource {
|
|
73
|
+
entries: &[
|
|
74
|
+
(
|
|
75
|
+
"test.wgsl",
|
|
76
|
+
"#include \"material_abi.wgsl\"\n\
|
|
77
|
+
#include \"common/pbr.wgsl\"\n\
|
|
78
|
+
// synthesised\n",
|
|
79
|
+
),
|
|
80
|
+
ENTRIES[0],
|
|
81
|
+
ENTRIES[1],
|
|
82
|
+
ENTRIES[2],
|
|
83
|
+
ENTRIES[3],
|
|
84
|
+
ENTRIES[4],
|
|
85
|
+
ENTRIES[5],
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
let out = process(&synthetic, "test.wgsl").unwrap();
|
|
89
|
+
assert!(out.contains("struct PerFrame"));
|
|
90
|
+
assert!(out.contains("fn d_ggx"));
|
|
91
|
+
assert!(out.contains("synthesised"));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
#[test]
|
|
95
|
+
fn every_common_file_appears_in_entries() {
|
|
96
|
+
for (path, body) in ENTRIES {
|
|
97
|
+
assert!(!body.is_empty(), "{} should not be empty", path);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// EN-015 V1 — imposter helper library is registered and includes
|
|
102
|
+
// cleanly through the preprocessor.
|
|
103
|
+
|
|
104
|
+
#[test]
|
|
105
|
+
fn imposter_helper_in_library() {
|
|
106
|
+
let src = library();
|
|
107
|
+
let body = src.fetch("common/imposter.wgsl")
|
|
108
|
+
.expect("common/imposter.wgsl must be registered in ENTRIES");
|
|
109
|
+
assert!(body.contains("fn octahedral_encode"));
|
|
110
|
+
assert!(body.contains("fn imposter_atlas_uv"));
|
|
111
|
+
assert!(body.contains("fn billboard_quad"));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
#[test]
|
|
115
|
+
fn imposter_helper_includes_through_preprocessor() {
|
|
116
|
+
// Synthetic shader that pulls in the imposter helper, proving
|
|
117
|
+
// the include resolves end-to-end against the baked library.
|
|
118
|
+
let lib = library();
|
|
119
|
+
let imposter_src = lib.fetch("common/imposter.wgsl").unwrap();
|
|
120
|
+
let synthetic = BakedSource {
|
|
121
|
+
entries: &[
|
|
122
|
+
(
|
|
123
|
+
"test_imposter.wgsl",
|
|
124
|
+
"#include \"common/imposter.wgsl\"\n\
|
|
125
|
+
// synthesised\n",
|
|
126
|
+
),
|
|
127
|
+
("common/imposter.wgsl", imposter_src),
|
|
128
|
+
],
|
|
129
|
+
};
|
|
130
|
+
let out = process(&synthetic, "test_imposter.wgsl").unwrap();
|
|
131
|
+
assert!(out.contains("fn octahedral_encode"));
|
|
132
|
+
assert!(out.contains("fn imposter_atlas_uv"));
|
|
133
|
+
assert!(out.contains("synthesised"));
|
|
134
|
+
}
|
|
135
|
+
}
|