render: process GltfScenes and Node local transforms
This commit is contained in:
parent
c1b5ca768f
commit
fba925512b
|
@ -1845,7 +1845,9 @@ dependencies = [
|
|||
"gltf",
|
||||
"image",
|
||||
"infer",
|
||||
"instant",
|
||||
"lyra-ecs",
|
||||
"lyra-math",
|
||||
"mime",
|
||||
"notify",
|
||||
"notify-debouncer-full",
|
||||
|
@ -3101,7 +3103,6 @@ dependencies = [
|
|||
"async-std",
|
||||
"fps_counter",
|
||||
"lyra-engine",
|
||||
"lyra-scripting",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
|
|
@ -6,8 +6,9 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
lyra-engine = { path = "../../", version = "0.0.1", features = ["lua_scripting"] }
|
||||
lyra-scripting = { path = "../../lyra-scripting", features = ["lua", "teal"] }
|
||||
lyra-engine = { path = "../../", version = "0.0.1" }
|
||||
#lyra-engine = { path = "../../", version = "0.0.1", features = ["lua_scripting"] }
|
||||
#lyra-scripting = { path = "../../lyra-scripting", features = ["lua", "teal"] }
|
||||
#lyra-ecs = { path = "../../lyra-ecs"}
|
||||
anyhow = "1.0.75"
|
||||
async-std = "1.12.0"
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,2 @@
|
|||
Sponza*
|
||||
Textures
|
|
@ -0,0 +1 @@
|
|||
To keep the size of this repository down, the Sponza scene is omitted from this repo. The files were downloaded from https://github.com/toji/sponza-optimized
|
|
@ -1,7 +1,7 @@
|
|||
use std::ptr::NonNull;
|
||||
|
||||
use lyra_engine::{math::{self, Vec3}, math::Transform, input::{KeyCode, ActionHandler, Action, ActionKind, LayoutId, ActionMapping, ActionSource, ActionMappingId, InputActionPlugin, MouseInput, MouseAxis, CommonActionLabel}, game::Game, render::{window::{CursorGrabMode, WindowOptions}, light::{PointLight, directional::DirectionalLight, SpotLight}}, change_tracker::Ct, ecs::{system::{Criteria, CriteriaSchedule, BatchedSystem, IntoSystem}, World, Component}, DeltaTime, scene::{ModelComponent, CameraComponent}, lua::{LuaScriptingPlugin, LuaScript}, Script, ScriptList};
|
||||
use lyra_engine::assets::{ResourceManager, Model};
|
||||
use lyra_engine::{assets::gltf::Gltf, ecs::{system::{BatchedSystem, Criteria, CriteriaSchedule, IntoSystem}, Component, World}, game::Game, input::{Action, ActionHandler, ActionKind, ActionMapping, ActionMappingId, ActionSource, InputActionPlugin, KeyCode, LayoutId, MouseAxis, MouseInput}, math::{self, Transform, Vec3}, render::light::{directional::DirectionalLight, PointLight, SpotLight}, scene::{CameraComponent, MeshComponent}, DeltaTime};
|
||||
use lyra_engine::assets::ResourceManager;
|
||||
|
||||
mod free_fly_camera;
|
||||
use free_fly_camera::{FreeFlyCameraPlugin, FreeFlyCamera};
|
||||
|
@ -16,6 +16,13 @@ pub enum ActionLabel {
|
|||
LookRoll,
|
||||
}
|
||||
|
||||
const ACTLBL_MOVE_UP_DOWN: &str = "MoveUpDown";
|
||||
const ACTLBL_MOVE_LEFT_RIGHT: &str = "MoveLeftRight";
|
||||
const ACTLBL_MOVE_FORWARD_BACKWARD: &str = "MoveForwardBackward";
|
||||
const ACTLBL_LOOK_LEFT_RIGHT: &str = "LookLeftRight";
|
||||
const ACTLBL_LOOK_UP_DOWN: &str = "LookUpDown";
|
||||
const ACTLBL_LOOK_ROLL: &str = "LookRoll";
|
||||
|
||||
struct FixedTimestep {
|
||||
max_tps: u32,
|
||||
fixed_time: f32,
|
||||
|
@ -86,30 +93,45 @@ async fn main() {
|
|||
//let diffuse_texture = resman.request::<Texture>("assets/happy-tree.png").unwrap();
|
||||
//let antique_camera_model = resman.request::<Model>("assets/AntiqueCamera.glb").unwrap();
|
||||
//let cube_model = resman.request::<Model>("assets/cube-texture-bin.glb").unwrap();
|
||||
let cube_model = resman.request::<Model>("assets/texture-sep/texture-sep.gltf").unwrap();
|
||||
let crate_model = resman.request::<Model>("assets/crate/crate.gltf").unwrap();
|
||||
//let sponza_model = resman.request::<Model>("assets/sponza/Sponza.gltf").unwrap();
|
||||
let cube_gltf = resman.request::<Gltf>("assets/texture-sep/texture-sep.gltf").unwrap();
|
||||
let crate_gltf = resman.request::<Gltf>("assets/crate/crate.gltf").unwrap();
|
||||
|
||||
let separate_gltf = resman.request::<Gltf>("assets/pos-testing/separate-nodes-two-cubes.glb").unwrap();
|
||||
drop(resman);
|
||||
|
||||
/* world.spawn((
|
||||
ModelComponent(antique_camera_model),
|
||||
Transform::from_xyz(0.0, -5.0, -10.0),
|
||||
)); */
|
||||
let cube_mesh = &cube_gltf.data_ref()
|
||||
.unwrap().meshes[0];
|
||||
let crate_mesh = &crate_gltf.data_ref()
|
||||
.unwrap().meshes[0];
|
||||
|
||||
/* world.spawn((
|
||||
ModelComponent(sponza_model),
|
||||
let separate_scene = &separate_gltf.data_ref()
|
||||
.unwrap().scenes[0];
|
||||
|
||||
/* let sponza_model = resman.request::<Gltf>("assets/sponza/Sponza.gltf").unwrap();
|
||||
drop(resman);
|
||||
|
||||
let sponza_scene = &sponza_model.data_ref()
|
||||
.unwrap().scenes[0];
|
||||
|
||||
world.spawn((
|
||||
sponza_scene.clone(),
|
||||
Transform::from_xyz(0.0, 0.0, 0.0),
|
||||
)); */
|
||||
|
||||
{
|
||||
let cube_tran = Transform::from_xyz(-3.5, 0.0, -8.0);
|
||||
world.spawn((
|
||||
separate_scene.clone(),
|
||||
Transform::from_xyz(0.0, -5.0, -10.0),
|
||||
));
|
||||
|
||||
/* {
|
||||
let cube_tran = Transform::from_xyz(-5.9026427, -1.8953488, -10.0);
|
||||
//cube_tran.rotate_y(math::Angle::Degrees(180.0));
|
||||
world.spawn((
|
||||
cube_tran,
|
||||
ModelComponent(crate_model.clone()),
|
||||
crate_mesh.clone(),
|
||||
CubeFlag,
|
||||
));
|
||||
}
|
||||
} */
|
||||
|
||||
{
|
||||
let mut light_tran = Transform::from_xyz(1.5, 2.5, 0.0);
|
||||
|
@ -124,11 +146,11 @@ async fn main() {
|
|||
specular: 1.3,
|
||||
},
|
||||
light_tran,
|
||||
ModelComponent(cube_model.clone()),
|
||||
cube_mesh.clone(),
|
||||
));
|
||||
}
|
||||
|
||||
{
|
||||
/* {
|
||||
let mut light_tran = Transform::from_xyz(-3.5, 0.2, -4.5);
|
||||
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
|
||||
world.spawn((
|
||||
|
@ -146,10 +168,32 @@ async fn main() {
|
|||
specular: 1.0,
|
||||
},
|
||||
Transform::from(light_tran),
|
||||
ModelComponent(cube_model.clone()),
|
||||
cube_mesh.clone(),
|
||||
));
|
||||
}
|
||||
|
||||
{
|
||||
let mut light_tran = Transform::from_xyz(2.0, 2.5, -9.5);
|
||||
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
|
||||
world.spawn((
|
||||
PointLight {
|
||||
color: Vec3::new(0.0, 0.0, 1.0),
|
||||
|
||||
intensity: 3.3,
|
||||
|
||||
constant: 1.0,
|
||||
linear: 0.09,
|
||||
quadratic: 0.032,
|
||||
|
||||
ambient: 0.2,
|
||||
diffuse: 1.0,
|
||||
specular: 1.3,
|
||||
},
|
||||
Transform::from(light_tran),
|
||||
cube_mesh.clone(),
|
||||
));
|
||||
} */
|
||||
|
||||
/* {
|
||||
let mut light_tran = Transform::from_xyz(-5.0, 2.5, -9.5);
|
||||
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
|
||||
|
@ -172,28 +216,6 @@ async fn main() {
|
|||
));
|
||||
} */
|
||||
|
||||
{
|
||||
let mut light_tran = Transform::from_xyz(2.0, 2.5, -9.5);
|
||||
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
|
||||
world.spawn((
|
||||
PointLight {
|
||||
color: Vec3::new(0.0, 0.0, 1.0),
|
||||
|
||||
intensity: 3.3,
|
||||
|
||||
constant: 1.0,
|
||||
linear: 0.09,
|
||||
quadratic: 0.032,
|
||||
|
||||
ambient: 0.2,
|
||||
diffuse: 1.0,
|
||||
specular: 1.3,
|
||||
},
|
||||
Transform::from(light_tran),
|
||||
ModelComponent(cube_model),
|
||||
));
|
||||
}
|
||||
|
||||
let mut camera = CameraComponent::new_3d();
|
||||
camera.transform.translation += math::Vec3::new(0.0, 0.0, 5.5);
|
||||
world.spawn(( camera, FreeFlyCamera::default() ));
|
||||
|
@ -211,7 +233,7 @@ async fn main() {
|
|||
|
||||
Ok(())
|
||||
};
|
||||
let fps_plugin = move |game: &mut Game| {
|
||||
let _fps_plugin = move |game: &mut Game| {
|
||||
let world = game.world_mut();
|
||||
world.add_resource(fps_counter::FPSCounter::new());
|
||||
};
|
||||
|
@ -246,54 +268,54 @@ async fn main() {
|
|||
};
|
||||
|
||||
let action_handler_plugin = |game: &mut Game| {
|
||||
/* let action_handler = ActionHandler::builder()
|
||||
let action_handler = ActionHandler::builder()
|
||||
.add_layout(LayoutId::from(0))
|
||||
|
||||
.add_action(CommonActionLabel::MoveForwardBackward, Action::new(ActionKind::Axis))
|
||||
.add_action(CommonActionLabel::MoveLeftRight, Action::new(ActionKind::Axis))
|
||||
.add_action(CommonActionLabel::MoveUpDown, Action::new(ActionKind::Axis))
|
||||
.add_action(CommonActionLabel::LookLeftRight, Action::new(ActionKind::Axis))
|
||||
.add_action(CommonActionLabel::LookUpDown, Action::new(ActionKind::Axis))
|
||||
.add_action(CommonActionLabel::LookRoll, Action::new(ActionKind::Axis))
|
||||
.add_action(ACTLBL_MOVE_FORWARD_BACKWARD, Action::new(ActionKind::Axis))
|
||||
.add_action(ACTLBL_MOVE_LEFT_RIGHT, Action::new(ActionKind::Axis))
|
||||
.add_action(ACTLBL_MOVE_UP_DOWN, Action::new(ActionKind::Axis))
|
||||
.add_action(ACTLBL_LOOK_LEFT_RIGHT, Action::new(ActionKind::Axis))
|
||||
.add_action(ACTLBL_LOOK_UP_DOWN, Action::new(ActionKind::Axis))
|
||||
.add_action(ACTLBL_LOOK_ROLL, Action::new(ActionKind::Axis))
|
||||
|
||||
.add_mapping(ActionMapping::builder(LayoutId::from(0), ActionMappingId::from(0))
|
||||
.bind(CommonActionLabel::MoveForwardBackward, &[
|
||||
.bind(ACTLBL_MOVE_FORWARD_BACKWARD, &[
|
||||
ActionSource::Keyboard(KeyCode::W).into_binding_modifier(1.0),
|
||||
ActionSource::Keyboard(KeyCode::S).into_binding_modifier(-1.0)
|
||||
])
|
||||
.bind(CommonActionLabel::MoveLeftRight, &[
|
||||
.bind(ACTLBL_MOVE_LEFT_RIGHT, &[
|
||||
ActionSource::Keyboard(KeyCode::A).into_binding_modifier(-1.0),
|
||||
ActionSource::Keyboard(KeyCode::D).into_binding_modifier(1.0)
|
||||
])
|
||||
.bind(CommonActionLabel::MoveUpDown, &[
|
||||
.bind(ACTLBL_MOVE_UP_DOWN, &[
|
||||
ActionSource::Keyboard(KeyCode::C).into_binding_modifier(1.0),
|
||||
ActionSource::Keyboard(KeyCode::Z).into_binding_modifier(-1.0)
|
||||
])
|
||||
.bind(CommonActionLabel::LookLeftRight, &[
|
||||
.bind(ACTLBL_LOOK_LEFT_RIGHT, &[
|
||||
ActionSource::Mouse(MouseInput::Axis(MouseAxis::X)).into_binding(),
|
||||
ActionSource::Keyboard(KeyCode::Left).into_binding_modifier(-1.0),
|
||||
ActionSource::Keyboard(KeyCode::Right).into_binding_modifier(1.0),
|
||||
//ActionSource::Gamepad(GamepadFormat::DualAxis, GamepadInput::Axis(GamepadAxis::RThumbstickX)).into_binding(),
|
||||
])
|
||||
.bind(CommonActionLabel::LookUpDown, &[
|
||||
.bind(ACTLBL_LOOK_UP_DOWN, &[
|
||||
ActionSource::Mouse(MouseInput::Axis(MouseAxis::Y)).into_binding(),
|
||||
ActionSource::Keyboard(KeyCode::Up).into_binding_modifier(-1.0),
|
||||
ActionSource::Keyboard(KeyCode::Down).into_binding_modifier(1.0),
|
||||
//ActionSource::Gamepad(GamepadFormat::DualAxis, GamepadInput::Axis(GamepadAxis::RThumbstickY)).into_binding(),
|
||||
])
|
||||
.bind(CommonActionLabel::LookRoll, &[
|
||||
.bind(ACTLBL_LOOK_ROLL, &[
|
||||
ActionSource::Keyboard(KeyCode::E).into_binding_modifier(-1.0),
|
||||
ActionSource::Keyboard(KeyCode::Q).into_binding_modifier(1.0),
|
||||
])
|
||||
.finish()
|
||||
);
|
||||
).finish();
|
||||
|
||||
let world = game.world_mut();
|
||||
world.add_resource(action_handler); */
|
||||
world.add_resource(action_handler);
|
||||
game.with_plugin(InputActionPlugin);
|
||||
};
|
||||
|
||||
let script_test_plugin = |game: &mut Game| {
|
||||
/* let script_test_plugin = |game: &mut Game| {
|
||||
game.with_plugin(LuaScriptingPlugin);
|
||||
|
||||
let world = game.world_mut();
|
||||
|
@ -306,13 +328,13 @@ async fn main() {
|
|||
let scripts = ScriptList::new(vec![script]);
|
||||
world.spawn((scripts,));
|
||||
|
||||
};
|
||||
}; */
|
||||
|
||||
Game::initialize().await
|
||||
.with_plugin(lyra_engine::DefaultPlugins)
|
||||
.with_startup_system(setup_sys.into_system())
|
||||
.with_plugin(action_handler_plugin)
|
||||
.with_plugin(script_test_plugin)
|
||||
//.with_plugin(script_test_plugin)
|
||||
//.with_plugin(fps_plugin)
|
||||
.with_plugin(jiggle_plugin)
|
||||
.with_plugin(FreeFlyCameraPlugin)
|
||||
|
|
|
@ -10,11 +10,11 @@ pub struct MaterialSpecular {
|
|||
}
|
||||
|
||||
impl MaterialSpecular {
|
||||
pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc<wgpu::BindGroupLayout>, value: &lyra_resource::Specular) -> Self {
|
||||
let tex = value.texture.as_ref().map(|t| t.data_ref())
|
||||
pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc<wgpu::BindGroupLayout>, value: &lyra_resource::gltf::Specular) -> Self {
|
||||
let tex = value.texture.as_ref().and_then(|t| t.data_ref())
|
||||
.map(|i| RenderTexture::from_image(device, queue, bg_layout.clone(), &i.image, None).unwrap());
|
||||
|
||||
let color_tex = value.color_texture.as_ref().map(|t| t.data_ref())
|
||||
let color_tex = value.color_texture.as_ref().and_then(|t| t.data_ref())
|
||||
.map(|i| RenderTexture::from_image(device, queue, bg_layout, &i.image, None).unwrap());
|
||||
|
||||
Self {
|
||||
|
@ -38,8 +38,8 @@ pub struct Material {
|
|||
}
|
||||
|
||||
impl Material {
|
||||
pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc<wgpu::BindGroupLayout>, value: &lyra_resource::Material) -> Self {
|
||||
let diffuse_texture = value.base_color_texture.as_ref().map(|t| t.data_ref())
|
||||
pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc<wgpu::BindGroupLayout>, value: &lyra_resource::gltf::Material) -> Self {
|
||||
let diffuse_texture = value.base_color_texture.as_ref().and_then(|t| t.data_ref())
|
||||
.map(|i| RenderTexture::from_image(device, queue, bg_layout.clone(), &i.image, None).unwrap());
|
||||
|
||||
let specular = value.specular.as_ref().map(|s| MaterialSpecular::from_resource(device, queue, bg_layout.clone(), s));
|
||||
|
|
|
@ -5,10 +5,13 @@ use std::borrow::Cow;
|
|||
use glam::Vec3;
|
||||
use instant::Instant;
|
||||
use itertools::izip;
|
||||
use lyra_ecs::Entity;
|
||||
use lyra_ecs::query::filter::{Has, Or};
|
||||
use lyra_ecs::{Entity, Tick};
|
||||
use lyra_ecs::query::{Entities, TickOf};
|
||||
use lyra_ecs::World;
|
||||
use tracing::{debug, warn};
|
||||
use lyra_resource::gltf::GltfScene;
|
||||
use tracing::{debug, debug_span, warn};
|
||||
use uuid::Uuid;
|
||||
use wgpu::{BindGroupLayout, Limits};
|
||||
use wgpu::util::DeviceExt;
|
||||
use winit::window::Window;
|
||||
|
@ -16,7 +19,7 @@ use winit::window::Window;
|
|||
use crate::math::Transform;
|
||||
use crate::render::material::MaterialUniform;
|
||||
use crate::render::render_buffer::BufferWrapperBuilder;
|
||||
use crate::scene::{ModelComponent, CameraComponent};
|
||||
use crate::scene::CameraComponent;
|
||||
|
||||
use super::camera::{RenderCamera, CameraUniform};
|
||||
use super::desc_buf_lay::DescVertexBufferLayout;
|
||||
|
@ -28,7 +31,10 @@ use super::transform_buffer_storage::TransformBuffers;
|
|||
use super::vertex::Vertex;
|
||||
use super::{render_pipeline::FullRenderPipeline, render_buffer::BufferStorage, render_job::RenderJob};
|
||||
|
||||
use lyra_resource::Mesh;
|
||||
use lyra_resource::{gltf::Mesh, ResHandle};
|
||||
|
||||
type MeshHandle = ResHandle<Mesh>;
|
||||
type SceneHandle = ResHandle<GltfScene>;
|
||||
|
||||
pub trait Renderer {
|
||||
fn prepare(&mut self, main_world: &mut World);
|
||||
|
@ -265,16 +271,19 @@ impl BasicRenderer {
|
|||
s
|
||||
}
|
||||
|
||||
fn update_mesh_buffers(&mut self, _entity: Entity, mesh: &Mesh) {
|
||||
if let Some(buffers) = self.mesh_buffers.get_mut(&mesh.uuid) {
|
||||
/// Checks if the mesh buffers in the GPU need to be updated.
|
||||
fn check_mesh_buffers(&mut self, _entity: Entity, meshh: &ResHandle<Mesh>) {
|
||||
let mesh_uuid = meshh.uuid();
|
||||
|
||||
if let (Some(mesh), Some(buffers)) = (meshh.data_ref(), self.mesh_buffers.get_mut(&mesh_uuid)) {
|
||||
// check if the buffer sizes dont match. If they dont, completely remake the buffers
|
||||
let vertices = mesh.position().unwrap();
|
||||
if buffers.buffer_vertex.count() != vertices.len() {
|
||||
debug!("Recreating buffers for mesh {}", mesh.uuid.to_string());
|
||||
let (vert, idx) = self.create_vertex_index_buffers(mesh);
|
||||
debug!("Recreating buffers for mesh {}", mesh_uuid.to_string());
|
||||
let (vert, idx) = self.create_vertex_index_buffers(&mesh);
|
||||
|
||||
// have to re-get buffers because of borrow checker
|
||||
let buffers = self.mesh_buffers.get_mut(&mesh.uuid).unwrap();
|
||||
let buffers = self.mesh_buffers.get_mut(&mesh_uuid).unwrap();
|
||||
buffers.buffer_indices = idx;
|
||||
buffers.buffer_vertex = vert;
|
||||
|
||||
|
@ -292,8 +301,8 @@ impl BasicRenderer {
|
|||
if let Some(index_buffer) = buffers.buffer_indices.as_ref() {
|
||||
let aligned_indices = match mesh.indices.as_ref().unwrap() {
|
||||
// U16 indices need to be aligned to u32, for wpgu, which are 4-bytes in size.
|
||||
lyra_resource::MeshIndices::U16(v) => bytemuck::pod_align_to::<u16, u32>(v).1,
|
||||
lyra_resource::MeshIndices::U32(v) => bytemuck::pod_align_to::<u32, u32>(v).1,
|
||||
lyra_resource::gltf::MeshIndices::U16(v) => bytemuck::pod_align_to::<u16, u32>(v).1,
|
||||
lyra_resource::gltf::MeshIndices::U32(v) => bytemuck::pod_align_to::<u32, u32>(v).1,
|
||||
};
|
||||
|
||||
let index_buffer = index_buffer.1.buffer();
|
||||
|
@ -327,8 +336,8 @@ impl BasicRenderer {
|
|||
let indices = match mesh.indices.as_ref() {
|
||||
Some(indices) => {
|
||||
let (idx_type, len, contents) = match indices {
|
||||
lyra_resource::MeshIndices::U16(v) => (wgpu::IndexFormat::Uint16, v.len(), bytemuck::cast_slice(v)),
|
||||
lyra_resource::MeshIndices::U32(v) => (wgpu::IndexFormat::Uint32, v.len(), bytemuck::cast_slice(v)),
|
||||
lyra_resource::gltf::MeshIndices::U16(v) => (wgpu::IndexFormat::Uint16, v.len(), bytemuck::cast_slice(v)),
|
||||
lyra_resource::gltf::MeshIndices::U32(v) => (wgpu::IndexFormat::Uint32, v.len(), bytemuck::cast_slice(v)),
|
||||
};
|
||||
|
||||
let index_buffer = self.device.create_buffer_init(
|
||||
|
@ -354,7 +363,11 @@ impl BasicRenderer {
|
|||
fn create_mesh_buffers(&mut self, mesh: &Mesh) -> MeshBufferStorage {
|
||||
let (vertex_buffer, buffer_indices) = self.create_vertex_index_buffers(mesh);
|
||||
|
||||
let material = Material::from_resource(&self.device, &self.queue, self.bgl_texture.clone(), &mesh.material());
|
||||
let material = mesh.material.as_ref()
|
||||
.expect("Material resource not loaded yet")
|
||||
.data_ref()
|
||||
.unwrap();
|
||||
let material = Material::from_resource(&self.device, &self.queue, self.bgl_texture.clone(), &material);
|
||||
let uni = MaterialUniform::from(&material);
|
||||
self.queue.write_buffer(&self.material_buffer.inner_buf, 0, bytemuck::bytes_of(&uni));
|
||||
debug!("Wrote material to buffer");
|
||||
|
@ -367,7 +380,7 @@ impl BasicRenderer {
|
|||
}
|
||||
|
||||
/// Processes the mesh for the renderer, storing and creating buffers as needed. Returns true if a new mesh was processed.
|
||||
fn process_mesh(&mut self, entity: Entity, transform: Transform, mesh: &Mesh) -> bool {
|
||||
fn process_mesh(&mut self, entity: Entity, transform: Transform, mesh: &Mesh, mesh_uuid: Uuid) -> bool {
|
||||
if self.transform_buffers.should_expand() {
|
||||
self.transform_buffers.expand_buffers(&self.device);
|
||||
}
|
||||
|
@ -376,15 +389,48 @@ impl BasicRenderer {
|
|||
entity, || ( transform.calculate_mat4(), glam::Mat3::from_quat(transform.rotation) ));
|
||||
|
||||
#[allow(clippy::map_entry)]
|
||||
if !self.mesh_buffers.contains_key(&mesh.uuid) {
|
||||
if !self.mesh_buffers.contains_key(&mesh_uuid) {
|
||||
// create the mesh's buffers
|
||||
let buffers = self.create_mesh_buffers(mesh);
|
||||
self.mesh_buffers.insert(mesh.uuid, buffers);
|
||||
self.entity_meshes.insert(entity, mesh.uuid);
|
||||
self.mesh_buffers.insert(mesh_uuid, buffers);
|
||||
self.entity_meshes.insert(entity, mesh_uuid);
|
||||
|
||||
true
|
||||
} else { false }
|
||||
}
|
||||
|
||||
fn interpolate_transforms(&mut self, now: Instant, last_epoch: Tick, entity: Entity, transform: &Transform, transform_epoch: Tick) -> Transform {
|
||||
let cached = match self.entity_last_transforms.get_mut(&entity) {
|
||||
Some(last) if transform_epoch == last_epoch => {
|
||||
last.from_transform = last.to_transform;
|
||||
last.to_transform = *transform;
|
||||
last.last_updated_at = Some(last.cached_at);
|
||||
last.cached_at = now;
|
||||
|
||||
last.clone()
|
||||
},
|
||||
Some(last) => last.clone(),
|
||||
None => {
|
||||
let cached = CachedTransform {
|
||||
last_updated_at: None,
|
||||
cached_at: now,
|
||||
from_transform: *transform,
|
||||
to_transform: *transform,
|
||||
};
|
||||
self.entity_last_transforms.insert(entity, cached.clone());
|
||||
cached
|
||||
}
|
||||
};
|
||||
|
||||
let fixed_time = match cached.last_updated_at {
|
||||
Some(last_updated_at) => cached.cached_at - last_updated_at,
|
||||
None => now - cached.cached_at
|
||||
}.as_secs_f32();
|
||||
let accumulator = (now - cached.cached_at).as_secs_f32();
|
||||
let alpha = accumulator / fixed_time;
|
||||
|
||||
cached.from_transform.lerp(cached.to_transform, alpha)
|
||||
}
|
||||
}
|
||||
|
||||
impl Renderer for BasicRenderer {
|
||||
|
@ -395,56 +441,70 @@ impl Renderer for BasicRenderer {
|
|||
|
||||
let now_inst = Instant::now();
|
||||
|
||||
for (entity, model, model_epoch, transform, transform_epoch) in main_world.view_iter::<(Entities, &ModelComponent, TickOf<ModelComponent>, &Transform, TickOf<Transform>)>() {
|
||||
let view = main_world.filtered_view_iter::<(Entities, &Transform, TickOf<Transform>), Or<Has<MeshHandle>, Has<SceneHandle>>>();
|
||||
for (entity, transform, transform_epoch) in view {
|
||||
alive_entities.insert(entity);
|
||||
|
||||
let cached = match self.entity_last_transforms.get_mut(&entity) {
|
||||
Some(last) if transform_epoch == last_epoch => {
|
||||
last.from_transform = last.to_transform;
|
||||
last.to_transform = *transform;
|
||||
last.last_updated_at = Some(last.cached_at);
|
||||
last.cached_at = now_inst;
|
||||
let mesh_view = main_world.view_one::<(&MeshHandle, TickOf<MeshHandle>)>(entity);
|
||||
if let Some((mesh_han, mesh_epoch)) = mesh_view.get() {
|
||||
let interop_pos = self.interpolate_transforms(now_inst, last_epoch, entity, &transform, transform_epoch);
|
||||
|
||||
last.clone()
|
||||
},
|
||||
Some(last) => last.clone(),
|
||||
None => {
|
||||
let cached = CachedTransform {
|
||||
last_updated_at: None,
|
||||
cached_at: now_inst,
|
||||
from_transform: *transform,
|
||||
to_transform: *transform,
|
||||
};
|
||||
self.entity_last_transforms.insert(entity, cached.clone());
|
||||
cached
|
||||
}
|
||||
};
|
||||
//debug!("Transform: {:?}, comp: {:?}", cached.to_transform.translation, transform.transform.translation);
|
||||
|
||||
let fixed_time = match cached.last_updated_at {
|
||||
Some(last_updated_at) => cached.cached_at - last_updated_at,
|
||||
None => now_inst - cached.cached_at
|
||||
}.as_secs_f32();
|
||||
let accumulator = (now_inst - cached.cached_at).as_secs_f32();
|
||||
let alpha = accumulator / fixed_time;
|
||||
|
||||
let transform_val = cached.from_transform.lerp(cached.to_transform, alpha);
|
||||
|
||||
let model = model.data_ref();
|
||||
for mesh in model.meshes.iter() {
|
||||
if !self.process_mesh(entity, transform_val, mesh) && model_epoch == last_epoch {
|
||||
self.update_mesh_buffers(entity, mesh);
|
||||
if let Some(mesh) = mesh_han.data_ref() {
|
||||
// if process mesh did not just create a new mesh, and the epoch
|
||||
// shows that the scene has changed, verify that the mesh buffers
|
||||
// dont need to be resent to the gpu.
|
||||
if !self.process_mesh(entity, interop_pos, &*mesh, mesh_han.uuid())
|
||||
&& mesh_epoch == last_epoch {
|
||||
self.check_mesh_buffers(entity, &mesh_han);
|
||||
}
|
||||
|
||||
let shader = mesh.material().shader_uuid.unwrap_or(0);
|
||||
let job = RenderJob::new(entity, shader, mesh.uuid, transform_val);
|
||||
let material = mesh.material.as_ref().unwrap()
|
||||
.data_ref().unwrap();
|
||||
let shader = material.shader_uuid.unwrap_or(0);
|
||||
let job = RenderJob::new(entity, shader, mesh_han.uuid(), interop_pos);
|
||||
self.render_jobs.push_back(job);
|
||||
}
|
||||
}
|
||||
|
||||
/* for (entity, mesh, mesh_epoch, transform) in main_world.query::<(Entities, &MeshComponent, EpochOf<MeshComponent>, &TransformComponent)>().iter() {
|
||||
debug!("TODO: Process MeshComponents"); // TODO: Process MeshComponents
|
||||
} */
|
||||
let scene_view = main_world.view_one::<(&SceneHandle, TickOf<SceneHandle>)>(entity);
|
||||
if let Some((scene_han, scene_epoch)) = scene_view.get() {
|
||||
// TODO: Rendering scenes
|
||||
|
||||
let scene_scope = debug_span!("scene", uuid = scene_han.uuid().to_string());
|
||||
let _enter = scene_scope.enter();
|
||||
|
||||
if let Some(scene) = scene_han.data_ref() {
|
||||
let interop_pos = self.interpolate_transforms(now_inst, last_epoch, entity, &transform, transform_epoch);
|
||||
let meshes = scene.collect_world_meshes();
|
||||
|
||||
for (mesh_han, mesh_pos) in meshes.into_iter() {
|
||||
if let Some(mesh) = mesh_han.data_ref() {
|
||||
let mesh_interp = interop_pos + mesh_pos;
|
||||
|
||||
let mesh_scope = debug_span!("mesh", uuid = mesh_han.uuid().to_string());
|
||||
let _enter = mesh_scope.enter();
|
||||
|
||||
debug!("mesh at {:?}", mesh_interp.translation);
|
||||
|
||||
// if process mesh did not just create a new mesh, and the epoch
|
||||
// shows that the scene has changed, verify that the mesh buffers
|
||||
// dont need to be resent to the gpu.
|
||||
if !self.process_mesh(entity, mesh_interp, &*mesh, mesh_han.uuid())
|
||||
&& scene_epoch == last_epoch {
|
||||
self.check_mesh_buffers(entity, &mesh_han);
|
||||
debug!("updating mesh buffers");
|
||||
}
|
||||
|
||||
let material = mesh.material.as_ref().unwrap()
|
||||
.data_ref().unwrap();
|
||||
let shader = material.shader_uuid.unwrap_or(0);
|
||||
let job = RenderJob::new(entity, shader, mesh_han.uuid(), interop_pos);
|
||||
self.render_jobs.push_back(job);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// collect dead entities
|
||||
self.transform_buffers.tick();
|
||||
|
|
|
@ -5,25 +5,6 @@ use lyra_resource::{ResHandle, Texture};
|
|||
|
||||
use super::render_buffer::BindGroupPair;
|
||||
|
||||
/* #[derive(Clone)]
|
||||
pub struct Texture {
|
||||
texture_id: u32,
|
||||
pub img: image::DynamicImage,
|
||||
}
|
||||
|
||||
impl Texture {
|
||||
pub fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self> {
|
||||
let img = image::load_from_memory(bytes)?;
|
||||
|
||||
Ok(Self {
|
||||
texture_id: 0,
|
||||
img,
|
||||
})
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct RenderTexture {
|
||||
pub inner_texture: wgpu::Texture,
|
||||
|
@ -153,8 +134,12 @@ impl RenderTexture {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn update_texture(&mut self, _device: &wgpu::Device, queue: &wgpu::Queue, texture: &Arc<ResHandle<Texture>>) {
|
||||
let texture = &texture.data_ref().image;
|
||||
/// Updates the texture on the gpu with the provided texture.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `texture` is not loaded
|
||||
pub fn update_texture(&mut self, _device: &wgpu::Device, queue: &wgpu::Queue, texture: &ResHandle<Texture>) {
|
||||
let texture = &texture.data_ref().unwrap().image;
|
||||
let rgba = texture.to_rgba8();
|
||||
let dimensions = texture.dimensions();
|
||||
let size = wgpu::Extent3d {
|
||||
|
|
|
@ -1,15 +1,37 @@
|
|||
use lyra_ecs::Component;
|
||||
use lyra_resource::Mesh;
|
||||
use lyra_reflect::Reflect;
|
||||
use lyra_resource::{gltf::Mesh, ResHandle};
|
||||
|
||||
#[derive(Clone, Component)]
|
||||
#[derive(Clone, Component, Reflect)]
|
||||
pub struct MeshComponent {
|
||||
pub mesh: Mesh,
|
||||
#[reflect(skip)]
|
||||
pub mesh: ResHandle<Mesh>,
|
||||
}
|
||||
|
||||
impl From<ResHandle<Mesh>> for MeshComponent {
|
||||
fn from(value: ResHandle<Mesh>) -> Self {
|
||||
Self {
|
||||
mesh: value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for MeshComponent {
|
||||
type Target = ResHandle<Mesh>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.mesh
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for MeshComponent {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.mesh
|
||||
}
|
||||
}
|
||||
|
||||
impl MeshComponent {
|
||||
pub fn new(mesh: Mesh) -> Self {
|
||||
Self {
|
||||
mesh,
|
||||
}
|
||||
pub fn new(mesh: ResHandle<Mesh>) -> Self {
|
||||
Self::from(mesh)
|
||||
}
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
pub mod mesh;
|
||||
pub use mesh::*;
|
||||
|
||||
pub mod model;
|
||||
pub use model::*;
|
||||
|
||||
pub mod camera;
|
||||
pub use camera::*;
|
||||
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
use lyra_ecs::Component;
|
||||
use lyra_reflect::Reflect;
|
||||
use lyra_resource::ResHandle;
|
||||
|
||||
use crate::assets::Model;
|
||||
|
||||
#[derive(Clone, Component, Reflect)]
|
||||
pub struct ModelComponent(#[reflect(skip)] pub ResHandle<Model>);
|
||||
|
||||
impl From<ResHandle<Model>> for ModelComponent {
|
||||
fn from(value: ResHandle<Model>) -> Self {
|
||||
ModelComponent(value)
|
||||
}
|
||||
}
|
||||
|
||||
/* impl From<ResHandle<Model> for ModelComponent {
|
||||
|
||||
} */
|
||||
|
||||
impl std::ops::Deref for ModelComponent {
|
||||
type Target = ResHandle<Model>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for ModelComponent {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
/* impl ModelComponent {
|
||||
pub fn new(model, material: Material) -> Self {
|
||||
Self {
|
||||
mesh,
|
||||
material
|
||||
}
|
||||
}
|
||||
} */
|
Loading…
Reference in New Issue