added vertex buffer
This commit is contained in:
parent
dce8b57b0e
commit
d26de46d92
|
@ -0,0 +1,2 @@
|
|||
# Blender 3.5.0 MTL File: 'None'
|
||||
# www.blender.org
|
|
@ -0,0 +1,25 @@
|
|||
# Blender 3.5.0
|
||||
# www.blender.org
|
||||
mtllib cube.mtl
|
||||
o Cube
|
||||
v -1.000000 -1.000000 1.000000
|
||||
v -1.000000 1.000000 1.000000
|
||||
v -1.000000 -1.000000 -1.000000
|
||||
v -1.000000 1.000000 -1.000000
|
||||
v 1.000000 -1.000000 1.000000
|
||||
v 1.000000 1.000000 1.000000
|
||||
v 1.000000 -1.000000 -1.000000
|
||||
v 1.000000 1.000000 -1.000000
|
||||
s 0
|
||||
f 2 3 1
|
||||
f 4 7 3
|
||||
f 8 5 7
|
||||
f 6 1 5
|
||||
f 7 1 3
|
||||
f 4 6 8
|
||||
f 2 4 3
|
||||
f 4 8 7
|
||||
f 8 6 5
|
||||
f 6 2 1
|
||||
f 7 5 1
|
||||
f 4 2 6
|
|
@ -0,0 +1,2 @@
|
|||
# Blender 3.5.0 MTL File: 'None'
|
||||
# www.blender.org
|
File diff suppressed because it is too large
Load Diff
|
@ -3,21 +3,21 @@ use cgmath::prelude::*;
|
|||
use cgmath::{Rad, Vector2, Vector3};
|
||||
|
||||
pub struct Camera {
|
||||
front: Vector3<f32>,
|
||||
left: Vector3<f32>,
|
||||
up: Vector3<f32>,
|
||||
pos: Vector3<f32>,
|
||||
fov: f32,
|
||||
pub(crate) front: Vector3<f32>,
|
||||
pub(crate) left: Vector3<f32>,
|
||||
pub(crate) up: Vector3<f32>,
|
||||
pub(crate) pos: Vector3<f32>,
|
||||
pub(crate) fov: f32,
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
front: Vector3::new(0.0, 0.0, 1.0),
|
||||
front: Vector3::new(0.0, 0.0, -1.0),
|
||||
left: Vector3::new(1.0, 0.0, 0.0),
|
||||
up: Vector3::new(0.0, 1.0, 0.0),
|
||||
pos: Vector3::new(0.0, 0.0, -4.0),
|
||||
up: Vector3::new(0.0, -1.0, 0.0),
|
||||
pos: Vector3::new(0.0, 0.0, 9.0),
|
||||
fov: 90.0f32
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ use vulkano::memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemo
|
|||
use vulkano::padded::Padded;
|
||||
use vulkano::pipeline::{ComputePipeline, Pipeline, PipelineBindPoint};
|
||||
use vulkano::sync::GpuFuture;
|
||||
use crate::shader::pathtracing::camera::Camera;
|
||||
use crate::vulkan::Renderer;
|
||||
|
||||
pub(crate) mod cs {
|
||||
|
@ -36,8 +37,9 @@ pub struct PathtracerPipeline {
|
|||
raw_image: Subbuffer<[[f32; 4]]>,
|
||||
seconds: Instant,
|
||||
uniform_buffer: Arc<SubbufferAllocator>,
|
||||
vertex_buffer: Subbuffer<[[f32; 3]]>,
|
||||
vertex_buffer: Subbuffer<[[f32; 4]]>,
|
||||
index_buffer: Subbuffer<[u32]>,
|
||||
camera: Camera
|
||||
}
|
||||
|
||||
impl PathtracerPipeline {
|
||||
|
@ -79,7 +81,8 @@ impl PathtracerPipeline {
|
|||
uniform_buffer: Arc::new(uniform_buffer),
|
||||
vertex_buffer,
|
||||
index_buffer,
|
||||
seconds: Instant::now()
|
||||
seconds: Instant::now(),
|
||||
camera: Camera::new()
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -118,13 +121,13 @@ impl PathtracerPipeline {
|
|||
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer,Arc<StandardCommandBufferAllocator>>
|
||||
) {
|
||||
let camera = cs::Camera {
|
||||
front: Padded::from([0f32, 0f32, 1f32]),
|
||||
left: Padded::from([1f32, 0f32, 0f32]),
|
||||
up: Padded::from([0f32, 1f32, 0f32]),
|
||||
front: Padded::from(Into::<[f32; 3]>::into(self.camera.front)),
|
||||
left: Padded::from(Into::<[f32; 3]>::into(self.camera.left)),
|
||||
up: Padded::from(Into::<[f32; 3]>::into(self.camera.up)),
|
||||
|
||||
position: [0f32, 0f32, -12f32],
|
||||
position: Into::<[f32; 3]>::into(self.camera.pos),
|
||||
|
||||
fov: 90f32
|
||||
fov: self.camera.fov,
|
||||
};
|
||||
|
||||
let subbuffer = self.uniform_buffer.allocate_sized().unwrap();
|
||||
|
@ -188,35 +191,33 @@ fn create_image(memory_allocator: &StandardMemoryAllocator, queue: &Arc<Queue>,
|
|||
(raw_image, image)
|
||||
}
|
||||
|
||||
fn load_example_scene() -> (Vec<[f32; 3]>, Vec<u32>) {
|
||||
fn load_example_scene() -> (Vec<[f32; 4]>, Vec<u32>) {
|
||||
let (mut models, materials) = tobj::load_obj("res/example-scene.obj", &tobj::GPU_LOAD_OPTIONS).expect("unable to load scene from obj");
|
||||
|
||||
let mut vertices:Vec<[f32; 3]> = Vec::new();
|
||||
let mut indices:Vec<u32> = Vec::new();
|
||||
let mut vertices:Vec<[f32; 4]> = vec![];
|
||||
let mut indices:Vec<u32> = vec![];
|
||||
|
||||
for model in models.iter_mut() {
|
||||
let num_triangles = model.mesh.positions.len() / 3;
|
||||
let offset = vertices.len() as u32;
|
||||
|
||||
for triangle_index in 0..num_triangles {
|
||||
let vertex_index = triangle_index * 3;
|
||||
for vertex_index in (0..model.mesh.positions.len()).step_by(3) {
|
||||
vertices.push([
|
||||
model.mesh.positions[vertex_index],
|
||||
model.mesh.positions[vertex_index + 1],
|
||||
model.mesh.positions[vertex_index + 2]
|
||||
model.mesh.positions[vertex_index + 2],
|
||||
0.0
|
||||
]);
|
||||
}
|
||||
|
||||
for index in model.mesh.indices.iter() {
|
||||
indices.push(*index);
|
||||
indices.push(*index + offset);
|
||||
}
|
||||
|
||||
// model.mesh.indices.iter_mut().for_each(|i| indices.push(*i));
|
||||
}
|
||||
|
||||
(vertices, indices)
|
||||
}
|
||||
|
||||
fn create_gpu_buffer(vertices: &Vec<[f32; 3]>, indices: &Vec<u32>, memory_allocator: &StandardMemoryAllocator) -> (Subbuffer<[[f32; 3]]>, Subbuffer<[u32]>) {
|
||||
fn create_gpu_buffer(vertices: &Vec<[f32; 4]>, indices: &Vec<u32>, memory_allocator: &StandardMemoryAllocator) -> (Subbuffer<[[f32; 4]]>, Subbuffer<[u32]>) {
|
||||
let vertex_buffer = Buffer::from_iter(
|
||||
memory_allocator,
|
||||
BufferCreateInfo {
|
||||
|
|
|
@ -25,6 +25,45 @@ uint get_pixel_index() {
|
|||
return gl_GlobalInvocationID.y * uint(program_metadata.resolution.x) + gl_GlobalInvocationID.x;
|
||||
}
|
||||
|
||||
vec3 project(in vec3 a, in vec3 b) {
|
||||
return a * (dot(a, b) / dot(a, a));
|
||||
}
|
||||
|
||||
void construct_orthonormal_basis(in vec3 up, out vec3 u, out vec3 v, out vec3 w) {
|
||||
u = normalize(up);
|
||||
|
||||
vec3 n2 = vec3(1) - u;
|
||||
vec3 n3 = vec3(1) - u.zxy;
|
||||
|
||||
vec3 w2 = normalize(n2 - (project(u, n2)));
|
||||
vec3 w3 = normalize(n3 - project(u, n3) - project(w2, n3));
|
||||
|
||||
v = w2;
|
||||
w = w3;
|
||||
}
|
||||
|
||||
vec3 cosine_weighted_hemisphere() {
|
||||
float u1 = random();
|
||||
float u2 = random();
|
||||
|
||||
float r = sqrt(u1);
|
||||
float theta = 2 * 3.1415926535 * u2;
|
||||
|
||||
float x = r * cos(theta);
|
||||
float y = r * sin(theta);
|
||||
|
||||
return vec3(x, y, sqrt(1.0 - u1));
|
||||
}
|
||||
|
||||
vec3 generate_diffuse_ray_direction(in vec3 nor) {
|
||||
vec3 hemisphere = cosine_weighted_hemisphere();
|
||||
|
||||
vec3 u, v, w;
|
||||
construct_orthonormal_basis(nor, u, v, w);
|
||||
|
||||
return normalize(u * hemisphere.x + v * hemisphere.y + w * hemisphere.z);
|
||||
}
|
||||
|
||||
void main() {
|
||||
init_random_state(floatBitsToInt(program_metadata.seconds));
|
||||
|
||||
|
@ -34,10 +73,20 @@ void main() {
|
|||
|
||||
vec3 color = vec3(0);
|
||||
|
||||
vec4 result = intersect_scene(camera_ray);
|
||||
Hit result = intersect_scene(camera_ray);
|
||||
|
||||
if (result.a == 1.0) {
|
||||
color = vec3(result.y, result.z, 0);
|
||||
if (result.depth < camera_ray.far) {
|
||||
Ray ao;
|
||||
ao.origin = camera_ray.origin + camera_ray.direction * result.depth;
|
||||
ao.direction = generate_diffuse_ray_direction(result.nor);
|
||||
ao.near = 1e-3;
|
||||
ao.far = 1e3;
|
||||
|
||||
Hit r2 = intersect_scene(ao);
|
||||
|
||||
if (r2.depth > 1.0) {
|
||||
color = vec3(1);
|
||||
}
|
||||
}
|
||||
|
||||
// index of the current pixel as array index
|
||||
|
|
|
@ -7,42 +7,54 @@ struct Ray {
|
|||
float far;
|
||||
};
|
||||
|
||||
struct Hit {
|
||||
vec3 nor;
|
||||
vec2 uv;
|
||||
float depth;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 3) buffer VertexBuffer {
|
||||
vec3 vertices[];
|
||||
vec4 vertices[];
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 4) buffer IndexBuffer {
|
||||
uint indices[];
|
||||
};
|
||||
|
||||
vec3 intersect_triangle(in Ray ray, in vec3 v0, in vec3 v1, in vec3 v2) {
|
||||
vec3 intersect_triangle(in Ray ray, in vec3 v0, in vec3 v1, in vec3 v2, out vec3 n) {
|
||||
vec3 v1v0 = v1 - v0;
|
||||
vec3 v2v0 = v2 - v0;
|
||||
vec3 rov0 = ray.origin - v0;
|
||||
vec3 n = cross(v1v0, v2v0);
|
||||
n = cross(v1v0, v2v0);
|
||||
|
||||
vec3 q = cross(rov0, ray.direction);
|
||||
float d = 1.0 / dot(ray.direction, n);
|
||||
float u = d * dot( -q, v2v0);
|
||||
float v = d * dot( q, v1v0);
|
||||
float t = d * dot( -n, rov0);
|
||||
|
||||
t = min(u, min(v, min(1.0 - (u + v), t)));
|
||||
if(u < 0.0 || v < 0.0 || (u+v) > 1.0 || d > 0.0)
|
||||
t = -1.0;
|
||||
|
||||
return vec3(t, u, v);
|
||||
}
|
||||
|
||||
vec4 intersect_scene(in Ray ray) {
|
||||
vec4 hit = vec4(ray.far, -1, -1, 0);
|
||||
Hit intersect_scene(in Ray ray) {
|
||||
Hit hit;
|
||||
hit.depth = ray.far;
|
||||
|
||||
for (int i = 0; i < indices.length(); i += 3) {
|
||||
vec3 v0 = vertices[indices[i]];
|
||||
vec3 v1 = vertices[indices[i + 1]];
|
||||
vec3 v2 = vertices[indices[i + 2]];
|
||||
vec3 v0 = vertices[indices[i]].xyz;
|
||||
vec3 v1 = vertices[indices[i + 1]].xyz;
|
||||
vec3 v2 = vertices[indices[i + 2]].xyz;
|
||||
|
||||
vec3 result = intersect_triangle(ray, v0, v1, v2);
|
||||
vec3 n;
|
||||
vec3 result = intersect_triangle(ray, v0, v1, v2, n);
|
||||
|
||||
if (result.x > ray.near && result.x < hit.x) {
|
||||
hit = vec4(result, 1);
|
||||
if (result.x > ray.near && result.x < hit.depth) {
|
||||
hit.uv = result.yz;
|
||||
hit.depth = result.x;
|
||||
hit.nor = n;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ mod device;
|
|||
pub(crate) mod textured_quad;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
use vulkano::device::{Device};
|
||||
use vulkano::image::{ImageAccess, ImageUsage, SwapchainImage};
|
||||
use vulkano::instance::{Instance, InstanceCreateInfo};
|
||||
|
@ -17,7 +18,7 @@ use vulkano::image::view::ImageView;
|
|||
use vulkano::pipeline::graphics::viewport::Viewport;
|
||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass};
|
||||
use vulkano::sync::{FlushError, GpuFuture};
|
||||
use winit::event::{Event, WindowEvent};
|
||||
use winit::event::{Event, VirtualKeyCode, WindowEvent};
|
||||
use crate::shader::composite::TextureDrawPipeline;
|
||||
use crate::shader::pathtracing::PathtracerPipeline;
|
||||
|
||||
|
@ -133,6 +134,8 @@ pub fn init() {
|
|||
|
||||
let mut now_keys = [false; 255];
|
||||
|
||||
let mut start_frame = Instant::now();
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
match event {
|
||||
Event::WindowEvent {
|
||||
|
@ -172,6 +175,8 @@ pub fn init() {
|
|||
}
|
||||
},
|
||||
Event::RedrawEventsCleared => {
|
||||
let elapsed = (Instant::now() - start_frame).as_secs_f32();
|
||||
|
||||
// Do not draw the frame when the screen dimensions are zero. On Windows, this can
|
||||
// occur when minimizing the application.
|
||||
let window = surface.object().unwrap().downcast_ref::<Window>().unwrap();
|
||||
|
@ -280,6 +285,8 @@ pub fn init() {
|
|||
// previous_frame_end = Some(sync::now(device.clone()).boxed());
|
||||
}
|
||||
}
|
||||
|
||||
start_frame = Instant::now();
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
|
Reference in New Issue