@bornengine/engine 0.4.16 → 0.5.1
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/README.md +24 -14
- package/native/android/Cargo.lock +577 -28
- package/native/android/Cargo.toml +2 -0
- package/native/android/src/lib.rs +39 -3
- package/native/ios/Cargo.lock +573 -24
- package/native/ios/Cargo.toml +2 -0
- package/native/ios/src/lib.rs +72 -9
- package/native/ios/src/text_input.rs +48 -0
- package/native/linux/Cargo.lock +623 -35
- package/native/linux/Cargo.toml +3 -0
- package/native/macos/Cargo.lock +630 -35
- package/native/macos/Cargo.toml +3 -0
- package/native/shared/Cargo.lock +430 -27
- package/native/shared/Cargo.toml +5 -0
- package/native/shared/build.rs +41 -1
- package/native/shared/src/engine.rs +54 -2
- package/native/shared/src/ffi.rs +54 -1
- package/native/shared/src/ffi_core/mod.rs +2 -0
- package/native/shared/src/ffi_core/ui.rs +182 -0
- package/native/shared/src/input.rs +317 -12
- package/native/shared/src/lib.rs +1 -0
- package/native/shared/src/renderer/mod.rs +47 -201
- package/native/shared/src/renderer/texture_store.rs +5 -0
- package/native/shared/src/renderer/ui_pass.rs +742 -0
- package/native/shared/src/textures.rs +2 -0
- package/native/shared/src/ui/commands.rs +213 -0
- package/native/shared/src/ui/egui.rs +1282 -0
- package/native/shared/src/ui/imgui.rs +1056 -0
- package/native/shared/src/ui/input.rs +173 -0
- package/native/shared/src/ui/mod.rs +252 -0
- package/native/shared/src/ui/responses.rs +61 -0
- package/native/tvos/Cargo.lock +576 -27
- package/native/tvos/Cargo.toml +2 -0
- package/native/visionos/Cargo.lock +571 -22
- package/native/visionos/Cargo.toml +2 -0
- package/native/watchos/src/ffi_stubs.rs +27 -0
- package/native/web/Cargo.lock +346 -11
- package/native/web/Cargo.toml +6 -0
- package/native/web/bloom_glue.js +84 -11
- package/native/web/build.sh +150 -34
- package/native/web/src/lib.rs +2 -0
- package/native/web/src/ui_ffi.rs +148 -0
- package/native/windows/Cargo.lock +638 -38
- package/native/windows/Cargo.toml +3 -0
- package/native/windows/src/lib.rs +50 -1
- package/native/windows/src/windows_text.rs +69 -0
- package/package.json +91 -2
- package/src/debug-ui/index.ts +4 -0
- package/src/debug-ui/types.ts +1 -0
- package/src/game/adapters/audio-source-component.ts +67 -0
- package/src/game/adapters/rigid-body-component.ts +69 -0
- package/src/game/adapters/scene-node-component.ts +49 -0
- package/src/game/game-component.ts +89 -0
- package/src/game/game-object.ts +338 -0
- package/src/game/game-scene.ts +303 -0
- package/src/game/index.ts +7 -0
- package/src/game/transform.ts +315 -0
- package/src/index.ts +27 -0
- package/src/ui/api.ts +240 -0
- package/src/ui/index.ts +5 -0
- package/src/ui/opcodes.ts +66 -0
- package/src/ui/types.ts +82 -0
|
@@ -15,6 +15,7 @@ mod planar_pass;
|
|
|
15
15
|
mod material_instancing;
|
|
16
16
|
mod postfx_chain;
|
|
17
17
|
mod scene_pass;
|
|
18
|
+
mod ui_pass;
|
|
18
19
|
mod gi_bake;
|
|
19
20
|
mod froxel;
|
|
20
21
|
mod lighting;
|
|
@@ -287,6 +288,8 @@ pub struct Renderer {
|
|
|
287
288
|
pub logical_width: u32,
|
|
288
289
|
pub logical_height: u32,
|
|
289
290
|
|
|
291
|
+
ui_renderer: ui_pass::UiRendererState,
|
|
292
|
+
|
|
290
293
|
// Pipelines
|
|
291
294
|
pipeline_2d: wgpu::RenderPipeline,
|
|
292
295
|
pipeline_3d: wgpu::RenderPipeline,
|
|
@@ -6333,6 +6336,8 @@ impl Renderer {
|
|
|
6333
6336
|
..Default::default()
|
|
6334
6337
|
});
|
|
6335
6338
|
|
|
6339
|
+
let ui_renderer = ui_pass::UiRendererState::new(&device, output_format);
|
|
6340
|
+
|
|
6336
6341
|
let mut renderer = Self {
|
|
6337
6342
|
headless_target: if surface.is_none() {
|
|
6338
6343
|
Some(device.create_texture(&wgpu::TextureDescriptor {
|
|
@@ -6361,6 +6366,7 @@ impl Renderer {
|
|
|
6361
6366
|
output_format,
|
|
6362
6367
|
logical_width,
|
|
6363
6368
|
logical_height,
|
|
6369
|
+
ui_renderer,
|
|
6364
6370
|
pipeline_2d,
|
|
6365
6371
|
pipeline_3d,
|
|
6366
6372
|
uniform_buffers,
|
|
@@ -9753,203 +9759,15 @@ impl Renderer {
|
|
|
9753
9759
|
self.material_per_view_bg_live = true;
|
|
9754
9760
|
}
|
|
9755
9761
|
|
|
9756
|
-
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
9760
|
-
|
|
9761
|
-
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
|
|
9765
|
-
// Q1: If rendering to a texture, use the RT view. Otherwise use the surface.
|
|
9766
|
-
// We take ownership of the RT views (via Option::take) to avoid holding a
|
|
9767
|
-
// borrow on `self` while the rest of end_frame mutates it.
|
|
9768
|
-
let rt_color = self.rt_color_view.take();
|
|
9769
|
-
let rt_depth = self.rt_depth_view.take();
|
|
9770
|
-
let using_rt = rt_color.is_some();
|
|
9771
|
-
|
|
9772
|
-
let surface_output = if using_rt {
|
|
9773
|
-
None
|
|
9774
|
-
} else {
|
|
9775
|
-
match self.acquire_frame() {
|
|
9776
|
-
Some(t) => Some(t),
|
|
9777
|
-
None => {
|
|
9778
|
-
// Swapchain lost+reconfigured. Restore RT views if set.
|
|
9779
|
-
self.rt_color_view = rt_color;
|
|
9780
|
-
self.rt_depth_view = rt_depth;
|
|
9781
|
-
return;
|
|
9782
|
-
}
|
|
9783
|
-
}
|
|
9784
|
-
};
|
|
9785
|
-
|
|
9786
|
-
let view: wgpu::TextureView;
|
|
9787
|
-
let owned_depth_view: wgpu::TextureView;
|
|
9788
|
-
|
|
9789
|
-
if let Some(ref rt_view) = rt_color {
|
|
9790
|
-
view = rt_view.clone();
|
|
9791
|
-
owned_depth_view = rt_depth.as_ref().unwrap().clone();
|
|
9792
|
-
} else {
|
|
9793
|
-
view = self.frame_texture(surface_output.as_ref().unwrap()).create_view(&wgpu::TextureViewDescriptor {
|
|
9794
|
-
format: Some(self.output_format),
|
|
9795
|
-
..Default::default()
|
|
9796
|
-
});
|
|
9797
|
-
owned_depth_view = self.depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
|
9798
|
-
}
|
|
9799
|
-
|
|
9800
|
-
// Restore RT views so they persist across frames.
|
|
9801
|
-
self.rt_color_view = rt_color;
|
|
9802
|
-
self.rt_depth_view = rt_depth;
|
|
9803
|
-
|
|
9804
|
-
let mut encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
|
9805
|
-
label: Some("bloom_encoder"),
|
|
9806
|
-
});
|
|
9807
|
-
|
|
9808
|
-
// Upload 2D data to persistent GPU buffers
|
|
9809
|
-
let has_2d = !self.vertices_2d.is_empty();
|
|
9810
|
-
if has_2d {
|
|
9811
|
-
let vb_size = std::mem::size_of_val(self.vertices_2d.as_slice());
|
|
9812
|
-
let ib_size = std::mem::size_of_val(self.indices_2d.as_slice());
|
|
9813
|
-
self.ensure_buffer_capacity_2d(vb_size, ib_size);
|
|
9814
|
-
self.queue.write_buffer(&self.persistent_vb_2d, 0, bytemuck::cast_slice(&self.vertices_2d));
|
|
9815
|
-
self.queue.write_buffer(&self.persistent_ib_2d, 0, bytemuck::cast_slice(&self.indices_2d));
|
|
9816
|
-
}
|
|
9817
|
-
|
|
9818
|
-
// Upload 3D data to persistent GPU buffers
|
|
9819
|
-
let has_3d = !self.vertices_3d.is_empty();
|
|
9820
|
-
if has_3d {
|
|
9821
|
-
let vb_size = std::mem::size_of_val(self.vertices_3d.as_slice());
|
|
9822
|
-
let ib_size = std::mem::size_of_val(self.indices_3d.as_slice());
|
|
9823
|
-
self.ensure_buffer_capacity_3d(vb_size, ib_size);
|
|
9824
|
-
self.queue.write_buffer(&self.persistent_vb_3d, 0, bytemuck::cast_slice(&self.vertices_3d));
|
|
9825
|
-
self.queue.write_buffer(&self.persistent_ib_3d, 0, bytemuck::cast_slice(&self.indices_3d));
|
|
9826
|
-
}
|
|
9827
|
-
|
|
9828
|
-
{
|
|
9829
|
-
// Only attach a depth target when we're drawing 3D. pipeline_2d is
|
|
9830
|
-
// depth-less; on some mobile Vulkan drivers (Adreno) pairing a
|
|
9831
|
-
// depth-less pipeline with a pass that carries a depth attachment
|
|
9832
|
-
// discards all draws silently. Matches the overlay_2d pass in
|
|
9833
|
-
// end_frame_with_scene, which also omits depth.
|
|
9834
|
-
let depth_attachment = if has_3d {
|
|
9835
|
-
Some(wgpu::RenderPassDepthStencilAttachment {
|
|
9836
|
-
view: &owned_depth_view,
|
|
9837
|
-
depth_ops: Some(wgpu::Operations {
|
|
9838
|
-
load: wgpu::LoadOp::Clear(1.0),
|
|
9839
|
-
store: wgpu::StoreOp::Store,
|
|
9840
|
-
}),
|
|
9841
|
-
stencil_ops: None,
|
|
9842
|
-
})
|
|
9843
|
-
} else {
|
|
9844
|
-
None
|
|
9845
|
-
};
|
|
9846
|
-
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
|
9847
|
-
label: Some("bloom_pass"),
|
|
9848
|
-
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
|
9849
|
-
view: &view,
|
|
9850
|
-
resolve_target: None,
|
|
9851
|
-
depth_slice: None,
|
|
9852
|
-
ops: wgpu::Operations {
|
|
9853
|
-
load: wgpu::LoadOp::Clear(self.clear_color),
|
|
9854
|
-
store: wgpu::StoreOp::Store,
|
|
9855
|
-
},
|
|
9856
|
-
})],
|
|
9857
|
-
depth_stencil_attachment: depth_attachment,
|
|
9858
|
-
timestamp_writes: None,
|
|
9859
|
-
occlusion_query_set: None,
|
|
9860
|
-
multiview_mask: None,
|
|
9861
|
-
});
|
|
9862
|
-
|
|
9863
|
-
// Draw 3D geometry first (with depth testing), batched by texture
|
|
9864
|
-
if has_3d {
|
|
9865
|
-
pass.set_pipeline(&self.pipeline_3d);
|
|
9866
|
-
pass.set_bind_group(0, &self.uniform_bind_group_3d, &[]);
|
|
9867
|
-
pass.set_bind_group(1, &self.lighting_bind_group, &[]);
|
|
9868
|
-
pass.set_bind_group(3, &self.joint_bind_group, &[]);
|
|
9869
|
-
pass.set_vertex_buffer(0, self.persistent_vb_3d.slice(..));
|
|
9870
|
-
pass.set_index_buffer(self.persistent_ib_3d.slice(..), wgpu::IndexFormat::Uint32);
|
|
9871
|
-
|
|
9872
|
-
if self.draw_calls_3d.is_empty() {
|
|
9873
|
-
// No draw calls tracked — draw all with white texture (backward compat)
|
|
9874
|
-
pass.set_bind_group(2, &self.texture_bind_groups[0], &[]);
|
|
9875
|
-
pass.draw_indexed(0..self.indices_3d.len() as u32, 0, 0..1);
|
|
9876
|
-
} else {
|
|
9877
|
-
let num_calls = self.draw_calls_3d.len();
|
|
9878
|
-
for i in 0..num_calls {
|
|
9879
|
-
let call = &self.draw_calls_3d[i];
|
|
9880
|
-
let next_start = if i + 1 < num_calls {
|
|
9881
|
-
self.draw_calls_3d[i + 1].index_start
|
|
9882
|
-
} else {
|
|
9883
|
-
self.indices_3d.len() as u32
|
|
9884
|
-
};
|
|
9885
|
-
let count = next_start - call.index_start;
|
|
9886
|
-
if count == 0 { continue; }
|
|
9887
|
-
let tex_idx = call.texture_idx as usize;
|
|
9888
|
-
if tex_idx < self.texture_bind_groups.len() {
|
|
9889
|
-
pass.set_bind_group(2, &self.texture_bind_groups[tex_idx], &[]);
|
|
9890
|
-
} else {
|
|
9891
|
-
pass.set_bind_group(2, &self.texture_bind_groups[0], &[]);
|
|
9892
|
-
}
|
|
9893
|
-
pass.draw_indexed(call.index_start..next_start, 0, 0..1);
|
|
9894
|
-
}
|
|
9895
|
-
}
|
|
9896
|
-
}
|
|
9897
|
-
|
|
9898
|
-
// Draw cached models (static models with GPU-resident buffers).
|
|
9899
|
-
// Use the scene pipeline so PBR-style material bindings (base
|
|
9900
|
-
// color + normal map) apply — drawModel should behave the same
|
|
9901
|
-
// as attachModelToNode for PBR purposes.
|
|
9902
|
-
if !self.model_draw_commands.is_empty() {
|
|
9903
|
-
pass.set_pipeline(&self.scene_pipeline);
|
|
9904
|
-
pass.set_bind_group(1, &self.lighting_bind_group, &[]);
|
|
9905
|
-
pass.set_bind_group(3, &self.joint_bind_group, &[]);
|
|
9906
|
-
|
|
9907
|
-
for cmd in &self.model_draw_commands {
|
|
9908
|
-
if let Some(Some(meshes)) = self.model_gpu_cache.get(&cmd.cache_handle) {
|
|
9909
|
-
if cmd.mesh_idx < meshes.len() {
|
|
9910
|
-
let mesh = &meshes[cmd.mesh_idx];
|
|
9911
|
-
pass.set_bind_group(0, &self.model_uniform_bind_groups[cmd.uniform_slot], &[]);
|
|
9912
|
-
pass.set_bind_group(2, &mesh.material_bg, &[]);
|
|
9913
|
-
pass.set_vertex_buffer(0, mesh.vb.slice(..));
|
|
9914
|
-
pass.set_index_buffer(mesh.ib.slice(..), wgpu::IndexFormat::Uint32);
|
|
9915
|
-
pass.draw_indexed(0..mesh.index_count, 0, 0..1);
|
|
9916
|
-
}
|
|
9917
|
-
}
|
|
9918
|
-
}
|
|
9919
|
-
}
|
|
9920
|
-
|
|
9921
|
-
// Draw 2D geometry (no depth testing, always passes)
|
|
9922
|
-
if has_2d {
|
|
9923
|
-
pass.set_pipeline(&self.pipeline_2d);
|
|
9924
|
-
pass.set_vertex_buffer(0, self.persistent_vb_2d.slice(..));
|
|
9925
|
-
pass.set_index_buffer(self.persistent_ib_2d.slice(..), wgpu::IndexFormat::Uint32);
|
|
9926
|
-
|
|
9927
|
-
let num_calls = self.draw_calls_2d.len();
|
|
9928
|
-
for i in 0..num_calls {
|
|
9929
|
-
let call = &self.draw_calls_2d[i];
|
|
9930
|
-
let next_start = if i + 1 < num_calls {
|
|
9931
|
-
self.draw_calls_2d[i + 1].index_start
|
|
9932
|
-
} else {
|
|
9933
|
-
self.indices_2d.len() as u32
|
|
9934
|
-
};
|
|
9935
|
-
let count = next_start - call.index_start;
|
|
9936
|
-
if count == 0 { continue; }
|
|
9937
|
-
|
|
9938
|
-
pass.set_bind_group(0, &self.uniform_bind_groups[call.uniform_idx as usize], &[]);
|
|
9939
|
-
if (call.texture_idx as usize) < self.texture_bind_groups.len() {
|
|
9940
|
-
pass.set_bind_group(1, &self.texture_bind_groups[call.texture_idx as usize], &[]);
|
|
9941
|
-
}
|
|
9942
|
-
pass.draw_indexed(call.index_start..next_start, 0, 0..1);
|
|
9943
|
-
}
|
|
9944
|
-
}
|
|
9945
|
-
}
|
|
9946
|
-
|
|
9947
|
-
self.queue.submit(std::iter::once(encoder.finish()));
|
|
9948
|
-
if let Some(out) = surface_output { self.present_frame(out); }
|
|
9949
|
-
}
|
|
9950
|
-
|
|
9951
|
-
/// Like end_frame, but also renders retained scene graph nodes.
|
|
9952
|
-
pub fn end_frame_with_scene(&mut self, scene: &mut crate::scene::SceneGraph, profiler: &mut crate::profiler::Profiler) {
|
|
9762
|
+
#[allow(unused_variables)]
|
|
9763
|
+
fn end_frame_with_scene_internal(
|
|
9764
|
+
&mut self,
|
|
9765
|
+
scene: &mut crate::scene::SceneGraph,
|
|
9766
|
+
profiler: &mut crate::profiler::Profiler,
|
|
9767
|
+
ui: Option<&mut crate::ui::UiSystem>,
|
|
9768
|
+
dt: f64,
|
|
9769
|
+
native_texture_indices: HashMap<u64, u32>,
|
|
9770
|
+
) {
|
|
9953
9771
|
if !self.material_per_view_bg_live {
|
|
9954
9772
|
self.refresh_material_per_view_bg();
|
|
9955
9773
|
}
|
|
@@ -10567,6 +10385,21 @@ impl Renderer {
|
|
|
10567
10385
|
profiler.end("overlay_2d");
|
|
10568
10386
|
}
|
|
10569
10387
|
|
|
10388
|
+
let ui_command_buffers =
|
|
10389
|
+
self.encode_egui_pass(&mut encoder, &view, using_rt || self.surface.is_none());
|
|
10390
|
+
|
|
10391
|
+
#[cfg(feature = "debug-ui")]
|
|
10392
|
+
if let Some(ui) = ui {
|
|
10393
|
+
self.encode_dear_imgui_pass(
|
|
10394
|
+
&mut encoder,
|
|
10395
|
+
&view,
|
|
10396
|
+
using_rt || self.surface.is_none(),
|
|
10397
|
+
ui,
|
|
10398
|
+
dt,
|
|
10399
|
+
&native_texture_indices,
|
|
10400
|
+
);
|
|
10401
|
+
}
|
|
10402
|
+
|
|
10570
10403
|
profiler.resolve(&mut encoder);
|
|
10571
10404
|
|
|
10572
10405
|
// If screenshot requested, copy rendered texture to staging buffer before submitting.
|
|
@@ -10609,7 +10442,11 @@ impl Renderer {
|
|
|
10609
10442
|
wgpu::Extent3d { width, height, depth_or_array_layers: 1 },
|
|
10610
10443
|
);
|
|
10611
10444
|
|
|
10612
|
-
self.queue.submit(
|
|
10445
|
+
self.queue.submit(
|
|
10446
|
+
ui_command_buffers
|
|
10447
|
+
.into_iter()
|
|
10448
|
+
.chain(std::iter::once(encoder.finish())),
|
|
10449
|
+
);
|
|
10613
10450
|
|
|
10614
10451
|
// Read back pixels synchronously
|
|
10615
10452
|
let slice = staging.slice(..);
|
|
@@ -10660,7 +10497,11 @@ impl Renderer {
|
|
|
10660
10497
|
self.screenshot_requested = false;
|
|
10661
10498
|
} else {
|
|
10662
10499
|
profiler.begin("queue_submit");
|
|
10663
|
-
self.queue.submit(
|
|
10500
|
+
self.queue.submit(
|
|
10501
|
+
ui_command_buffers
|
|
10502
|
+
.into_iter()
|
|
10503
|
+
.chain(std::iter::once(encoder.finish())),
|
|
10504
|
+
);
|
|
10664
10505
|
profiler.end("queue_submit");
|
|
10665
10506
|
}
|
|
10666
10507
|
|
|
@@ -10682,9 +10523,15 @@ impl Renderer {
|
|
|
10682
10523
|
|
|
10683
10524
|
#[cfg(target_arch = "wasm32")]
|
|
10684
10525
|
{
|
|
10685
|
-
self.queue.submit(
|
|
10526
|
+
self.queue.submit(
|
|
10527
|
+
ui_command_buffers
|
|
10528
|
+
.into_iter()
|
|
10529
|
+
.chain(std::iter::once(encoder.finish())),
|
|
10530
|
+
);
|
|
10686
10531
|
}
|
|
10687
10532
|
|
|
10533
|
+
self.free_pending_egui_textures();
|
|
10534
|
+
|
|
10688
10535
|
profiler.begin("swap_present");
|
|
10689
10536
|
if let Some(out) = output {
|
|
10690
10537
|
self.present_frame(out);
|
|
@@ -12553,4 +12400,3 @@ impl Renderer {
|
|
|
12553
12400
|
self.material_system.update_frame_uniforms(&self.queue, &per_frame, &per_view);
|
|
12554
12401
|
}
|
|
12555
12402
|
}
|
|
12556
|
-
|
|
@@ -75,6 +75,9 @@ impl Renderer {
|
|
|
75
75
|
self.textures[i] = texture;
|
|
76
76
|
self.texture_bind_groups[i] = bind_group;
|
|
77
77
|
self.texture_sizes[i] = (width, height);
|
|
78
|
+
self.refresh_egui_texture_index(idx);
|
|
79
|
+
#[cfg(feature = "debug-ui")]
|
|
80
|
+
self.refresh_dear_imgui_texture_index(idx);
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
/// Register a texture with optional normal-map preprocessing.
|
|
@@ -328,6 +331,8 @@ impl Renderer {
|
|
|
328
331
|
self.textures[i] = white;
|
|
329
332
|
self.texture_bind_groups[i] = bind_group;
|
|
330
333
|
self.texture_sizes[i] = (0, 0);
|
|
334
|
+
#[cfg(feature = "debug-ui")]
|
|
335
|
+
self.refresh_dear_imgui_texture_index(idx);
|
|
331
336
|
}
|
|
332
337
|
|
|
333
338
|
/// Drop a model's cached GPU meshes. Must be called when the model is
|