@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.
Files changed (213) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +231 -0
  3. package/native/android/Cargo.lock +1848 -0
  4. package/native/android/Cargo.toml +24 -0
  5. package/native/android/src/lib.rs +702 -0
  6. package/native/ios/Cargo.lock +1690 -0
  7. package/native/ios/Cargo.toml +32 -0
  8. package/native/ios/src/lib.rs +1267 -0
  9. package/native/linux/Cargo.lock +3279 -0
  10. package/native/linux/Cargo.toml +29 -0
  11. package/native/linux/src/lib.rs +1331 -0
  12. package/native/macos/Cargo.lock +3310 -0
  13. package/native/macos/Cargo.toml +46 -0
  14. package/native/macos/src/lib.rs +1302 -0
  15. package/native/shared/Cargo.lock +1899 -0
  16. package/native/shared/Cargo.toml +62 -0
  17. package/native/shared/assets/default_font.ttf +0 -0
  18. package/native/shared/build.rs +270 -0
  19. package/native/shared/shaders/common/clouds.wgsl +122 -0
  20. package/native/shared/shaders/common/fog.wgsl +16 -0
  21. package/native/shared/shaders/common/foliage_wind.wgsl +98 -0
  22. package/native/shared/shaders/common/imposter.wgsl +112 -0
  23. package/native/shared/shaders/common/pbr.wgsl +186 -0
  24. package/native/shared/shaders/common/shadows.wgsl +186 -0
  25. package/native/shared/shaders/common/sky.wgsl +8 -0
  26. package/native/shared/shaders/common/tonemap.wgsl +25 -0
  27. package/native/shared/shaders/impulse_field.wgsl +57 -0
  28. package/native/shared/shaders/material_abi.wgsl +383 -0
  29. package/native/shared/shaders/materials/test_minimal.wgsl +42 -0
  30. package/native/shared/src/anim_mixer.rs +61 -0
  31. package/native/shared/src/attach.rs +263 -0
  32. package/native/shared/src/audio/decode.rs +123 -0
  33. package/native/shared/src/audio/mod.rs +863 -0
  34. package/native/shared/src/audio/render.rs +892 -0
  35. package/native/shared/src/audio/spsc.rs +156 -0
  36. package/native/shared/src/audio/stream.rs +226 -0
  37. package/native/shared/src/custom_shaders.rs +104 -0
  38. package/native/shared/src/decals.rs +245 -0
  39. package/native/shared/src/drs.rs +211 -0
  40. package/native/shared/src/engine.rs +261 -0
  41. package/native/shared/src/ffi.rs +116 -0
  42. package/native/shared/src/ffi_core/assets.rs +388 -0
  43. package/native/shared/src/ffi_core/audio_ffi.rs +184 -0
  44. package/native/shared/src/ffi_core/draw.rs +334 -0
  45. package/native/shared/src/ffi_core/game_loop.rs +577 -0
  46. package/native/shared/src/ffi_core/input.rs +234 -0
  47. package/native/shared/src/ffi_core/mod.rs +127 -0
  48. package/native/shared/src/ffi_core/models.rs +1154 -0
  49. package/native/shared/src/ffi_core/ragdoll_ffi.rs +261 -0
  50. package/native/shared/src/ffi_core/scene.rs +626 -0
  51. package/native/shared/src/ffi_core/vfx.rs +212 -0
  52. package/native/shared/src/ffi_core/visual.rs +691 -0
  53. package/native/shared/src/frame_callbacks.rs +122 -0
  54. package/native/shared/src/geometry.rs +236 -0
  55. package/native/shared/src/handles.rs +182 -0
  56. package/native/shared/src/input.rs +448 -0
  57. package/native/shared/src/jolt_sys.rs +822 -0
  58. package/native/shared/src/lib.rs +55 -0
  59. package/native/shared/src/models.rs +1093 -0
  60. package/native/shared/src/models_gltf.rs +1280 -0
  61. package/native/shared/src/particles.rs +391 -0
  62. package/native/shared/src/physics_jolt.rs +1908 -0
  63. package/native/shared/src/picking.rs +298 -0
  64. package/native/shared/src/postfx.rs +345 -0
  65. package/native/shared/src/profiler.rs +492 -0
  66. package/native/shared/src/ragdoll.rs +474 -0
  67. package/native/shared/src/renderer/atmosphere_lut.rs +573 -0
  68. package/native/shared/src/renderer/brdf_lut.rs +154 -0
  69. package/native/shared/src/renderer/draw2d.rs +143 -0
  70. package/native/shared/src/renderer/formats.rs +822 -0
  71. package/native/shared/src/renderer/froxel.rs +421 -0
  72. package/native/shared/src/renderer/gi_bake.rs +653 -0
  73. package/native/shared/src/renderer/graph.rs +462 -0
  74. package/native/shared/src/renderer/hiz.rs +269 -0
  75. package/native/shared/src/renderer/hot_reload.rs +390 -0
  76. package/native/shared/src/renderer/impulse_field.rs +456 -0
  77. package/native/shared/src/renderer/lighting.rs +154 -0
  78. package/native/shared/src/renderer/material_instancing.rs +171 -0
  79. package/native/shared/src/renderer/material_pipeline.rs +700 -0
  80. package/native/shared/src/renderer/material_system.rs +1996 -0
  81. package/native/shared/src/renderer/material_system_tests.rs +601 -0
  82. package/native/shared/src/renderer/material_system_wasm.rs +41 -0
  83. package/native/shared/src/renderer/mod.rs +12556 -0
  84. package/native/shared/src/renderer/model_draw.rs +641 -0
  85. package/native/shared/src/renderer/occlusion.rs +429 -0
  86. package/native/shared/src/renderer/planar_pass.rs +593 -0
  87. package/native/shared/src/renderer/planar_reflection.rs +499 -0
  88. package/native/shared/src/renderer/post_pass.rs +249 -0
  89. package/native/shared/src/renderer/postfx_chain.rs +728 -0
  90. package/native/shared/src/renderer/pt_pass.rs +577 -0
  91. package/native/shared/src/renderer/scene_pass.rs +607 -0
  92. package/native/shared/src/renderer/shader_include.rs +205 -0
  93. package/native/shared/src/renderer/shader_library.rs +135 -0
  94. package/native/shared/src/renderer/shaders/ao.rs +570 -0
  95. package/native/shared/src/renderer/shaders/core.rs +1243 -0
  96. package/native/shared/src/renderer/shaders/env.rs +907 -0
  97. package/native/shared/src/renderer/shaders/gi.rs +810 -0
  98. package/native/shared/src/renderer/shaders/mod.rs +19 -0
  99. package/native/shared/src/renderer/shaders/post.rs +1558 -0
  100. package/native/shared/src/renderer/shaders/pt.rs +1859 -0
  101. package/native/shared/src/renderer/shaders/ssgi.rs +1586 -0
  102. package/native/shared/src/renderer/shadow_pass.rs +731 -0
  103. package/native/shared/src/renderer/ssgi_pass.rs +392 -0
  104. package/native/shared/src/renderer/ssr_pass.rs +188 -0
  105. package/native/shared/src/renderer/texture_store.rs +473 -0
  106. package/native/shared/src/renderer/transient.rs +591 -0
  107. package/native/shared/src/renderer/types.rs +941 -0
  108. package/native/shared/src/renderer/util.rs +152 -0
  109. package/native/shared/src/scene.rs +1362 -0
  110. package/native/shared/src/sdf_cache.rs +274 -0
  111. package/native/shared/src/shadows.rs +1036 -0
  112. package/native/shared/src/staging.rs +102 -0
  113. package/native/shared/src/string_header.rs +266 -0
  114. package/native/shared/src/text_renderer.rs +502 -0
  115. package/native/shared/src/textures.rs +197 -0
  116. package/native/tvos/Cargo.lock +1693 -0
  117. package/native/tvos/Cargo.toml +36 -0
  118. package/native/tvos/metal-patched/Cargo.toml +178 -0
  119. package/native/tvos/metal-patched/LICENSE-APACHE +201 -0
  120. package/native/tvos/metal-patched/LICENSE-MIT +25 -0
  121. package/native/tvos/metal-patched/src/acceleration_structure.rs +667 -0
  122. package/native/tvos/metal-patched/src/acceleration_structure_pass.rs +108 -0
  123. package/native/tvos/metal-patched/src/argument.rs +366 -0
  124. package/native/tvos/metal-patched/src/blitpass.rs +102 -0
  125. package/native/tvos/metal-patched/src/buffer.rs +71 -0
  126. package/native/tvos/metal-patched/src/capturedescriptor.rs +76 -0
  127. package/native/tvos/metal-patched/src/capturemanager.rs +113 -0
  128. package/native/tvos/metal-patched/src/commandbuffer.rs +192 -0
  129. package/native/tvos/metal-patched/src/commandqueue.rs +44 -0
  130. package/native/tvos/metal-patched/src/computepass.rs +107 -0
  131. package/native/tvos/metal-patched/src/constants.rs +152 -0
  132. package/native/tvos/metal-patched/src/counters.rs +119 -0
  133. package/native/tvos/metal-patched/src/depthstencil.rs +190 -0
  134. package/native/tvos/metal-patched/src/device.rs +2134 -0
  135. package/native/tvos/metal-patched/src/drawable.rs +39 -0
  136. package/native/tvos/metal-patched/src/encoder.rs +2041 -0
  137. package/native/tvos/metal-patched/src/heap.rs +281 -0
  138. package/native/tvos/metal-patched/src/indirect_encoder.rs +344 -0
  139. package/native/tvos/metal-patched/src/lib.rs +657 -0
  140. package/native/tvos/metal-patched/src/library.rs +902 -0
  141. package/native/tvos/metal-patched/src/mps.rs +575 -0
  142. package/native/tvos/metal-patched/src/pipeline/compute.rs +475 -0
  143. package/native/tvos/metal-patched/src/pipeline/mod.rs +71 -0
  144. package/native/tvos/metal-patched/src/pipeline/render.rs +762 -0
  145. package/native/tvos/metal-patched/src/renderpass.rs +443 -0
  146. package/native/tvos/metal-patched/src/resource.rs +182 -0
  147. package/native/tvos/metal-patched/src/sampler.rs +165 -0
  148. package/native/tvos/metal-patched/src/sync.rs +178 -0
  149. package/native/tvos/metal-patched/src/texture.rs +352 -0
  150. package/native/tvos/metal-patched/src/types.rs +90 -0
  151. package/native/tvos/metal-patched/src/vertexdescriptor.rs +250 -0
  152. package/native/tvos/src/audio_backend.rs +197 -0
  153. package/native/tvos/src/lib.rs +1891 -0
  154. package/native/visionos/Cargo.lock +1693 -0
  155. package/native/visionos/Cargo.toml +40 -0
  156. package/native/visionos/src/audio_backend.rs +197 -0
  157. package/native/visionos/src/lib.rs +1887 -0
  158. package/native/watchos/Cargo.lock +16 -0
  159. package/native/watchos/Cargo.toml +19 -0
  160. package/native/watchos/shaders/bloom_postfx.metal +99 -0
  161. package/native/watchos/src/BloomWatchApp.swift +1267 -0
  162. package/native/watchos/src/BloomWatchAudio.swift +179 -0
  163. package/native/watchos/src/audio.rs +55 -0
  164. package/native/watchos/src/draw_list.rs +229 -0
  165. package/native/watchos/src/ffi_stubs.rs +915 -0
  166. package/native/watchos/src/ffi_stubs_manual.rs +35 -0
  167. package/native/watchos/src/lib.rs +1124 -0
  168. package/native/watchos/src/models.rs +746 -0
  169. package/native/watchos/src/postfx.rs +95 -0
  170. package/native/watchos/src/scene.rs +534 -0
  171. package/native/watchos/src/textures.rs +184 -0
  172. package/native/web/Cargo.lock +1657 -0
  173. package/native/web/Cargo.toml +43 -0
  174. package/native/web/bloom_glue.js +695 -0
  175. package/native/web/build.sh +131 -0
  176. package/native/web/index.html +35 -0
  177. package/native/web/jolt_bridge.js +1519 -0
  178. package/native/web/src/input_ffi.rs +286 -0
  179. package/native/web/src/lib.rs +1796 -0
  180. package/native/web/src/material_ffi.rs +710 -0
  181. package/native/web/src/parity_ffi.rs +343 -0
  182. package/native/web/src/physics_ffi.rs +643 -0
  183. package/native/web/src/ragdoll_ffi.rs +250 -0
  184. package/native/web/src/render_settings.rs +98 -0
  185. package/native/windows/Cargo.lock +1815 -0
  186. package/native/windows/Cargo.toml +68 -0
  187. package/native/windows/src/lib.rs +1486 -0
  188. package/package.json +4279 -0
  189. package/src/audio/index.ts +315 -0
  190. package/src/core/colors.ts +63 -0
  191. package/src/core/index.ts +1206 -0
  192. package/src/core/keys.ts +63 -0
  193. package/src/core/types.ts +104 -0
  194. package/src/index.ts +171 -0
  195. package/src/math/index.ts +516 -0
  196. package/src/mobile/index.ts +294 -0
  197. package/src/models/index.ts +1258 -0
  198. package/src/physics/index.ts +1134 -0
  199. package/src/scene/index.ts +698 -0
  200. package/src/shapes/index.ts +120 -0
  201. package/src/text/index.ts +48 -0
  202. package/src/textures/index.ts +187 -0
  203. package/src/vfx/index.ts +191 -0
  204. package/src/world/index.ts +24 -0
  205. package/src/world/loader.ts +423 -0
  206. package/src/world/prefab.ts +217 -0
  207. package/src/world/render.ts +172 -0
  208. package/src/world/saver.ts +108 -0
  209. package/src/world/serialize.ts +301 -0
  210. package/src/world/terrain.ts +355 -0
  211. package/src/world/types.ts +160 -0
  212. package/src/world/validate.ts +319 -0
  213. package/src/world/version.ts +114 -0
