added index buffer for rendering

This commit is contained in:
Sven Vogel 2023-04-07 00:56:39 +02:00
parent 35083ee148
commit 624e19d84c
10 changed files with 153 additions and 72 deletions

View File

@ -1,7 +1,5 @@
use eruption::init; mod vulkan;
fn main() { fn main() {
init(); vulkan::init();
} }

View File

@ -1,25 +0,0 @@
pub(crate) mod vs {
vulkano_shaders::shader! {
ty: "vertex",
src: r"
#version 450
layout(location = 0) in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
",
}
}
pub(crate) mod fs {
vulkano_shaders::shader! {
ty: "fragment",
src: r"
#version 450
layout(location = 0) out vec4 f_color;
void main() {
f_color = vec4(1.0, 0.0, 0.0, 1.0);
}
",
}
}

View File

@ -1,4 +1,4 @@
mod composit; mod composite;
use std::sync::Arc; use std::sync::Arc;
use vulkano::device::Device; use vulkano::device::Device;
@ -11,8 +11,8 @@ use crate::Vertex2d;
pub fn create_program(render_pass: &Arc<RenderPass>, device: &Arc<Device>) -> Arc<GraphicsPipeline> { pub fn create_program(render_pass: &Arc<RenderPass>, device: &Arc<Device>) -> Arc<GraphicsPipeline> {
let vs = composit::vs::load(device.clone()).unwrap(); let vs = composite::vs::load(device.clone()).unwrap();
let fs = composit::fs::load(device.clone()).unwrap(); let fs = composite::fs::load(device.clone()).unwrap();
// Before we draw we have to create what is called a pipeline. This is similar to an OpenGL // Before we draw we have to create what is called a pipeline. This is similar to an OpenGL
// program, but much more specific. // program, but much more specific.

View File

@ -0,0 +1,16 @@
#version 450
#include <pathtracing/pathtracer.glsl>
layout(location = 0) in vec2 texture_coordinate;
layout(location = 0) out vec4 frag_color;
void main() {
vec2 uv = texture_coordinate;
vec3 color = trace_path(uv);
frag_color = vec4(color, 1.0);
}

View File

@ -0,0 +1,11 @@
#version 450
layout(location = 0) in vec2 position;
layout(location = 1) in vec2 texture;
layout(location = 0) out vec2 texture_coordinate;
void main() {
texture_coordinate = texture;
gl_Position = vec4(position, 0.0, 1.0);
}

View File

@ -0,0 +1,22 @@
layout(push_constant) uniform Camera {
vec3 position;
vec3 front;
vec3 up;
vec3 left;
float fov;
} camera;
vec3 generate_view_ray_direction(in vec2 uv) {
// convert camera fov from degrees to relative factor for scaling normalized front vector
float fov = 1.0 / tan(DegreeToRadians(camera.fov) * 0.5);
return normalize(camera.front * fov + camera.up * uv.x + camera.left * uv.y);
}
Ray generate_view_ray(in vec2 uv) {
Ray view_ray;
view_ray.origin = camera.position;
view_ray.direction = generate_view_ray_direction(uv);
return view_ray;
}

View File

@ -0,0 +1,7 @@
#define DegreeToRadians(x) (x * 0.01745329251994330)
struct Ray {
vec3 origin;
vec3 direction;
};

View File

@ -0,0 +1,9 @@
#include <pathtracing/common.glsl>
#include <pathtracing/camera.glsl>
vec3 trace_path(in vec2 uv) {
Ray view_ray = generate_view_ray(uv);
return view_ray.direction;
}

14
src/vulkan/composite.rs Normal file
View File

@ -0,0 +1,14 @@
pub(crate) mod vs {
vulkano_shaders::shader! {
ty: "vertex",
path: "src/shader/src/composite.vert"
}
}
pub(crate) mod fs {
vulkano_shaders::shader! {
ty: "fragment",
include: ["src/shader/src"],
path: "src/shader/src/composite.frag"
}
}

View File

@ -1,4 +1,4 @@
mod shader; mod composite;
use std::sync::Arc; use std::sync::Arc;
use vulkano::device::{Device, DeviceCreateInfo, DeviceExtensions, Properties, Queue, QueueCreateInfo, QueueFlags}; use vulkano::device::{Device, DeviceCreateInfo, DeviceExtensions, Properties, Queue, QueueCreateInfo, QueueFlags};
@ -11,7 +11,7 @@ use vulkano::{sync, VulkanLibrary};
use vulkano_win::VkSurfaceBuild; use vulkano_win::VkSurfaceBuild;
use winit::event_loop::{ControlFlow, EventLoop}; use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::{Window, WindowBuilder}; use winit::window::{Window, WindowBuilder};
use vulkano::buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}; use vulkano::buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer};
use vulkano::command_buffer::allocator::StandardCommandBufferAllocator; use vulkano::command_buffer::allocator::StandardCommandBufferAllocator;
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents}; use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents};
use vulkano::image::view::ImageView; use vulkano::image::view::ImageView;
@ -29,29 +29,36 @@ use winit::event::{Event, WindowEvent};
struct Vertex2d { struct Vertex2d {
#[format(R32G32_SFLOAT)] #[format(R32G32_SFLOAT)]
position: [f32; 2], position: [f32; 2],
#[format(R32G32_SFLOAT)]
texture: [f32; 2]
} }
const QUAD_VERTICES: [Vertex2d; 6] = [ fn textured_quad() -> (Vec<Vertex2d>, Vec<u32>) {
Vertex2d { (
position: [-1.0, -1.0] vec![
}, Vertex2d {
Vertex2d { position: [-1.0, -1.0],
position: [1.0, -1.0] texture: [0.0, 0.0]
}, },
Vertex2d { Vertex2d {
position: [1.0, 1.0] position: [1.0, -1.0],
}, texture: [1.0, 0.0]
},
Vertex2d { Vertex2d {
position: [-1.0, -1.0] position: [1.0, 1.0],
}, texture: [1.0, 1.0]
Vertex2d { },
position: [1.0, 1.0] Vertex2d {
}, position: [-1.0, 1.0],
Vertex2d { texture: [0.0, 1.0]
position: [-1.0, 1.0] }
} ],
]; vec![
0, 1, 2,
0, 2, 3
]
)
}
pub fn init() { pub fn init() {
let lib = VulkanLibrary::new().unwrap(); let lib = VulkanLibrary::new().unwrap();
@ -96,18 +103,7 @@ pub fn init() {
let memory_allocator = StandardMemoryAllocator::new_default(device.clone()); let memory_allocator = StandardMemoryAllocator::new_default(device.clone());
let vertex_buffer = Buffer::from_iter( let (vertex_buffer, index_buffer) = create_quad_buffer(&memory_allocator);
&memory_allocator,
BufferCreateInfo {
usage: BufferUsage::VERTEX_BUFFER,
..Default::default()
},
AllocationCreateInfo {
usage: MemoryUsage::Upload,
..Default::default()
},
QUAD_VERTICES,
).unwrap();
// At this point, OpenGL initialization would be finished. However in Vulkan it is not. OpenGL // At this point, OpenGL initialization would be finished. However in Vulkan it is not. OpenGL
// implicitly does a lot of computation whenever you draw. In Vulkan, you have to do all this // implicitly does a lot of computation whenever you draw. In Vulkan, you have to do all this
@ -157,7 +153,7 @@ pub fn init() {
// that, we store the submission of the previous frame here. // that, we store the submission of the previous frame here.
let mut previous_frame_end = Some(sync::now(device.clone()).boxed()); let mut previous_frame_end = Some(sync::now(device.clone()).boxed());
let pipeline = shader::create_program(&render_pass, &device); let pipeline = composite::create_program(&render_pass, &device);
event_loop.run(move |event, _, control_flow| { event_loop.run(move |event, _, control_flow| {
match event { match event {
@ -204,7 +200,7 @@ pub fn init() {
// window. Simply restarting the loop is the easiest way to fix this // window. Simply restarting the loop is the easiest way to fix this
// issue. // issue.
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return, Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("failed to recreate swapchain: {e}"), Err(e) => panic!("failed to recreate swapchain: {}", e),
}; };
swapchain = new_swapchain; swapchain = new_swapchain;
@ -234,7 +230,7 @@ pub fn init() {
recreate_swapchain = true; recreate_swapchain = true;
return; return;
} }
Err(e) => panic!("failed to acquire next image: {e}"), Err(e) => panic!("failed to acquire next image: {}", e),
}; };
// `acquire_next_image` can be successful, but suboptimal. This means that the // `acquire_next_image` can be successful, but suboptimal. This means that the
@ -287,8 +283,9 @@ pub fn init() {
.set_viewport(0, [viewport.clone()]) .set_viewport(0, [viewport.clone()])
.bind_pipeline_graphics(pipeline.clone()) .bind_pipeline_graphics(pipeline.clone())
.bind_vertex_buffers(0, vertex_buffer.clone()) .bind_vertex_buffers(0, vertex_buffer.clone())
.bind_index_buffer(index_buffer.clone())
// We add a draw command. // We add a draw command.
.draw(vertex_buffer.len() as u32, 1, 0, 0) .draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0)
.unwrap() .unwrap()
// We leave the render pass. Note that if we had multiple subpasses we could // We leave the render pass. Note that if we had multiple subpasses we could
// have called `next_subpass` to jump to the next subpass. // have called `next_subpass` to jump to the next subpass.
@ -327,7 +324,7 @@ pub fn init() {
previous_frame_end = Some(sync::now(device.clone()).boxed()); previous_frame_end = Some(sync::now(device.clone()).boxed());
} }
Err(e) => { Err(e) => {
panic!("failed to flush future: {e}"); panic!("failed to flush future: {}", e);
// previous_frame_end = Some(sync::now(device.clone()).boxed()); // previous_frame_end = Some(sync::now(device.clone()).boxed());
} }
} }
@ -337,6 +334,38 @@ pub fn init() {
}); });
} }
fn create_quad_buffer(memory_allocator: &StandardMemoryAllocator) -> (Subbuffer<[Vertex2d]>, Subbuffer<[u32]>) {
let (vertices, indices) = textured_quad();
let vertex_buffer = Buffer::from_iter(
memory_allocator,
BufferCreateInfo {
usage: BufferUsage::VERTEX_BUFFER,
..Default::default()
},
AllocationCreateInfo {
usage: MemoryUsage::Upload,
..Default::default()
},
vertices,
).unwrap();
let index_buffer = Buffer::from_iter(
memory_allocator,
BufferCreateInfo {
usage: BufferUsage::INDEX_BUFFER,
..Default::default()
},
AllocationCreateInfo {
usage: MemoryUsage::Upload,
..Default::default()
},
indices,
).unwrap();
(vertex_buffer, index_buffer)
}
/// This function is called once during initialization, then again whenever the window is resized. /// This function is called once during initialization, then again whenever the window is resized.
fn window_size_dependent_setup( fn window_size_dependent_setup(
images: &[Arc<SwapchainImage>], images: &[Arc<SwapchainImage>],