Significant render refactoring, implement transformation matrix
This commit is contained in:
parent
53db829e19
commit
265c3dbc5a
|
@ -95,15 +95,6 @@ version = "1.0.69"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
|
checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "approx"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
|
@ -427,16 +418,6 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cgmath"
|
|
||||||
version = "0.18.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317"
|
|
||||||
dependencies = [
|
|
||||||
"approx",
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codespan-reporting"
|
name = "codespan-reporting"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
|
@ -727,6 +708,15 @@ version = "0.27.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
|
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glam"
|
||||||
|
version = "0.24.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ad83ab008a4fa3b31dfa713dd41b5a9bdea1e94e4cf1e2fc274ffbd49b0271d3"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gloo-timers"
|
name = "gloo-timers"
|
||||||
version = "0.2.6"
|
version = "0.2.6"
|
||||||
|
@ -791,7 +781,7 @@ checksum = "0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"gpu-descriptor-types",
|
"gpu-descriptor-types",
|
||||||
"hashbrown",
|
"hashbrown 0.12.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -812,6 +802,15 @@ dependencies = [
|
||||||
"ahash 0.7.6",
|
"ahash 0.7.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
||||||
|
dependencies = [
|
||||||
|
"ahash 0.8.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hassle-rs"
|
name = "hassle-rs"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
@ -827,6 +826,16 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hecs"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d2711ad60b74f2f3d0c0ac338a58410a5249da44005971ae806d2925e6b5167"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown 0.13.2",
|
||||||
|
"spin",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.2.6"
|
version = "0.2.6"
|
||||||
|
@ -874,7 +883,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"hashbrown",
|
"hashbrown 0.12.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -990,7 +999,8 @@ dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cgmath",
|
"glam",
|
||||||
|
"hecs",
|
||||||
"image",
|
"image",
|
||||||
"instant",
|
"instant",
|
||||||
"specs",
|
"specs",
|
||||||
|
@ -1569,7 +1579,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "102269e720bb814df57e136161cad841f2b6f411e003ac748fc48aaf2363bea3"
|
checksum = "102269e720bb814df57e136161cad841f2b6f411e003ac748fc48aaf2363bea3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"hashbrown",
|
"hashbrown 0.12.3",
|
||||||
"mopa",
|
"mopa",
|
||||||
"rayon",
|
"rayon",
|
||||||
"shred-derive",
|
"shred-derive",
|
||||||
|
@ -1673,7 +1683,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4ea85dac2880f84d4025ff5ace80cda6d8bc43bc88b6a389b9277fcf894b51e9"
|
checksum = "4ea85dac2880f84d4025ff5ace80cda6d8bc43bc88b6a389b9277fcf894b51e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-queue",
|
"crossbeam-queue",
|
||||||
"hashbrown",
|
"hashbrown 0.12.3",
|
||||||
"hibitset",
|
"hibitset",
|
||||||
"log",
|
"log",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
@ -1694,6 +1704,12 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spirv"
|
name = "spirv"
|
||||||
version = "0.2.0+1.5.4"
|
version = "0.2.0+1.5.4"
|
||||||
|
|
|
@ -17,10 +17,12 @@ cfg-if = "1"
|
||||||
bytemuck = { version = "1.12", features = [ "derive" ] }
|
bytemuck = { version = "1.12", features = [ "derive" ] }
|
||||||
image = { version = "0.24", default-features = false, features = ["png", "jpeg"] }
|
image = { version = "0.24", default-features = false, features = ["png", "jpeg"] }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
cgmath = "0.18"
|
#cgmath = "0.18"
|
||||||
tobj = { version = "3.2.1", features = [
|
tobj = { version = "3.2.1", features = [
|
||||||
"async",
|
"async",
|
||||||
]}
|
]}
|
||||||
instant = "0.1"
|
instant = "0.1"
|
||||||
async-trait = "0.1.65"
|
async-trait = "0.1.65"
|
||||||
specs = { version = "0.18.0", features = [ "derive" ] }
|
specs = { version = "0.18.0", features = [ "derive" ] }
|
||||||
|
hecs = "0.10.3"
|
||||||
|
glam = { version = "0.24.0", features = ["bytemuck"] }
|
||||||
|
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
@ -10,13 +10,16 @@ struct VertexOutput {
|
||||||
@location(0) tex_coords: vec2<f32>,
|
@location(0) tex_coords: vec2<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@group(1) @binding(0)
|
||||||
|
var<uniform> u_model_transform: mat4x4<f32>;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(
|
fn vs_main(
|
||||||
model: VertexInput,
|
model: VertexInput,
|
||||||
) -> VertexOutput {
|
) -> VertexOutput {
|
||||||
var out: VertexOutput;
|
var out: VertexOutput;
|
||||||
out.tex_coords = model.tex_coords;
|
out.tex_coords = model.tex_coords;
|
||||||
out.clip_position = vec4<f32>(model.position, 1.0);
|
out.clip_position = u_model_transform * vec4<f32>(model.position, 1.0);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
pub mod model_2d;
|
pub mod model_2d;
|
||||||
|
pub mod transform;
|
|
@ -1,4 +1,18 @@
|
||||||
#[derive(Component, Debug, Default)]
|
use specs::{Component, DenseVecStorage};
|
||||||
pub struct Model2d {
|
|
||||||
pub vertices: Vec<Vertex>,
|
use crate::render::{vertex::Vertex, mesh::Mesh, material::Material};
|
||||||
|
|
||||||
|
#[derive(Component, Clone)]
|
||||||
|
pub struct Model2dComponent {
|
||||||
|
pub mesh: Mesh,
|
||||||
|
pub material: Material,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Model2dComponent {
|
||||||
|
pub fn new(mesh: Mesh, material: Material) -> Self {
|
||||||
|
Self {
|
||||||
|
mesh,
|
||||||
|
material
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
use specs::{Component, DenseVecStorage};
|
||||||
|
|
||||||
|
use crate::render::transform::Transform;
|
||||||
|
|
||||||
|
#[derive(Component, Clone)]
|
||||||
|
pub struct TransformComponent {
|
||||||
|
pub transform: Transform,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TransformComponent {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
transform: Transform::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransformComponent {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_transform(transform: Transform) -> Self {
|
||||||
|
Self {
|
||||||
|
transform
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
78
src/game.rs
78
src/game.rs
|
@ -1,9 +1,8 @@
|
||||||
use std::{sync::Arc};
|
use std::{sync::Arc, cell::RefCell};
|
||||||
|
|
||||||
use async_std::{task::block_on, sync::Mutex};
|
use async_std::{task::block_on, sync::Mutex};
|
||||||
|
|
||||||
use specs::{Dispatcher, World};
|
use hecs::World;
|
||||||
|
|
||||||
use tracing::{metadata::LevelFilter, info, debug, warn};
|
use tracing::{metadata::LevelFilter, info, debug, warn};
|
||||||
use tracing_subscriber::{
|
use tracing_subscriber::{
|
||||||
layer::{Layer, SubscriberExt},
|
layer::{Layer, SubscriberExt},
|
||||||
|
@ -13,24 +12,22 @@ use tracing_subscriber::{
|
||||||
|
|
||||||
use winit::{window::{WindowBuilder, Window}, event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode}, event_loop::{EventLoop, ControlFlow}};
|
use winit::{window::{WindowBuilder, Window}, event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode}, event_loop::{EventLoop, ControlFlow}};
|
||||||
|
|
||||||
use crate::{render::renderer::{Renderer, BasicRenderer}, input_event::InputEvent};
|
use crate::{render::{renderer::{Renderer, BasicRenderer}, render_job::RenderJob}, input_event::InputEvent, ecs::components::{model_2d::Model2dComponent, transform::TransformComponent}};
|
||||||
|
|
||||||
struct GameLoop<'a, 'b> {
|
struct GameLoop {
|
||||||
window: Arc<Window>,
|
window: Arc<Window>,
|
||||||
renderer: Box<dyn Renderer>,
|
renderer: Box<dyn Renderer>,
|
||||||
|
|
||||||
world: Arc<Mutex<World>>,
|
world: Arc<Mutex<World>>,
|
||||||
system_dispatchers: Vec<Dispatcher<'a, 'b>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> GameLoop<'a, 'b> {
|
impl GameLoop {
|
||||||
pub async fn new(window: Arc<Window>, world: Arc<Mutex<World>>, system_dispatchers: Vec<Dispatcher<'a, 'b>>) -> GameLoop<'a, 'b> {
|
pub async fn new(window: Arc<Window>, world: Arc<Mutex<World>>) -> GameLoop {
|
||||||
Self {
|
Self {
|
||||||
window: Arc::clone(&window),
|
window: Arc::clone(&window),
|
||||||
renderer: Box::new(BasicRenderer::create_with_window(window).await),
|
renderer: Box::new(BasicRenderer::create_with_window(window).await),
|
||||||
|
|
||||||
world,
|
world,
|
||||||
system_dispatchers,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,10 +40,10 @@ impl<'a, 'b> GameLoop<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update(&mut self) {
|
async fn update(&mut self) {
|
||||||
let world = self.world.lock().await;
|
/* let world = self.world.lock().await;
|
||||||
for dispatcher in self.system_dispatchers.iter_mut() {
|
for dispatcher in self.system_dispatchers.iter_mut() {
|
||||||
dispatcher.dispatch(&world);
|
dispatcher.dispatch(&world);
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn input_update(&mut self, event: &InputEvent) -> Option<ControlFlow> {
|
async fn input_update(&mut self, event: &InputEvent) -> Option<ControlFlow> {
|
||||||
|
@ -120,8 +117,41 @@ impl<'a, 'b> GameLoop<'a, 'b> {
|
||||||
},
|
},
|
||||||
|
|
||||||
Event::RedrawRequested(window_id) if window_id == self.window.id() => {
|
Event::RedrawRequested(window_id) if window_id == self.window.id() => {
|
||||||
|
// Update the world
|
||||||
self.update().await;
|
self.update().await;
|
||||||
|
|
||||||
|
|
||||||
|
// Collect models from the ecs world
|
||||||
|
/* let mut jobs = vec![];
|
||||||
|
let world = self.world.lock().await;
|
||||||
|
let model2d_storage = world.read_storage::<Model2d>();
|
||||||
|
|
||||||
|
for model in model2d_storage.join() {
|
||||||
|
let job = RenderJob::new(&model.mesh);
|
||||||
|
jobs.push(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
// drop some stuff for the borrow checker
|
||||||
|
drop(model2d_storage);
|
||||||
|
drop(world);
|
||||||
|
|
||||||
|
for job in jobs.iter() {
|
||||||
|
println!("job");
|
||||||
|
} */
|
||||||
|
|
||||||
|
let mut world = self.world.lock().await;
|
||||||
|
|
||||||
|
for (ent, (transform,)) in world.query_mut::<(&mut TransformComponent,)>() {
|
||||||
|
transform.transform.translate_vec3(glam::Vec3::new(0.0, 0.001, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ent, (transform,)) in world.query::<(&TransformComponent,)>().iter() {
|
||||||
|
println!("transform pos: {:?}", transform.transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.renderer.as_mut().prepare(&world).await;
|
||||||
|
drop(world);
|
||||||
|
|
||||||
match self.renderer.as_mut().render().await {
|
match self.renderer.as_mut().render().await {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
// Reconfigure the surface if lost
|
// Reconfigure the surface if lost
|
||||||
|
@ -141,22 +171,20 @@ impl<'a, 'b> GameLoop<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Game<'a, 'b> {
|
pub struct Game {
|
||||||
world: Option<Arc<Mutex<World>>>,
|
world: Option<Arc<Mutex<World>>>,
|
||||||
system_dispatchers: Option<Vec<Dispatcher<'a, 'b>>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> Default for Game<'a, 'b> {
|
impl Default for Game {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
world: None,
|
world: None,
|
||||||
system_dispatchers: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> Game<'static, 'static> {
|
impl Game {
|
||||||
pub async fn initialize() -> Game<'static, 'static> {
|
pub async fn initialize() -> Game {
|
||||||
let filter = FilterFn::new(|metadata| {
|
let filter = FilterFn::new(|metadata| {
|
||||||
metadata.module_path()
|
metadata.module_path()
|
||||||
.unwrap_or_else(|| metadata.target())
|
.unwrap_or_else(|| metadata.target())
|
||||||
|
@ -184,27 +212,13 @@ impl<'a, 'b> Game<'static, 'static> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_dispatchers(&mut self, dispatchers: Vec<Dispatcher<'static, 'static>>) -> &mut Self {
|
|
||||||
self.system_dispatchers = Some(dispatchers);
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_dispatcher(&mut self, dispatcher: Dispatcher<'static, 'static>) -> &mut Self {
|
|
||||||
self.system_dispatchers.get_or_insert_with(|| Vec::new()).push(dispatcher);
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn run(&mut self) {
|
pub async fn run(&mut self) {
|
||||||
let world = self.world.take().expect("ECS World was never given to Game!");
|
let world = self.world.take().expect("ECS World was never given to Game!");
|
||||||
let system_dispatchers = self.system_dispatchers
|
|
||||||
.take().unwrap_or_else(|| Vec::new());
|
|
||||||
|
|
||||||
let event_loop = EventLoop::new();
|
let event_loop = EventLoop::new();
|
||||||
let window = Arc::new(WindowBuilder::new().build(&event_loop).unwrap());
|
let window = Arc::new(WindowBuilder::new().build(&event_loop).unwrap());
|
||||||
|
|
||||||
let mut g_loop = GameLoop::new(Arc::clone(&window), world, system_dispatchers).await;
|
let mut g_loop = GameLoop::new(Arc::clone(&window), world).await;
|
||||||
|
|
||||||
event_loop.run(move |event, _, control_flow| {
|
event_loop.run(move |event, _, control_flow| {
|
||||||
g_loop.run_sync(event, control_flow);
|
g_loop.run_sync(event, control_flow);
|
||||||
|
|
62
src/main.rs
62
src/main.rs
|
@ -1,13 +1,20 @@
|
||||||
mod system;
|
|
||||||
mod game;
|
mod game;
|
||||||
mod render;
|
mod render;
|
||||||
mod input_event;
|
mod input_event;
|
||||||
mod resources;
|
mod resources;
|
||||||
|
mod ecs;
|
||||||
|
|
||||||
|
use ecs::components::model_2d::Model2dComponent;
|
||||||
|
|
||||||
|
use ecs::components::transform::TransformComponent;
|
||||||
use game::Game;
|
use game::Game;
|
||||||
use specs::*;
|
use hecs::World;
|
||||||
|
|
||||||
#[derive(Component, Debug, Default)]
|
use crate::render::material::Material;
|
||||||
|
use crate::render::texture::Texture;
|
||||||
|
//use specs::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
struct Point2d {
|
struct Point2d {
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
|
@ -28,7 +35,7 @@ impl Point2d {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
struct Point3d {
|
struct Point3d {
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
|
@ -51,29 +58,34 @@ impl Point3d {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestingSystem;
|
|
||||||
|
|
||||||
impl<'a> System<'a> for TestingSystem {
|
|
||||||
// These are the resources required for execution.
|
|
||||||
// You can also define a struct and `#[derive(SystemData)]`,
|
|
||||||
// see the `full` example.
|
|
||||||
type SystemData = (ReadStorage<'a, Point2d>,);
|
|
||||||
|
|
||||||
fn run(&mut self, (point,): Self::SystemData) {
|
|
||||||
// The `.join()` combines multiple component storages,
|
|
||||||
// so we get access to all entities which have
|
|
||||||
// both a position and a velocity.
|
|
||||||
for (point,) in (&point,).join() {
|
|
||||||
//point.0 += vel.0;
|
|
||||||
println!("Entity at: {}", point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
world.register::<Point2d>();
|
|
||||||
|
world.spawn((Point2d::new(10, 10), Point3d::new(50, 50, 50)));
|
||||||
|
|
||||||
|
let diffuse_bytes = include_bytes!("../res/happy-tree.png");
|
||||||
|
let diffuse_texture = Texture::from_bytes(diffuse_bytes).unwrap();
|
||||||
|
world.spawn((Model2dComponent::new(
|
||||||
|
render::mesh::Mesh {
|
||||||
|
vertices: crate::render::vertex::VERTICES.to_vec(),
|
||||||
|
indices: Some(crate::render::vertex::INDICES.to_vec())
|
||||||
|
}, Material {
|
||||||
|
shader_id: 0,
|
||||||
|
texture: diffuse_texture
|
||||||
|
}),
|
||||||
|
TransformComponent::new(),
|
||||||
|
));
|
||||||
|
|
||||||
|
for (id, (point2d,)) in world.query::<(&Point2d,)>().iter() {
|
||||||
|
println!("Entity {} is at 2d position: {:?}", id.id(), point2d);
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::initialize().await
|
||||||
|
.with_world(world)
|
||||||
|
.run().await;
|
||||||
|
|
||||||
|
/* world.register::<Point2d>();
|
||||||
world.register::<Point3d>();
|
world.register::<Point3d>();
|
||||||
|
|
||||||
world.create_entity()
|
world.create_entity()
|
||||||
|
@ -89,7 +101,7 @@ async fn main() {
|
||||||
Game::initialize().await
|
Game::initialize().await
|
||||||
.with_world(world)
|
.with_world(world)
|
||||||
.with_dispatcher(dispatcher)
|
.with_dispatcher(dispatcher)
|
||||||
.run().await;
|
.run().await; */
|
||||||
|
|
||||||
/* let mut game = Game::initialize().await;
|
/* let mut game = Game::initialize().await;
|
||||||
game.run().await; */
|
game.run().await; */
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
use super::texture::Texture;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Material {
|
||||||
|
pub shader_id: u32,
|
||||||
|
pub texture: Texture,
|
||||||
|
}
|
|
@ -2,28 +2,23 @@ use wgpu::{BindGroup, BindGroupLayout};
|
||||||
|
|
||||||
use super::{vertex::Vertex, render_buffer::{BufferStorage}};
|
use super::{vertex::Vertex, render_buffer::{BufferStorage}};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Mesh {
|
pub struct Mesh {
|
||||||
//material
|
|
||||||
//texture: Option<Texture>,
|
|
||||||
pub vertices: Vec<Vertex>,
|
pub vertices: Vec<Vertex>,
|
||||||
pub indices: Option<Vec<u16>>,
|
pub indices: Option<Vec<u16>>,
|
||||||
|
|
||||||
pub buffer_vertex: BufferStorage,
|
/* pub buffer_vertex: BufferStorage,
|
||||||
pub buffer_indices: Option<BufferStorage>, // TOOD: make optional
|
pub buffer_indices: Option<BufferStorage>, // TOOD: make optional
|
||||||
|
|
||||||
pub texture_bindgroup: Option<BindGroup>,
|
pub texture_bindgroup: Option<BindGroup>,
|
||||||
pub texture_layout: Option<BindGroupLayout>
|
pub texture_layout: Option<BindGroupLayout> */
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mesh {
|
impl Mesh {
|
||||||
pub fn new(vertices: Vec<Vertex>, indices: Option<Vec<u16>>, buffer_vertex: BufferStorage, buffer_indices: Option<BufferStorage>, texture_bindgroup: Option<BindGroup>, texture_layout: Option<BindGroupLayout>) -> Self {
|
pub fn new(vertices: Vec<Vertex>, indices: Option<Vec<u16>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
vertices,
|
vertices,
|
||||||
indices,
|
indices,
|
||||||
buffer_vertex,
|
|
||||||
buffer_indices,
|
|
||||||
texture_bindgroup,
|
|
||||||
texture_layout,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,3 +6,6 @@ pub mod render_buffer;
|
||||||
pub mod render_job;
|
pub mod render_job;
|
||||||
pub mod mesh;
|
pub mod mesh;
|
||||||
pub mod texture;
|
pub mod texture;
|
||||||
|
pub mod shader_loader;
|
||||||
|
pub mod material;
|
||||||
|
pub mod transform;
|
|
@ -1,17 +1,31 @@
|
||||||
use super::{mesh::Mesh};
|
use hecs::Entity;
|
||||||
|
|
||||||
|
use super::{mesh::Mesh, material::Material};
|
||||||
|
|
||||||
pub struct RenderJob {
|
pub struct RenderJob {
|
||||||
mesh: Mesh
|
mesh: Mesh,
|
||||||
|
material: Material,
|
||||||
|
entity: Entity,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderJob {
|
impl RenderJob {
|
||||||
pub fn new(mesh: Mesh) -> Self {
|
pub fn new(mesh: Mesh, material: Material, entity: Entity) -> Self {
|
||||||
Self {
|
Self {
|
||||||
mesh,
|
mesh,
|
||||||
|
material,
|
||||||
|
entity,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mesh(&self)-> &Mesh {
|
pub fn mesh(&self)-> &Mesh {
|
||||||
&self.mesh
|
&self.mesh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn material(&self)-> &Material {
|
||||||
|
&self.material
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn entity(&self)-> Entity {
|
||||||
|
self.entity
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,19 +1,18 @@
|
||||||
use std::ops::Range;
|
use std::{ops::Range, cell::Ref};
|
||||||
|
|
||||||
use wgpu::{PipelineLayout, RenderPipeline, RenderPass};
|
use wgpu::{PipelineLayout, RenderPipeline, RenderPass, VertexBufferLayout, BindGroupLayout};
|
||||||
|
|
||||||
use super::{render_job::RenderJob, vertex::Vertex, desc_buf_lay::DescVertexBufferLayout};
|
use super::{render_job::RenderJob, vertex::Vertex, desc_buf_lay::DescVertexBufferLayout};
|
||||||
|
|
||||||
pub struct FullRenderPipeline {
|
pub struct FullRenderPipeline {
|
||||||
layout: PipelineLayout,
|
layout: PipelineLayout,
|
||||||
wgpu_pipeline: RenderPipeline,
|
wgpu_pipeline: RenderPipeline,
|
||||||
jobs: Vec<RenderJob>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FullRenderPipeline {
|
impl FullRenderPipeline {
|
||||||
pub fn new(device: &wgpu::Device, config: &wgpu::SurfaceConfiguration, shader: &wgpu::ShaderModule, jobs: Vec<RenderJob>) -> Self {
|
pub fn new(device: &wgpu::Device, config: &wgpu::SurfaceConfiguration, shader: &wgpu::ShaderModule, buffer_layouts: Vec<VertexBufferLayout>, bind_group_layouts: Vec<&BindGroupLayout>) -> FullRenderPipeline {
|
||||||
// Extract the layouts from all the jobs
|
// Extract the layouts from all the jobs
|
||||||
let mut buffer_layouts = vec![];
|
/* let mut buffer_layouts = vec![];
|
||||||
let mut bind_group_layouts = vec![];
|
let mut bind_group_layouts = vec![];
|
||||||
for job in jobs.iter() {
|
for job in jobs.iter() {
|
||||||
// Push layout for the vertex buffer, index buffer doesn't need one
|
// Push layout for the vertex buffer, index buffer doesn't need one
|
||||||
|
@ -22,7 +21,7 @@ impl FullRenderPipeline {
|
||||||
if let Some(layout) = job.mesh().texture_layout.as_ref() {
|
if let Some(layout) = job.mesh().texture_layout.as_ref() {
|
||||||
bind_group_layouts.push(layout);
|
bind_group_layouts.push(layout);
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
let render_pipeline_layout =
|
let render_pipeline_layout =
|
||||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
|
@ -72,7 +71,6 @@ impl FullRenderPipeline {
|
||||||
Self {
|
Self {
|
||||||
layout: render_pipeline_layout,
|
layout: render_pipeline_layout,
|
||||||
wgpu_pipeline: render_pipeline,
|
wgpu_pipeline: render_pipeline,
|
||||||
jobs,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,10 +84,11 @@ impl FullRenderPipeline {
|
||||||
&self.wgpu_pipeline
|
&self.wgpu_pipeline
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render<'a>(&'a self, pass: &mut RenderPass<'a>, vertices: Range<u32>, instances: Range<u32>) {
|
pub fn render<'a>(&'a self, jobs: &'a Vec<RenderJob>, pass: &'a mut RenderPass<'a>, vertices: Range<u32>, instances: Range<u32>) {
|
||||||
pass.set_pipeline(&self.wgpu_pipeline);
|
todo!()
|
||||||
|
/* pass.set_pipeline(&self.wgpu_pipeline);
|
||||||
|
|
||||||
for job in self.jobs.iter() {
|
for job in jobs.iter() {
|
||||||
let mesh = job.mesh();
|
let mesh = job.mesh();
|
||||||
|
|
||||||
if let Some(tex) = mesh.texture_bindgroup.as_ref() {
|
if let Some(tex) = mesh.texture_bindgroup.as_ref() {
|
||||||
|
@ -106,6 +105,6 @@ impl FullRenderPipeline {
|
||||||
pass.set_vertex_buffer(mesh.buffer_vertex.slot(), mesh.buffer_vertex.buffer().slice(..));
|
pass.set_vertex_buffer(mesh.buffer_vertex.slot(), mesh.buffer_vertex.buffer().slice(..));
|
||||||
pass.draw(vertices.clone(), instances.clone());
|
pass.draw(vertices.clone(), instances.clone());
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,23 +1,43 @@
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use async_std::sync::Mutex;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use wgpu::{BindGroup, BindGroupLayout};
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
use winit::window::Window;
|
use winit::window::Window;
|
||||||
|
|
||||||
|
use hecs::{World, Entity};
|
||||||
|
|
||||||
|
use crate::ecs::components::model_2d::Model2dComponent;
|
||||||
|
use crate::ecs::components::transform::TransformComponent;
|
||||||
use crate::resources;
|
use crate::resources;
|
||||||
|
|
||||||
use super::texture::Texture;
|
use super::desc_buf_lay::DescVertexBufferLayout;
|
||||||
|
use super::texture::RenderTexture;
|
||||||
|
use super::transform::Transform;
|
||||||
use super::{render_pipeline::FullRenderPipeline, vertex::{VERTICES}, render_buffer::BufferStorage, render_job::RenderJob, mesh::Mesh};
|
use super::{render_pipeline::FullRenderPipeline, vertex::{VERTICES}, render_buffer::BufferStorage, render_job::RenderJob, mesh::Mesh};
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Renderer {
|
pub trait Renderer {
|
||||||
|
async fn prepare(&mut self, main_world: &World);
|
||||||
async fn render(&mut self) -> Result<(), wgpu::SurfaceError>;
|
async fn render(&mut self) -> Result<(), wgpu::SurfaceError>;
|
||||||
async fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>);
|
async fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>);
|
||||||
|
|
||||||
fn surface_size(&self) -> winit::dpi::PhysicalSize<u32>;
|
fn surface_size(&self) -> winit::dpi::PhysicalSize<u32>;
|
||||||
fn add_render_pipeline(&mut self, pipeline: FullRenderPipeline);
|
fn add_render_pipeline(&mut self, shader_id: u32, pipeline: Arc<FullRenderPipeline>);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RenderBufferStorage {
|
||||||
|
buffer_vertex: BufferStorage,
|
||||||
|
buffer_indices: Option<BufferStorage>,
|
||||||
|
|
||||||
|
render_texture: Option<RenderTexture>,
|
||||||
|
texture_bindgroup: Option<BindGroup>,
|
||||||
|
texture_layout: Option<BindGroupLayout>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BasicRenderer {
|
pub struct BasicRenderer {
|
||||||
|
@ -30,7 +50,14 @@ pub struct BasicRenderer {
|
||||||
|
|
||||||
pub clear_color: wgpu::Color,
|
pub clear_color: wgpu::Color,
|
||||||
|
|
||||||
pub render_pipelines: Vec<FullRenderPipeline>,
|
pub render_pipelines: HashMap<u32, Arc<FullRenderPipeline>>,
|
||||||
|
pub render_jobs: HashMap<u32, Vec<RenderJob>>,
|
||||||
|
|
||||||
|
buffer_storage: HashMap<Entity, RenderBufferStorage>, // TODO: clean up left over buffers from deleted entities/components
|
||||||
|
|
||||||
|
transform_uniform: Transform,
|
||||||
|
transform_bind_group: wgpu::BindGroup,
|
||||||
|
transform_buffer: wgpu::Buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BasicRenderer {
|
impl BasicRenderer {
|
||||||
|
@ -89,8 +116,8 @@ impl BasicRenderer {
|
||||||
surface.configure(&device, &config);
|
surface.configure(&device, &config);
|
||||||
|
|
||||||
|
|
||||||
let diffuse_bytes = include_bytes!("../../res/happy-tree.png");
|
/* let diffuse_bytes = include_bytes!("../../res/happy-tree.png");
|
||||||
let diffuse_texture = Texture::from_bytes(&device, &queue, diffuse_bytes, "happy-tree.png").unwrap();
|
let diffuse_texture = RenderTexture::from_bytes(&device, &queue, diffuse_bytes, "happy-tree.png").unwrap(); */
|
||||||
|
|
||||||
let texture_bind_group_layout =
|
let texture_bind_group_layout =
|
||||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
|
@ -117,7 +144,171 @@ impl BasicRenderer {
|
||||||
label: Some("texture_bind_group_layout"),
|
label: Some("texture_bind_group_layout"),
|
||||||
});
|
});
|
||||||
|
|
||||||
let diffuse_bind_group = device.create_bind_group(
|
let transform_bind_group_layout =
|
||||||
|
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 0,
|
||||||
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Texture {
|
||||||
|
multisampled: false,
|
||||||
|
view_dimension: wgpu::TextureViewDimension::D2,
|
||||||
|
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
label: Some("texture_bind_group_layout"),
|
||||||
|
});
|
||||||
|
|
||||||
|
/* let diffuse_bind_group = device.create_bind_group(
|
||||||
|
&wgpu::BindGroupDescriptor {
|
||||||
|
layout: &texture_bind_group_layout,
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 0,
|
||||||
|
resource: wgpu::BindingResource::TextureView(diffuse_texture.view()),
|
||||||
|
},
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 1,
|
||||||
|
resource: wgpu::BindingResource::Sampler(diffuse_texture.sampler()),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
label: Some("diffuse_bind_group"),
|
||||||
|
}
|
||||||
|
); */
|
||||||
|
|
||||||
|
|
||||||
|
let shader_src = resources::load_string("shader/base_2d.wgsl").await.expect("Failed to load shader!");
|
||||||
|
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||||
|
label: Some("Shader"),
|
||||||
|
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(&shader_src)),
|
||||||
|
});
|
||||||
|
|
||||||
|
let transform_uniform = Transform::new();
|
||||||
|
let transform_buffer = device.create_buffer_init(
|
||||||
|
&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some("Camera Buffer"),
|
||||||
|
contents: bytemuck::cast_slice(&[transform_uniform]),
|
||||||
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let transform_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 0,
|
||||||
|
visibility: wgpu::ShaderStages::VERTEX,
|
||||||
|
ty: wgpu::BindingType::Buffer {
|
||||||
|
ty: wgpu::BufferBindingType::Uniform,
|
||||||
|
has_dynamic_offset: false,
|
||||||
|
min_binding_size: None,
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
label: Some("transform_bind_group_layout"),
|
||||||
|
});
|
||||||
|
|
||||||
|
let transform_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
|
layout: &transform_bind_group_layout,
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 0,
|
||||||
|
resource: transform_buffer.as_entire_binding(),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
label: Some("transform_bind_group"),
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let mut pipelines = HashMap::new();
|
||||||
|
pipelines.insert(0, Arc::new(FullRenderPipeline::new(&device, &config, &shader,
|
||||||
|
vec![super::vertex::Vertex::desc(),], vec![&texture_bind_group_layout, &transform_bind_group_layout])));
|
||||||
|
|
||||||
|
Self {
|
||||||
|
window,
|
||||||
|
surface,
|
||||||
|
device,
|
||||||
|
queue,
|
||||||
|
config,
|
||||||
|
size,
|
||||||
|
clear_color: wgpu::Color {
|
||||||
|
r: 0.1,
|
||||||
|
g: 0.2,
|
||||||
|
b: 0.3,
|
||||||
|
a: 1.0,
|
||||||
|
},
|
||||||
|
render_pipelines: pipelines,
|
||||||
|
render_jobs: HashMap::new(),
|
||||||
|
buffer_storage: HashMap::new(),
|
||||||
|
|
||||||
|
transform_uniform,
|
||||||
|
transform_buffer,
|
||||||
|
transform_bind_group,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_model_buffers(&mut self, model_2d: &Model2dComponent) -> RenderBufferStorage {
|
||||||
|
let mesh = &model_2d.mesh;
|
||||||
|
|
||||||
|
let vertex_buffer = self.device.create_buffer_init(
|
||||||
|
&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some("Vertex Buffer"),
|
||||||
|
contents: bytemuck::cast_slice(mesh.vertices.as_slice()),
|
||||||
|
usage: wgpu::BufferUsages::VERTEX,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let buffer_indices = match mesh.indices.as_ref() {
|
||||||
|
Some(indices) => {
|
||||||
|
let index_buffer = self.device.create_buffer_init(
|
||||||
|
&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some("Index Buffer"),
|
||||||
|
contents: bytemuck::cast_slice(&indices),
|
||||||
|
usage: wgpu::BufferUsages::INDEX,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let buffer_indices = BufferStorage::new(index_buffer, 0, Some(indices.len() as u32));
|
||||||
|
|
||||||
|
Some(buffer_indices)
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let texture_img = &model_2d.material.texture;
|
||||||
|
let diffuse_texture = RenderTexture::from_image(&self.device, &self.queue, &texture_img.img, 0, Some("happy-tree.png")).unwrap();
|
||||||
|
|
||||||
|
let texture_bind_group_layout =
|
||||||
|
self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 0,
|
||||||
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Texture {
|
||||||
|
multisampled: false,
|
||||||
|
view_dimension: wgpu::TextureViewDimension::D2,
|
||||||
|
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 1,
|
||||||
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
|
// This should match the filterable field of the
|
||||||
|
// corresponding Texture entry above.
|
||||||
|
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
label: Some("texture_bind_group_layout"),
|
||||||
|
});
|
||||||
|
|
||||||
|
let diffuse_bind_group = self.device.create_bind_group(
|
||||||
&wgpu::BindGroupDescriptor {
|
&wgpu::BindGroupDescriptor {
|
||||||
layout: &texture_bind_group_layout,
|
layout: &texture_bind_group_layout,
|
||||||
entries: &[
|
entries: &[
|
||||||
|
@ -134,63 +325,53 @@ impl BasicRenderer {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
RenderBufferStorage {
|
||||||
let shader_src = resources::load_string("shader.wgsl").await.expect("Failed to load shader!");
|
buffer_vertex: BufferStorage::new(vertex_buffer, 0, None),
|
||||||
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
buffer_indices,
|
||||||
label: Some("Shader"),
|
render_texture: None,
|
||||||
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(&shader_src)),
|
texture_layout: None,
|
||||||
});
|
texture_bindgroup: Some(diffuse_bind_group),
|
||||||
|
|
||||||
let vertex_buffer = device.create_buffer_init(
|
|
||||||
&wgpu::util::BufferInitDescriptor {
|
|
||||||
label: Some("Vertex Buffer"),
|
|
||||||
contents: bytemuck::cast_slice(super::vertex::VERTICES),
|
|
||||||
usage: wgpu::BufferUsages::VERTEX,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let index_buffer = device.create_buffer_init(
|
|
||||||
&wgpu::util::BufferInitDescriptor {
|
|
||||||
label: Some("Index Buffer"),
|
|
||||||
contents: bytemuck::cast_slice(super::vertex::INDICES),
|
|
||||||
usage: wgpu::BufferUsages::INDEX,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let job = RenderJob::new(Mesh::new(
|
|
||||||
super::vertex::VERTICES.to_vec(), Some(super::vertex::INDICES.to_vec()),
|
|
||||||
BufferStorage::new(vertex_buffer, 0, None),
|
|
||||||
Some(BufferStorage::new(index_buffer, 0, Some(super::vertex::INDICES.len() as u32))),
|
|
||||||
Some(diffuse_bind_group), Some(texture_bind_group_layout)
|
|
||||||
));
|
|
||||||
|
|
||||||
let pipelines = vec![
|
|
||||||
FullRenderPipeline::new(&device, &config, &shader,
|
|
||||||
vec![job,])
|
|
||||||
];
|
|
||||||
|
|
||||||
Self {
|
|
||||||
window,
|
|
||||||
surface,
|
|
||||||
device,
|
|
||||||
queue,
|
|
||||||
config,
|
|
||||||
size,
|
|
||||||
clear_color: wgpu::Color {
|
|
||||||
r: 0.1,
|
|
||||||
g: 0.2,
|
|
||||||
b: 0.3,
|
|
||||||
a: 1.0,
|
|
||||||
},
|
|
||||||
render_pipelines: pipelines,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Renderer for BasicRenderer {
|
impl Renderer for BasicRenderer {
|
||||||
|
async fn prepare(&mut self, main_world: &World) {
|
||||||
|
for (entity, (model, transform)) in main_world.query::<(&Model2dComponent, Option<&TransformComponent>)>().iter() {
|
||||||
|
let job = RenderJob::new(model.mesh.clone(), model.material.clone(), entity);
|
||||||
|
|
||||||
|
// Insert the new job into the queue
|
||||||
|
if let Some(shader_jobs) = self.render_jobs.get_mut(&model.material.shader_id) {
|
||||||
|
shader_jobs.push(job);
|
||||||
|
} else {
|
||||||
|
self.render_jobs.insert(model.material.shader_id, vec![job]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.buffer_storage.get(&entity).is_none() {
|
||||||
|
let buffers = self.create_model_buffers(model);
|
||||||
|
self.buffer_storage.insert(entity, buffers);
|
||||||
|
} else {
|
||||||
|
let mesh = &model.mesh;
|
||||||
|
|
||||||
|
// update existing buffers
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(transform) = transform {
|
||||||
|
self.transform_uniform = transform.transform;
|
||||||
|
|
||||||
|
self.queue.write_buffer(&self.transform_buffer, 0, bytemuck::cast_slice(&[self.transform_uniform]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_render_pipeline(&mut self, shader_id: u32, pipeline: Arc<FullRenderPipeline>) {
|
||||||
|
self.render_pipelines.insert(shader_id, pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
async fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
|
async fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
|
||||||
|
let jobs = &self.render_jobs;
|
||||||
|
|
||||||
let output = self.surface.get_current_texture()?;
|
let output = self.surface.get_current_texture()?;
|
||||||
let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
|
let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
|
||||||
|
@ -199,9 +380,9 @@ impl Renderer for BasicRenderer {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Loop through all the render pipelines and draw the buffers.
|
// Loop through all the render pipelines and draw the buffers.
|
||||||
for pipeline in self.render_pipelines.iter() {
|
for (shader_id, pipeline) in self.render_pipelines.iter() {
|
||||||
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
label: Some("Basic Renderer's Render Pass"),
|
label: Some("Render Pass"),
|
||||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||||
view: &view,
|
view: &view,
|
||||||
resolve_target: None,
|
resolve_target: None,
|
||||||
|
@ -213,7 +394,34 @@ impl Renderer for BasicRenderer {
|
||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
pipeline.render(&mut render_pass, 0..VERTICES.len() as u32, 0..1);
|
render_pass.set_pipeline(pipeline.get_wgpu_pipeline());
|
||||||
|
|
||||||
|
let pipeline_jobs = jobs.get(shader_id);
|
||||||
|
if let Some(jobs) = pipeline_jobs {
|
||||||
|
for job in jobs.iter() {
|
||||||
|
let mesh = job.mesh();
|
||||||
|
let buffers = self.buffer_storage.get(&job.entity()).unwrap(); // TODO: create buffers if not made
|
||||||
|
|
||||||
|
if let Some(tex) = buffers.texture_bindgroup.as_ref() {
|
||||||
|
render_pass.set_bind_group(0, &tex, &[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
render_pass.set_bind_group(1, &self.transform_bind_group, &[]);
|
||||||
|
|
||||||
|
if let Some(indices) = buffers.buffer_indices.as_ref() {
|
||||||
|
let indices_len = indices.count().unwrap(); // index buffers will have count, if not thats a bug
|
||||||
|
|
||||||
|
render_pass.set_vertex_buffer(buffers.buffer_vertex.slot(), buffers.buffer_vertex.buffer().slice(..));
|
||||||
|
render_pass.set_index_buffer(indices.buffer().slice(..), wgpu::IndexFormat::Uint16);
|
||||||
|
render_pass.draw_indexed(0..indices_len, 0, 0..1);
|
||||||
|
} else {
|
||||||
|
render_pass.set_vertex_buffer(buffers.buffer_vertex.slot(), buffers.buffer_vertex.buffer().slice(..));
|
||||||
|
render_pass.draw(0..mesh.vertices.len() as u32, 0..1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//pipeline.render(&jobs, &mut render_pass, 0..VERTICES.len() as u32, 0..1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.queue.submit(std::iter::once(encoder.finish()));
|
self.queue.submit(std::iter::once(encoder.finish()));
|
||||||
|
@ -234,8 +442,4 @@ impl Renderer for BasicRenderer {
|
||||||
fn surface_size(&self) -> winit::dpi::PhysicalSize<u32> {
|
fn surface_size(&self) -> winit::dpi::PhysicalSize<u32> {
|
||||||
self.size
|
self.size
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_render_pipeline(&mut self, pipeline: FullRenderPipeline) {
|
|
||||||
self.render_pipelines.push(pipeline);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,19 +1,42 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use image::GenericImageView;
|
use image::GenericImageView;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[derive(Clone)]
|
||||||
pub struct Texture {
|
pub struct Texture {
|
||||||
texture: wgpu::Texture,
|
texture_id: u32,
|
||||||
view: wgpu::TextureView,
|
pub img: image::DynamicImage,
|
||||||
sampler: wgpu::Sampler,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Texture {
|
impl Texture {
|
||||||
pub fn from_bytes(device: &wgpu::Device, queue: &wgpu::Queue, bytes: &[u8], label: &str) -> anyhow::Result<Self> {
|
pub fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self> {
|
||||||
let img = image::load_from_memory(bytes)?;
|
let img = image::load_from_memory(bytes)?;
|
||||||
Self::from_image(device, queue, &img, Some(label))
|
|
||||||
|
Ok(Self {
|
||||||
|
texture_id: 0,
|
||||||
|
img,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_image(device: &wgpu::Device, queue: &wgpu::Queue, img: &image::DynamicImage, label: Option<&str> ) -> anyhow::Result<Self> {
|
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct RenderTexture {
|
||||||
|
texture_id: u32,
|
||||||
|
texture: Arc<wgpu::Texture>,
|
||||||
|
view: Arc<wgpu::TextureView>,
|
||||||
|
sampler: Arc<wgpu::Sampler>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderTexture {
|
||||||
|
pub fn from_bytes(device: &wgpu::Device, queue: &wgpu::Queue, bytes: &[u8], texture_id: u32, label: &str) -> anyhow::Result<Self> {
|
||||||
|
let img = image::load_from_memory(bytes)?;
|
||||||
|
Self::from_image(device, queue, &img, texture_id, Some(label))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_image(device: &wgpu::Device, queue: &wgpu::Queue, img: &image::DynamicImage, texture_id: u32, label: Option<&str>) -> anyhow::Result<Self> {
|
||||||
let rgba = img.to_rgba8();
|
let rgba = img.to_rgba8();
|
||||||
let dimensions = img.dimensions();
|
let dimensions = img.dimensions();
|
||||||
|
|
||||||
|
@ -64,10 +87,41 @@ impl Texture {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(Self { texture, view, sampler })
|
Ok(Self {
|
||||||
|
texture_id,
|
||||||
|
texture: Arc::new(texture),
|
||||||
|
view: Arc::new(view),
|
||||||
|
sampler: Arc::new(sampler),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn texture(&self) -> &wgpu::Texture {
|
pub fn update_texture(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, texture: &Texture) {
|
||||||
|
let rgba = texture.img.to_rgba8();
|
||||||
|
let dimensions = texture.img.dimensions();
|
||||||
|
let size = wgpu::Extent3d {
|
||||||
|
width: dimensions.0,
|
||||||
|
height: dimensions.1,
|
||||||
|
depth_or_array_layers: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
queue.write_texture(
|
||||||
|
wgpu::ImageCopyTexture {
|
||||||
|
aspect: wgpu::TextureAspect::All,
|
||||||
|
texture: &self.texture,
|
||||||
|
mip_level: 0,
|
||||||
|
origin: wgpu::Origin3d::ZERO,
|
||||||
|
},
|
||||||
|
&rgba,
|
||||||
|
wgpu::ImageDataLayout {
|
||||||
|
offset: 0,
|
||||||
|
bytes_per_row: std::num::NonZeroU32::new(4 * dimensions.0),
|
||||||
|
rows_per_image: std::num::NonZeroU32::new(dimensions.1),
|
||||||
|
},
|
||||||
|
size,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inner_texture(&self) -> &wgpu::Texture {
|
||||||
&self.texture
|
&self.texture
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
use glam::Vec3;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
|
pub struct Transform {
|
||||||
|
matrix: glam::Mat4,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Transform {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
matrix: glam::Mat4::IDENTITY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Transform {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_glam(matrix: glam::Mat4) -> Self {
|
||||||
|
Self {
|
||||||
|
matrix,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn translate_vec3(&mut self, vec: Vec3) -> &mut Self {
|
||||||
|
/* let first_col = self.matrix.col(0);
|
||||||
|
let second_col = self.matrix.col(1);
|
||||||
|
let third_col = self.matrix.col(2);
|
||||||
|
|
||||||
|
//let fourth_col = self.matrix.col_mut(3);
|
||||||
|
let w_axis = &mut self.matrix.w_axis;
|
||||||
|
//first_col.w
|
||||||
|
//fourth_col = fourth_col.x * vec.x + second_col * vec.y + third_col * vec.z + fourth_col.clone();
|
||||||
|
w_axis.x += vec.x;
|
||||||
|
w_axis.y += vec.y;
|
||||||
|
w_axis.z += vec.z; */
|
||||||
|
|
||||||
|
let translation = glam::Mat4::from_translation(vec);
|
||||||
|
self.matrix *= translation;
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue