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"
|
||||
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]]
|
||||
name = "combine"
|
||||
version = "4.6.7"
|
||||
|
|
@ -1105,9 +1096,6 @@ checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
|
|||
[[package]]
|
||||
name = "mars"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"colored",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
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;
|
||||
// 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 glam::{Vec2, Affine3A, Vec3, Vec4, Mat4, EulerRot, Quat};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasm_bindgen::prelude::*;
|
||||
use winit::dpi::PhysicalPosition;
|
||||
|
|
@ -16,10 +14,13 @@ use winit::{
|
|||
keyboard::{KeyCode, PhysicalKey},
|
||||
window::Window,
|
||||
};
|
||||
use crate::render;
|
||||
use crate::render::{Renderer, SimpleTexture};
|
||||
use crate::world::{SimpleObject, World};
|
||||
|
||||
struct Controller {
|
||||
buttons: HashMap<MouseButton, bool>,
|
||||
keys: HashMap<KeyCode, bool>,
|
||||
buttons: HashMap<MouseButton,bool>,
|
||||
keys: HashMap<KeyCode,bool>,
|
||||
mouse: Vec2,
|
||||
}
|
||||
|
||||
|
|
@ -28,7 +29,7 @@ impl Controller {
|
|||
Controller {
|
||||
buttons: Default::default(),
|
||||
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>,
|
||||
}
|
||||
|
||||
const BLOCKS: i32 = 1;
|
||||
const BLOCKS: i32 = 50;
|
||||
|
||||
impl AppState {
|
||||
// We don't need this to be async right now,
|
||||
// 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();
|
||||
world.add_renderer(Renderer::new(&window).await?);
|
||||
let mut clients = Vec::new();
|
||||
{
|
||||
let file = world
|
||||
.renderer
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.load_from_gltf(include_bytes!("assets/cube.glb"));
|
||||
let file = world.renderer.as_mut().unwrap().load_from_gltf( include_bytes!("assets/cube.glb"));
|
||||
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 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"));
|
||||
|
|
@ -71,16 +64,9 @@ impl AppState {
|
|||
world.add_object(block.clone());
|
||||
{
|
||||
let mut model = block.0.borrow_mut();
|
||||
model.model.as_mut().unwrap().instance.transform = Mat4::from_translation(
|
||||
Vec3::new(-x as f32 * 3.0, -8.0, -y as f32 * 3.0),
|
||||
)
|
||||
model.model.as_mut().unwrap().instance.transform = Mat4::from_translation(Vec3::new(-x as f32 * 3.0,0.0,-y as f32 * 3.0))
|
||||
* Mat4::from_rotation_z((x * y) as f32 / 1.23);
|
||||
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,
|
||||
);
|
||||
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);
|
||||
}
|
||||
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();
|
||||
(size.width, size.height)
|
||||
(size.width,size.height)
|
||||
}
|
||||
|
||||
pub fn resize(&mut self, width: u32, height: u32) {
|
||||
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) {
|
||||
match (code, is_pressed) {
|
||||
(KeyCode::Escape, true) => event_loop.exit(),
|
||||
(KeyCode::Space, true) => {}
|
||||
(KeyCode::Space, true) => {},
|
||||
(KeyCode::KeyR, true) => {
|
||||
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>) {
|
||||
if let Some(true) = self.controller.buttons.get(&MouseButton::Right) {
|
||||
self.world.renderer.as_mut().unwrap().eye.rotate(
|
||||
position.x as f32 - self.controller.mouse.x,
|
||||
position.y as f32 - self.controller.mouse.y,
|
||||
);
|
||||
self.world.renderer.as_mut().unwrap().eye.rotate(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);
|
||||
}
|
||||
|
||||
fn handle_mouse_button(&mut self, button: MouseButton, state: ElementState) {
|
||||
self.controller.buttons.insert(button, state.is_pressed());
|
||||
fn handle_mouse_button(&mut self, button: MouseButton, state: ElementState ) {
|
||||
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::RedrawRequested => {
|
||||
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| {
|
||||
if let Some(true) = state.controller.keys.get(&keycode) {
|
||||
|
|
@ -261,13 +245,7 @@ impl ApplicationHandler<AppState> for App {
|
|||
movement.y -= 1.0;
|
||||
}
|
||||
|
||||
state
|
||||
.world
|
||||
.renderer
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.eye
|
||||
.control(movement * 0.1);
|
||||
state.world.renderer.as_mut().unwrap().eye.control(movement * 0.1);
|
||||
match state.world.renderer.as_mut().unwrap().render(&state.window) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
|
|
@ -277,24 +255,13 @@ impl ApplicationHandler<AppState> for App {
|
|||
}
|
||||
}
|
||||
for object in state.clients.iter() {
|
||||
object
|
||||
.0
|
||||
.borrow_mut()
|
||||
.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),
|
||||
object.0.borrow_mut().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 {
|
||||
button,
|
||||
state: element,
|
||||
..
|
||||
} => state.handle_mouse_button(button, element),
|
||||
WindowEvent::MouseInput { button, state: element, .. } => state.handle_mouse_button(button,element),
|
||||
WindowEvent::CursorMoved { position: pos, .. } => state.handle_mouse_moved(pos),
|
||||
WindowEvent::KeyboardInput {
|
||||
event:
|
||||
|
|
|
|||
|
|
@ -4,26 +4,16 @@ struct Environment {
|
|||
dir: vec4<f32>,
|
||||
}
|
||||
|
||||
struct Eye {
|
||||
// from camera to screen
|
||||
proj: mat4x4<f32>,
|
||||
// from screen to camera
|
||||
inv: mat4x4<f32>,
|
||||
// world to camera
|
||||
struct View {
|
||||
view: mat4x4<f32>,
|
||||
// camera transform
|
||||
frame: mat4x4<f32>,
|
||||
}
|
||||
|
||||
// Vertex shader
|
||||
@group(0) @binding(0)
|
||||
var<uniform> eye: Eye;
|
||||
var<uniform> view: View;
|
||||
@group(0) @binding(1)
|
||||
var<uniform> environment: Environment;
|
||||
@group(0) @binding(2)
|
||||
var sky_sampler: sampler;
|
||||
@group(0) @binding(3)
|
||||
var sky_texture: texture_2d<f32>;
|
||||
|
||||
struct VertexInput {
|
||||
@location(0) position: vec3<f32>,
|
||||
|
|
@ -70,7 +60,7 @@ fn vs_main(
|
|||
out.world_normal = model_rot_matrix * model.normal;
|
||||
var world_position: vec4<f32> = model_matrix * vec4<f32>(model.position, 1.0);
|
||||
out.world_position = world_position.xyz;
|
||||
out.clip_position = eye.proj * eye.view * world_position;
|
||||
out.clip_position = view.view * world_position;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
@ -85,79 +75,23 @@ var t_normal: texture_2d<f32>;
|
|||
@group(1) @binding(3)
|
||||
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
|
||||
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
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 diffuse_color = object_color.xyz;
|
||||
let specular_color = vec3<f32>(0.0,0.0,0.0);
|
||||
let reflection = sky_aspect(reflect(normalize(in.world_position-translation(eye.frame).xyz),normalize(in.world_normal)));
|
||||
let tangent_normal = object_normal.xyz * 2.0 - 1.0;
|
||||
let light_dir = normalize(environment.dir.xyz);
|
||||
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 view_dir = normalize(eye.frame[3].xyz - in.world_position);
|
||||
//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 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;
|
||||
|
||||
return vec4<f32>(reflection.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);
|
||||
return vec4<f32>(result.xyz,object_color.a);
|
||||
}
|
||||
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 glam::camera::lh::proj::directx::perspective;
|
||||
use env_logger::Env;
|
||||
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::util::DeviceExt;
|
||||
|
||||
pub(crate) struct Eye {
|
||||
pub(crate) frame: Affine3A,
|
||||
|
|
@ -13,66 +13,54 @@ pub(crate) struct Eye {
|
|||
z_far: f32,
|
||||
fov_y: f32,
|
||||
pub(crate) environment_buffer: wgpu::Buffer,
|
||||
pub(crate) camera_buffer: wgpu::Buffer,
|
||||
pub(crate) buffer: wgpu::Buffer,
|
||||
pub(crate) layout: wgpu::BindGroupLayout,
|
||||
pub(crate) group: wgpu::BindGroup,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Pod, Copy, Clone, Zeroable)]
|
||||
pub struct Environment {
|
||||
struct Environment {
|
||||
ambient: Vec4,
|
||||
light: Vec4,
|
||||
dir: Vec4,
|
||||
}
|
||||
|
||||
impl Eye {
|
||||
pub(crate) fn write(&mut self, queue: &Queue) {
|
||||
let camera = Mat4::from_mat3_translation(
|
||||
self.frame.matrix3.into(),
|
||||
Vec3::from(self.frame.translation),
|
||||
);
|
||||
pub(crate) fn view(&self) -> Mat4 {
|
||||
let projection = perspective(self.fov_y, self.aspect_ratio, self.z_near, self.z_far);
|
||||
queue.write_buffer(
|
||||
&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]),
|
||||
);
|
||||
projection * self.frame.inverse()
|
||||
}
|
||||
pub(crate) fn new(device: &Device, width: u32, height: u32, skybox: SimpleTexture) -> Eye {
|
||||
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
pub(crate) fn write(&mut self, queue: &Queue) {
|
||||
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"),
|
||||
contents: bytemuck::cast_slice(&[
|
||||
Mat4::from_translation(Vec3::new(0.0, 2.0, -8.0)),
|
||||
Mat4::IDENTITY,
|
||||
Mat4::IDENTITY,
|
||||
Mat4::IDENTITY,
|
||||
]),
|
||||
contents: bytemuck::cast_slice(&[Mat4::from_translation(Vec3::new(0.0,2.0,-8.0)),Mat4::IDENTITY]),
|
||||
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 {
|
||||
ambient: Vec4::new(0.15, 0.15, 0.15, 0.0),
|
||||
light: Vec4::new(1.0, 1.0, 1.0, 0.0),
|
||||
dir: Vec4::new(dir.x, dir.y, dir.z, 0.0),
|
||||
ambient: Vec4::new(0.15,0.15,0.15, 0.0),
|
||||
light: Vec4::new(1.0,1.0,1.0, 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(""),
|
||||
contents: bytemuck::cast_slice(&[environment]),
|
||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
let layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
|
|
@ -95,28 +83,25 @@ impl Eye {
|
|||
min_binding_size: 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"),
|
||||
});
|
||||
|
||||
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 {
|
||||
aspect_ratio: width as f32 / height as f32,
|
||||
|
|
@ -124,54 +109,13 @@ impl Eye {
|
|||
fov_y: 90.0,
|
||||
z_near: 0.1,
|
||||
z_far: 1000.0,
|
||||
camera_buffer,
|
||||
buffer,
|
||||
group,
|
||||
layout,
|
||||
environment,
|
||||
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) {
|
||||
self.aspect_ratio = width as f32 / height as f32
|
||||
}
|
||||
|
|
@ -179,9 +123,9 @@ impl Eye {
|
|||
self.frame *= Affine3A::from_translation(delta);
|
||||
}
|
||||
pub(crate) fn rotate(&mut self, yaw: f32, pitch: f32) {
|
||||
let (mut y, mut x, z) = self.frame.matrix3.to_euler(EulerRot::YXZ);
|
||||
x = (x + pitch * 0.005).clamp(-1.4, 1.4);
|
||||
let (mut y,mut x,z) = self.frame.matrix3.to_euler(EulerRot::YXZ);
|
||||
x = (x + pitch * 0.005).clamp(-1.4,1.4);
|
||||
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;
|
||||
|
||||
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::collections::HashMap;
|
||||
use glam::prelude::*;
|
||||
use std::collections::{HashMap};
|
||||
use std::error::Error;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::hash::{BuildHasherDefault, Hash, Hasher};
|
||||
use std::ops::Range;
|
||||
use std::ops::{Range};
|
||||
use std::rc::Rc;
|
||||
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::util::DeviceExt;
|
||||
use wgpu::{Device, Queue};
|
||||
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)]
|
||||
#[derive(Pod, Zeroable, Copy, Clone)]
|
||||
#[derive(Pod,Zeroable,Copy,Clone)]
|
||||
pub struct SimpleModelInstance {
|
||||
pub transform: Mat4,
|
||||
pub color: Vec4,
|
||||
pub lights: [u16; 16],
|
||||
pub lights: [u16;16],
|
||||
pub point_lights: u32,
|
||||
pub spot_lights: u32,
|
||||
pub metal: f32,
|
||||
|
|
@ -34,7 +34,7 @@ pub struct SimpleModelInstance {
|
|||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Pod, Copy, Clone, Zeroable)]
|
||||
#[derive(Pod,Copy,Clone,Zeroable)]
|
||||
pub struct SimpleLightInstance {
|
||||
pub location: Vec4,
|
||||
pub rotation: Vec4,
|
||||
|
|
@ -62,15 +62,14 @@ pub struct SimpleInstances {
|
|||
instance_buffer: wgpu::Buffer,
|
||||
//light_ref_last: usize,
|
||||
//light_ref_buffer: wgpu::Buffer,
|
||||
objects:
|
||||
FastHashMap<Id<SimpleMesh>, FastHashMap<Id<SimpleMaterial>, FastHashSet<SimpleObject>>>,
|
||||
lights: FastHashMap<SimpleLight, usize>,
|
||||
objects: FastHashMap<Id<SimpleMesh>,FastHashMap<Id<SimpleMaterial>,FastHashSet<SimpleObject>>>,
|
||||
lights: FastHashMap<SimpleLight,usize>,
|
||||
}
|
||||
|
||||
enum SimpleRenderCode {
|
||||
Material(wgpu::BindGroup),
|
||||
Mesh((wgpu::Buffer, u32), Option<(wgpu::Buffer, u32)>),
|
||||
Draw(Range<u32>),
|
||||
Mesh((wgpu::Buffer,u32),Option<(wgpu::Buffer,u32)>),
|
||||
Draw(Range<u32>)
|
||||
}
|
||||
|
||||
struct SimpleRenderProgram(Vec<SimpleRenderCode>);
|
||||
|
|
@ -87,15 +86,13 @@ impl SimpleRenderProgram {
|
|||
let mut indexed = false;
|
||||
for code in self.0 {
|
||||
match code {
|
||||
SimpleRenderCode::Material(material) => pass.set_bind_group(
|
||||
Renderer::SIMPLE_RENDER_TEXTURE_GROUP_POSITION,
|
||||
&material,
|
||||
&[],
|
||||
),
|
||||
SimpleRenderCode::Mesh(vertices, indices) => {
|
||||
SimpleRenderCode::Material(material) => {
|
||||
pass.set_bind_group(Renderer::SIMPLE_RENDER_TEXTURE_GROUP_POSITION,&material,&[])
|
||||
}
|
||||
SimpleRenderCode::Mesh(vertices,indices) => {
|
||||
pass.set_vertex_buffer(0, vertices.0.slice(..));
|
||||
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;
|
||||
indexed = true;
|
||||
} else {
|
||||
|
|
@ -121,10 +118,8 @@ impl SimpleInstances {
|
|||
if let Some(ref model) = object.0.borrow().model {
|
||||
self.instance_count += 1;
|
||||
self.objects
|
||||
.entry(model.mesh.clone())
|
||||
.or_insert(FastHashMap::with_hasher(BuildHasherDefault::new()))
|
||||
.entry(model.material.clone())
|
||||
.or_insert(FastHashSet::with_hasher(BuildHasherDefault::new()))
|
||||
.entry(model.mesh.clone()).or_insert(FastHashMap::with_hasher(BuildHasherDefault::new()))
|
||||
.entry(model.material.clone()).or_insert(FastHashSet::with_hasher(BuildHasherDefault::new()))
|
||||
.insert(object.clone());
|
||||
}
|
||||
}
|
||||
|
|
@ -133,17 +128,15 @@ impl SimpleInstances {
|
|||
if let Some(ref model) = object.0.borrow().model {
|
||||
self.instance_count -= 1;
|
||||
self.objects
|
||||
.entry(model.mesh.clone())
|
||||
.or_insert(FastHashMap::with_hasher(BuildHasherDefault::new()))
|
||||
.entry(model.material.clone())
|
||||
.or_insert(FastHashSet::with_hasher(BuildHasherDefault::new()))
|
||||
.entry(model.mesh.clone()).or_insert(FastHashMap::with_hasher(BuildHasherDefault::new()))
|
||||
.entry(model.material.clone()).or_insert(FastHashSet::with_hasher(BuildHasherDefault::new()))
|
||||
.remove(&object);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_light(&mut self, light: SimpleLight) {
|
||||
self.light_count += 1;
|
||||
self.lights.insert(light, 0);
|
||||
self.lights.insert(light,0);
|
||||
}
|
||||
|
||||
pub fn remove_light(&mut self, light: &SimpleLight) {
|
||||
|
|
@ -151,12 +144,7 @@ impl SimpleInstances {
|
|||
self.lights.remove(light);
|
||||
}
|
||||
|
||||
pub fn reallocate_buffer(
|
||||
device: &wgpu::Device,
|
||||
buffer: &mut wgpu::Buffer,
|
||||
count: usize,
|
||||
item_size: usize,
|
||||
) {
|
||||
pub fn reallocate_buffer(device: &wgpu::Device, queue: &wgpu::Queue, buffer: &mut wgpu::Buffer, count: usize, item_size: usize) {
|
||||
let size = buffer.size() / item_size as wgpu::BufferAddress;
|
||||
if count > SimpleInstances::MIN_SIZE as usize {
|
||||
let mut reallocate: Option<usize> = None;
|
||||
|
|
@ -184,82 +172,51 @@ impl SimpleInstances {
|
|||
wgpu::BufferSize::new(self.instance_buffer.size()).unwrap()
|
||||
).unwrap();
|
||||
*/
|
||||
SimpleInstances::reallocate_buffer(
|
||||
device,
|
||||
&mut self.light_buffer,
|
||||
self.light_count,
|
||||
size_of::<SimpleLight>(),
|
||||
);
|
||||
let mut buffer = queue
|
||||
.write_buffer_with(
|
||||
SimpleInstances::reallocate_buffer(device, queue, &mut self.light_buffer, self.light_count, size_of::<SimpleLight>());
|
||||
let mut buffer = queue.write_buffer_with(
|
||||
&self.light_buffer,
|
||||
0 as wgpu::BufferAddress,
|
||||
wgpu::BufferSize::new(self.light_buffer.size()).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
).unwrap();
|
||||
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;
|
||||
let begin = *index * stride;
|
||||
buffer
|
||||
.slice(begin..begin + stride)
|
||||
.copy_from_slice(bytemuck::cast_slice(&[light.0.borrow().instance]));
|
||||
buffer.slice(begin..begin + stride).copy_from_slice(bytemuck::cast_slice(&[light.0.borrow().instance]));
|
||||
}
|
||||
}
|
||||
fn write_instances(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
) -> SimpleRenderProgram {
|
||||
pub fn write_instances(&mut self, device: &wgpu::Device, queue: &wgpu::Queue) -> SimpleRenderProgram {
|
||||
let mut program = SimpleRenderProgram::new();
|
||||
SimpleInstances::reallocate_buffer(
|
||||
device,
|
||||
&mut self.instance_buffer,
|
||||
self.instance_count,
|
||||
size_of::<SimpleModelInstance>(),
|
||||
);
|
||||
let mut buffer = queue
|
||||
.write_buffer_with(
|
||||
SimpleInstances::reallocate_buffer(device, queue, &mut self.instance_buffer, self.instance_count, size_of::<SimpleModelInstance>());
|
||||
let mut buffer = queue.write_buffer_with(
|
||||
&self.instance_buffer,
|
||||
0 as wgpu::BufferAddress,
|
||||
wgpu::BufferSize::new(self.instance_buffer.size()).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
wgpu::BufferSize::new(self.instance_buffer.size()).unwrap()
|
||||
).unwrap();
|
||||
let mut index: u32 = 0;
|
||||
let stride = size_of::<SimpleModelInstance>();
|
||||
for (mesh, materials) in self.objects.iter() {
|
||||
program.push(SimpleRenderCode::Mesh(
|
||||
mesh.it.vertices.clone(),
|
||||
mesh.it.indices.clone(),
|
||||
));
|
||||
for (mesh,materials) in self.objects.iter() {
|
||||
program.push(SimpleRenderCode::Mesh(mesh.it.vertices.clone(), mesh.it.indices.clone()));
|
||||
for (material, objects) in materials.iter() {
|
||||
program.push(SimpleRenderCode::Material(material.it.group.clone()));
|
||||
let before = index;
|
||||
for object in objects.iter() {
|
||||
let begin = index as usize * stride;
|
||||
buffer
|
||||
.slice(begin..begin + stride)
|
||||
.copy_from_slice(bytemuck::cast_slice(&[object
|
||||
.0
|
||||
.borrow()
|
||||
.model
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.instance]));
|
||||
buffer.slice(begin .. begin + stride).copy_from_slice(bytemuck::cast_slice(&[object.0.borrow().model.as_ref().unwrap().instance]));
|
||||
index += 1;
|
||||
}
|
||||
program.push(SimpleRenderCode::Draw(Range::from(before..index)));
|
||||
}
|
||||
}
|
||||
};
|
||||
program
|
||||
}
|
||||
|
||||
fn desc() -> wgpu::VertexBufferLayout<'static> {
|
||||
use std::mem;
|
||||
wgpu::VertexBufferLayout {
|
||||
array_stride: size_of::<SimpleModelInstance>() as wgpu::BufferAddress,
|
||||
step_mode: wgpu::VertexStepMode::Instance,
|
||||
attributes: &[
|
||||
// todo: is this too big?
|
||||
attributes: &[ // todo: is this too big?
|
||||
wgpu::VertexAttribute {
|
||||
offset: 0,
|
||||
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 {
|
||||
label: Some("Instance Buffer"),
|
||||
size: (size_of::<SimpleModelInstance>() * SimpleInstances::MIN_SIZE as usize)
|
||||
as wgpu::BufferAddress,
|
||||
size: (size_of::<SimpleModelInstance>() * SimpleInstances::MIN_SIZE as usize) as wgpu::BufferAddress,
|
||||
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
let light_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("Light Buffer"),
|
||||
size: (size_of::<SimpleLightInstance>() * SimpleInstances::MIN_SIZE as usize)
|
||||
as wgpu::BufferAddress,
|
||||
size: (size_of::<SimpleLightInstance>() * SimpleInstances::MIN_SIZE as usize) as wgpu::BufferAddress,
|
||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||
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"),
|
||||
size: (size_of::<u32>() * SimpleInstances::MIN_SIZE as usize) as wgpu::BufferAddress,
|
||||
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});*/
|
||||
mapped_at_creation: false
|
||||
});
|
||||
SimpleInstances {
|
||||
light_count: 0,
|
||||
//light_ref_last: 0,
|
||||
|
|
@ -347,9 +302,7 @@ pub struct Renderer {
|
|||
pub(crate) eye: eye::Eye,
|
||||
material_layout: wgpu::BindGroupLayout,
|
||||
default_texture: SimpleTexture,
|
||||
default_material: SimpleMaterial,
|
||||
sky_pipeline: wgpu::RenderPipeline,
|
||||
instance_pipeline: wgpu::RenderPipeline,
|
||||
pipeline: wgpu::RenderPipeline,
|
||||
depth_texture: SimpleTexture,
|
||||
pub(crate) instances: SimpleInstances,
|
||||
}
|
||||
|
|
@ -384,39 +337,34 @@ impl SimpleVertex {
|
|||
offset: size_of::<[f32; 6]>() as wgpu::BufferAddress,
|
||||
shader_location: 2,
|
||||
format: wgpu::VertexFormat::Float32x2,
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct SimpleMesh {
|
||||
indices: Option<(wgpu::Buffer, u32)>,
|
||||
indices: Option<(wgpu::Buffer,u32)>,
|
||||
vertices: (wgpu::Buffer, u32),
|
||||
}
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
pub struct SimpleTexture {
|
||||
pub(crate) struct SimpleTexture {
|
||||
texture: wgpu::Texture,
|
||||
view: wgpu::TextureView,
|
||||
}
|
||||
pub struct TextureProperties {
|
||||
struct TextureProperties {
|
||||
width: u32,
|
||||
height: u32,
|
||||
}
|
||||
// todo: use texture compression!
|
||||
impl SimpleTexture {
|
||||
pub fn load(
|
||||
device: &Device,
|
||||
queue: &Queue,
|
||||
slice: impl AsRef<[u8]>,
|
||||
properties: TextureProperties,
|
||||
) -> SimpleTexture {
|
||||
pub fn load(device: &Device, queue: &Queue, slice: impl AsRef<[u8]>, properties: TextureProperties) -> SimpleTexture {
|
||||
let size = wgpu::Extent3d {
|
||||
width: properties.width,
|
||||
height: properties.height,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
let diffuse_texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
let diffuse_texture = device.create_texture(
|
||||
&wgpu::TextureDescriptor {
|
||||
size,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
|
|
@ -425,9 +373,9 @@ impl SimpleTexture {
|
|||
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
||||
label: Some("texture"),
|
||||
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(
|
||||
wgpu::TexelCopyTextureInfo {
|
||||
texture: &diffuse_texture,
|
||||
|
|
@ -480,41 +428,20 @@ struct MaterialProperties {
|
|||
filter: wgpu::FilterMode,
|
||||
}
|
||||
|
||||
impl Default for MaterialProperties {
|
||||
fn default() -> MaterialProperties {
|
||||
MaterialProperties {
|
||||
edge: wgpu::AddressMode::Repeat,
|
||||
filter: wgpu::FilterMode::Linear,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
impl SimpleMaterial {
|
||||
fn new(renderer: &Renderer, base: &SimpleTexture, normal: &SimpleTexture, reflect: &SimpleTexture, config: MaterialProperties) -> SimpleMaterial {
|
||||
let sampler = renderer.device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
address_mode_u: config.edge,
|
||||
address_mode_v: config.edge,
|
||||
address_mode_w: config.edge,
|
||||
mag_filter: config.filter,
|
||||
min_filter: config.filter,
|
||||
mipmap_filter: wgpu::MipmapFilterMode::Nearest,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
});
|
||||
let group = renderer.device.create_bind_group(
|
||||
&wgpu::BindGroupDescriptor {
|
||||
layout: &renderer.material_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
|
|
@ -534,8 +461,11 @@ impl SimpleMaterial {
|
|||
},
|
||||
],
|
||||
label: Some("diffuse_bind_group"),
|
||||
});
|
||||
SimpleMaterial { group }
|
||||
}
|
||||
);
|
||||
SimpleMaterial {
|
||||
group,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -544,7 +474,7 @@ struct PoolError(String);
|
|||
|
||||
impl Display for PoolError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
write!(f,"{}",self.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -563,7 +493,7 @@ impl SimpleTreeNode {
|
|||
} else {
|
||||
for child in self.children.iter() {
|
||||
if let Some(object) = child.first_object() {
|
||||
return Some(object);
|
||||
return Some(object)
|
||||
}
|
||||
}
|
||||
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 {
|
||||
const SIMPLE_RENDER_EYE_GROUP_POSITION: u32 = 0;
|
||||
|
|
@ -584,55 +514,25 @@ impl Renderer {
|
|||
id: self.id_count,
|
||||
}
|
||||
}
|
||||
pub fn load_texture_from_bytes(
|
||||
&mut self,
|
||||
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())
|
||||
};
|
||||
pub fn load_texture_from_bytes(&mut self, slice: impl AsRef<[u8]>) -> SimpleTexture {
|
||||
let image = image::load_from_memory(slice.as_ref());
|
||||
if let Ok(data) = image {
|
||||
let data = data.into_rgba8();
|
||||
SimpleTexture::load(
|
||||
&self.device,
|
||||
&self.queue,
|
||||
data.as_bytes(),
|
||||
TextureProperties {
|
||||
SimpleTexture::load(&self.device, &self.queue, data.as_bytes(), TextureProperties {
|
||||
width: data.width(),
|
||||
height: data.height(),
|
||||
},
|
||||
)
|
||||
})
|
||||
} else {
|
||||
println!("failed to load texture! error: {:?}", image.unwrap_err());
|
||||
self.default_texture.clone()
|
||||
}
|
||||
}
|
||||
pub fn new_material(
|
||||
&mut self,
|
||||
base: &SimpleTexture,
|
||||
normal: &SimpleTexture,
|
||||
reflect: &SimpleTexture,
|
||||
) -> Id<SimpleMaterial> {
|
||||
self.new_id(SimpleMaterial::new(
|
||||
&self.device,
|
||||
&self.material_layout,
|
||||
base,
|
||||
normal,
|
||||
reflect,
|
||||
MaterialProperties {
|
||||
pub fn new_material(&mut self, base: &SimpleTexture, normal: &SimpleTexture, reflect: &SimpleTexture) -> Id<SimpleMaterial> {
|
||||
self.new_id(SimpleMaterial::new(self, base, normal, reflect, MaterialProperties {
|
||||
edge: wgpu::AddressMode::Repeat,
|
||||
filter: wgpu::FilterMode::Linear,
|
||||
},
|
||||
))
|
||||
}))
|
||||
}
|
||||
pub fn new_texture_from_gltf(
|
||||
&mut self,
|
||||
info: &gltf::texture::Texture,
|
||||
images: &Vec<gltf::image::Data>,
|
||||
) -> SimpleTexture {
|
||||
pub fn new_texture_from_gltf(&mut self, info: &gltf::texture::Texture, images: &Vec<gltf::image::Data>) -> SimpleTexture {
|
||||
if let Some(image) = images.get(info.source().index()) {
|
||||
let mut new_pixels = Vec::new();
|
||||
let pixels: &Vec<u8>;
|
||||
|
|
@ -646,18 +546,15 @@ impl Renderer {
|
|||
}
|
||||
pixels = &new_pixels;
|
||||
}
|
||||
gltf::image::Format::R8G8B8A8 => pixels = &image.pixels,
|
||||
_ => return self.default_texture.clone(),
|
||||
gltf::image::Format::R8G8B8A8 => {
|
||||
pixels = &image.pixels
|
||||
}
|
||||
SimpleTexture::load(
|
||||
&self.device,
|
||||
&self.queue,
|
||||
pixels.as_slice(),
|
||||
TextureProperties {
|
||||
_ => return self.default_texture.clone()
|
||||
}
|
||||
SimpleTexture::load(&self.device, &self.queue, pixels.as_slice(), TextureProperties {
|
||||
width: image.width,
|
||||
height: image.height,
|
||||
},
|
||||
)
|
||||
})
|
||||
} else {
|
||||
self.default_texture.clone()
|
||||
}
|
||||
|
|
@ -666,47 +563,22 @@ impl Renderer {
|
|||
&mut self,
|
||||
primitive: gltf::Primitive,
|
||||
meshes: &mut HashMap<GltfVertexBufferKey, SimpleMesh>,
|
||||
buffers: &[gltf::buffer::Data],
|
||||
buffers: &[gltf::buffer::Data]
|
||||
) -> Id<SimpleMesh> {
|
||||
let position_index = primitive
|
||||
.get(&Semantic::Positions)
|
||||
.and_then(|it| it.view())
|
||||
.and_then(|it| Some(it.buffer().index()));
|
||||
let normals_index = primitive
|
||||
.get(&Semantic::Normals)
|
||||
.and_then(|it| it.view())
|
||||
.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 position_index = primitive.get(&Semantic::Positions).and_then(|it| it.view()).and_then(|it| Some(it.buffer().index()));
|
||||
let normals_index = primitive.get(&Semantic::Normals).and_then(|it| it.view()).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 reader = primitive.reader(|buffer| Some(&buffers[buffer.index()]));
|
||||
let mut vertex_data: Vec<SimpleVertex>;
|
||||
if let Some(positions) = reader.read_positions() {
|
||||
vertex_data = Vec::with_capacity(positions.len());
|
||||
let mut normal = reader.read_normals().map(|it| it.into_iter());
|
||||
let mut tex_coord = reader
|
||||
.read_tex_coords(0)
|
||||
.map(|it| it.into_f32().into_iter());
|
||||
let mut tex_coord = reader.read_tex_coords(0).map(|it| it.into_f32().into_iter());
|
||||
let mut tangent = reader.read_tangents().map(|it| it.into_iter());
|
||||
tangents = tangent.is_some();
|
||||
for position in positions {
|
||||
|
|
@ -716,53 +588,46 @@ impl Renderer {
|
|||
if let Some(normal) = normals.next() {
|
||||
normal
|
||||
} else {
|
||||
[0.0; 3]
|
||||
[0.0;3]
|
||||
}
|
||||
} else {
|
||||
[0.0; 3]
|
||||
[0.0;3]
|
||||
},
|
||||
tex_coord: if let Some(ref mut tex_coords) = tex_coord {
|
||||
tex_coords.next()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.unwrap_or([0.0; 2]),
|
||||
tangent: [0.0; 3], // todo: tangent from model
|
||||
bitangent: [0.0; 3],
|
||||
}.unwrap_or([0.0;2]),
|
||||
tangent: [0.0;3], // todo: tangent from model
|
||||
bitangent: [0.0;3],
|
||||
})
|
||||
}
|
||||
} else {
|
||||
vertex_data = Vec::new();
|
||||
}
|
||||
let vertex_buffer =
|
||||
self.device
|
||||
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
let vertex_buffer = self.device.create_buffer_init(
|
||||
&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Vertex Buffer"),
|
||||
contents: bytemuck::cast_slice(vertex_data.as_slice()),
|
||||
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 index_data: Vec<u32> = indices.into_u32().collect();
|
||||
Some((
|
||||
self.device
|
||||
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
Some((self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Index Buffer"),
|
||||
contents: bytemuck::cast_slice(index_data.as_slice()),
|
||||
usage: wgpu::BufferUsages::INDEX,
|
||||
}),
|
||||
index_data.len() as u32,
|
||||
))
|
||||
}), index_data.len() as u32))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
SimpleMesh {
|
||||
indices: indices_result,
|
||||
vertices: vertices_result,
|
||||
vertices: vertices_result
|
||||
}
|
||||
})
|
||||
.clone(),
|
||||
)
|
||||
}).clone())
|
||||
}
|
||||
pub fn load_node_from_gltf(
|
||||
&mut self,
|
||||
|
|
@ -775,7 +640,7 @@ impl Renderer {
|
|||
let mut tree_node = SimpleTreeNode {
|
||||
object: None,
|
||||
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() {
|
||||
let len = mesh.primitives().len();
|
||||
|
|
@ -787,34 +652,25 @@ impl Renderer {
|
|||
let rough = pbr.roughness_factor();
|
||||
let light = primitive.material().emissive_factor();
|
||||
let base = match pbr.base_color_texture() {
|
||||
Some(info) => textures
|
||||
.entry(info.texture().source().index())
|
||||
.or_insert_with(|| self.new_texture_from_gltf(&info.texture(), &images))
|
||||
.clone(),
|
||||
None => self.default_texture.clone(),
|
||||
Some(info) => textures.entry(info.texture().source().index()).or_insert_with(|| self.new_texture_from_gltf(&info.texture(), &images)).clone(),
|
||||
None => self.default_texture.clone()
|
||||
};
|
||||
let reflect = match pbr.metallic_roughness_texture() {
|
||||
Some(info) => textures
|
||||
.entry(info.texture().source().index())
|
||||
.or_insert_with(|| self.new_texture_from_gltf(&info.texture(), &images))
|
||||
.clone(),
|
||||
None => self.default_texture.clone(),
|
||||
Some(info) => textures.entry(info.texture().source().index()).or_insert_with(|| self.new_texture_from_gltf(&info.texture(), &images)).clone(),
|
||||
None => self.default_texture.clone()
|
||||
};
|
||||
let normal = match material.normal_texture() {
|
||||
Some(info) => textures
|
||||
.entry(info.texture().source().index())
|
||||
.or_insert_with(|| self.new_texture_from_gltf(&info.texture(), &images))
|
||||
.clone(),
|
||||
None => self.default_texture.clone(),
|
||||
Some(info) => textures.entry(info.texture().source().index()).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 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 {
|
||||
model: Some(SimpleModelData {
|
||||
instance: SimpleModelInstance {
|
||||
transform: Mat4::default(),
|
||||
color: Vec4::from_array(color),
|
||||
lights: [0; 16],
|
||||
lights: [0;16],
|
||||
point_lights: 0,
|
||||
spot_lights: 0,
|
||||
metal,
|
||||
|
|
@ -835,15 +691,13 @@ impl Renderer {
|
|||
tree_node.children.push(SimpleTreeNode {
|
||||
object: Some(object),
|
||||
children: Vec::new(),
|
||||
name: "Primitive".to_string(),
|
||||
name: "Primitive".to_string()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
for node in node.children() {
|
||||
tree_node
|
||||
.children
|
||||
.push(self.load_node_from_gltf(node, meshes, textures, images, buffers));
|
||||
tree_node.children.push(self.load_node_from_gltf(node,meshes,textures,images,buffers));
|
||||
}
|
||||
tree_node
|
||||
}
|
||||
|
|
@ -863,13 +717,7 @@ impl Renderer {
|
|||
name: scene.name().unwrap_or("Scene").to_string(),
|
||||
};
|
||||
for node in scene.nodes() {
|
||||
scene_node.children.push(self.load_node_from_gltf(
|
||||
node,
|
||||
&mut meshes,
|
||||
&mut textures,
|
||||
&images,
|
||||
&buffers,
|
||||
));
|
||||
scene_node.children.push(self.load_node_from_gltf(node, &mut meshes, &mut textures, &images, &buffers));
|
||||
}
|
||||
root.children.push(scene_node)
|
||||
}
|
||||
|
|
@ -880,9 +728,6 @@ impl Renderer {
|
|||
self.surface.configure(&self.device, &self.config);
|
||||
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> {
|
||||
let bounds = window.inner_size();
|
||||
let width = bounds.width;
|
||||
|
|
@ -948,22 +793,16 @@ impl Renderer {
|
|||
desired_maximum_frame_latency: 2,
|
||||
};
|
||||
|
||||
let shader =
|
||||
device.create_shader_module(wgpu::include_wgsl!("../assets/SimpleShader.wgsl"));
|
||||
let eye = Eye::new(&device, width, height);
|
||||
|
||||
let default_texture = SimpleTexture::load(
|
||||
&device,
|
||||
&queue,
|
||||
[0, 0, 255, 255],
|
||||
TextureProperties {
|
||||
let shader = device.create_shader_module(wgpu::include_wgsl!("../assets/SimpleShader.wgsl"));
|
||||
|
||||
let texture = SimpleTexture::load(&device, &queue, [255,255,255,255], TextureProperties {
|
||||
width: 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: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
|
|
@ -1000,24 +839,30 @@ impl Renderer {
|
|||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
}
|
||||
],
|
||||
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"),
|
||||
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,
|
||||
});
|
||||
|
||||
let instance_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("Render Pipeline"),
|
||||
layout: Some(&pipeline_layout),
|
||||
layout: Some(&render_pipeline_layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module: &shader,
|
||||
entry_point: Some("vs_main"),
|
||||
buffers: &[SimpleVertex::desc(), SimpleInstances::desc()],
|
||||
buffers: &[
|
||||
SimpleVertex::desc(),SimpleInstances::desc(),
|
||||
],
|
||||
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
|
|
@ -1032,7 +877,7 @@ impl Renderer {
|
|||
})],
|
||||
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||
}),
|
||||
primitive: Default::default(), /*wgpu::PrimitiveState {
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
strip_index_format: None,
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
|
|
@ -1040,12 +885,12 @@ impl Renderer {
|
|||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
unclipped_depth: false,
|
||||
conservative: false,
|
||||
}*/
|
||||
},
|
||||
depth_stencil: Some(wgpu::DepthStencilState {
|
||||
stencil: wgpu::StencilState::default(),
|
||||
format: wgpu::TextureFormat::Depth32Float,
|
||||
depth_write_enabled: Some(true),
|
||||
depth_compare: Some(wgpu::CompareFunction::Less),
|
||||
stencil: wgpu::StencilState::default(),
|
||||
bias: wgpu::DepthBiasState::default(),
|
||||
}),
|
||||
multisample: wgpu::MultisampleState {
|
||||
|
|
@ -1057,45 +902,7 @@ impl Renderer {
|
|||
cache: None,
|
||||
});
|
||||
|
||||
//todo: use a pipeline cache!
|
||||
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.
|
||||
let size = wgpu::Extent3d { // 2.
|
||||
width: config.width.max(1),
|
||||
height: config.height.max(1),
|
||||
depth_or_array_layers: 1,
|
||||
|
|
@ -1113,8 +920,8 @@ impl Renderer {
|
|||
};
|
||||
let depth_texture = device.create_texture(&desc);
|
||||
let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
let depth_sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
// 4.
|
||||
let depth_sampler = device.create_sampler(
|
||||
&wgpu::SamplerDescriptor { // 4.
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
|
|
@ -1125,37 +932,31 @@ impl Renderer {
|
|||
lod_min_clamp: 0.0,
|
||||
lod_max_clamp: 100.0,
|
||||
..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"),
|
||||
contents: bytemuck::cast_slice(&DEFAULT_VERTICES),
|
||||
usage: wgpu::BufferUsages::VERTEX,
|
||||
});
|
||||
|
||||
let default_material = SimpleMaterial::new(
|
||||
&device,
|
||||
&texture_bind_group_layout,
|
||||
&default_texture,
|
||||
&default_texture,
|
||||
&default_texture,
|
||||
MaterialProperties::default(),
|
||||
}
|
||||
);
|
||||
|
||||
Ok(Renderer {
|
||||
id_count: 0,
|
||||
material_layout: texture_bind_group_layout,
|
||||
default_texture,
|
||||
default_material,
|
||||
default_texture: texture,
|
||||
depth_texture: SimpleTexture {
|
||||
texture: depth_texture,
|
||||
view: depth_view,
|
||||
},
|
||||
instances,
|
||||
sky_pipeline,
|
||||
instance_pipeline,
|
||||
pipeline,
|
||||
surface,
|
||||
config,
|
||||
device,
|
||||
|
|
@ -1165,6 +966,7 @@ impl Renderer {
|
|||
}
|
||||
pub(crate) fn render(&mut self, window: &Arc<Window>) -> anyhow::Result<()> {
|
||||
window.request_redraw();
|
||||
|
||||
let output = match self.surface.get_current_texture() {
|
||||
wgpu::CurrentSurfaceTexture::Success(surface_texture) => surface_texture,
|
||||
wgpu::CurrentSurfaceTexture::Suboptimal(surface_texture) => {
|
||||
|
|
@ -1191,7 +993,7 @@ impl Renderer {
|
|||
.texture
|
||||
.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
|
||||
.device
|
||||
|
|
@ -1207,12 +1009,7 @@ impl Renderer {
|
|||
resolve_target: None,
|
||||
depth_slice: None,
|
||||
ops: wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(wgpu::Color {
|
||||
r: 0.5,
|
||||
g: 0.6,
|
||||
b: 0.8,
|
||||
a: 1.0,
|
||||
}),
|
||||
load: wgpu::LoadOp::Clear(Default::default()),
|
||||
store: wgpu::StoreOp::Store,
|
||||
},
|
||||
})],
|
||||
|
|
@ -1229,15 +1026,10 @@ impl Renderer {
|
|||
multiview_mask: None,
|
||||
});
|
||||
|
||||
pass.set_pipeline(&self.instance_pipeline);
|
||||
pass.set_pipeline(&self.pipeline);
|
||||
pass.set_bind_group(0, &self.eye.group, &[]);
|
||||
pass.set_vertex_buffer(1, self.instances.instance_buffer.slice(..));
|
||||
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()));
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use crate::render::{Renderer, SimpleLightData, SimpleModelData};
|
||||
use glam::{DVec3, IVec3, Mat4, UVec3, Vec3, Vec4Swizzles};
|
||||
use std::cell::RefCell;
|
||||
use std::hash::{BuildHasherDefault, Hash, Hasher};
|
||||
use std::ops::{Div, Mul};
|
||||
use std::rc::Rc;
|
||||
use glam::{DVec3, IVec3, Mat4, UVec3, Vec3, Vec4Swizzles};
|
||||
use wgpu::naga::{FastHashMap, FastHashSet};
|
||||
use crate::render::{SimpleModelData, SimpleLightData, Renderer};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Shape {
|
||||
|
|
@ -59,7 +59,7 @@ impl SimpleObject {
|
|||
|
||||
impl PartialEq for SimpleObject {
|
||||
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,
|
||||
material: u8,
|
||||
interests: FastHashSet<Interest>,
|
||||
blocks: [Option<Box<Block>>; 64],
|
||||
blocks: [Option<Box<Block>>;64],
|
||||
}
|
||||
|
||||
const TREE_ATTACK: usize = 4;
|
||||
|
|
@ -107,11 +107,11 @@ impl Block {
|
|||
let index = (rel.x + rel.y * 4 + rel.z * 16) as usize;
|
||||
match self.blocks[index] {
|
||||
Some(ref mut block) => {
|
||||
block.place_pos(interest, new_pos, rad, cs);
|
||||
}
|
||||
block.place_pos(interest,new_pos,rad,cs);
|
||||
},
|
||||
None => {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -123,26 +123,25 @@ impl Block {
|
|||
match self.debug {
|
||||
Some(ref mut debug) => {
|
||||
if value {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
if value {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
for maybe_block in self.blocks.iter_mut() {
|
||||
if let Some(block) = maybe_block {
|
||||
block.debug_step(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct World {
|
||||
chunk_size: u32,
|
||||
map: FastHashMap<IVec3, Block>,
|
||||
map: FastHashMap<IVec3,Block>,
|
||||
pub renderer: Option<Renderer>,
|
||||
debug_world_map: bool,
|
||||
debug_world_map_object: Option<SimpleObject>,
|
||||
|
|
@ -160,12 +159,7 @@ impl World {
|
|||
}
|
||||
pub fn add_renderer(&mut self, renderer: Renderer) {
|
||||
self.renderer = Some(renderer);
|
||||
self.debug_world_map_object = self
|
||||
.renderer
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.load_from_gltf(include_bytes!("../assets/cube.glb"))
|
||||
.first_object()
|
||||
self.debug_world_map_object = self.renderer.as_mut().unwrap().load_from_gltf(include_bytes!("../assets/debug.glb")).first_object()
|
||||
}
|
||||
pub fn add_object(&mut self, object: SimpleObject) {
|
||||
self.place(Interest::Object(object.clone()));
|
||||
|
|
@ -176,8 +170,12 @@ impl World {
|
|||
pub fn set_debug(&mut self, value: bool) {
|
||||
self.debug_world_map = value;
|
||||
}
|
||||
pub fn light_step(&mut self) {}
|
||||
pub fn object_step(&mut self) {}
|
||||
pub fn light_step(&mut self) {
|
||||
|
||||
}
|
||||
pub fn object_step(&mut self) {
|
||||
|
||||
}
|
||||
pub fn debug_step(&mut self) {
|
||||
self.light_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 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 {
|
||||
let block_pos = IVec3::new(x, y, z);
|
||||
let block_pos = IVec3::new(x,y,z);
|
||||
let block_pos_f32 = block_pos.as_vec3();
|
||||
if block_pos_f32.distance_squared(pos) < rad + c_rad {
|
||||
self.map.entry(block_pos).or_insert_with(|| {
|
||||
|
|
@ -210,19 +208,16 @@ impl World {
|
|||
}
|
||||
}
|
||||
fn place(&mut self, interest: Interest) {
|
||||
let (pos, rad) = match &interest {
|
||||
let (pos,rad) = match &interest {
|
||||
Interest::Light(light) => {
|
||||
let light = light.0.borrow();
|
||||
(light.instance.location.xyz(), light.instance.color.length())
|
||||
}
|
||||
(light.instance.location.xyz(),light.instance.color.length())
|
||||
},
|
||||
Interest::Object(object) => {
|
||||
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