Actually render a model with texture

This commit is contained in:
Timothy Warren 2023-04-20 11:01:17 -04:00
parent e88564d894
commit e5a30c50a9
5 changed files with 16109 additions and 56 deletions

View File

@ -7,7 +7,6 @@ edition = "2021"
[dependencies]
anyhow = "1"
lazy_static = "1"
log = "0.4"
nalgebra-glm = "0.17"
png = "0.17"

16053
resources/viking_room.obj Normal file

File diff suppressed because it is too large Load Diff

BIN
resources/viking_room.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

View File

@ -5,7 +5,6 @@ use data::AppData;
use structs::*;
use ::anyhow::{anyhow, Result};
use ::lazy_static::lazy_static;
use ::nalgebra_glm as glm;
use ::std::collections::HashSet;
use ::std::mem::size_of;
@ -30,53 +29,6 @@ pub const DEVICE_EXTENSIONS: &[vk::ExtensionName] = &[vk::KHR_SWAPCHAIN_EXTENSIO
/// The maximum number of frames that can be processed concurrently.
pub const MAX_FRAMES_IN_FLIGHT: usize = 2;
lazy_static! {
pub static ref VERTICES: Vec<Vertex> = vec![
Vertex::new(
glm::vec3(-0.5, -0.5, 0.0),
glm::vec3(1.0, 0.0, 0.0),
glm::vec2(1.0, 0.0)
),
Vertex::new(
glm::vec3(0.5, -0.5, 0.0),
glm::vec3(0.0, 1.0, 0.0),
glm::vec2(0.0, 0.0)
),
Vertex::new(
glm::vec3(0.5, 0.5, 0.0),
glm::vec3(0.0, 0.0, 1.0),
glm::vec2(0.0, 1.0)
),
Vertex::new(
glm::vec3(-0.5, 0.5, 0.0),
glm::vec3(1.0, 1.0, 1.0),
glm::vec2(1.0, 1.0)
),
Vertex::new(
glm::vec3(-0.5, -0.5, -0.5),
glm::vec3(1.0, 0.0, 0.0),
glm::vec2(1.0, 0.0)
),
Vertex::new(
glm::vec3(0.5, -0.5, -0.5),
glm::vec3(0.0, 1.0, 0.0),
glm::vec2(0.0, 0.0)
),
Vertex::new(
glm::vec3(0.5, 0.5, -0.5),
glm::vec3(0.0, 0.0, 1.0),
glm::vec2(0.0, 1.0)
),
Vertex::new(
glm::vec3(-0.5, 0.5, -0.5),
glm::vec3(1.0, 1.0, 1.0),
glm::vec2(1.0, 1.0)
),
];
}
pub const INDICES: &[u16] = &[0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4];
/// Our Vulkan app.
#[derive(Clone, Debug)]
pub struct App {

View File

@ -4,9 +4,12 @@ use crate::VALIDATION_ENABLED;
use ::anyhow::{anyhow, Result};
use ::log::*;
use ::std::collections::HashMap;
use ::std::collections::HashSet;
use ::std::ffi::CStr;
use ::std::fs::File;
use ::std::hash::{Hash, Hasher};
use ::std::io::BufReader;
use ::std::os::raw::c_void;
use ::std::ptr::copy_nonoverlapping as memcpy;
use ::vulkanalia::prelude::v1_0::*;
@ -71,6 +74,9 @@ pub(crate) struct AppData {
texture_image_memory: vk::DeviceMemory,
texture_image_view: vk::ImageView,
texture_sampler: vk::Sampler,
// Model
vertices: Vec<Vertex>,
indices: Vec<u32>,
// Buffers
vertex_buffer: vk::Buffer,
vertex_buffer_memory: vk::DeviceMemory,
@ -117,6 +123,7 @@ impl AppData {
self.create_texture_image(&instance, &device)?;
self.create_texture_image_view(&device)?;
self.create_texture_sampler(&device)?;
self.load_model()?;
self.create_vertex_buffer(&instance, &device)?;
self.create_index_buffer(&instance, &device)?;
self.create_uniform_buffers(&instance, &device)?;
@ -799,7 +806,7 @@ impl AppData {
fn create_texture_image(&mut self, instance: &Instance, device: &Device) -> Result<()> {
// Load the image
let image = File::open("resources/texture.png")?;
let image = File::open("resources/viking_room.png")?;
let decoder = png::Decoder::new(image);
let mut reader = decoder.read_info()?;
@ -903,13 +910,55 @@ impl AppData {
Ok(())
}
//================================================
// Model
//================================================
unsafe fn load_model(&mut self) -> Result<()> {
let mut reader = BufReader::new(File::open("resources/viking_room.obj")?);
let (models, _) = tobj::load_obj_buf(
&mut reader,
&tobj::LoadOptions {
triangulate: true,
..Default::default()
},
|_| Ok(Default::default()),
)?;
for model in &models {
for index in &model.mesh.indices {
let pos_offset = (3 * index) as usize;
let tex_coord_offset = (2 * index) as usize;
let vertex = Vertex::new(
glm::vec3(
model.mesh.positions[pos_offset],
model.mesh.positions[pos_offset + 1],
model.mesh.positions[pos_offset + 2],
),
glm::vec3(1.0, 1.0, 1.0),
glm::vec2(
model.mesh.texcoords[tex_coord_offset],
1.0 - model.mesh.texcoords[tex_coord_offset + 1],
),
);
self.vertices.push(vertex);
self.indices.push(self.indices.len() as u32);
}
}
Ok(())
}
//================================================
// Buffers
//================================================
unsafe fn create_vertex_buffer(&mut self, instance: &Instance, device: &Device) -> Result<()> {
// Create staging buffer
let size = (size_of::<Vertex>() * VERTICES.len()) as u64;
let size = (size_of::<Vertex>() * self.vertices.len()) as u64;
let (staging_buffer, staging_buffer_memory) = self.create_buffer(
instance,
device,
@ -920,7 +969,7 @@ impl AppData {
let memory =
device.map_memory(staging_buffer_memory, 0, size, vk::MemoryMapFlags::empty())?;
memcpy(VERTICES.as_ptr(), memory.cast(), VERTICES.len());
memcpy(self.vertices.as_ptr(), memory.cast(), self.vertices.len());
device.unmap_memory(staging_buffer_memory);
// Create vertex buffer
@ -946,7 +995,7 @@ impl AppData {
}
unsafe fn create_index_buffer(&mut self, instance: &Instance, device: &Device) -> Result<()> {
let size = (size_of::<u16>() * INDICES.len()) as u64;
let size = (size_of::<u32>() * self.indices.len()) as u64;
let (staging_buffer, staging_buffer_memory) = self.create_buffer(
instance,
device,
@ -957,7 +1006,7 @@ impl AppData {
let memory =
device.map_memory(staging_buffer_memory, 0, size, vk::MemoryMapFlags::empty())?;
memcpy(INDICES.as_ptr(), memory.cast(), INDICES.len());
memcpy(self.indices.as_ptr(), memory.cast(), self.indices.len());
device.unmap_memory(staging_buffer_memory);
let (index_buffer, index_buffer_memory) = self.create_buffer(
@ -1128,7 +1177,7 @@ impl AppData {
*command_buffer,
self.index_buffer,
0,
vk::IndexType::UINT16,
vk::IndexType::UINT32,
);
device.cmd_bind_descriptor_sets(
*command_buffer,
@ -1138,7 +1187,7 @@ impl AppData {
&[self.descriptor_sets[i]],
&[],
);
device.cmd_draw_indexed(*command_buffer, INDICES.len() as u32, 1, 0, 0, 0);
device.cmd_draw_indexed(*command_buffer, self.indices.len() as u32, 1, 0, 0, 0);
device.cmd_end_render_pass(*command_buffer);
device.end_command_buffer(*command_buffer)?;