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:
Christian Lincoln 2026-09-03 22:55:16 +01:00
parent 3231ed9190
commit 6685277e29
10 changed files with 1438 additions and 1818 deletions

12
Cargo.lock generated
View file

@ -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

Binary file not shown.

View file

@ -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,6 +14,9 @@ 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>,
@ -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>> {
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)
}
@ -101,6 +87,7 @@ impl AppState {
pub fn resize(&mut self, width: u32, height: u32) {
if width > 0 && height > 0 {
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,10 +110,7 @@ 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);
}
@ -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(
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),
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:

View file

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

View file

@ -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,53 +13,39 @@ 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 environment = Environment {
@ -68,11 +54,13 @@ impl Eye {
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
}

View file

@ -1,23 +1,23 @@
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] = [];
@ -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>>>,
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>),
Draw(Range<u32>)
}
struct SimpleRenderProgram(Vec<SimpleRenderCode>);
@ -87,11 +86,9 @@ 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::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 {
@ -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,10 +128,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()))
.remove(&object);
}
}
@ -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() {
*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(),
));
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,8 +337,8 @@ impl SimpleVertex {
offset: size_of::<[f32; 6]>() as wgpu::BufferAddress,
shader_location: 2,
format: wgpu::VertexFormat::Float32x2,
},
],
}
]
}
}
}
@ -395,28 +348,23 @@ pub struct SimpleMesh {
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,
}
}
}
@ -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
@ -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 {
@ -725,8 +597,7 @@ impl Renderer {
tex_coords.next()
} else {
None
}
.unwrap_or([0.0; 2]),
}.unwrap_or([0.0;2]),
tangent: [0.0;3], // todo: tangent from model
bitangent: [0.0;3],
})
@ -734,35 +605,29 @@ impl Renderer {
} 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 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,25 +652,16 @@ 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);
@ -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) => {
@ -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()));

View file

@ -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 {
@ -108,7 +108,7 @@ impl Block {
match self.blocks[index] {
Some(ref mut block) => {
block.place_pos(interest,new_pos,rad,cs);
}
},
None => {
let mut block = Box::new(Block::new());
block.place_pos(interest,new_pos,rad,cs);
@ -123,20 +123,19 @@ 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)
}
}
}
}
@ -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();
@ -214,14 +212,11 @@ impl World {
Interest::Light(light) => {
let light = light.0.borrow();
(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);
}