Move camera location into push constants
This commit is contained in:
parent
12159dd0b5
commit
50144c7b02
|
|
@ -1,9 +1,9 @@
|
|||
use std::error::Error;
|
||||
|
||||
use glam::{mat3, uvec2, vec2, vec3, Vec3};
|
||||
use glam::{mat3, uvec2, Vec3};
|
||||
use image::ImageReader;
|
||||
use present::Presenter;
|
||||
use trace::{Tracer, TracerData, TracerEnv, Vertex};
|
||||
use trace::{Tracer, TracerData, TracerEnv};
|
||||
use winit::{
|
||||
event::{Event, WindowEvent},
|
||||
event_loop::EventLoop,
|
||||
|
|
@ -22,25 +22,19 @@ struct CamLoc {
|
|||
right: Vec3,
|
||||
}
|
||||
|
||||
fn make_viewport(cam: CamLoc, w: u32, h: u32) -> [Vertex; 4] {
|
||||
fn make_viewport(cam: CamLoc, w: u32, h: u32) -> trace::CameraLocation {
|
||||
let size = uvec2(w, h).as_vec2();
|
||||
let size = size.normalize();
|
||||
let (w, h, d) = (size.x, size.y, 1.);
|
||||
let screen_coord = [vec2(-1., -1.), vec2(1., -1.), vec2(-1., 1.), vec2(1., 1.)];
|
||||
|
||||
let eye = cam.eye;
|
||||
let fwd = cam.forward.normalize();
|
||||
let up = cam.right.cross(fwd).normalize();
|
||||
let right = up.cross(fwd);
|
||||
let fwd = d * cam.forward.normalize();
|
||||
let up = h * cam.right.cross(fwd).normalize();
|
||||
let right = w * up.cross(fwd).normalize();
|
||||
|
||||
let m = mat3(fwd, right, up);
|
||||
|
||||
let world_coord = [vec3(d, -w, -h), vec3(d, w, -h), vec3(d, -w, h), vec3(d, w, h)];
|
||||
[0, 1, 2, 3].map(|k| Vertex {
|
||||
eye,
|
||||
world: eye + m * world_coord[k],
|
||||
screen: screen_coord[k],
|
||||
})
|
||||
trace::CameraLocation {
|
||||
eye: cam.eye,
|
||||
view: mat3(fwd, right, up),
|
||||
}
|
||||
}
|
||||
|
||||
const N_SPHERES: u32 = 100;
|
||||
|
|
@ -60,7 +54,7 @@ fn main() {
|
|||
|
||||
let output_format = wgpu::TextureFormat::Bgra8UnormSrgb;
|
||||
let hdr_format = wgpu::TextureFormat::Rgba16Float;
|
||||
let mut tracer = Tracer::new(&device, hdr_format);
|
||||
let tracer = Tracer::new(&device, hdr_format);
|
||||
let mut rng = rand_pcg::Pcg32::new(42, 0);
|
||||
let sphere_params: Vec<_> = {
|
||||
let distr = anim::distr();
|
||||
|
|
@ -149,10 +143,7 @@ fn main() {
|
|||
let eye = camera_params.to_sphere(time).center;
|
||||
let right = camera_params.deriv(time);
|
||||
let forward = target_params.to_sphere(time).center - eye;
|
||||
tracer.set_view(
|
||||
&queue,
|
||||
&make_viewport(CamLoc { eye, forward, right }, size.width, size.height),
|
||||
);
|
||||
let view = make_viewport(CamLoc { eye, forward, right }, size.width, size.height);
|
||||
let spheres: Vec<_> = sphere_params.iter().map(|p| p.to_sphere(time)).collect();
|
||||
let data = TracerData::new(&device, &tracer, &spheres);
|
||||
tracer.render(
|
||||
|
|
@ -165,6 +156,7 @@ fn main() {
|
|||
sphere_count: N_SPHERES,
|
||||
seed: frame,
|
||||
},
|
||||
view,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -222,7 +214,7 @@ async fn init_gpu(wnd: &Window) -> Result<(wgpu::Device, wgpu::Queue, wgpu::Surf
|
|||
label: None,
|
||||
required_features: wgpu::Features::PUSH_CONSTANTS,
|
||||
required_limits: wgpu::Limits {
|
||||
max_push_constant_size: 32,
|
||||
max_push_constant_size: 128,
|
||||
..Default::default()
|
||||
},
|
||||
memory_hints: Default::default(),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::mem::{self, offset_of};
|
||||
use std::mem;
|
||||
|
||||
use bytemuck::{bytes_of, cast_slice, Pod, Zeroable};
|
||||
use glam::{Vec2, Vec3};
|
||||
use glam::{vec2, Mat3, Vec2, Vec3};
|
||||
use wgpu::util::DeviceExt;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
|
||||
|
|
@ -13,6 +13,47 @@ pub struct Params {
|
|||
pub seed: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct CameraLocation {
|
||||
pub eye: Vec3,
|
||||
pub view: Mat3,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
|
||||
#[repr(C)]
|
||||
struct ParamsData {
|
||||
params: Params,
|
||||
camera: CameraData,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
|
||||
#[repr(C)]
|
||||
struct CameraData {
|
||||
u: Vec3,
|
||||
pad1: f32,
|
||||
v: Vec3,
|
||||
pad2: f32,
|
||||
w: Vec3,
|
||||
pad3: f32,
|
||||
eye: Vec3,
|
||||
pad4: f32,
|
||||
}
|
||||
|
||||
impl From<CameraLocation> for CameraData {
|
||||
fn from(value: CameraLocation) -> Self {
|
||||
CameraData {
|
||||
u: value.view.x_axis,
|
||||
v: value.view.y_axis,
|
||||
w: value.view.z_axis,
|
||||
eye: value.eye,
|
||||
pad1: 0.,
|
||||
pad2: 0.,
|
||||
pad3: 0.,
|
||||
pad4: 0.,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Sphere {
|
||||
pub center: Vec3,
|
||||
|
|
@ -24,9 +65,7 @@ pub struct Sphere {
|
|||
|
||||
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
|
||||
#[repr(C)]
|
||||
pub struct Vertex {
|
||||
pub eye: Vec3,
|
||||
pub world: Vec3,
|
||||
struct Vertex {
|
||||
pub screen: Vec2,
|
||||
}
|
||||
|
||||
|
|
@ -71,11 +110,11 @@ static SHADER: &str = include_str!("trace.wgsl");
|
|||
|
||||
impl Tracer {
|
||||
pub fn new(device: &wgpu::Device, format: wgpu::TextureFormat) -> Self {
|
||||
let view_buf = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
let screen_coord = [vec2(-1., -1.), vec2(1., -1.), vec2(-1., 1.), vec2(1., 1.)];
|
||||
let view_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: None,
|
||||
size: (4 * mem::size_of::<Vertex>()) as u64,
|
||||
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
contents: cast_slice(&screen_coord),
|
||||
usage: wgpu::BufferUsages::VERTEX,
|
||||
});
|
||||
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: None,
|
||||
|
|
@ -120,7 +159,7 @@ impl Tracer {
|
|||
bind_group_layouts: &[&spheres_bgl, &envmap_bgl],
|
||||
push_constant_ranges: &[wgpu::PushConstantRange {
|
||||
stages: wgpu::ShaderStages::FRAGMENT,
|
||||
range: 0..16,
|
||||
range: 0..mem::size_of::<ParamsData>() as u32,
|
||||
}],
|
||||
});
|
||||
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
|
|
@ -133,23 +172,11 @@ impl Tracer {
|
|||
buffers: &[wgpu::VertexBufferLayout {
|
||||
array_stride: size_of::<Vertex>() as u64,
|
||||
step_mode: wgpu::VertexStepMode::Vertex,
|
||||
attributes: &[
|
||||
wgpu::VertexAttribute {
|
||||
attributes: &[wgpu::VertexAttribute {
|
||||
shader_location: 0,
|
||||
offset: offset_of!(Vertex, eye) as u64,
|
||||
format: wgpu::VertexFormat::Float32x3,
|
||||
},
|
||||
wgpu::VertexAttribute {
|
||||
shader_location: 1,
|
||||
offset: offset_of!(Vertex, world) as u64,
|
||||
format: wgpu::VertexFormat::Float32x3,
|
||||
},
|
||||
wgpu::VertexAttribute {
|
||||
shader_location: 2,
|
||||
offset: offset_of!(Vertex, screen) as u64,
|
||||
offset: 0,
|
||||
format: wgpu::VertexFormat::Float32x2,
|
||||
},
|
||||
],
|
||||
}],
|
||||
}],
|
||||
},
|
||||
primitive: wgpu::PrimitiveState {
|
||||
|
|
@ -189,13 +216,23 @@ impl Tracer {
|
|||
Self { view_buf, pipeline }
|
||||
}
|
||||
|
||||
pub fn set_view(&mut self, queue: &wgpu::Queue, vertices: &[Vertex; 4]) {
|
||||
queue.write_buffer(&self.view_buf, 0, bytes_of(vertices));
|
||||
}
|
||||
|
||||
pub fn render(&self, pass: &mut wgpu::RenderPass, data: &TracerData, env: &TracerEnv, params: Params) {
|
||||
pub fn render(
|
||||
&self,
|
||||
pass: &mut wgpu::RenderPass,
|
||||
data: &TracerData,
|
||||
env: &TracerEnv,
|
||||
params: Params,
|
||||
camera: CameraLocation,
|
||||
) {
|
||||
pass.set_pipeline(&self.pipeline);
|
||||
pass.set_push_constants(wgpu::ShaderStages::FRAGMENT, 0, bytes_of(¶ms));
|
||||
pass.set_push_constants(
|
||||
wgpu::ShaderStages::FRAGMENT,
|
||||
0,
|
||||
bytes_of(&ParamsData {
|
||||
params,
|
||||
camera: camera.into(),
|
||||
}),
|
||||
);
|
||||
pass.set_vertex_buffer(0, self.view_buf.slice(..));
|
||||
pass.set_bind_group(0, &data.bindings, &[]);
|
||||
pass.set_bind_group(1, &env.bindings, &[]);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ struct Params {
|
|||
min_strength: f32,
|
||||
sphere_count: i32,
|
||||
seed: u32,
|
||||
view: mat3x3f,
|
||||
eye: vec3f,
|
||||
}
|
||||
|
||||
struct Sphere {
|
||||
|
|
@ -14,9 +16,7 @@ struct Sphere {
|
|||
}
|
||||
|
||||
struct Vertex {
|
||||
@location(0) eye: vec3f,
|
||||
@location(1) world: vec3f,
|
||||
@location(2) screen: vec2f,
|
||||
@location(0) screen: vec2f,
|
||||
}
|
||||
|
||||
struct Varying {
|
||||
|
|
@ -32,7 +32,7 @@ var<push_constant> params: Params;
|
|||
|
||||
@vertex
|
||||
fn on_vertex(in: Vertex) -> Varying {
|
||||
return Varying(in.eye, in.world, vec4(in.screen, 0.0, 1.0));
|
||||
return Varying(params.eye, params.eye + params.view * vec3(1.0, in.screen), vec4(in.screen, 0.0, 1.0));
|
||||
}
|
||||
|
||||
@fragment
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user