@@ -0,0 +1,250 @@
1
+ //! EN-063 — ragdolls on web.
2
+ //!
3
+ //! The native ragdoll FFI (`bloom-shared/src/ffi_core/ragdoll_ffi.rs`) is a
4
+ //! thin choreography layer: `ragdoll::plan()` decides the capsules, Jolt
5
+ //! creates them, `Ragdoll::attach/apply` map simulated bodies back onto the
6
+ //! skinning palette. All of that planning/pose math is pure Rust and compiles
7
+ //! on wasm32 — the only thing missing on web was the Jolt half, which lives
8
+ //! in JS (`jolt_bridge.js`). So this module is the same choreography with
9
+ //! `eng.jolt.*` swapped for the bridge externs, plus one new bridge function
10
+ //! (`constraintSixDofLockedTranslation`) for the joint type ragdolls use.
11
+ //!
12
+ //! Tuning constants (12 bodies, 0.38 radius fraction, the rot limits, the
13
+ //! friction/damping set) are copied from the native FFI verbatim — a corpse
14
+ //! must read the same on every platform.
15
+
16
+ use crate::engine;
17
+ use crate::physics_ffi::{
18
+ jb_body_add_impulse, jb_body_create, jb_body_destroy, jb_body_get_position,
19
+ jb_body_get_rotation, jb_body_set_angular_damping, jb_body_set_friction,
20
+ jb_body_set_linear_damping, jb_body_set_restitution, jb_constraint_destroy,
21
+ jb_constraint_six_dof, jb_shape_capsule,
22
+ };
23
+ use wasm_bindgen::prelude::*;
24
+
25
+ #[wasm_bindgen]
26
+ pub fn bloom_ragdoll_create() -> f64 {
27
+ engine().ragdolls.create() as f64
28
+ }
29
+
30
+ #[wasm_bindgen]
31
+ pub fn bloom_ragdoll_activate(
32
+ rag: f64,
33
+ anim: f64,
34
+ world: f64,
35
+ scale: f64,
36
+ px: f64,
37
+ py: f64,
38
+ pz: f64,
39
+ rot_y: f64,
40
+ ) -> f64 {
41
+ let eng = engine();
42
+
43
+ let builds = {
44
+ let Some(a) = eng.models.get_animation(anim) else {
45
+ return 0.0;
46
+ };
47
+ // 12 bodies / 0.38 radius fraction — same sweet spot as native (spine
48
+ // + limbs; past that you buy fingers, which cost solver time and buy
49
+ // jitter).
50
+ bloom_shared::ragdoll::plan(
51
+ a,
52
+ scale as f32,
53
+ [px as f32, py as f32, pz as f32],
54
+ rot_y as f32,
55
+ 12,
56
+ 0.38,
57
+ )
58
+ };
59
+ if builds.is_empty() {
60
+ return 0.0;
61
+ }
62
+
63
+ // --- bodies (layer 1 = MOVING, motion type 2 = DYNAMIC)
64
+ let mut bodies: Vec<f64> = Vec::with_capacity(builds.len());
65
+ for b in builds.iter() {
66
+ let shape = jb_shape_capsule(b.half_height as f64, b.radius as f64);
67
+ if shape == 0.0 {
68
+ bodies.push(0.0);
69
+ continue;
70
+ }
71
+ let q = bloom_shared::ragdoll::quat_from_mat(&b.world);
72
+ let body = jb_body_create(
73
+ world,
74
+ shape,
75
+ 2.0,
76
+ b.world[3][0] as f64,
77
+ b.world[3][1] as f64,
78
+ b.world[3][2] as f64,
79
+ q[0] as f64,
80
+ q[1] as f64,
81
+ q[2] as f64,
82
+ q[3] as f64,
83
+ 1.0,
84
+ );
85
+ if body != 0.0 {
86
+ jb_body_set_friction(body, 0.8); // corpses do not skate
87
+ jb_body_set_restitution(body, 0.02); // they do not bounce
88
+ jb_body_set_linear_damping(body, 0.20);
89
+ // Angular damping does most of the work of making this read as a
90
+ // body rather than a rag.
91
+ jb_body_set_angular_damping(body, 0.75);
92
+ }
93
+ bodies.push(body);
94
+ }
95
+
96
+ // --- joints. Tight-ish; twist (y) held hardest — an over-twisted limb is
97
+ // the single most obviously WRONG thing a ragdoll can do.
98
+ let rot_limits: [f64; 6] = [-0.8, 0.8, -0.25, 0.25, -0.8, 0.8];
99
+ let mut constraints: Vec<f64> = Vec::new();
100
+ for (i, b) in builds.iter().enumerate() {
101
+ if b.parent_bone == usize::MAX {
102
+ continue;
103
+ }
104
+ let pa = bodies.get(b.parent_bone).copied().unwrap_or(0.0);
105
+ let pb = bodies.get(i).copied().unwrap_or(0.0);
106
+ if pa == 0.0 || pb == 0.0 {
107
+ continue;
108
+ }
109
+ let c = jb_constraint_six_dof(
110
+ pa,
111
+ pb,
112
+ b.anchor[0] as f64,
113
+ b.anchor[1] as f64,
114
+ b.anchor[2] as f64,
115
+ b.anchor[0] as f64,
116
+ b.anchor[1] as f64,
117
+ b.anchor[2] as f64,
118
+ rot_limits[0],
119
+ rot_limits[1],
120
+ rot_limits[2],
121
+ rot_limits[3],
122
+ rot_limits[4],
123
+ rot_limits[5],
124
+ 1.0, // anchors given in world space
125
+ );
126
+ if c != 0.0 {
127
+ constraints.push(c);
128
+ }
129
+ }
130
+
131
+ let Some(a) = eng.models.get_animation(anim) else {
132
+ return 0.0;
133
+ };
134
+ let Some(r) = eng.ragdolls.get_mut(rag as u32) else {
135
+ return 0.0;
136
+ };
137
+ r.attach(
138
+ &builds,
139
+ &bodies,
140
+ constraints,
141
+ a,
142
+ scale as f32,
143
+ [px as f32, py as f32, pz as f32],
144
+ rot_y as f32,
145
+ );
146
+ 1.0
147
+ }
148
+
149
+ #[wasm_bindgen]
150
+ pub fn bloom_ragdoll_push(rag: f64, dx: f64, dy: f64, dz: f64, impulse: f64) {
151
+ let eng = engine();
152
+ let Some(r) = eng.ragdolls.get(rag as u32) else {
153
+ return;
154
+ };
155
+ if !r.active {
156
+ return;
157
+ }
158
+ let bodies = r.bodies();
159
+ if bodies.is_empty() {
160
+ return;
161
+ }
162
+ // Spread the impulse over the bodies so a 12-bone corpse and a 4-bone one
163
+ // take off at the same speed.
164
+ let per = impulse / (bodies.len() as f64);
165
+ for b in bodies {
166
+ jb_body_add_impulse(b, dx * per, dy * per, dz * per);
167
+ }
168
+ }
169
+
170
+ #[wasm_bindgen]
171
+ pub fn bloom_ragdoll_update(rag: f64, anim: f64, dt: f64) -> f64 {
172
+ let eng = engine();
173
+
174
+ let (bodies, scale, pos, rot) = {
175
+ let Some(r) = eng.ragdolls.get(rag as u32) else {
176
+ return 0.0;
177
+ };
178
+ if !r.active {
179
+ return 0.0;
180
+ }
181
+ let (s, p, ry) = r.upload_params();
182
+ (r.bodies(), s, p, ry)
183
+ };
184
+
185
+ let mut world: Vec<[[f32; 4]; 4]> = Vec::with_capacity(bodies.len());
186
+ for b in bodies.iter() {
187
+ let p = [
188
+ jb_body_get_position(*b, 0.0) as f32,
189
+ jb_body_get_position(*b, 1.0) as f32,
190
+ jb_body_get_position(*b, 2.0) as f32,
191
+ ];
192
+ let q = [
193
+ jb_body_get_rotation(*b, 0.0) as f32,
194
+ jb_body_get_rotation(*b, 1.0) as f32,
195
+ jb_body_get_rotation(*b, 2.0) as f32,
196
+ jb_body_get_rotation(*b, 3.0) as f32,
197
+ ];
198
+ world.push(bloom_shared::ragdoll::from_pos_quat(p, q));
199
+ }
200
+
201
+ {
202
+ let Some(r) = eng.ragdolls.get_mut(rag as u32) else {
203
+ return 0.0;
204
+ };
205
+ r.age += dt as f32;
206
+ }
207
+ let age = eng.ragdolls.get(rag as u32).map(|r| r.age).unwrap_or(0.0);
208
+
209
+ // Split borrow: apply() needs &mut ModelAnimation and &Ragdoll.
210
+ let ragdoll_ptr: *const bloom_shared::ragdoll::Ragdoll =
211
+ match eng.ragdolls.get(rag as u32) {
212
+ Some(r) => r,
213
+ None => return 0.0,
214
+ };
215
+ if let Some(a) = eng.models.get_animation_mut(anim) {
216
+ unsafe { (*ragdoll_ptr).apply(a, &world) };
217
+ }
218
+
219
+ if let Some(a) = eng.models.get_animation(anim) {
220
+ if !a.joint_matrices.is_empty() {
221
+ let (s, c) = (rot.sin(), rot.cos());
222
+ // PT-7: anim handle = prev-palette pairing key.
223
+ eng.renderer
224
+ .set_joint_matrices_scaled(anim.to_bits(), &a.joint_matrices, scale, pos, s, c);
225
+ }
226
+ }
227
+ age as f64
228
+ }
229
+
230
+ #[wasm_bindgen]
231
+ pub fn bloom_ragdoll_release(rag: f64) {
232
+ let eng = engine();
233
+ let (bodies, cons) = {
234
+ let Some(r) = eng.ragdolls.get(rag as u32) else {
235
+ return;
236
+ };
237
+ (r.bodies(), r.constraint_handles().to_vec())
238
+ };
239
+ // Constraints first: destroying a body out from under a live constraint
240
+ // is how you get a use-after-free in the solver.
241
+ for c in cons {
242
+ jb_constraint_destroy(c);
243
+ }
244
+ for b in bodies {
245
+ jb_body_destroy(b);
246
+ }
247
+ if let Some(r) = eng.ragdolls.get_mut(rag as u32) {
248
+ *r = bloom_shared::ragdoll::Ragdoll::new();
249
+ }
250
+ }
@@ -0,0 +1,98 @@
1
+ //! Renderer-settings FFI surface for web — wasm_bindgen wrappers over
2
+ //! the same shared engine methods native's define_core_ffi! generates
3
+ //! wrappers for. Split from lib.rs (2000-line file policy).
4
+
5
+ use crate::engine;
6
+ use wasm_bindgen::prelude::*;
7
+
8
+ // ---------------------------------------------------------------------------
9
+ // Renderer settings — parity with the native define_core_ffi! surface.
10
+ // (Added when tools/validate-ffi.js gained web coverage; these were the
11
+ // silent gaps that made web games' graphics settings no-ops.)
12
+ // ---------------------------------------------------------------------------
13
+
14
+ #[wasm_bindgen]
15
+ pub fn bloom_set_fog(r: f64, g: f64, b: f64, density: f64, height_ref: f64, height_falloff: f64) {
16
+ let r_ = engine();
17
+ r_.renderer.set_fog_color(r as f32, g as f32, b as f32);
18
+ r_.renderer.set_fog_density(density as f32);
19
+ r_.renderer.set_fog_height_falloff(height_ref as f32, height_falloff as f32);
20
+ }
21
+ #[wasm_bindgen]
22
+ pub fn bloom_set_chromatic_aberration(strength: f64) { engine().renderer.set_chromatic_aberration(strength as f32); }
23
+ #[wasm_bindgen]
24
+ pub fn bloom_set_vignette(strength: f64, softness: f64) { engine().renderer.set_vignette(strength as f32, softness as f32); }
25
+ #[wasm_bindgen]
26
+ pub fn bloom_set_film_grain(strength: f64) { engine().renderer.set_film_grain(strength as f32); }
27
+ #[wasm_bindgen]
28
+ pub fn bloom_set_sun_shafts(strength: f64, decay: f64, r: f64, g: f64, b: f64) {
29
+ let eng = engine();
30
+ eng.renderer.set_sun_shaft_strength(strength as f32);
31
+ eng.renderer.set_sun_shaft_decay(decay as f32);
32
+ eng.renderer.set_sun_shaft_color(r as f32, g as f32, b as f32);
33
+ }
34
+ #[wasm_bindgen]
35
+ pub fn bloom_set_auto_exposure(on: f64) { engine().renderer.set_auto_exposure(on != 0.0); }
36
+ #[wasm_bindgen]
37
+ pub fn bloom_set_manual_exposure(value: f64) { engine().renderer.set_manual_exposure(value as f32); }
38
+ #[wasm_bindgen]
39
+ pub fn bloom_set_taa_enabled(on: f64) { engine().renderer.set_taa_enabled(on != 0.0); }
40
+ #[wasm_bindgen]
41
+ pub fn bloom_set_occlusion_culling(on: f64) { engine().renderer.occlusion.enabled = on != 0.0; }
42
+ #[wasm_bindgen]
43
+ pub fn bloom_set_render_scale(scale: f64) { engine().renderer.set_render_scale(scale as f32); }
44
+ #[wasm_bindgen]
45
+ pub fn bloom_get_render_scale() -> f64 { engine().renderer.render_scale() as f64 }
46
+ #[wasm_bindgen]
47
+ pub fn bloom_set_upscale_mode(mode: f64) { engine().renderer.set_upscale_mode(mode as u32); }
48
+ #[wasm_bindgen]
49
+ pub fn bloom_set_cas_strength(strength: f64) { engine().renderer.set_cas_strength(strength as f32); }
50
+ #[wasm_bindgen]
51
+ pub fn bloom_get_physical_width() -> f64 { engine().renderer.physical_width() as f64 }
52
+ #[wasm_bindgen]
53
+ pub fn bloom_get_physical_height() -> f64 { engine().renderer.physical_height() as f64 }
54
+ #[wasm_bindgen]
55
+ pub fn bloom_set_auto_resolution(target_hz: f64, enabled: f64) {
56
+ let eng = engine();
57
+ if enabled != 0.0 {
58
+ let current = eng.renderer.render_scale();
59
+ eng.drs.enable(target_hz as f32, current);
60
+ } else {
61
+ eng.drs.disable();
62
+ }
63
+ }
64
+ #[wasm_bindgen]
65
+ pub fn bloom_set_env_intensity(intensity: f64) { engine().renderer.set_env_intensity(intensity as f32); }
66
+ #[wasm_bindgen]
67
+ pub fn bloom_set_ssgi_enabled(enabled: f64) { engine().renderer.set_ssgi_enabled(enabled != 0.0); }
68
+ #[wasm_bindgen]
69
+ pub fn bloom_set_ssgi_intensity(intensity: f64) { engine().renderer.set_ssgi_intensity(intensity as f32); }
70
+ #[wasm_bindgen]
71
+ pub fn bloom_set_ssgi_radius(radius: f64) { engine().renderer.set_ssgi_radius(radius as f32); }
72
+ #[wasm_bindgen]
73
+ pub fn bloom_set_dof(enabled: f64, focus_distance: f64, aperture: f64) {
74
+ let r = &mut engine().renderer;
75
+ r.set_dof_enabled(enabled != 0.0);
76
+ r.set_dof_focus_distance(focus_distance as f32);
77
+ r.set_dof_aperture(aperture as f32);
78
+ }
79
+
80
+ // LOD: pointer-taking variants share the cross-module WASM memory TODO
81
+ // with bloom_scene_update_geometry above; the model-based variant works.
82
+ #[wasm_bindgen]
83
+ pub fn bloom_scene_set_lod(
84
+ _handle: f64, _lod_index: f64, _vert_ptr: f64, _vert_count: f64,
85
+ _idx_ptr: f64, _idx_count: f64, _max_coverage: f64,
86
+ ) {
87
+ // TODO: Phase 4 — pointer/buffer passing from Perry WASM linear memory.
88
+ }
89
+ #[wasm_bindgen]
90
+ pub fn bloom_scene_attach_model_lod(node: f64, model: f64, mesh_index: f64, lod_index: f64, max_coverage: f64) {
91
+ let eng = engine();
92
+ let mi = mesh_index as usize;
93
+ let Some(md) = eng.models.models.get(model) else { return };
94
+ if mi >= md.meshes.len() { return; }
95
+ let mesh = &md.meshes[mi];
96
+ let (v, i) = (mesh.vertices.clone(), mesh.indices.clone());
97
+ eng.scene.set_lod_geometry(node, lod_index as usize, v, i, max_coverage as f32);
98
+ }