added vertex buffer

This commit is contained in:
Sven Vogel 2023-04-14 14:44:28 +02:00
parent dce8b57b0e
commit d26de46d92
9 changed files with 1588 additions and 43 deletions

2
res/cube.mtl Normal file
View File

@ -0,0 +1,2 @@
# Blender 3.5.0 MTL File: 'None'
# www.blender.org

25
res/cube.obj Normal file
View File

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

2
res/sphere.mtl Normal file
View File

@ -0,0 +1,2 @@
# Blender 3.5.0 MTL File: 'None'
# www.blender.org

1447
res/sphere.obj Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -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 );
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;
}
}

View File

@ -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();
}
_ => (),
}