Revert "Added skybox to renderer and reflections to shader. Builds and runs. Flickering with many objects in scene, assuming swap chain issue."
This reverts commit 3231ed9190.
This commit is contained in:
parent
3231ed9190
commit
6685277e29
10 changed files with 1438 additions and 1818 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
|
@ -349,15 +349,6 @@ version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
|
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "colored"
|
|
||||||
version = "3.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34"
|
|
||||||
dependencies = [
|
|
||||||
"windows-sys 0.61.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "combine"
|
name = "combine"
|
||||||
version = "4.6.7"
|
version = "4.6.7"
|
||||||
|
|
@ -1105,9 +1096,6 @@ checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mars"
|
name = "mars"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
|
||||||
"colored",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
|
|
|
||||||
BIN
game.core
BIN
game.core
Binary file not shown.
87
src/app.rs
87
src/app.rs
|
|
@ -1,9 +1,7 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
// Credit of most code to https://sotrh.github.io/learn-wgpu/ since I'm not familiar with wgpu
|
// Credit of most code to https://sotrh.github.io/learn-wgpu/ since I'm not familiar with wgpu
|
||||||
use crate::render::Renderer;
|
|
||||||
use crate::world::{SimpleObject, World};
|
|
||||||
use glam::{Affine3A, EulerRot, Mat4, Quat, Vec2, Vec3, Vec4};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use glam::{Vec2, Affine3A, Vec3, Vec4, Mat4, EulerRot, Quat};
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
use winit::dpi::PhysicalPosition;
|
use winit::dpi::PhysicalPosition;
|
||||||
|
|
@ -16,10 +14,13 @@ use winit::{
|
||||||
keyboard::{KeyCode, PhysicalKey},
|
keyboard::{KeyCode, PhysicalKey},
|
||||||
window::Window,
|
window::Window,
|
||||||
};
|
};
|
||||||
|
use crate::render;
|
||||||
|
use crate::render::{Renderer, SimpleTexture};
|
||||||
|
use crate::world::{SimpleObject, World};
|
||||||
|
|
||||||
struct Controller {
|
struct Controller {
|
||||||
buttons: HashMap<MouseButton, bool>,
|
buttons: HashMap<MouseButton,bool>,
|
||||||
keys: HashMap<KeyCode, bool>,
|
keys: HashMap<KeyCode,bool>,
|
||||||
mouse: Vec2,
|
mouse: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,7 +29,7 @@ impl Controller {
|
||||||
Controller {
|
Controller {
|
||||||
buttons: Default::default(),
|
buttons: Default::default(),
|
||||||
keys: HashMap::new(),
|
keys: HashMap::new(),
|
||||||
mouse: Vec2::new(0.0, 0.0),
|
mouse: Vec2::new(0.0,0.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -40,27 +41,19 @@ pub struct AppState {
|
||||||
clients: Vec<SimpleObject>,
|
clients: Vec<SimpleObject>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const BLOCKS: i32 = 1;
|
const BLOCKS: i32 = 50;
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
// We don't need this to be async right now,
|
// We don't need this to be async right now,
|
||||||
// but we will in the next tutorial
|
// but we will in the next tutorial
|
||||||
pub async fn new(window: Arc<Window>) -> Result<AppState, Box<dyn std::error::Error>> {
|
pub async fn new(window: Arc<Window>) -> Result<AppState,Box<dyn std::error::Error>> {
|
||||||
|
let size = window.inner_size();
|
||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
world.add_renderer(Renderer::new(&window).await?);
|
world.add_renderer(Renderer::new(&window).await?);
|
||||||
let mut clients = Vec::new();
|
let mut clients = Vec::new();
|
||||||
{
|
{
|
||||||
let file = world
|
let file = world.renderer.as_mut().unwrap().load_from_gltf( include_bytes!("assets/cube.glb"));
|
||||||
.renderer
|
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.load_from_gltf(include_bytes!("assets/cube.glb"));
|
|
||||||
let block = file.first_object().unwrap();
|
let block = file.first_object().unwrap();
|
||||||
let skybox = world.renderer.as_mut().unwrap().load_texture_from_bytes(
|
|
||||||
include_bytes!("assets/skybox1.png"),
|
|
||||||
Some(image::ImageFormat::Png),
|
|
||||||
);
|
|
||||||
world.renderer.as_mut().unwrap().set_skybox(skybox);
|
|
||||||
//let color = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/color.png"));
|
//let color = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/color.png"));
|
||||||
//let normal = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/normal.png"));
|
//let normal = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/normal.png"));
|
||||||
//let roughness = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/roughness.png"));
|
//let roughness = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/roughness.png"));
|
||||||
|
|
@ -71,16 +64,9 @@ impl AppState {
|
||||||
world.add_object(block.clone());
|
world.add_object(block.clone());
|
||||||
{
|
{
|
||||||
let mut model = block.0.borrow_mut();
|
let mut model = block.0.borrow_mut();
|
||||||
model.model.as_mut().unwrap().instance.transform = Mat4::from_translation(
|
model.model.as_mut().unwrap().instance.transform = Mat4::from_translation(Vec3::new(-x as f32 * 3.0,0.0,-y as f32 * 3.0))
|
||||||
Vec3::new(-x as f32 * 3.0, -8.0, -y as f32 * 3.0),
|
|
||||||
)
|
|
||||||
* Mat4::from_rotation_z((x * y) as f32 / 1.23);
|
* Mat4::from_rotation_z((x * y) as f32 / 1.23);
|
||||||
model.model.as_mut().unwrap().instance.color = Vec4::new(
|
model.model.as_mut().unwrap().instance.color = Vec4::new(0.3,(x + BLOCKS) as f32 / BLOCKS as f32,(y + BLOCKS) as f32 / BLOCKS as f32,1.0);
|
||||||
0.3,
|
|
||||||
(x + BLOCKS) as f32 / BLOCKS as f32,
|
|
||||||
(y + BLOCKS) as f32 / BLOCKS as f32,
|
|
||||||
1.0,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
clients.push(block)
|
clients.push(block)
|
||||||
}
|
}
|
||||||
|
|
@ -94,14 +80,15 @@ impl AppState {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bounds(&self) -> (u32, u32) {
|
pub fn bounds(&self) -> (u32,u32) {
|
||||||
let size = self.window.inner_size();
|
let size = self.window.inner_size();
|
||||||
(size.width, size.height)
|
(size.width,size.height)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize(&mut self, width: u32, height: u32) {
|
pub fn resize(&mut self, width: u32, height: u32) {
|
||||||
if width > 0 && height > 0 {
|
if width > 0 && height > 0 {
|
||||||
self.world.renderer.as_mut().unwrap().resize(width, height);
|
let max = 2048;
|
||||||
|
self.world.renderer.as_mut().unwrap().resize(width,height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,7 +99,7 @@ impl AppState {
|
||||||
fn handle_key(&mut self, event_loop: &ActiveEventLoop, code: KeyCode, is_pressed: bool) {
|
fn handle_key(&mut self, event_loop: &ActiveEventLoop, code: KeyCode, is_pressed: bool) {
|
||||||
match (code, is_pressed) {
|
match (code, is_pressed) {
|
||||||
(KeyCode::Escape, true) => event_loop.exit(),
|
(KeyCode::Escape, true) => event_loop.exit(),
|
||||||
(KeyCode::Space, true) => {}
|
(KeyCode::Space, true) => {},
|
||||||
(KeyCode::KeyR, true) => {
|
(KeyCode::KeyR, true) => {
|
||||||
self.world.renderer.as_mut().unwrap().eye.frame = Affine3A::IDENTITY
|
self.world.renderer.as_mut().unwrap().eye.frame = Affine3A::IDENTITY
|
||||||
}
|
}
|
||||||
|
|
@ -123,16 +110,13 @@ impl AppState {
|
||||||
|
|
||||||
fn handle_mouse_moved(&mut self, position: PhysicalPosition<f64>) {
|
fn handle_mouse_moved(&mut self, position: PhysicalPosition<f64>) {
|
||||||
if let Some(true) = self.controller.buttons.get(&MouseButton::Right) {
|
if let Some(true) = self.controller.buttons.get(&MouseButton::Right) {
|
||||||
self.world.renderer.as_mut().unwrap().eye.rotate(
|
self.world.renderer.as_mut().unwrap().eye.rotate(position.x as f32 - self.controller.mouse.x, position.y as f32 - self.controller.mouse.y);
|
||||||
position.x as f32 - self.controller.mouse.x,
|
|
||||||
position.y as f32 - self.controller.mouse.y,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
self.controller.mouse = Vec2::new(position.x as f32, position.y as f32);
|
self.controller.mouse = Vec2::new(position.x as f32, position.y as f32);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mouse_button(&mut self, button: MouseButton, state: ElementState) {
|
fn handle_mouse_button(&mut self, button: MouseButton, state: ElementState ) {
|
||||||
self.controller.buttons.insert(button, state.is_pressed());
|
self.controller.buttons.insert(button,state.is_pressed());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,7 +216,7 @@ impl ApplicationHandler<AppState> for App {
|
||||||
WindowEvent::Resized(size) => state.resize(size.width, size.height),
|
WindowEvent::Resized(size) => state.resize(size.width, size.height),
|
||||||
WindowEvent::RedrawRequested => {
|
WindowEvent::RedrawRequested => {
|
||||||
state.update();
|
state.update();
|
||||||
let mut movement = Vec3::new(0.0, 0.0, 0.0);
|
let mut movement = Vec3::new(0.0,0.0,0.0);
|
||||||
|
|
||||||
let pressed = |keycode: KeyCode| {
|
let pressed = |keycode: KeyCode| {
|
||||||
if let Some(true) = state.controller.keys.get(&keycode) {
|
if let Some(true) = state.controller.keys.get(&keycode) {
|
||||||
|
|
@ -261,13 +245,7 @@ impl ApplicationHandler<AppState> for App {
|
||||||
movement.y -= 1.0;
|
movement.y -= 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
state
|
state.world.renderer.as_mut().unwrap().eye.control(movement * 0.1);
|
||||||
.world
|
|
||||||
.renderer
|
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.eye
|
|
||||||
.control(movement * 0.1);
|
|
||||||
match state.world.renderer.as_mut().unwrap().render(&state.window) {
|
match state.world.renderer.as_mut().unwrap().render(&state.window) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
@ -277,24 +255,13 @@ impl ApplicationHandler<AppState> for App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for object in state.clients.iter() {
|
for object in state.clients.iter() {
|
||||||
object
|
object.0.borrow_mut().model.as_mut().unwrap().instance.transform *= Mat4::from_rotation_translation(
|
||||||
.0
|
Quat::from_euler(EulerRot::XYZ,0.001,-0.001,0.001),
|
||||||
.borrow_mut()
|
Vec3::new(0.0,0.0,0.0)
|
||||||
.model
|
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.instance
|
|
||||||
.transform *= Mat4::from_rotation_translation(
|
|
||||||
Quat::from_euler(EulerRot::XYZ, 0.001, -0.001, 0.001),
|
|
||||||
Vec3::new(0.0, 0.0, 0.0),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WindowEvent::MouseInput {
|
WindowEvent::MouseInput { button, state: element, .. } => state.handle_mouse_button(button,element),
|
||||||
button,
|
|
||||||
state: element,
|
|
||||||
..
|
|
||||||
} => state.handle_mouse_button(button, element),
|
|
||||||
WindowEvent::CursorMoved { position: pos, .. } => state.handle_mouse_moved(pos),
|
WindowEvent::CursorMoved { position: pos, .. } => state.handle_mouse_moved(pos),
|
||||||
WindowEvent::KeyboardInput {
|
WindowEvent::KeyboardInput {
|
||||||
event:
|
event:
|
||||||
|
|
|
||||||
|
|
@ -4,26 +4,16 @@ struct Environment {
|
||||||
dir: vec4<f32>,
|
dir: vec4<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Eye {
|
struct View {
|
||||||
// from camera to screen
|
|
||||||
proj: mat4x4<f32>,
|
|
||||||
// from screen to camera
|
|
||||||
inv: mat4x4<f32>,
|
|
||||||
// world to camera
|
|
||||||
view: mat4x4<f32>,
|
view: mat4x4<f32>,
|
||||||
// camera transform
|
|
||||||
frame: mat4x4<f32>,
|
frame: mat4x4<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vertex shader
|
// Vertex shader
|
||||||
@group(0) @binding(0)
|
@group(0) @binding(0)
|
||||||
var<uniform> eye: Eye;
|
var<uniform> view: View;
|
||||||
@group(0) @binding(1)
|
@group(0) @binding(1)
|
||||||
var<uniform> environment: Environment;
|
var<uniform> environment: Environment;
|
||||||
@group(0) @binding(2)
|
|
||||||
var sky_sampler: sampler;
|
|
||||||
@group(0) @binding(3)
|
|
||||||
var sky_texture: texture_2d<f32>;
|
|
||||||
|
|
||||||
struct VertexInput {
|
struct VertexInput {
|
||||||
@location(0) position: vec3<f32>,
|
@location(0) position: vec3<f32>,
|
||||||
|
|
@ -70,7 +60,7 @@ fn vs_main(
|
||||||
out.world_normal = model_rot_matrix * model.normal;
|
out.world_normal = model_rot_matrix * model.normal;
|
||||||
var world_position: vec4<f32> = model_matrix * vec4<f32>(model.position, 1.0);
|
var world_position: vec4<f32> = model_matrix * vec4<f32>(model.position, 1.0);
|
||||||
out.world_position = world_position.xyz;
|
out.world_position = world_position.xyz;
|
||||||
out.clip_position = eye.proj * eye.view * world_position;
|
out.clip_position = view.view * world_position;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,79 +75,23 @@ var t_normal: texture_2d<f32>;
|
||||||
@group(1) @binding(3)
|
@group(1) @binding(3)
|
||||||
var t_rough: texture_2d<f32>;
|
var t_rough: texture_2d<f32>;
|
||||||
|
|
||||||
fn sky_aspect(look: vec3<f32>) -> vec4<f32> {
|
|
||||||
var pi = 3.14159;
|
|
||||||
let u_angle = atan2(look.x,look.z);
|
|
||||||
let u = (u_angle/pi) + 0.5; // from -pi/2 -> pi/2 into 0 -> 1
|
|
||||||
let v_angle = atan2(-look.y,sqrt(look.x * look.x + look.z * look.z));
|
|
||||||
let v = (v_angle/pi) + 0.5;//(v_angle/pi) + 0.5; // from -pi/2 -> pi/2 into 0 -> 1
|
|
||||||
let uv = vec2<f32>(u,v); // Get UV on skybox
|
|
||||||
return textureSample(sky_texture, sky_sampler, uv);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rotation(mat: mat4x4<f32>) -> mat3x3<f32> {
|
|
||||||
return mat3x3<f32>(
|
|
||||||
mat[0].xyz,
|
|
||||||
mat[1].xyz,
|
|
||||||
mat[2].xyz,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn translation(mat: mat4x4<f32>) -> vec4<f32> {
|
|
||||||
//return vec4<f32>(mat[0][3],mat[1][3],mat[2][3],mat[3][3]);
|
|
||||||
return mat[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
let object_color: vec4<f32> = textureSample(t_diffuse, s_diffuse, in.tex_coords);
|
let object_color: vec4<f32> = textureSample(t_diffuse, s_diffuse, in.tex_coords);
|
||||||
let object_normal: vec4<f32> = textureSample(t_normal, s_diffuse, in.tex_coords);
|
let object_normal: vec4<f32> = textureSample(t_normal, s_diffuse, in.tex_coords);
|
||||||
|
|
||||||
let diffuse_color = object_color.xyz;
|
let tangent_normal = object_normal.xyz * 2.0 - 1.0;
|
||||||
let specular_color = vec3<f32>(0.0,0.0,0.0);
|
let light_dir = normalize(environment.dir.xyz);
|
||||||
let reflection = sky_aspect(reflect(normalize(in.world_position-translation(eye.frame).xyz),normalize(in.world_normal)));
|
let view_dir = normalize(view.frame[3].xyz - in.world_position);
|
||||||
|
let half_dir = normalize(view_dir + light_dir);
|
||||||
|
|
||||||
//let result = (environment.ambient.xyz + diffuse_color + specular_color) * object_color.xyz;
|
let diffuse_strength = max(dot(tangent_normal, light_dir), 0.0);
|
||||||
|
let diffuse_color = environment.light.xyz * diffuse_strength;
|
||||||
|
|
||||||
//let light_dir = normalize(environment.dir.xyz);
|
let specular_strength = pow(max(dot(tangent_normal, half_dir), 0.0), 32.0);
|
||||||
//let view_dir = normalize(eye.frame[3].xyz - in.world_position);
|
let specular_color = specular_strength * environment.light.xyz;
|
||||||
//let half_dir = normalize(view_dir + light_dir);
|
|
||||||
|
|
||||||
//let diffuse_strength = max(dot(tangent_normal, light_dir), 0.0);
|
|
||||||
//let diffuse_color = environment.light.xyz * diffuse_strength;
|
|
||||||
|
|
||||||
//let specular_strength = pow(max(dot(tangent_normal, half_dir), 0.0), 32.0);
|
|
||||||
//let specular_color = specular_strength * environment.light.xyz;
|
|
||||||
|
|
||||||
let result = (environment.ambient.xyz + diffuse_color.xyz + specular_color.xyz) * object_color.xyz;
|
let result = (environment.ambient.xyz + diffuse_color.xyz + specular_color.xyz) * object_color.xyz;
|
||||||
|
|
||||||
return vec4<f32>(reflection.xyz,object_color.a);
|
return vec4<f32>(result.xyz,object_color.a);
|
||||||
}
|
|
||||||
|
|
||||||
struct SkyOutput {
|
|
||||||
@builtin(position) position: vec4<f32>,
|
|
||||||
@location(0) pos: vec4<f32> // unadulterated by WGSL
|
|
||||||
}
|
|
||||||
|
|
||||||
const TRI_VERTICES = array(
|
|
||||||
vec4(-1.0, -1.0, 1.0, 1.0),
|
|
||||||
vec4(-1.0, 1.0, 1.0, 1.0),
|
|
||||||
vec4( 1.0, -1.0, 1.0, 1.0),
|
|
||||||
vec4( 1.0, 1.0, 1.0, 1.0),
|
|
||||||
vec4(-1.0, 1.0, 1.0, 1.0),
|
|
||||||
vec4( 1.0, -1.0, 1.0, 1.0),
|
|
||||||
);
|
|
||||||
|
|
||||||
@vertex
|
|
||||||
fn vs_sky(@builtin(vertex_index) index: u32) -> SkyOutput {
|
|
||||||
var out: SkyOutput;
|
|
||||||
out.position = TRI_VERTICES[index];
|
|
||||||
out.pos = out.position;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@fragment
|
|
||||||
fn fs_sky(in: SkyOutput) -> @location(0) vec4<f32> {
|
|
||||||
let look = rotation(eye.frame) * in.pos.xyz;
|
|
||||||
return sky_aspect(look);
|
|
||||||
}
|
}
|
||||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 MiB |
BIN
src/assets/test.png
Executable file
BIN
src/assets/test.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 254 KiB |
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::render::{MaterialProperties, SimpleTexture};
|
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use glam::camera::lh::proj::directx::perspective;
|
use env_logger::Env;
|
||||||
use glam::{Affine3A, EulerRot, Mat3A, Mat4, Vec3, Vec4};
|
use glam::{Affine3A, EulerRot, Mat3A, Mat4, Vec3, Vec4};
|
||||||
use wgpu::util::DeviceExt;
|
use glam::camera::lh::proj::directx::perspective;
|
||||||
use wgpu::{Device, Queue};
|
use wgpu::{Device, Queue};
|
||||||
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
pub(crate) struct Eye {
|
pub(crate) struct Eye {
|
||||||
pub(crate) frame: Affine3A,
|
pub(crate) frame: Affine3A,
|
||||||
|
|
@ -13,66 +13,54 @@ pub(crate) struct Eye {
|
||||||
z_far: f32,
|
z_far: f32,
|
||||||
fov_y: f32,
|
fov_y: f32,
|
||||||
pub(crate) environment_buffer: wgpu::Buffer,
|
pub(crate) environment_buffer: wgpu::Buffer,
|
||||||
pub(crate) camera_buffer: wgpu::Buffer,
|
pub(crate) buffer: wgpu::Buffer,
|
||||||
pub(crate) layout: wgpu::BindGroupLayout,
|
pub(crate) layout: wgpu::BindGroupLayout,
|
||||||
pub(crate) group: wgpu::BindGroup,
|
pub(crate) group: wgpu::BindGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Pod, Copy, Clone, Zeroable)]
|
#[derive(Pod, Copy, Clone, Zeroable)]
|
||||||
pub struct Environment {
|
struct Environment {
|
||||||
ambient: Vec4,
|
ambient: Vec4,
|
||||||
light: Vec4,
|
light: Vec4,
|
||||||
dir: Vec4,
|
dir: Vec4,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eye {
|
impl Eye {
|
||||||
pub(crate) fn write(&mut self, queue: &Queue) {
|
pub(crate) fn view(&self) -> Mat4 {
|
||||||
let camera = Mat4::from_mat3_translation(
|
|
||||||
self.frame.matrix3.into(),
|
|
||||||
Vec3::from(self.frame.translation),
|
|
||||||
);
|
|
||||||
let projection = perspective(self.fov_y, self.aspect_ratio, self.z_near, self.z_far);
|
let projection = perspective(self.fov_y, self.aspect_ratio, self.z_near, self.z_far);
|
||||||
queue.write_buffer(
|
projection * self.frame.inverse()
|
||||||
&self.camera_buffer,
|
|
||||||
0,
|
|
||||||
bytemuck::cast_slice(&[
|
|
||||||
projection,
|
|
||||||
camera * projection.inverse(),
|
|
||||||
camera.inverse(),
|
|
||||||
camera,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
queue.write_buffer(
|
|
||||||
&self.environment_buffer,
|
|
||||||
0,
|
|
||||||
bytemuck::cast_slice(&[self.environment]),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
pub(crate) fn new(device: &Device, width: u32, height: u32, skybox: SimpleTexture) -> Eye {
|
pub(crate) fn write(&mut self, queue: &Queue) {
|
||||||
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
queue.write_buffer(&self.buffer,0,bytemuck::cast_slice(&[
|
||||||
|
self.view(),
|
||||||
|
Mat4::from_mat3_translation(self.frame.matrix3.into(), Vec3::from(self.frame.translation))
|
||||||
|
]));
|
||||||
|
queue.write_buffer(&self.environment_buffer,0,bytemuck::cast_slice(&[self.environment]));
|
||||||
|
}
|
||||||
|
pub(crate) fn new(device: &Device, width: u32, height: u32) -> Eye {
|
||||||
|
let buffer = device.create_buffer_init(
|
||||||
|
&wgpu::util::BufferInitDescriptor {
|
||||||
label: Some("Camera Buffer"),
|
label: Some("Camera Buffer"),
|
||||||
contents: bytemuck::cast_slice(&[
|
contents: bytemuck::cast_slice(&[Mat4::from_translation(Vec3::new(0.0,2.0,-8.0)),Mat4::IDENTITY]),
|
||||||
Mat4::from_translation(Vec3::new(0.0, 2.0, -8.0)),
|
|
||||||
Mat4::IDENTITY,
|
|
||||||
Mat4::IDENTITY,
|
|
||||||
Mat4::IDENTITY,
|
|
||||||
]),
|
|
||||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
let dir = Vec3::new(1.0, 0.5, 1.0).normalize();
|
let dir = Vec3::new(1.0,0.5,1.0).normalize();
|
||||||
let environment = Environment {
|
let environment = Environment {
|
||||||
ambient: Vec4::new(0.15, 0.15, 0.15, 0.0),
|
ambient: Vec4::new(0.15,0.15,0.15, 0.0),
|
||||||
light: Vec4::new(1.0, 1.0, 1.0, 0.0),
|
light: Vec4::new(1.0,1.0,1.0, 0.0),
|
||||||
dir: Vec4::new(dir.x, dir.y, dir.z, 0.0),
|
dir: Vec4::new(dir.x,dir.y,dir.z,0.0),
|
||||||
};
|
};
|
||||||
|
|
||||||
let environment_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
let environment_buffer = device.create_buffer_init(
|
||||||
|
&wgpu::util::BufferInitDescriptor {
|
||||||
label: Some(""),
|
label: Some(""),
|
||||||
contents: bytemuck::cast_slice(&[environment]),
|
contents: bytemuck::cast_slice(&[environment]),
|
||||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
let layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
let layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
entries: &[
|
entries: &[
|
||||||
|
|
@ -95,28 +83,25 @@ impl Eye {
|
||||||
min_binding_size: None,
|
min_binding_size: None,
|
||||||
},
|
},
|
||||||
count: None,
|
count: None,
|
||||||
},
|
}
|
||||||
wgpu::BindGroupLayoutEntry {
|
|
||||||
binding: 2,
|
|
||||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
|
||||||
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
|
||||||
count: None,
|
|
||||||
},
|
|
||||||
wgpu::BindGroupLayoutEntry {
|
|
||||||
binding: 3,
|
|
||||||
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("eye_bind_group_layout"),
|
label: Some("eye_bind_group_layout"),
|
||||||
});
|
});
|
||||||
|
|
||||||
let group = Eye::bind_group(&layout, device, &camera_buffer, &environment_buffer, skybox);
|
let group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
|
layout: &layout,
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 0,
|
||||||
|
resource: buffer.as_entire_binding(),
|
||||||
|
},
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 1,
|
||||||
|
resource: environment_buffer.as_entire_binding(),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
label: Some("eye_bind_group"),
|
||||||
|
});
|
||||||
|
|
||||||
Eye {
|
Eye {
|
||||||
aspect_ratio: width as f32 / height as f32,
|
aspect_ratio: width as f32 / height as f32,
|
||||||
|
|
@ -124,54 +109,13 @@ impl Eye {
|
||||||
fov_y: 90.0,
|
fov_y: 90.0,
|
||||||
z_near: 0.1,
|
z_near: 0.1,
|
||||||
z_far: 1000.0,
|
z_far: 1000.0,
|
||||||
camera_buffer,
|
buffer,
|
||||||
group,
|
group,
|
||||||
layout,
|
layout,
|
||||||
environment,
|
environment,
|
||||||
environment_buffer,
|
environment_buffer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn bind_group(
|
|
||||||
layout: &wgpu::BindGroupLayout,
|
|
||||||
device: &wgpu::Device,
|
|
||||||
camera: &wgpu::Buffer,
|
|
||||||
environment: &wgpu::Buffer,
|
|
||||||
skybox: SimpleTexture,
|
|
||||||
) -> wgpu::BindGroup {
|
|
||||||
device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
||||||
layout: &layout,
|
|
||||||
entries: &[
|
|
||||||
wgpu::BindGroupEntry {
|
|
||||||
binding: 0,
|
|
||||||
resource: camera.as_entire_binding(),
|
|
||||||
},
|
|
||||||
wgpu::BindGroupEntry {
|
|
||||||
binding: 1,
|
|
||||||
resource: environment.as_entire_binding(),
|
|
||||||
},
|
|
||||||
wgpu::BindGroupEntry {
|
|
||||||
binding: 2,
|
|
||||||
resource: wgpu::BindingResource::Sampler(
|
|
||||||
&MaterialProperties::default().sampler(device),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
wgpu::BindGroupEntry {
|
|
||||||
binding: 3,
|
|
||||||
resource: wgpu::BindingResource::TextureView(&skybox.view),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
label: Some("eye_bind_group"),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
pub fn skybox(&mut self, device: &wgpu::Device, texture: SimpleTexture) {
|
|
||||||
self.group = Eye::bind_group(
|
|
||||||
&self.layout,
|
|
||||||
device,
|
|
||||||
&self.camera_buffer,
|
|
||||||
&self.environment_buffer,
|
|
||||||
texture,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
pub(crate) fn resize(&mut self, width: u32, height: u32) {
|
pub(crate) fn resize(&mut self, width: u32, height: u32) {
|
||||||
self.aspect_ratio = width as f32 / height as f32
|
self.aspect_ratio = width as f32 / height as f32
|
||||||
}
|
}
|
||||||
|
|
@ -179,9 +123,9 @@ impl Eye {
|
||||||
self.frame *= Affine3A::from_translation(delta);
|
self.frame *= Affine3A::from_translation(delta);
|
||||||
}
|
}
|
||||||
pub(crate) fn rotate(&mut self, yaw: f32, pitch: f32) {
|
pub(crate) fn rotate(&mut self, yaw: f32, pitch: f32) {
|
||||||
let (mut y, mut x, z) = self.frame.matrix3.to_euler(EulerRot::YXZ);
|
let (mut y,mut x,z) = self.frame.matrix3.to_euler(EulerRot::YXZ);
|
||||||
x = (x + pitch * 0.005).clamp(-1.4, 1.4);
|
x = (x + pitch * 0.005).clamp(-1.4,1.4);
|
||||||
y += yaw * 0.005;
|
y += yaw * 0.005;
|
||||||
self.frame.matrix3 = Mat3A::from_euler(EulerRot::YXZ, y, x, z);
|
self.frame.matrix3 = Mat3A::from_euler(EulerRot::YXZ,y,x,z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,32 +1,32 @@
|
||||||
pub mod eye;
|
pub mod eye;
|
||||||
|
|
||||||
use crate::render::eye::Eye;
|
|
||||||
use crate::world::{Shape, SimpleColliderData, SimpleLight, SimpleObject, SimpleObjectData};
|
|
||||||
use bytemuck::{Pod, Zeroable};
|
|
||||||
use glam::prelude::*;
|
|
||||||
use gltf::Semantic;
|
|
||||||
use image::EncodableLayout;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use glam::prelude::*;
|
||||||
|
use std::collections::{HashMap};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
use std::hash::{BuildHasherDefault, Hash, Hasher};
|
use std::hash::{BuildHasherDefault, Hash, Hasher};
|
||||||
use std::ops::Range;
|
use std::ops::{Range};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
use gltf::{Gltf, Node, Semantic};
|
||||||
|
use image::EncodableLayout;
|
||||||
|
use wgpu::{Device, Queue};
|
||||||
use wgpu::naga::{FastHashMap, FastHashSet};
|
use wgpu::naga::{FastHashMap, FastHashSet};
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
use wgpu::{Device, Queue};
|
|
||||||
use winit::window::Window;
|
use winit::window::Window;
|
||||||
|
use crate::render::eye::Eye;
|
||||||
|
use crate::world::{Shape, SimpleColliderData, SimpleLight, SimpleObject, SimpleObjectData};
|
||||||
|
|
||||||
const DEFAULT_VERTICES: [SimpleVertex; 0] = [];
|
const DEFAULT_VERTICES: [SimpleVertex;0] = [];
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Pod, Zeroable, Copy, Clone)]
|
#[derive(Pod,Zeroable,Copy,Clone)]
|
||||||
pub struct SimpleModelInstance {
|
pub struct SimpleModelInstance {
|
||||||
pub transform: Mat4,
|
pub transform: Mat4,
|
||||||
pub color: Vec4,
|
pub color: Vec4,
|
||||||
pub lights: [u16; 16],
|
pub lights: [u16;16],
|
||||||
pub point_lights: u32,
|
pub point_lights: u32,
|
||||||
pub spot_lights: u32,
|
pub spot_lights: u32,
|
||||||
pub metal: f32,
|
pub metal: f32,
|
||||||
|
|
@ -34,7 +34,7 @@ pub struct SimpleModelInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Pod, Copy, Clone, Zeroable)]
|
#[derive(Pod,Copy,Clone,Zeroable)]
|
||||||
pub struct SimpleLightInstance {
|
pub struct SimpleLightInstance {
|
||||||
pub location: Vec4,
|
pub location: Vec4,
|
||||||
pub rotation: Vec4,
|
pub rotation: Vec4,
|
||||||
|
|
@ -62,15 +62,14 @@ pub struct SimpleInstances {
|
||||||
instance_buffer: wgpu::Buffer,
|
instance_buffer: wgpu::Buffer,
|
||||||
//light_ref_last: usize,
|
//light_ref_last: usize,
|
||||||
//light_ref_buffer: wgpu::Buffer,
|
//light_ref_buffer: wgpu::Buffer,
|
||||||
objects:
|
objects: FastHashMap<Id<SimpleMesh>,FastHashMap<Id<SimpleMaterial>,FastHashSet<SimpleObject>>>,
|
||||||
FastHashMap<Id<SimpleMesh>, FastHashMap<Id<SimpleMaterial>, FastHashSet<SimpleObject>>>,
|
lights: FastHashMap<SimpleLight,usize>,
|
||||||
lights: FastHashMap<SimpleLight, usize>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SimpleRenderCode {
|
enum SimpleRenderCode {
|
||||||
Material(wgpu::BindGroup),
|
Material(wgpu::BindGroup),
|
||||||
Mesh((wgpu::Buffer, u32), Option<(wgpu::Buffer, u32)>),
|
Mesh((wgpu::Buffer,u32),Option<(wgpu::Buffer,u32)>),
|
||||||
Draw(Range<u32>),
|
Draw(Range<u32>)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SimpleRenderProgram(Vec<SimpleRenderCode>);
|
struct SimpleRenderProgram(Vec<SimpleRenderCode>);
|
||||||
|
|
@ -87,15 +86,13 @@ impl SimpleRenderProgram {
|
||||||
let mut indexed = false;
|
let mut indexed = false;
|
||||||
for code in self.0 {
|
for code in self.0 {
|
||||||
match code {
|
match code {
|
||||||
SimpleRenderCode::Material(material) => pass.set_bind_group(
|
SimpleRenderCode::Material(material) => {
|
||||||
Renderer::SIMPLE_RENDER_TEXTURE_GROUP_POSITION,
|
pass.set_bind_group(Renderer::SIMPLE_RENDER_TEXTURE_GROUP_POSITION,&material,&[])
|
||||||
&material,
|
}
|
||||||
&[],
|
SimpleRenderCode::Mesh(vertices,indices) => {
|
||||||
),
|
|
||||||
SimpleRenderCode::Mesh(vertices, indices) => {
|
|
||||||
pass.set_vertex_buffer(0, vertices.0.slice(..));
|
pass.set_vertex_buffer(0, vertices.0.slice(..));
|
||||||
if let Some(indices) = indices {
|
if let Some(indices) = indices {
|
||||||
pass.set_index_buffer(indices.0.slice(..), wgpu::IndexFormat::Uint32);
|
pass.set_index_buffer(indices.0.slice(..),wgpu::IndexFormat::Uint32);
|
||||||
count = indices.1;
|
count = indices.1;
|
||||||
indexed = true;
|
indexed = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -121,10 +118,8 @@ impl SimpleInstances {
|
||||||
if let Some(ref model) = object.0.borrow().model {
|
if let Some(ref model) = object.0.borrow().model {
|
||||||
self.instance_count += 1;
|
self.instance_count += 1;
|
||||||
self.objects
|
self.objects
|
||||||
.entry(model.mesh.clone())
|
.entry(model.mesh.clone()).or_insert(FastHashMap::with_hasher(BuildHasherDefault::new()))
|
||||||
.or_insert(FastHashMap::with_hasher(BuildHasherDefault::new()))
|
.entry(model.material.clone()).or_insert(FastHashSet::with_hasher(BuildHasherDefault::new()))
|
||||||
.entry(model.material.clone())
|
|
||||||
.or_insert(FastHashSet::with_hasher(BuildHasherDefault::new()))
|
|
||||||
.insert(object.clone());
|
.insert(object.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -133,17 +128,15 @@ impl SimpleInstances {
|
||||||
if let Some(ref model) = object.0.borrow().model {
|
if let Some(ref model) = object.0.borrow().model {
|
||||||
self.instance_count -= 1;
|
self.instance_count -= 1;
|
||||||
self.objects
|
self.objects
|
||||||
.entry(model.mesh.clone())
|
.entry(model.mesh.clone()).or_insert(FastHashMap::with_hasher(BuildHasherDefault::new()))
|
||||||
.or_insert(FastHashMap::with_hasher(BuildHasherDefault::new()))
|
.entry(model.material.clone()).or_insert(FastHashSet::with_hasher(BuildHasherDefault::new()))
|
||||||
.entry(model.material.clone())
|
|
||||||
.or_insert(FastHashSet::with_hasher(BuildHasherDefault::new()))
|
|
||||||
.remove(&object);
|
.remove(&object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_light(&mut self, light: SimpleLight) {
|
pub fn add_light(&mut self, light: SimpleLight) {
|
||||||
self.light_count += 1;
|
self.light_count += 1;
|
||||||
self.lights.insert(light, 0);
|
self.lights.insert(light,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_light(&mut self, light: &SimpleLight) {
|
pub fn remove_light(&mut self, light: &SimpleLight) {
|
||||||
|
|
@ -151,12 +144,7 @@ impl SimpleInstances {
|
||||||
self.lights.remove(light);
|
self.lights.remove(light);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reallocate_buffer(
|
pub fn reallocate_buffer(device: &wgpu::Device, queue: &wgpu::Queue, buffer: &mut wgpu::Buffer, count: usize, item_size: usize) {
|
||||||
device: &wgpu::Device,
|
|
||||||
buffer: &mut wgpu::Buffer,
|
|
||||||
count: usize,
|
|
||||||
item_size: usize,
|
|
||||||
) {
|
|
||||||
let size = buffer.size() / item_size as wgpu::BufferAddress;
|
let size = buffer.size() / item_size as wgpu::BufferAddress;
|
||||||
if count > SimpleInstances::MIN_SIZE as usize {
|
if count > SimpleInstances::MIN_SIZE as usize {
|
||||||
let mut reallocate: Option<usize> = None;
|
let mut reallocate: Option<usize> = None;
|
||||||
|
|
@ -184,82 +172,51 @@ impl SimpleInstances {
|
||||||
wgpu::BufferSize::new(self.instance_buffer.size()).unwrap()
|
wgpu::BufferSize::new(self.instance_buffer.size()).unwrap()
|
||||||
).unwrap();
|
).unwrap();
|
||||||
*/
|
*/
|
||||||
SimpleInstances::reallocate_buffer(
|
SimpleInstances::reallocate_buffer(device, queue, &mut self.light_buffer, self.light_count, size_of::<SimpleLight>());
|
||||||
device,
|
let mut buffer = queue.write_buffer_with(
|
||||||
&mut self.light_buffer,
|
|
||||||
self.light_count,
|
|
||||||
size_of::<SimpleLight>(),
|
|
||||||
);
|
|
||||||
let mut buffer = queue
|
|
||||||
.write_buffer_with(
|
|
||||||
&self.light_buffer,
|
&self.light_buffer,
|
||||||
0 as wgpu::BufferAddress,
|
0 as wgpu::BufferAddress,
|
||||||
wgpu::BufferSize::new(self.light_buffer.size()).unwrap(),
|
wgpu::BufferSize::new(self.light_buffer.size()).unwrap(),
|
||||||
)
|
).unwrap();
|
||||||
.unwrap();
|
|
||||||
let stride = size_of::<SimpleLight>();
|
let stride = size_of::<SimpleLight>();
|
||||||
for (new_index, (light, index)) in self.lights.iter_mut().enumerate() {
|
for (new_index,(light,index)) in self.lights.iter_mut().enumerate() {
|
||||||
*index = new_index + 1;
|
*index = new_index + 1;
|
||||||
let begin = *index * stride;
|
let begin = *index * stride;
|
||||||
buffer
|
buffer.slice(begin..begin + stride).copy_from_slice(bytemuck::cast_slice(&[light.0.borrow().instance]));
|
||||||
.slice(begin..begin + stride)
|
|
||||||
.copy_from_slice(bytemuck::cast_slice(&[light.0.borrow().instance]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn write_instances(
|
pub fn write_instances(&mut self, device: &wgpu::Device, queue: &wgpu::Queue) -> SimpleRenderProgram {
|
||||||
&mut self,
|
|
||||||
device: &wgpu::Device,
|
|
||||||
queue: &wgpu::Queue,
|
|
||||||
) -> SimpleRenderProgram {
|
|
||||||
let mut program = SimpleRenderProgram::new();
|
let mut program = SimpleRenderProgram::new();
|
||||||
SimpleInstances::reallocate_buffer(
|
SimpleInstances::reallocate_buffer(device, queue, &mut self.instance_buffer, self.instance_count, size_of::<SimpleModelInstance>());
|
||||||
device,
|
let mut buffer = queue.write_buffer_with(
|
||||||
&mut self.instance_buffer,
|
|
||||||
self.instance_count,
|
|
||||||
size_of::<SimpleModelInstance>(),
|
|
||||||
);
|
|
||||||
let mut buffer = queue
|
|
||||||
.write_buffer_with(
|
|
||||||
&self.instance_buffer,
|
&self.instance_buffer,
|
||||||
0 as wgpu::BufferAddress,
|
0 as wgpu::BufferAddress,
|
||||||
wgpu::BufferSize::new(self.instance_buffer.size()).unwrap(),
|
wgpu::BufferSize::new(self.instance_buffer.size()).unwrap()
|
||||||
)
|
).unwrap();
|
||||||
.unwrap();
|
|
||||||
let mut index: u32 = 0;
|
let mut index: u32 = 0;
|
||||||
let stride = size_of::<SimpleModelInstance>();
|
let stride = size_of::<SimpleModelInstance>();
|
||||||
for (mesh, materials) in self.objects.iter() {
|
for (mesh,materials) in self.objects.iter() {
|
||||||
program.push(SimpleRenderCode::Mesh(
|
program.push(SimpleRenderCode::Mesh(mesh.it.vertices.clone(), mesh.it.indices.clone()));
|
||||||
mesh.it.vertices.clone(),
|
|
||||||
mesh.it.indices.clone(),
|
|
||||||
));
|
|
||||||
for (material, objects) in materials.iter() {
|
for (material, objects) in materials.iter() {
|
||||||
program.push(SimpleRenderCode::Material(material.it.group.clone()));
|
program.push(SimpleRenderCode::Material(material.it.group.clone()));
|
||||||
let before = index;
|
let before = index;
|
||||||
for object in objects.iter() {
|
for object in objects.iter() {
|
||||||
let begin = index as usize * stride;
|
let begin = index as usize * stride;
|
||||||
buffer
|
buffer.slice(begin .. begin + stride).copy_from_slice(bytemuck::cast_slice(&[object.0.borrow().model.as_ref().unwrap().instance]));
|
||||||
.slice(begin..begin + stride)
|
|
||||||
.copy_from_slice(bytemuck::cast_slice(&[object
|
|
||||||
.0
|
|
||||||
.borrow()
|
|
||||||
.model
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.instance]));
|
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
program.push(SimpleRenderCode::Draw(Range::from(before..index)));
|
program.push(SimpleRenderCode::Draw(Range::from(before..index)));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
program
|
program
|
||||||
}
|
}
|
||||||
|
|
||||||
fn desc() -> wgpu::VertexBufferLayout<'static> {
|
fn desc() -> wgpu::VertexBufferLayout<'static> {
|
||||||
|
use std::mem;
|
||||||
wgpu::VertexBufferLayout {
|
wgpu::VertexBufferLayout {
|
||||||
array_stride: size_of::<SimpleModelInstance>() as wgpu::BufferAddress,
|
array_stride: size_of::<SimpleModelInstance>() as wgpu::BufferAddress,
|
||||||
step_mode: wgpu::VertexStepMode::Instance,
|
step_mode: wgpu::VertexStepMode::Instance,
|
||||||
attributes: &[
|
attributes: &[ // todo: is this too big?
|
||||||
// todo: is this too big?
|
|
||||||
wgpu::VertexAttribute {
|
wgpu::VertexAttribute {
|
||||||
offset: 0,
|
offset: 0,
|
||||||
shader_location: 4,
|
shader_location: 4,
|
||||||
|
|
@ -304,27 +261,25 @@ impl SimpleInstances {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(device: &wgpu::Device) -> SimpleInstances {
|
pub fn new(device: &wgpu::Device, queue: &wgpu::Queue) -> SimpleInstances {
|
||||||
let instance_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
let instance_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
label: Some("Instance Buffer"),
|
label: Some("Instance Buffer"),
|
||||||
size: (size_of::<SimpleModelInstance>() * SimpleInstances::MIN_SIZE as usize)
|
size: (size_of::<SimpleModelInstance>() * SimpleInstances::MIN_SIZE as usize) as wgpu::BufferAddress,
|
||||||
as wgpu::BufferAddress,
|
|
||||||
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||||
mapped_at_creation: false,
|
mapped_at_creation: false,
|
||||||
});
|
});
|
||||||
let light_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
let light_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
label: Some("Light Buffer"),
|
label: Some("Light Buffer"),
|
||||||
size: (size_of::<SimpleLightInstance>() * SimpleInstances::MIN_SIZE as usize)
|
size: (size_of::<SimpleLightInstance>() * SimpleInstances::MIN_SIZE as usize) as wgpu::BufferAddress,
|
||||||
as wgpu::BufferAddress,
|
|
||||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||||
mapped_at_creation: false,
|
mapped_at_creation: false,
|
||||||
});
|
});
|
||||||
/*let light_ref_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
let light_ref_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
label: Some("Light Ref Buffer"),
|
label: Some("Light Ref Buffer"),
|
||||||
size: (size_of::<u32>() * SimpleInstances::MIN_SIZE as usize) as wgpu::BufferAddress,
|
size: (size_of::<u32>() * SimpleInstances::MIN_SIZE as usize) as wgpu::BufferAddress,
|
||||||
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
|
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
|
||||||
mapped_at_creation: false,
|
mapped_at_creation: false
|
||||||
});*/
|
});
|
||||||
SimpleInstances {
|
SimpleInstances {
|
||||||
light_count: 0,
|
light_count: 0,
|
||||||
//light_ref_last: 0,
|
//light_ref_last: 0,
|
||||||
|
|
@ -347,9 +302,7 @@ pub struct Renderer {
|
||||||
pub(crate) eye: eye::Eye,
|
pub(crate) eye: eye::Eye,
|
||||||
material_layout: wgpu::BindGroupLayout,
|
material_layout: wgpu::BindGroupLayout,
|
||||||
default_texture: SimpleTexture,
|
default_texture: SimpleTexture,
|
||||||
default_material: SimpleMaterial,
|
pipeline: wgpu::RenderPipeline,
|
||||||
sky_pipeline: wgpu::RenderPipeline,
|
|
||||||
instance_pipeline: wgpu::RenderPipeline,
|
|
||||||
depth_texture: SimpleTexture,
|
depth_texture: SimpleTexture,
|
||||||
pub(crate) instances: SimpleInstances,
|
pub(crate) instances: SimpleInstances,
|
||||||
}
|
}
|
||||||
|
|
@ -384,39 +337,34 @@ impl SimpleVertex {
|
||||||
offset: size_of::<[f32; 6]>() as wgpu::BufferAddress,
|
offset: size_of::<[f32; 6]>() as wgpu::BufferAddress,
|
||||||
shader_location: 2,
|
shader_location: 2,
|
||||||
format: wgpu::VertexFormat::Float32x2,
|
format: wgpu::VertexFormat::Float32x2,
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct SimpleMesh {
|
pub struct SimpleMesh {
|
||||||
indices: Option<(wgpu::Buffer, u32)>,
|
indices: Option<(wgpu::Buffer,u32)>,
|
||||||
vertices: (wgpu::Buffer, u32),
|
vertices: (wgpu::Buffer, u32),
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||||
pub struct SimpleTexture {
|
pub(crate) struct SimpleTexture {
|
||||||
texture: wgpu::Texture,
|
texture: wgpu::Texture,
|
||||||
view: wgpu::TextureView,
|
view: wgpu::TextureView,
|
||||||
}
|
}
|
||||||
pub struct TextureProperties {
|
struct TextureProperties {
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
}
|
}
|
||||||
// todo: use texture compression!
|
|
||||||
impl SimpleTexture {
|
impl SimpleTexture {
|
||||||
pub fn load(
|
pub fn load(device: &Device, queue: &Queue, slice: impl AsRef<[u8]>, properties: TextureProperties) -> SimpleTexture {
|
||||||
device: &Device,
|
|
||||||
queue: &Queue,
|
|
||||||
slice: impl AsRef<[u8]>,
|
|
||||||
properties: TextureProperties,
|
|
||||||
) -> SimpleTexture {
|
|
||||||
let size = wgpu::Extent3d {
|
let size = wgpu::Extent3d {
|
||||||
width: properties.width,
|
width: properties.width,
|
||||||
height: properties.height,
|
height: properties.height,
|
||||||
depth_or_array_layers: 1,
|
depth_or_array_layers: 1,
|
||||||
};
|
};
|
||||||
let diffuse_texture = device.create_texture(&wgpu::TextureDescriptor {
|
let diffuse_texture = device.create_texture(
|
||||||
|
&wgpu::TextureDescriptor {
|
||||||
size,
|
size,
|
||||||
mip_level_count: 1,
|
mip_level_count: 1,
|
||||||
sample_count: 1,
|
sample_count: 1,
|
||||||
|
|
@ -425,9 +373,9 @@ impl SimpleTexture {
|
||||||
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
||||||
label: Some("texture"),
|
label: Some("texture"),
|
||||||
view_formats: &[],
|
view_formats: &[],
|
||||||
});
|
}
|
||||||
let diffuse_texture_view =
|
);
|
||||||
diffuse_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
let diffuse_texture_view = diffuse_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
queue.write_texture(
|
queue.write_texture(
|
||||||
wgpu::TexelCopyTextureInfo {
|
wgpu::TexelCopyTextureInfo {
|
||||||
texture: &diffuse_texture,
|
texture: &diffuse_texture,
|
||||||
|
|
@ -480,41 +428,20 @@ struct MaterialProperties {
|
||||||
filter: wgpu::FilterMode,
|
filter: wgpu::FilterMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MaterialProperties {
|
impl SimpleMaterial {
|
||||||
fn default() -> MaterialProperties {
|
fn new(renderer: &Renderer, base: &SimpleTexture, normal: &SimpleTexture, reflect: &SimpleTexture, config: MaterialProperties) -> SimpleMaterial {
|
||||||
MaterialProperties {
|
let sampler = renderer.device.create_sampler(&wgpu::SamplerDescriptor {
|
||||||
edge: wgpu::AddressMode::Repeat,
|
address_mode_u: config.edge,
|
||||||
filter: wgpu::FilterMode::Linear,
|
address_mode_v: config.edge,
|
||||||
}
|
address_mode_w: config.edge,
|
||||||
}
|
mag_filter: config.filter,
|
||||||
}
|
min_filter: config.filter,
|
||||||
|
|
||||||
impl MaterialProperties {
|
|
||||||
fn sampler(&self, device: &wgpu::Device) -> wgpu::Sampler {
|
|
||||||
device.create_sampler(&wgpu::SamplerDescriptor {
|
|
||||||
address_mode_u: self.edge,
|
|
||||||
address_mode_v: self.edge,
|
|
||||||
address_mode_w: self.edge,
|
|
||||||
mag_filter: self.filter,
|
|
||||||
min_filter: self.filter,
|
|
||||||
mipmap_filter: wgpu::MipmapFilterMode::Nearest,
|
mipmap_filter: wgpu::MipmapFilterMode::Nearest,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
});
|
||||||
}
|
let group = renderer.device.create_bind_group(
|
||||||
}
|
&wgpu::BindGroupDescriptor {
|
||||||
|
layout: &renderer.material_layout,
|
||||||
impl SimpleMaterial {
|
|
||||||
fn new(
|
|
||||||
device: &wgpu::Device,
|
|
||||||
layout: &wgpu::BindGroupLayout,
|
|
||||||
base: &SimpleTexture,
|
|
||||||
normal: &SimpleTexture,
|
|
||||||
reflect: &SimpleTexture,
|
|
||||||
config: MaterialProperties,
|
|
||||||
) -> SimpleMaterial {
|
|
||||||
let sampler = config.sampler(&device);
|
|
||||||
let group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
||||||
layout: layout,
|
|
||||||
entries: &[
|
entries: &[
|
||||||
wgpu::BindGroupEntry {
|
wgpu::BindGroupEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
|
|
@ -534,8 +461,11 @@ impl SimpleMaterial {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
label: Some("diffuse_bind_group"),
|
label: Some("diffuse_bind_group"),
|
||||||
});
|
}
|
||||||
SimpleMaterial { group }
|
);
|
||||||
|
SimpleMaterial {
|
||||||
|
group,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -544,7 +474,7 @@ struct PoolError(String);
|
||||||
|
|
||||||
impl Display for PoolError {
|
impl Display for PoolError {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}", self.0)
|
write!(f,"{}",self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,7 +493,7 @@ impl SimpleTreeNode {
|
||||||
} else {
|
} else {
|
||||||
for child in self.children.iter() {
|
for child in self.children.iter() {
|
||||||
if let Some(object) = child.first_object() {
|
if let Some(object) = child.first_object() {
|
||||||
return Some(object);
|
return Some(object)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
@ -571,7 +501,7 @@ impl SimpleTreeNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type GltfVertexBufferKey = (Option<usize>, Option<usize>, Option<usize>, Option<usize>);
|
type GltfVertexBufferKey = (Option<usize>,Option<usize>,Option<usize>,Option<usize>);
|
||||||
|
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
const SIMPLE_RENDER_EYE_GROUP_POSITION: u32 = 0;
|
const SIMPLE_RENDER_EYE_GROUP_POSITION: u32 = 0;
|
||||||
|
|
@ -584,55 +514,25 @@ impl Renderer {
|
||||||
id: self.id_count,
|
id: self.id_count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn load_texture_from_bytes(
|
pub fn load_texture_from_bytes(&mut self, slice: impl AsRef<[u8]>) -> SimpleTexture {
|
||||||
&mut self,
|
let image = image::load_from_memory(slice.as_ref());
|
||||||
slice: impl AsRef<[u8]>,
|
|
||||||
format: Option<image::ImageFormat>,
|
|
||||||
) -> SimpleTexture {
|
|
||||||
let image = if let Some(format) = format {
|
|
||||||
image::load_from_memory_with_format(slice.as_ref(), format)
|
|
||||||
} else {
|
|
||||||
image::load_from_memory(slice.as_ref())
|
|
||||||
};
|
|
||||||
if let Ok(data) = image {
|
if let Ok(data) = image {
|
||||||
let data = data.into_rgba8();
|
let data = data.into_rgba8();
|
||||||
SimpleTexture::load(
|
SimpleTexture::load(&self.device, &self.queue, data.as_bytes(), TextureProperties {
|
||||||
&self.device,
|
|
||||||
&self.queue,
|
|
||||||
data.as_bytes(),
|
|
||||||
TextureProperties {
|
|
||||||
width: data.width(),
|
width: data.width(),
|
||||||
height: data.height(),
|
height: data.height(),
|
||||||
},
|
})
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
println!("failed to load texture! error: {:?}", image.unwrap_err());
|
|
||||||
self.default_texture.clone()
|
self.default_texture.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn new_material(
|
pub fn new_material(&mut self, base: &SimpleTexture, normal: &SimpleTexture, reflect: &SimpleTexture) -> Id<SimpleMaterial> {
|
||||||
&mut self,
|
self.new_id(SimpleMaterial::new(self, base, normal, reflect, MaterialProperties {
|
||||||
base: &SimpleTexture,
|
|
||||||
normal: &SimpleTexture,
|
|
||||||
reflect: &SimpleTexture,
|
|
||||||
) -> Id<SimpleMaterial> {
|
|
||||||
self.new_id(SimpleMaterial::new(
|
|
||||||
&self.device,
|
|
||||||
&self.material_layout,
|
|
||||||
base,
|
|
||||||
normal,
|
|
||||||
reflect,
|
|
||||||
MaterialProperties {
|
|
||||||
edge: wgpu::AddressMode::Repeat,
|
edge: wgpu::AddressMode::Repeat,
|
||||||
filter: wgpu::FilterMode::Linear,
|
filter: wgpu::FilterMode::Linear,
|
||||||
},
|
}))
|
||||||
))
|
|
||||||
}
|
}
|
||||||
pub fn new_texture_from_gltf(
|
pub fn new_texture_from_gltf(&mut self, info: &gltf::texture::Texture, images: &Vec<gltf::image::Data>) -> SimpleTexture {
|
||||||
&mut self,
|
|
||||||
info: &gltf::texture::Texture,
|
|
||||||
images: &Vec<gltf::image::Data>,
|
|
||||||
) -> SimpleTexture {
|
|
||||||
if let Some(image) = images.get(info.source().index()) {
|
if let Some(image) = images.get(info.source().index()) {
|
||||||
let mut new_pixels = Vec::new();
|
let mut new_pixels = Vec::new();
|
||||||
let pixels: &Vec<u8>;
|
let pixels: &Vec<u8>;
|
||||||
|
|
@ -646,18 +546,15 @@ impl Renderer {
|
||||||
}
|
}
|
||||||
pixels = &new_pixels;
|
pixels = &new_pixels;
|
||||||
}
|
}
|
||||||
gltf::image::Format::R8G8B8A8 => pixels = &image.pixels,
|
gltf::image::Format::R8G8B8A8 => {
|
||||||
_ => return self.default_texture.clone(),
|
pixels = &image.pixels
|
||||||
}
|
}
|
||||||
SimpleTexture::load(
|
_ => return self.default_texture.clone()
|
||||||
&self.device,
|
}
|
||||||
&self.queue,
|
SimpleTexture::load(&self.device, &self.queue, pixels.as_slice(), TextureProperties {
|
||||||
pixels.as_slice(),
|
|
||||||
TextureProperties {
|
|
||||||
width: image.width,
|
width: image.width,
|
||||||
height: image.height,
|
height: image.height,
|
||||||
},
|
})
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
self.default_texture.clone()
|
self.default_texture.clone()
|
||||||
}
|
}
|
||||||
|
|
@ -666,47 +563,22 @@ impl Renderer {
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: gltf::Primitive,
|
primitive: gltf::Primitive,
|
||||||
meshes: &mut HashMap<GltfVertexBufferKey, SimpleMesh>,
|
meshes: &mut HashMap<GltfVertexBufferKey, SimpleMesh>,
|
||||||
buffers: &[gltf::buffer::Data],
|
buffers: &[gltf::buffer::Data]
|
||||||
) -> Id<SimpleMesh> {
|
) -> Id<SimpleMesh> {
|
||||||
let position_index = primitive
|
let position_index = primitive.get(&Semantic::Positions).and_then(|it| it.view()).and_then(|it| Some(it.buffer().index()));
|
||||||
.get(&Semantic::Positions)
|
let normals_index = primitive.get(&Semantic::Normals).and_then(|it| it.view()).and_then(|it| Some(it.buffer().index()));
|
||||||
.and_then(|it| it.view())
|
let tex_coords_index = primitive.get(&Semantic::TexCoords(0)).and_then(|it| it.view()).and_then(|it| Some(it.buffer().index()));
|
||||||
.and_then(|it| Some(it.buffer().index()));
|
let indices_index = primitive.indices().and_then(|it| it.view()).and_then(|it| Some(it.buffer().index()));
|
||||||
let normals_index = primitive
|
let tangent_index = primitive.get(&Semantic::Tangents).and_then(|it| it.view()).and_then(|it| Some(it.buffer().index()));
|
||||||
.get(&Semantic::Normals)
|
let key = (position_index,normals_index,tex_coords_index,indices_index);
|
||||||
.and_then(|it| it.view())
|
self.new_id(meshes.entry(key).or_insert_with(|| {
|
||||||
.and_then(|it| Some(it.buffer().index()));
|
|
||||||
let tex_coords_index = primitive
|
|
||||||
.get(&Semantic::TexCoords(0))
|
|
||||||
.and_then(|it| it.view())
|
|
||||||
.and_then(|it| Some(it.buffer().index()));
|
|
||||||
let indices_index = primitive
|
|
||||||
.indices()
|
|
||||||
.and_then(|it| it.view())
|
|
||||||
.and_then(|it| Some(it.buffer().index()));
|
|
||||||
let tangent_index = primitive
|
|
||||||
.get(&Semantic::Tangents)
|
|
||||||
.and_then(|it| it.view())
|
|
||||||
.and_then(|it| Some(it.buffer().index()));
|
|
||||||
let key = (
|
|
||||||
position_index,
|
|
||||||
normals_index,
|
|
||||||
tex_coords_index,
|
|
||||||
indices_index,
|
|
||||||
);
|
|
||||||
self.new_id(
|
|
||||||
meshes
|
|
||||||
.entry(key)
|
|
||||||
.or_insert_with(|| {
|
|
||||||
let mut tangents = false;
|
let mut tangents = false;
|
||||||
let reader = primitive.reader(|buffer| Some(&buffers[buffer.index()]));
|
let reader = primitive.reader(|buffer| Some(&buffers[buffer.index()]));
|
||||||
let mut vertex_data: Vec<SimpleVertex>;
|
let mut vertex_data: Vec<SimpleVertex>;
|
||||||
if let Some(positions) = reader.read_positions() {
|
if let Some(positions) = reader.read_positions() {
|
||||||
vertex_data = Vec::with_capacity(positions.len());
|
vertex_data = Vec::with_capacity(positions.len());
|
||||||
let mut normal = reader.read_normals().map(|it| it.into_iter());
|
let mut normal = reader.read_normals().map(|it| it.into_iter());
|
||||||
let mut tex_coord = reader
|
let mut tex_coord = reader.read_tex_coords(0).map(|it| it.into_f32().into_iter());
|
||||||
.read_tex_coords(0)
|
|
||||||
.map(|it| it.into_f32().into_iter());
|
|
||||||
let mut tangent = reader.read_tangents().map(|it| it.into_iter());
|
let mut tangent = reader.read_tangents().map(|it| it.into_iter());
|
||||||
tangents = tangent.is_some();
|
tangents = tangent.is_some();
|
||||||
for position in positions {
|
for position in positions {
|
||||||
|
|
@ -716,53 +588,46 @@ impl Renderer {
|
||||||
if let Some(normal) = normals.next() {
|
if let Some(normal) = normals.next() {
|
||||||
normal
|
normal
|
||||||
} else {
|
} else {
|
||||||
[0.0; 3]
|
[0.0;3]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
[0.0; 3]
|
[0.0;3]
|
||||||
},
|
},
|
||||||
tex_coord: if let Some(ref mut tex_coords) = tex_coord {
|
tex_coord: if let Some(ref mut tex_coords) = tex_coord {
|
||||||
tex_coords.next()
|
tex_coords.next()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}.unwrap_or([0.0;2]),
|
||||||
.unwrap_or([0.0; 2]),
|
tangent: [0.0;3], // todo: tangent from model
|
||||||
tangent: [0.0; 3], // todo: tangent from model
|
bitangent: [0.0;3],
|
||||||
bitangent: [0.0; 3],
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vertex_data = Vec::new();
|
vertex_data = Vec::new();
|
||||||
}
|
}
|
||||||
let vertex_buffer =
|
let vertex_buffer = self.device.create_buffer_init(
|
||||||
self.device
|
&wgpu::util::BufferInitDescriptor {
|
||||||
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
||||||
label: Some("Vertex Buffer"),
|
label: Some("Vertex Buffer"),
|
||||||
contents: bytemuck::cast_slice(vertex_data.as_slice()),
|
contents: bytemuck::cast_slice(vertex_data.as_slice()),
|
||||||
usage: wgpu::BufferUsages::VERTEX,
|
usage: wgpu::BufferUsages::VERTEX,
|
||||||
});
|
}
|
||||||
let vertices_result = (vertex_buffer, vertex_data.len() as u32);
|
);
|
||||||
|
let vertices_result = (vertex_buffer,vertex_data.len() as u32);
|
||||||
let indices_result = if let Some(indices) = reader.read_indices() {
|
let indices_result = if let Some(indices) = reader.read_indices() {
|
||||||
let index_data: Vec<u32> = indices.into_u32().collect();
|
let index_data: Vec<u32> = indices.into_u32().collect();
|
||||||
Some((
|
Some((self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
self.device
|
|
||||||
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
||||||
label: Some("Index Buffer"),
|
label: Some("Index Buffer"),
|
||||||
contents: bytemuck::cast_slice(index_data.as_slice()),
|
contents: bytemuck::cast_slice(index_data.as_slice()),
|
||||||
usage: wgpu::BufferUsages::INDEX,
|
usage: wgpu::BufferUsages::INDEX,
|
||||||
}),
|
}), index_data.len() as u32))
|
||||||
index_data.len() as u32,
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
SimpleMesh {
|
SimpleMesh {
|
||||||
indices: indices_result,
|
indices: indices_result,
|
||||||
vertices: vertices_result,
|
vertices: vertices_result
|
||||||
}
|
}
|
||||||
})
|
}).clone())
|
||||||
.clone(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
pub fn load_node_from_gltf(
|
pub fn load_node_from_gltf(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
@ -775,7 +640,7 @@ impl Renderer {
|
||||||
let mut tree_node = SimpleTreeNode {
|
let mut tree_node = SimpleTreeNode {
|
||||||
object: None,
|
object: None,
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
name: node.name().unwrap_or("Node").to_string(),
|
name: node.name().unwrap_or("Node").to_string()
|
||||||
};
|
};
|
||||||
if let Some(mesh) = node.mesh() {
|
if let Some(mesh) = node.mesh() {
|
||||||
let len = mesh.primitives().len();
|
let len = mesh.primitives().len();
|
||||||
|
|
@ -787,34 +652,25 @@ impl Renderer {
|
||||||
let rough = pbr.roughness_factor();
|
let rough = pbr.roughness_factor();
|
||||||
let light = primitive.material().emissive_factor();
|
let light = primitive.material().emissive_factor();
|
||||||
let base = match pbr.base_color_texture() {
|
let base = match pbr.base_color_texture() {
|
||||||
Some(info) => textures
|
Some(info) => textures.entry(info.texture().source().index()).or_insert_with(|| self.new_texture_from_gltf(&info.texture(), &images)).clone(),
|
||||||
.entry(info.texture().source().index())
|
None => self.default_texture.clone()
|
||||||
.or_insert_with(|| self.new_texture_from_gltf(&info.texture(), &images))
|
|
||||||
.clone(),
|
|
||||||
None => self.default_texture.clone(),
|
|
||||||
};
|
};
|
||||||
let reflect = match pbr.metallic_roughness_texture() {
|
let reflect = match pbr.metallic_roughness_texture() {
|
||||||
Some(info) => textures
|
Some(info) => textures.entry(info.texture().source().index()).or_insert_with(|| self.new_texture_from_gltf(&info.texture(), &images)).clone(),
|
||||||
.entry(info.texture().source().index())
|
None => self.default_texture.clone()
|
||||||
.or_insert_with(|| self.new_texture_from_gltf(&info.texture(), &images))
|
|
||||||
.clone(),
|
|
||||||
None => self.default_texture.clone(),
|
|
||||||
};
|
};
|
||||||
let normal = match material.normal_texture() {
|
let normal = match material.normal_texture() {
|
||||||
Some(info) => textures
|
Some(info) => textures.entry(info.texture().source().index()).or_insert_with(|| self.new_texture_from_gltf(&info.texture(), &images)).clone(),
|
||||||
.entry(info.texture().source().index())
|
None => self.default_texture.clone()
|
||||||
.or_insert_with(|| self.new_texture_from_gltf(&info.texture(), &images))
|
|
||||||
.clone(),
|
|
||||||
None => self.default_texture.clone(),
|
|
||||||
};
|
};
|
||||||
let material = self.new_material(&base, &normal, &reflect);
|
let material = self.new_material(&base, &normal, &reflect);
|
||||||
let mesh = self.new_mesh_from_gltf(primitive, meshes, buffers);
|
let mesh = self.new_mesh_from_gltf(primitive,meshes,buffers);
|
||||||
let object = SimpleObject(Rc::new(RefCell::new(SimpleObjectData {
|
let object = SimpleObject(Rc::new(RefCell::new(SimpleObjectData {
|
||||||
model: Some(SimpleModelData {
|
model: Some(SimpleModelData {
|
||||||
instance: SimpleModelInstance {
|
instance: SimpleModelInstance {
|
||||||
transform: Mat4::default(),
|
transform: Mat4::default(),
|
||||||
color: Vec4::from_array(color),
|
color: Vec4::from_array(color),
|
||||||
lights: [0; 16],
|
lights: [0;16],
|
||||||
point_lights: 0,
|
point_lights: 0,
|
||||||
spot_lights: 0,
|
spot_lights: 0,
|
||||||
metal,
|
metal,
|
||||||
|
|
@ -835,15 +691,13 @@ impl Renderer {
|
||||||
tree_node.children.push(SimpleTreeNode {
|
tree_node.children.push(SimpleTreeNode {
|
||||||
object: Some(object),
|
object: Some(object),
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
name: "Primitive".to_string(),
|
name: "Primitive".to_string()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for node in node.children() {
|
for node in node.children() {
|
||||||
tree_node
|
tree_node.children.push(self.load_node_from_gltf(node,meshes,textures,images,buffers));
|
||||||
.children
|
|
||||||
.push(self.load_node_from_gltf(node, meshes, textures, images, buffers));
|
|
||||||
}
|
}
|
||||||
tree_node
|
tree_node
|
||||||
}
|
}
|
||||||
|
|
@ -863,13 +717,7 @@ impl Renderer {
|
||||||
name: scene.name().unwrap_or("Scene").to_string(),
|
name: scene.name().unwrap_or("Scene").to_string(),
|
||||||
};
|
};
|
||||||
for node in scene.nodes() {
|
for node in scene.nodes() {
|
||||||
scene_node.children.push(self.load_node_from_gltf(
|
scene_node.children.push(self.load_node_from_gltf(node, &mut meshes, &mut textures, &images, &buffers));
|
||||||
node,
|
|
||||||
&mut meshes,
|
|
||||||
&mut textures,
|
|
||||||
&images,
|
|
||||||
&buffers,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
root.children.push(scene_node)
|
root.children.push(scene_node)
|
||||||
}
|
}
|
||||||
|
|
@ -880,9 +728,6 @@ impl Renderer {
|
||||||
self.surface.configure(&self.device, &self.config);
|
self.surface.configure(&self.device, &self.config);
|
||||||
self.eye.resize(width, height);
|
self.eye.resize(width, height);
|
||||||
}
|
}
|
||||||
pub fn set_skybox(&mut self, skybox: SimpleTexture) {
|
|
||||||
self.eye.skybox(&self.device, skybox);
|
|
||||||
}
|
|
||||||
pub async fn new(window: &Arc<Window>) -> anyhow::Result<Self> {
|
pub async fn new(window: &Arc<Window>) -> anyhow::Result<Self> {
|
||||||
let bounds = window.inner_size();
|
let bounds = window.inner_size();
|
||||||
let width = bounds.width;
|
let width = bounds.width;
|
||||||
|
|
@ -948,22 +793,16 @@ impl Renderer {
|
||||||
desired_maximum_frame_latency: 2,
|
desired_maximum_frame_latency: 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
let shader =
|
let eye = Eye::new(&device, width, height);
|
||||||
device.create_shader_module(wgpu::include_wgsl!("../assets/SimpleShader.wgsl"));
|
|
||||||
|
|
||||||
let default_texture = SimpleTexture::load(
|
let shader = device.create_shader_module(wgpu::include_wgsl!("../assets/SimpleShader.wgsl"));
|
||||||
&device,
|
|
||||||
&queue,
|
let texture = SimpleTexture::load(&device, &queue, [255,255,255,255], TextureProperties {
|
||||||
[0, 0, 255, 255],
|
|
||||||
TextureProperties {
|
|
||||||
width: 1,
|
width: 1,
|
||||||
height: 1,
|
height: 1,
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
let eye = Eye::new(&device, width, height, default_texture.clone());
|
let texture_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
let texture_bind_group_layout =
|
|
||||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
|
||||||
entries: &[
|
entries: &[
|
||||||
wgpu::BindGroupLayoutEntry {
|
wgpu::BindGroupLayoutEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
|
|
@ -1000,24 +839,30 @@ impl Renderer {
|
||||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||||
},
|
},
|
||||||
count: None,
|
count: None,
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
label: Some("texture_bind_group_layout"),
|
label: Some("texture_bind_group_layout"),
|
||||||
});
|
});
|
||||||
|
|
||||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
let render_pipeline_layout =
|
||||||
|
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
label: Some("Render Pipeline Layout"),
|
label: Some("Render Pipeline Layout"),
|
||||||
bind_group_layouts: &[Some(&eye.layout), Some(&texture_bind_group_layout)],
|
bind_group_layouts: &[
|
||||||
|
Some(&eye.layout),
|
||||||
|
Some(&texture_bind_group_layout),
|
||||||
|
],
|
||||||
immediate_size: 0,
|
immediate_size: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
let instance_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||||
label: Some("Render Pipeline"),
|
label: Some("Render Pipeline"),
|
||||||
layout: Some(&pipeline_layout),
|
layout: Some(&render_pipeline_layout),
|
||||||
vertex: wgpu::VertexState {
|
vertex: wgpu::VertexState {
|
||||||
module: &shader,
|
module: &shader,
|
||||||
entry_point: Some("vs_main"),
|
entry_point: Some("vs_main"),
|
||||||
buffers: &[SimpleVertex::desc(), SimpleInstances::desc()],
|
buffers: &[
|
||||||
|
SimpleVertex::desc(),SimpleInstances::desc(),
|
||||||
|
],
|
||||||
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||||
},
|
},
|
||||||
fragment: Some(wgpu::FragmentState {
|
fragment: Some(wgpu::FragmentState {
|
||||||
|
|
@ -1032,7 +877,7 @@ impl Renderer {
|
||||||
})],
|
})],
|
||||||
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||||
}),
|
}),
|
||||||
primitive: Default::default(), /*wgpu::PrimitiveState {
|
primitive: wgpu::PrimitiveState {
|
||||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||||
strip_index_format: None,
|
strip_index_format: None,
|
||||||
front_face: wgpu::FrontFace::Ccw,
|
front_face: wgpu::FrontFace::Ccw,
|
||||||
|
|
@ -1040,12 +885,12 @@ impl Renderer {
|
||||||
polygon_mode: wgpu::PolygonMode::Fill,
|
polygon_mode: wgpu::PolygonMode::Fill,
|
||||||
unclipped_depth: false,
|
unclipped_depth: false,
|
||||||
conservative: false,
|
conservative: false,
|
||||||
}*/
|
},
|
||||||
depth_stencil: Some(wgpu::DepthStencilState {
|
depth_stencil: Some(wgpu::DepthStencilState {
|
||||||
stencil: wgpu::StencilState::default(),
|
|
||||||
format: wgpu::TextureFormat::Depth32Float,
|
format: wgpu::TextureFormat::Depth32Float,
|
||||||
depth_write_enabled: Some(true),
|
depth_write_enabled: Some(true),
|
||||||
depth_compare: Some(wgpu::CompareFunction::Less),
|
depth_compare: Some(wgpu::CompareFunction::Less),
|
||||||
|
stencil: wgpu::StencilState::default(),
|
||||||
bias: wgpu::DepthBiasState::default(),
|
bias: wgpu::DepthBiasState::default(),
|
||||||
}),
|
}),
|
||||||
multisample: wgpu::MultisampleState {
|
multisample: wgpu::MultisampleState {
|
||||||
|
|
@ -1057,45 +902,7 @@ impl Renderer {
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
//todo: use a pipeline cache!
|
let size = wgpu::Extent3d { // 2.
|
||||||
let sky_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
|
||||||
label: Some("Sky Pipeline"),
|
|
||||||
layout: Some(&pipeline_layout),
|
|
||||||
vertex: wgpu::VertexState {
|
|
||||||
module: &shader,
|
|
||||||
entry_point: Some("vs_sky"),
|
|
||||||
compilation_options: Default::default(),
|
|
||||||
buffers: &[],
|
|
||||||
},
|
|
||||||
fragment: Some(wgpu::FragmentState {
|
|
||||||
module: &shader,
|
|
||||||
entry_point: Some("fs_sky"),
|
|
||||||
compilation_options: Default::default(),
|
|
||||||
targets: &[Some(wgpu::ColorTargetState {
|
|
||||||
// 4.
|
|
||||||
format: config.format,
|
|
||||||
blend: Some(wgpu::BlendState::REPLACE),
|
|
||||||
write_mask: wgpu::ColorWrites::ALL,
|
|
||||||
})],
|
|
||||||
}),
|
|
||||||
primitive: wgpu::PrimitiveState {
|
|
||||||
front_face: wgpu::FrontFace::Cw,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
depth_stencil: Some(wgpu::DepthStencilState {
|
|
||||||
format: wgpu::TextureFormat::Depth32Float,
|
|
||||||
depth_write_enabled: Some(false),
|
|
||||||
depth_compare: Some(wgpu::CompareFunction::LessEqual),
|
|
||||||
stencil: wgpu::StencilState::default(),
|
|
||||||
bias: wgpu::DepthBiasState::default(),
|
|
||||||
}),
|
|
||||||
multisample: wgpu::MultisampleState::default(),
|
|
||||||
multiview_mask: None,
|
|
||||||
cache: None,
|
|
||||||
});
|
|
||||||
|
|
||||||
let size = wgpu::Extent3d {
|
|
||||||
// 2.
|
|
||||||
width: config.width.max(1),
|
width: config.width.max(1),
|
||||||
height: config.height.max(1),
|
height: config.height.max(1),
|
||||||
depth_or_array_layers: 1,
|
depth_or_array_layers: 1,
|
||||||
|
|
@ -1113,8 +920,8 @@ impl Renderer {
|
||||||
};
|
};
|
||||||
let depth_texture = device.create_texture(&desc);
|
let depth_texture = device.create_texture(&desc);
|
||||||
let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
let depth_sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
let depth_sampler = device.create_sampler(
|
||||||
// 4.
|
&wgpu::SamplerDescriptor { // 4.
|
||||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||||
|
|
@ -1125,37 +932,31 @@ impl Renderer {
|
||||||
lod_min_clamp: 0.0,
|
lod_min_clamp: 0.0,
|
||||||
lod_max_clamp: 100.0,
|
lod_max_clamp: 100.0,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
let instances = SimpleInstances::new(&device);
|
let instances = SimpleInstances::new(&device,&queue);
|
||||||
|
|
||||||
let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
let staging_belt = wgpu::util::StagingBelt::new(device.clone(), 0x1024);
|
||||||
|
|
||||||
|
let buffer = device.create_buffer_init(
|
||||||
|
&wgpu::util::BufferInitDescriptor {
|
||||||
label: Some("Vertex Buffer"),
|
label: Some("Vertex Buffer"),
|
||||||
contents: bytemuck::cast_slice(&DEFAULT_VERTICES),
|
contents: bytemuck::cast_slice(&DEFAULT_VERTICES),
|
||||||
usage: wgpu::BufferUsages::VERTEX,
|
usage: wgpu::BufferUsages::VERTEX,
|
||||||
});
|
}
|
||||||
|
|
||||||
let default_material = SimpleMaterial::new(
|
|
||||||
&device,
|
|
||||||
&texture_bind_group_layout,
|
|
||||||
&default_texture,
|
|
||||||
&default_texture,
|
|
||||||
&default_texture,
|
|
||||||
MaterialProperties::default(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(Renderer {
|
Ok(Renderer {
|
||||||
id_count: 0,
|
id_count: 0,
|
||||||
material_layout: texture_bind_group_layout,
|
material_layout: texture_bind_group_layout,
|
||||||
default_texture,
|
default_texture: texture,
|
||||||
default_material,
|
|
||||||
depth_texture: SimpleTexture {
|
depth_texture: SimpleTexture {
|
||||||
texture: depth_texture,
|
texture: depth_texture,
|
||||||
view: depth_view,
|
view: depth_view,
|
||||||
},
|
},
|
||||||
instances,
|
instances,
|
||||||
sky_pipeline,
|
pipeline,
|
||||||
instance_pipeline,
|
|
||||||
surface,
|
surface,
|
||||||
config,
|
config,
|
||||||
device,
|
device,
|
||||||
|
|
@ -1165,6 +966,7 @@ impl Renderer {
|
||||||
}
|
}
|
||||||
pub(crate) fn render(&mut self, window: &Arc<Window>) -> anyhow::Result<()> {
|
pub(crate) fn render(&mut self, window: &Arc<Window>) -> anyhow::Result<()> {
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
|
|
||||||
let output = match self.surface.get_current_texture() {
|
let output = match self.surface.get_current_texture() {
|
||||||
wgpu::CurrentSurfaceTexture::Success(surface_texture) => surface_texture,
|
wgpu::CurrentSurfaceTexture::Success(surface_texture) => surface_texture,
|
||||||
wgpu::CurrentSurfaceTexture::Suboptimal(surface_texture) => {
|
wgpu::CurrentSurfaceTexture::Suboptimal(surface_texture) => {
|
||||||
|
|
@ -1191,7 +993,7 @@ impl Renderer {
|
||||||
.texture
|
.texture
|
||||||
.create_view(&wgpu::TextureViewDescriptor::default());
|
.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
|
||||||
let program = self.instances.write_instances(&self.device, &self.queue);
|
let program = self.instances.write_instances(&self.device,&self.queue);
|
||||||
|
|
||||||
let mut encoder = self
|
let mut encoder = self
|
||||||
.device
|
.device
|
||||||
|
|
@ -1207,12 +1009,7 @@ impl Renderer {
|
||||||
resolve_target: None,
|
resolve_target: None,
|
||||||
depth_slice: None,
|
depth_slice: None,
|
||||||
ops: wgpu::Operations {
|
ops: wgpu::Operations {
|
||||||
load: wgpu::LoadOp::Clear(wgpu::Color {
|
load: wgpu::LoadOp::Clear(Default::default()),
|
||||||
r: 0.5,
|
|
||||||
g: 0.6,
|
|
||||||
b: 0.8,
|
|
||||||
a: 1.0,
|
|
||||||
}),
|
|
||||||
store: wgpu::StoreOp::Store,
|
store: wgpu::StoreOp::Store,
|
||||||
},
|
},
|
||||||
})],
|
})],
|
||||||
|
|
@ -1229,15 +1026,10 @@ impl Renderer {
|
||||||
multiview_mask: None,
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
pass.set_pipeline(&self.instance_pipeline);
|
pass.set_pipeline(&self.pipeline);
|
||||||
pass.set_bind_group(0, &self.eye.group, &[]);
|
pass.set_bind_group(0, &self.eye.group, &[]);
|
||||||
pass.set_vertex_buffer(1, self.instances.instance_buffer.slice(..));
|
pass.set_vertex_buffer(1, self.instances.instance_buffer.slice(..));
|
||||||
program.render(&mut pass);
|
program.render(&mut pass);
|
||||||
|
|
||||||
pass.set_bind_group(1, &self.default_material.group, &[]);
|
|
||||||
|
|
||||||
pass.set_pipeline(&self.sky_pipeline);
|
|
||||||
pass.draw(0..6, 0..1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.queue.submit(Some(encoder.finish()));
|
self.queue.submit(Some(encoder.finish()));
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use crate::render::{Renderer, SimpleLightData, SimpleModelData};
|
|
||||||
use glam::{DVec3, IVec3, Mat4, UVec3, Vec3, Vec4Swizzles};
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::hash::{BuildHasherDefault, Hash, Hasher};
|
use std::hash::{BuildHasherDefault, Hash, Hasher};
|
||||||
use std::ops::{Div, Mul};
|
use std::ops::{Div, Mul};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use glam::{DVec3, IVec3, Mat4, UVec3, Vec3, Vec4Swizzles};
|
||||||
use wgpu::naga::{FastHashMap, FastHashSet};
|
use wgpu::naga::{FastHashMap, FastHashSet};
|
||||||
|
use crate::render::{SimpleModelData, SimpleLightData, Renderer};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Shape {
|
pub enum Shape {
|
||||||
|
|
@ -59,7 +59,7 @@ impl SimpleObject {
|
||||||
|
|
||||||
impl PartialEq for SimpleObject {
|
impl PartialEq for SimpleObject {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
Rc::ptr_eq(&self.0, &other.0)
|
Rc::ptr_eq(&self.0,&other.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@ struct Block {
|
||||||
velocity: Vec3,
|
velocity: Vec3,
|
||||||
material: u8,
|
material: u8,
|
||||||
interests: FastHashSet<Interest>,
|
interests: FastHashSet<Interest>,
|
||||||
blocks: [Option<Box<Block>>; 64],
|
blocks: [Option<Box<Block>>;64],
|
||||||
}
|
}
|
||||||
|
|
||||||
const TREE_ATTACK: usize = 4;
|
const TREE_ATTACK: usize = 4;
|
||||||
|
|
@ -107,11 +107,11 @@ impl Block {
|
||||||
let index = (rel.x + rel.y * 4 + rel.z * 16) as usize;
|
let index = (rel.x + rel.y * 4 + rel.z * 16) as usize;
|
||||||
match self.blocks[index] {
|
match self.blocks[index] {
|
||||||
Some(ref mut block) => {
|
Some(ref mut block) => {
|
||||||
block.place_pos(interest, new_pos, rad, cs);
|
block.place_pos(interest,new_pos,rad,cs);
|
||||||
}
|
},
|
||||||
None => {
|
None => {
|
||||||
let mut block = Box::new(Block::new());
|
let mut block = Box::new(Block::new());
|
||||||
block.place_pos(interest, new_pos, rad, cs);
|
block.place_pos(interest,new_pos,rad,cs);
|
||||||
self.blocks[index] = Some(block);
|
self.blocks[index] = Some(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -123,26 +123,25 @@ impl Block {
|
||||||
match self.debug {
|
match self.debug {
|
||||||
Some(ref mut debug) => {
|
Some(ref mut debug) => {
|
||||||
if value {
|
if value {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
None => {
|
None => {
|
||||||
if value {
|
if value {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for maybe_block in self.blocks.iter_mut() {
|
|
||||||
if let Some(block) = maybe_block {
|
|
||||||
block.debug_step(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct World {
|
pub struct World {
|
||||||
chunk_size: u32,
|
chunk_size: u32,
|
||||||
map: FastHashMap<IVec3, Block>,
|
map: FastHashMap<IVec3,Block>,
|
||||||
pub renderer: Option<Renderer>,
|
pub renderer: Option<Renderer>,
|
||||||
debug_world_map: bool,
|
debug_world_map: bool,
|
||||||
debug_world_map_object: Option<SimpleObject>,
|
debug_world_map_object: Option<SimpleObject>,
|
||||||
|
|
@ -160,12 +159,7 @@ impl World {
|
||||||
}
|
}
|
||||||
pub fn add_renderer(&mut self, renderer: Renderer) {
|
pub fn add_renderer(&mut self, renderer: Renderer) {
|
||||||
self.renderer = Some(renderer);
|
self.renderer = Some(renderer);
|
||||||
self.debug_world_map_object = self
|
self.debug_world_map_object = self.renderer.as_mut().unwrap().load_from_gltf(include_bytes!("../assets/debug.glb")).first_object()
|
||||||
.renderer
|
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.load_from_gltf(include_bytes!("../assets/cube.glb"))
|
|
||||||
.first_object()
|
|
||||||
}
|
}
|
||||||
pub fn add_object(&mut self, object: SimpleObject) {
|
pub fn add_object(&mut self, object: SimpleObject) {
|
||||||
self.place(Interest::Object(object.clone()));
|
self.place(Interest::Object(object.clone()));
|
||||||
|
|
@ -176,8 +170,12 @@ impl World {
|
||||||
pub fn set_debug(&mut self, value: bool) {
|
pub fn set_debug(&mut self, value: bool) {
|
||||||
self.debug_world_map = value;
|
self.debug_world_map = value;
|
||||||
}
|
}
|
||||||
pub fn light_step(&mut self) {}
|
pub fn light_step(&mut self) {
|
||||||
pub fn object_step(&mut self) {}
|
|
||||||
|
}
|
||||||
|
pub fn object_step(&mut self) {
|
||||||
|
|
||||||
|
}
|
||||||
pub fn debug_step(&mut self) {
|
pub fn debug_step(&mut self) {
|
||||||
self.light_step();
|
self.light_step();
|
||||||
self.object_step();
|
self.object_step();
|
||||||
|
|
@ -191,7 +189,7 @@ impl World {
|
||||||
for x in (pos.x - rad).div(cs) as i32..=(pos.x + rad).div(cs).ceil() as i32 {
|
for x in (pos.x - rad).div(cs) as i32..=(pos.x + rad).div(cs).ceil() as i32 {
|
||||||
for y in (pos.y - rad).div(cs) as i32..=(pos.y + rad).div(cs).ceil() as i32 {
|
for y in (pos.y - rad).div(cs) as i32..=(pos.y + rad).div(cs).ceil() as i32 {
|
||||||
for z in (pos.z - rad).div(cs) as i32..=(pos.z + rad).div(cs).ceil() as i32 {
|
for z in (pos.z - rad).div(cs) as i32..=(pos.z + rad).div(cs).ceil() as i32 {
|
||||||
let block_pos = IVec3::new(x, y, z);
|
let block_pos = IVec3::new(x,y,z);
|
||||||
let block_pos_f32 = block_pos.as_vec3();
|
let block_pos_f32 = block_pos.as_vec3();
|
||||||
if block_pos_f32.distance_squared(pos) < rad + c_rad {
|
if block_pos_f32.distance_squared(pos) < rad + c_rad {
|
||||||
self.map.entry(block_pos).or_insert_with(|| {
|
self.map.entry(block_pos).or_insert_with(|| {
|
||||||
|
|
@ -210,19 +208,16 @@ impl World {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn place(&mut self, interest: Interest) {
|
fn place(&mut self, interest: Interest) {
|
||||||
let (pos, rad) = match &interest {
|
let (pos,rad) = match &interest {
|
||||||
Interest::Light(light) => {
|
Interest::Light(light) => {
|
||||||
let light = light.0.borrow();
|
let light = light.0.borrow();
|
||||||
(light.instance.location.xyz(), light.instance.color.length())
|
(light.instance.location.xyz(),light.instance.color.length())
|
||||||
}
|
},
|
||||||
Interest::Object(object) => {
|
Interest::Object(object) => {
|
||||||
let collider = &object.0.borrow().collider;
|
let collider = &object.0.borrow().collider;
|
||||||
(
|
(collider.transform.to_scale_rotation_translation().2,collider.radius)
|
||||||
collider.transform.to_scale_rotation_translation().2,
|
},
|
||||||
collider.radius,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
self.place_pos(interest, pos, rad);
|
self.place_pos(interest,pos,rad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue