Added skybox to renderer and reflections to shader. Builds and runs. Flickering with many objects in scene, assuming swap chain issue.
This commit is contained in:
parent
efe98454d9
commit
3231ed9190
10 changed files with 1829 additions and 1449 deletions
|
|
@ -1,131 +1,187 @@
|
|||
use crate::render::{MaterialProperties, SimpleTexture};
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use env_logger::Env;
|
||||
use glam::{Affine3A, EulerRot, Mat3A, Mat4, Vec3, Vec4};
|
||||
use glam::camera::lh::proj::directx::perspective;
|
||||
use wgpu::{Device, Queue};
|
||||
use glam::{Affine3A, EulerRot, Mat3A, Mat4, Vec3, Vec4};
|
||||
use wgpu::util::DeviceExt;
|
||||
use wgpu::{Device, Queue};
|
||||
|
||||
pub(crate) struct Eye {
|
||||
pub(crate) frame: Affine3A,
|
||||
pub(crate) environment: Environment,
|
||||
aspect_ratio: f32,
|
||||
z_near: f32,
|
||||
z_far: f32,
|
||||
fov_y: f32,
|
||||
pub(crate) environment_buffer: wgpu::Buffer,
|
||||
pub(crate) buffer: wgpu::Buffer,
|
||||
pub(crate) layout: wgpu::BindGroupLayout,
|
||||
pub(crate) group: wgpu::BindGroup,
|
||||
pub(crate) frame: Affine3A,
|
||||
pub(crate) environment: Environment,
|
||||
aspect_ratio: f32,
|
||||
z_near: f32,
|
||||
z_far: f32,
|
||||
fov_y: f32,
|
||||
pub(crate) environment_buffer: wgpu::Buffer,
|
||||
pub(crate) camera_buffer: wgpu::Buffer,
|
||||
pub(crate) layout: wgpu::BindGroupLayout,
|
||||
pub(crate) group: wgpu::BindGroup,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Pod, Copy, Clone, Zeroable)]
|
||||
struct Environment {
|
||||
ambient: Vec4,
|
||||
light: Vec4,
|
||||
dir: Vec4,
|
||||
pub struct Environment {
|
||||
ambient: Vec4,
|
||||
light: Vec4,
|
||||
dir: Vec4,
|
||||
}
|
||||
|
||||
impl Eye {
|
||||
pub(crate) fn view(&self) -> Mat4 {
|
||||
let projection = perspective(self.fov_y, self.aspect_ratio, self.z_near, self.z_far);
|
||||
projection * self.frame.inverse()
|
||||
}
|
||||
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]),
|
||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||
}
|
||||
);
|
||||
|
||||
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),
|
||||
};
|
||||
|
||||
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: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
}
|
||||
],
|
||||
label: Some("eye_bind_group_layout"),
|
||||
});
|
||||
|
||||
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,
|
||||
frame: Affine3A::IDENTITY,
|
||||
fov_y: 90.0,
|
||||
z_near: 0.1,
|
||||
z_far: 1000.0,
|
||||
buffer,
|
||||
group,
|
||||
layout,
|
||||
environment,
|
||||
environment_buffer,
|
||||
pub(crate) fn write(&mut self, queue: &Queue) {
|
||||
let camera = Mat4::from_mat3_translation(
|
||||
self.frame.matrix3.into(),
|
||||
Vec3::from(self.frame.translation),
|
||||
);
|
||||
let projection = perspective(self.fov_y, self.aspect_ratio, self.z_near, self.z_far);
|
||||
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]),
|
||||
);
|
||||
}
|
||||
}
|
||||
pub(crate) fn resize(&mut self, width: u32, height: u32) {
|
||||
self.aspect_ratio = width as f32 / height as f32
|
||||
}
|
||||
pub(crate) fn control(&mut self, delta: Vec3) {
|
||||
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);
|
||||
y += yaw * 0.005;
|
||||
self.frame.matrix3 = Mat3A::from_euler(EulerRot::YXZ,y,x,z);
|
||||
}
|
||||
}
|
||||
pub(crate) fn new(device: &Device, width: u32, height: u32, skybox: SimpleTexture) -> Eye {
|
||||
let camera_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,
|
||||
]),
|
||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||
});
|
||||
|
||||
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),
|
||||
};
|
||||
|
||||
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: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
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);
|
||||
|
||||
Eye {
|
||||
aspect_ratio: width as f32 / height as f32,
|
||||
frame: Affine3A::IDENTITY,
|
||||
fov_y: 90.0,
|
||||
z_near: 0.1,
|
||||
z_far: 1000.0,
|
||||
camera_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
|
||||
}
|
||||
pub(crate) fn control(&mut self, delta: Vec3) {
|
||||
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);
|
||||
y += yaw * 0.005;
|
||||
self.frame.matrix3 = Mat3A::from_euler(EulerRot::YXZ, y, x, z);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue