@@ -3,7 +3,7 @@ layout(location = 1) in vec4 vertex_color; | |||
layout(location = 0) out vec4 frag_color; | |||
layout(binding = 1) uniform sampler2D u_sampler; | |||
layout(binding = 2) uniform sampler2D u_sampler; | |||
void main() { | |||
frag_color = texture(u_sampler, vertex_texcoord.xy); | |||
@@ -1,24 +1,42 @@ | |||
layout(location = 0) in vec3 in_position; | |||
layout(location = 1) in vec3 in_texcoord; | |||
layout(location = 2) in vec3 in_normal; | |||
layout(location = 3) in vec4 in_color; | |||
layout(location = 3) in vec4 in_blendindices; | |||
layout(location = 4) in vec4 in_blendweights; | |||
layout(location = 5) in vec4 in_color; | |||
layout(location = 0) out vec3 vertex_texcoord; | |||
layout(location = 1) out vec4 vertex_color; | |||
layout(binding = 0) uniform Uniforms { | |||
mat4 obj; | |||
mat4 cam; | |||
mat4 prj; | |||
mat4 object; | |||
mat4 camera; | |||
mat4 projec; | |||
} uniforms; | |||
layout(binding = 1) uniform BoneMatrices { | |||
mat4 matrices[128]; | |||
} bones; | |||
void main() { | |||
gl_Position = | |||
uniforms.prj * | |||
uniforms.cam * | |||
uniforms.obj * | |||
/* | |||
mat4 vertex_matrix = | |||
bones.matrices[int(in_blendindices.x)] * in_blendweights.x + | |||
bones.matrices[int(in_blendindices.y)] * in_blendweights.y + | |||
bones.matrices[int(in_blendindices.z)] * in_blendweights.z + | |||
bones.matrices[int(in_blendindices.w)] * in_blendweights.w; | |||
*/ | |||
vec4 position = | |||
//vertex_matrix * | |||
vec4(in_position, 1.0); | |||
gl_Position = | |||
uniforms.projec * | |||
uniforms.camera * | |||
uniforms.object * | |||
position; | |||
vertex_texcoord = in_texcoord; | |||
vertex_color = in_color; | |||
} | |||
@@ -4,6 +4,7 @@ pub mod image; | |||
pub mod model; | |||
pub mod read; | |||
pub mod text; | |||
pub mod uniforms; | |||
pub mod vertex; | |||
pub mod vfs; | |||
@@ -2,10 +2,11 @@ use crate::{ | |||
data::{read, vertex::Vertex}, | |||
ffi, | |||
}; | |||
use glam::{Vec3A, Vec4}; | |||
use glam::{Mat4, Quat, Vec3, Vec3A, Vec4}; | |||
use smol_str::SmolStr; | |||
use std::{ | |||
collections::HashMap, | |||
convert::TryInto, | |||
io::{self, Read, Seek, SeekFrom}, | |||
ops::Range, | |||
str::Utf8Error, | |||
@@ -32,6 +33,8 @@ struct VertexZipper { | |||
pos_v: std::vec::IntoIter<Vec3A>, | |||
tex_v: std::vec::IntoIter<Vec3A>, | |||
nrm_v: std::vec::IntoIter<Vec3A>, | |||
idx_v: std::vec::IntoIter<Vec4>, | |||
wgt_v: std::vec::IntoIter<Vec4>, | |||
clr_v: std::vec::IntoIter<Vec4>, | |||
} | |||
@@ -41,26 +44,56 @@ pub struct Mesh { | |||
idx: Range<usize>, | |||
} | |||
pub struct Joint { | |||
//nam: SmolStr, | |||
par: Option<usize>, | |||
mat: Mat4, | |||
} | |||
pub struct Pose { | |||
par: Option<usize>, | |||
msk: u32, | |||
ofs: [f32; 10], | |||
scl: [f32; 10], | |||
} | |||
/// Data to be uploaded to the GPU. Separate from Model so that it may | |||
/// be dropped after upload. | |||
pub struct ModelData { | |||
pub vtx: Vec<Vertex>, | |||
pub idx: Vec<u32>, | |||
} | |||
/// Run-time model data. Anything necessary for passing commands to | |||
/// the GPU. | |||
pub struct Model { | |||
meshes: HashMap<SmolStr, Mesh>, | |||
num_frmc: usize, | |||
frames: Vec<u16>, | |||
joints: Vec<Joint>, | |||
poses: Vec<Pose>, | |||
} | |||
impl Iterator for VertexZipper { | |||
type Item = (Option<Vec3A>, Option<Vec3A>, Option<Vec3A>, Option<Vec4>); | |||
type Item = ( | |||
Option<Vec3A>, | |||
Option<Vec3A>, | |||
Option<Vec3A>, | |||
Option<Vec4>, | |||
Option<Vec4>, | |||
Option<Vec4>, | |||
); | |||
fn next(&mut self) -> Option<Self::Item> { | |||
match ( | |||
self.pos_v.next(), | |||
self.tex_v.next(), | |||
self.nrm_v.next(), | |||
self.idx_v.next(), | |||
self.wgt_v.next(), | |||
self.clr_v.next(), | |||
) { | |||
(None, None, None, None) => None, | |||
(None, None, None, None, None, None) => None, | |||
tuple => Some(tuple), | |||
} | |||
} | |||
@@ -97,14 +130,14 @@ impl Mesh { | |||
} | |||
impl Model { | |||
pub fn read<R>(rd: &mut R) -> Result<(Self, ModelData), ErrModelRead> | |||
pub fn read<R>(rd: &mut R) -> Result<(Self, ModelData), Err> | |||
where | |||
R: Read + Seek, | |||
{ | |||
fn from_stab(stab: &[u8], sbeg: usize) -> Result<&str, ErrModelRead> { | |||
let sbeg = stab.get(sbeg..).ok_or(ErrModelRead::TextOffset)?; | |||
fn from_stab(stab: &[u8], sbeg: usize) -> Result<&str, Err> { | |||
let sbeg = stab.get(sbeg..).ok_or(Err::TextOffset)?; | |||
let send = ffi::end_of_cstr(sbeg); | |||
let sbeg = sbeg.get(..send).ok_or(ErrModelRead::TextOffset)?; | |||
let sbeg = sbeg.get(..send).ok_or(Err::TextOffset)?; | |||
Ok(std::str::from_utf8(sbeg)?) | |||
} | |||
@@ -112,7 +145,7 @@ impl Model { | |||
rd.read_exact(&mut head)?; | |||
if &head[0..20] != b"INTERQUAKEMODEL\0\x02\0\0\0" { | |||
return Err(ErrModelRead::Magic); | |||
return Err(Err::Magic); | |||
} | |||
let num_text = read::u32le_sz(&head, 28); | |||
@@ -124,28 +157,27 @@ impl Model { | |||
let ofs_vinf = read::u32le_64(&head, 52); | |||
let num_tris = read::u32le_sz(&head, 56); | |||
let ofs_tris = read::u32le_64(&head, 60); | |||
/* | |||
let ofs_adja = read::u32le_64(&head, 64); | |||
let num_join = read::u32le_sz(&head, 68); | |||
let ofs_join = read::u32le_64(&head, 72); | |||
let num_pose = read::u32le_sz(&head, 76); | |||
let ofs_pose = read::u32le_64(&head, 80); | |||
let num_anim = read::u32le_sz(&head, 84); | |||
let ofs_anim = read::u32le_64(&head, 88); | |||
//let num_anim = read::u32le_sz(&head, 84); | |||
//let ofs_anim = read::u32le_64(&head, 88); | |||
let num_frms = read::u32le_sz(&head, 92); | |||
let num_frmc = read::u32le_sz(&head, 96); | |||
let ofs_frms = read::u32le_64(&head, 100); | |||
let ofs_bnds = read::u32le_64(&head, 104); | |||
let num_cmmt = read::u32le_sz(&head, 108); | |||
let ofs_cmmt = read::u32le_64(&head, 112); | |||
let num_exts = read::u32le_sz(&head, 116); | |||
let ofs_exts = read::u32le_64(&head, 120); | |||
*/ | |||
//let ofs_bnds = read::u32le_64(&head, 104); | |||
if num_join != 0 && num_pose != 0 && num_pose != num_join { | |||
return Err(Err::NumPoses); | |||
} | |||
// collect vertex info | |||
let mut pos_v = Vec::with_capacity(num_vert); | |||
let mut tex_v = Vec::with_capacity(num_vert); | |||
let mut nrm_v = Vec::with_capacity(num_vert); | |||
let mut idx_v = Vec::with_capacity(num_vert); | |||
let mut wgt_v = Vec::with_capacity(num_vert); | |||
let mut clr_v = Vec::with_capacity(num_vert); | |||
rd.seek(SeekFrom::Start(ofs_vinf))?; | |||
@@ -184,10 +216,22 @@ impl Model { | |||
// ignore tangents for now | |||
} | |||
4 => { | |||
// ignore blend indices for now | |||
for idx in read::hunk(rd, 4 * num_vert)?.chunks(4) { | |||
let idx0 = f32::from(idx[0]); | |||
let idx1 = f32::from(idx[1]); | |||
let idx2 = f32::from(idx[2]); | |||
let idx3 = f32::from(idx[3]); | |||
idx_v.push(Vec4::new(idx0, idx1, idx2, idx3)); | |||
} | |||
} | |||
5 => { | |||
// ignore blend weights for now | |||
for wgt in read::hunk(rd, 4 * num_vert)?.chunks(4) { | |||
let wgt0 = f32::from(wgt[0]) / 255.0; | |||
let wgt1 = f32::from(wgt[1]) / 255.0; | |||
let wgt2 = f32::from(wgt[2]) / 255.0; | |||
let wgt3 = f32::from(wgt[3]) / 255.0; | |||
wgt_v.push(Vec4::new(wgt0, wgt1, wgt2, wgt3)); | |||
} | |||
} | |||
6 => { | |||
for clr in read::hunk(rd, 4 * num_vert)?.chunks(4) { | |||
@@ -198,7 +242,7 @@ impl Model { | |||
clr_v.push(Vec4::new(r, g, b, a)); | |||
} | |||
} | |||
_ => return Err(ErrModelRead::UnknownType), | |||
_ => return Err(Err::UnknownType), | |||
} | |||
} | |||
@@ -207,17 +251,21 @@ impl Model { | |||
pos_v: pos_v.into_iter(), | |||
tex_v: tex_v.into_iter(), | |||
nrm_v: nrm_v.into_iter(), | |||
idx_v: idx_v.into_iter(), | |||
wgt_v: wgt_v.into_iter(), | |||
clr_v: clr_v.into_iter(), | |||
}; | |||
let mut vert_dat = Vec::with_capacity(num_vert); | |||
for (pos, tex, nrm, clr) in zipper { | |||
let pos = pos.unwrap_or(Vec3A::new(0.0, 0.0, 0.0)); | |||
let tex = tex.unwrap_or(Vec3A::new(0.0, 0.0, 0.0)); | |||
let nrm = nrm.unwrap_or(Vec3A::new(0.0, 0.0, 0.0)); | |||
let clr = clr.unwrap_or(Vec4::new(1.0, 1.0, 1.0, 1.0)); | |||
vert_dat.push(Vertex { pos, tex, nrm, clr }); | |||
for (pos, tex, nrm, idx, wgt, clr) in zipper { | |||
let pos = pos.unwrap_or_else(|| Vec3A::new(0.0, 0.0, 0.0)); | |||
let tex = tex.unwrap_or_else(|| Vec3A::new(0.0, 0.0, 0.0)); | |||
let nrm = nrm.unwrap_or_else(|| Vec3A::new(0.0, 0.0, 0.0)); | |||
let idx = idx.unwrap_or_else(|| Vec4::new(0.0, 0.0, 0.0, 0.0)); | |||
let wgt = wgt.unwrap_or_else(|| Vec4::new(0.0, 0.0, 0.0, 0.0)); | |||
let clr = clr.unwrap_or_else(|| Vec4::new(1.0, 1.0, 1.0, 1.0)); | |||
vert_dat.push(Vertex { pos, tex, nrm, idx, wgt, clr }); | |||
} | |||
// collect index info | |||
@@ -258,7 +306,109 @@ impl Model { | |||
meshes.insert(nam, Mesh { mat, vtx, idx }); | |||
} | |||
Ok((Self { meshes }, ModelData { vtx: vert_dat, idx: indx_dat })) | |||
// collect joint info | |||
let mut joints = Vec::with_capacity(num_join); | |||
rd.seek(SeekFrom::Start(ofs_join))?; | |||
for join in read::hunk(rd, num_join * 4 * 12)?.chunks(4 * 12) { | |||
let trs = &mut [0.0; 10]; | |||
//let nam = read::u32le_sz(join, 0); | |||
let par = read::u32le_sz(join, 4); | |||
let trs = read::array(read::f32le_32, join, trs, 4, 8); | |||
//let nam = SmolStr::new(from_stab(&stab, nam)?); | |||
let par = if par & 0x8000_0000 != 0 { None } else { Some(par) }; | |||
let mat = Mat4::from_scale_rotation_translation( | |||
Vec3::new(trs[0], trs[1], trs[2]), | |||
Quat::from_xyzw(trs[3], trs[4], trs[5], trs[6]), | |||
Vec3::new(trs[7], trs[8], trs[9]), | |||
); | |||
joints.push(Joint { /*nam,*/ par, mat }); | |||
} | |||
// collect frames | |||
let mut frames = Vec::with_capacity(num_frms * num_frmc); | |||
rd.seek(SeekFrom::Start(ofs_frms))?; | |||
for samp in read::hunk(rd, num_frms * num_frmc * 2)?.chunks(2) { | |||
frames.push(read::u16le_16(samp, 0)); | |||
} | |||
// collect pose info | |||
let mut poses = Vec::with_capacity(num_pose); | |||
rd.seek(SeekFrom::Start(ofs_pose))?; | |||
for pose in read::hunk(rd, num_pose * 4 * 22)?.chunks(4 * 22) { | |||
let ofs = &mut [0.0; 10]; | |||
let scl = &mut [0.0; 10]; | |||
let par = read::u32le_sz(pose, 0); | |||
let msk = read::u32le_32(pose, 4); | |||
let ofs = read::array(read::f32le_32, pose, ofs, 4, 8); | |||
let scl = read::array(read::f32le_32, pose, scl, 4, 48); | |||
let par = if par & 0x8000_0000 != 0 { None } else { Some(par) }; | |||
poses.push(Pose { | |||
par, | |||
msk, | |||
ofs: ofs.try_into().unwrap(), | |||
scl: scl.try_into().unwrap(), | |||
}); | |||
} | |||
Ok(( | |||
Self { meshes, num_frmc, frames, joints, poses }, | |||
ModelData { vtx: vert_dat, idx: indx_dat }, | |||
)) | |||
} | |||
pub fn num_frames(&self) -> usize { | |||
self.frames.len() / self.num_frmc | |||
} | |||
pub fn frame(&self, joint: usize, frame: usize) -> Option<Mat4> { | |||
Some(self.joint_mat(joint)? * self.pose_mat(joint, frame)?) | |||
} | |||
pub fn pose_mat(&self, joint: usize, frame: usize) -> Option<Mat4> { | |||
let pose = self.poses.get(joint)?; | |||
let mut trs = [0.0; 10]; | |||
let mut frames = self.frames.iter().skip(frame * self.num_frmc); | |||
for i in 0..10 { | |||
if pose.msk & 1 << i != 0 { | |||
let frame = f32::from(*frames.next()?); | |||
trs[i] = pose.ofs[i] + frame * pose.scl[i]; | |||
} | |||
} | |||
let mut mat = Mat4::from_scale_rotation_translation( | |||
Vec3::new(trs[0], trs[1], trs[2]), | |||
Quat::from_xyzw(trs[3], trs[4], trs[5], trs[6]), | |||
Vec3::new(trs[7], trs[8], trs[9]), | |||
); | |||
if let Some(parent) = pose.par { | |||
mat = self.pose_mat(parent, frame)? * mat; | |||
} | |||
Some(mat) | |||
} | |||
fn joint_mat(&self, joint: usize) -> Option<Mat4> { | |||
let jnt = self.joints.get(joint)?; | |||
let mut mat = jnt.mat; | |||
if let Some(parent) = jnt.par { | |||
mat = self.joint_mat(parent)? * mat; | |||
} | |||
Some(mat) | |||
} | |||
} | |||
@@ -24,6 +24,20 @@ pub fn f32le_32(b: &[u8], p: usize) -> f32 { | |||
f32::from_le_bytes([b[p], b[p + 1], b[p + 2], b[p + 3]]) | |||
} | |||
pub fn array<'a, 'b, T>( | |||
f: impl Fn(&[u8], usize) -> T, | |||
b: &'a [u8], | |||
v: &'b mut [T], | |||
step: usize, | |||
beg: usize, | |||
) -> &'b [T] { | |||
for (i, p) in (beg..beg + v.len() * step).step_by(step).enumerate() { | |||
v[i] = f(b, p); | |||
} | |||
v | |||
} | |||
pub fn hunk(rd: &mut impl Read, size: usize) -> io::Result<Vec<u8>> { | |||
let mut data = Vec::with_capacity(size); | |||
unsafe { | |||
@@ -0,0 +1,10 @@ | |||
use glam::Mat4; | |||
#[repr(C)] | |||
pub struct Uniforms { | |||
pub object: Mat4, | |||
pub camera: Mat4, | |||
pub projec: Mat4, | |||
} | |||
// EOF |
@@ -1,4 +1,3 @@ | |||
use ash::vk; | |||
use glam::{Vec3A, Vec4}; | |||
#[repr(C)] | |||
@@ -6,43 +5,9 @@ pub struct Vertex { | |||
pub pos: Vec3A, | |||
pub tex: Vec3A, | |||
pub nrm: Vec3A, | |||
pub idx: Vec4, | |||
pub wgt: Vec4, | |||
pub clr: Vec4, | |||
} | |||
impl Vertex { | |||
pub const BIND_DESC: [vk::VertexInputBindingDescription; 1] = | |||
[vk::VertexInputBindingDescription { | |||
binding: 0, | |||
stride: std::mem::size_of::<Self>() as u32, | |||
input_rate: vk::VertexInputRate::VERTEX, | |||
}]; | |||
pub const ATTR_DESC: [vk::VertexInputAttributeDescription; 4] = [ | |||
vk::VertexInputAttributeDescription { | |||
location: 0, | |||
binding: 0, | |||
format: vk::Format::R32G32B32_SFLOAT, | |||
offset: 0, | |||
}, | |||
vk::VertexInputAttributeDescription { | |||
location: 1, | |||
binding: 0, | |||
format: vk::Format::R32G32B32_SFLOAT, | |||
offset: 16, | |||
}, | |||
vk::VertexInputAttributeDescription { | |||
location: 2, | |||
binding: 0, | |||
format: vk::Format::R32G32B32_SFLOAT, | |||
offset: 32, | |||
}, | |||
vk::VertexInputAttributeDescription { | |||
location: 3, | |||
binding: 0, | |||
format: vk::Format::R32G32B32A32_SFLOAT, | |||
offset: 48, | |||
}, | |||
]; | |||
} | |||
// EOF |
@@ -21,7 +21,8 @@ mod shader; | |||
mod spir; | |||
mod surface; | |||
mod swapchain; | |||
mod uniforms; | |||
pub mod misc; | |||
pub use self::{ | |||
buffer::Buffer, | |||
@@ -50,12 +51,6 @@ pub use self::{ | |||
spir::Spir, | |||
surface::Surface, | |||
swapchain::Swapchain, | |||
uniforms::Uniforms, | |||
}; | |||
/// Returns the size of `data` as a `vk::DeviceSize`. | |||
pub(self) const fn dev_size_of<T>(data: &[T]) -> ash::vk::DeviceSize { | |||
(std::mem::size_of::<T>() * data.len()) as ash::vk::DeviceSize | |||
} | |||
// EOF |
@@ -1,8 +1,6 @@ | |||
use crate::{ | |||
data::{self, vertex::Vertex}, | |||
render::{ | |||
dev_size_of, CommandPool, Device, ErrAllocMem, GetDevice, Uniforms, | |||
}, | |||
render::{misc::dev_size_of, CommandPool, Device, ErrAllocMem, GetDevice}, | |||
}; | |||
use ash::{version::DeviceV1_0, vk}; | |||
use std::{ptr, rc::Rc}; | |||
@@ -132,9 +130,10 @@ impl Buffer { | |||
} | |||
/// Creates a uniform buffer. | |||
pub fn create_uniform(device: Rc<Device>) -> Result<Rc<Self>, ErrAllocMem> { | |||
let size = std::mem::size_of::<Uniforms>() as vk::DeviceSize; | |||
pub fn create_uniform( | |||
device: Rc<Device>, | |||
size: vk::DeviceSize, | |||
) -> Result<Rc<Self>, ErrAllocMem> { | |||
let (handle, memory) = unsafe { | |||
create_buffer( | |||
&device, | |||
@@ -1,4 +1,4 @@ | |||
use crate::render::{Device, GetDevice, Sampler, Uniforms}; | |||
use crate::render::{misc, Device, GetDevice}; | |||
use ash::{version::DeviceV1_0, vk}; | |||
use std::rc::Rc; | |||
@@ -16,11 +16,9 @@ impl GetDevice for DescriptorSetLayout { | |||
impl DescriptorSetLayout { | |||
pub fn create(device: Rc<Device>) -> Result<Rc<Self>, vk::Result> { | |||
let descs = [Uniforms::BIND_DESC, Sampler::BIND_DESC]; | |||
let create_info = vk::DescriptorSetLayoutCreateInfo { | |||
binding_count: descs.len() as u32, | |||
p_bindings: descs.as_ptr(), | |||
binding_count: misc::DSC_BIND_DESC.len() as u32, | |||
p_bindings: misc::DSC_BIND_DESC.as_ptr(), | |||
..Default::default() | |||
}; | |||
@@ -1,6 +1,5 @@ | |||
use crate::render::{ | |||
Buffer, DescriptorSetLayout, Device, GetDevice, ImageView, Sampler, | |||
Uniforms, | |||
misc, Buffer, DescriptorSetLayout, Device, GetDevice, ImageView, Sampler, | |||
}; | |||
use ash::{version::DeviceV1_0, vk}; | |||
use std::rc::Rc; | |||
@@ -9,7 +8,7 @@ pub struct DescriptorPool { | |||
handle: vk::DescriptorPool, | |||
pub layout: Rc<DescriptorSetLayout>, | |||
pub buffers: Vec<Rc<Buffer>>, | |||
pub buffers: Vec<(Rc<Buffer>, Rc<Buffer>)>, | |||
pub sets: Vec<vk::DescriptorSet>, | |||
pub image_view: Rc<ImageView>, | |||
pub sampler: Rc<Sampler>, | |||
@@ -24,11 +23,15 @@ impl GetDevice for DescriptorPool { | |||
impl DescriptorPool { | |||
pub fn create( | |||
layout: Rc<DescriptorSetLayout>, | |||
buffers: Vec<Rc<Buffer>>, | |||
buffers: Vec<(Rc<Buffer>, Rc<Buffer>)>, | |||
image_view: Rc<ImageView>, | |||
sampler: Rc<Sampler>, | |||
) -> Result<Rc<Self>, vk::Result> { | |||
let size_info = [ | |||
vk::DescriptorPoolSize { | |||
ty: vk::DescriptorType::UNIFORM_BUFFER, | |||
descriptor_count: buffers.len() as u32, | |||
}, | |||
vk::DescriptorPoolSize { | |||
ty: vk::DescriptorType::UNIFORM_BUFFER, | |||
descriptor_count: buffers.len() as u32, | |||
@@ -62,48 +65,58 @@ impl DescriptorPool { | |||
let sets = | |||
unsafe { layout.get_device().allocate_descriptor_sets(&alloc_info)? }; | |||
let write_infos = buffers | |||
.iter() | |||
.map(|buffer| { | |||
( | |||
vk::DescriptorBufferInfo { | |||
buffer: ***buffer, | |||
range: std::mem::size_of::<Uniforms>() as vk::DeviceSize, | |||
..Default::default() | |||
}, | |||
vk::DescriptorImageInfo { | |||
sampler: **sampler, | |||
image_view: **image_view, | |||
image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, | |||
}, | |||
) | |||
}) | |||
.collect::<Vec<_>>(); | |||
let write_descriptors = sets | |||
.iter() | |||
.zip(&write_infos) | |||
.flat_map(|(dst_set, (buffer_info, image_info))| { | |||
vec![ | |||
vk::WriteDescriptorSet { | |||
dst_set: *dst_set, | |||
dst_binding: Uniforms::BIND_IDEN, | |||
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER, | |||
descriptor_count: 1, | |||
p_buffer_info: &*buffer_info, | |||
..Default::default() | |||
}, | |||
vk::WriteDescriptorSet { | |||
dst_set: *dst_set, | |||
dst_binding: Sampler::BIND_IDEN, | |||
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, | |||
descriptor_count: 1, | |||
p_image_info: &*image_info, | |||
..Default::default() | |||
}, | |||
] | |||
}) | |||
.collect::<Vec<_>>(); | |||
let mut write_infos = Vec::with_capacity(buffers.len()); | |||
for (ufm_buf, bon_buf) in buffers.iter() { | |||
write_infos.push(( | |||
vk::DescriptorBufferInfo { | |||
buffer: ***ufm_buf, | |||
range: misc::UFM_BIND_SIZE, | |||
..Default::default() | |||
}, | |||
vk::DescriptorBufferInfo { | |||
buffer: ***bon_buf, | |||
range: misc::BON_BIND_SIZE, | |||
..Default::default() | |||
}, | |||
vk::DescriptorImageInfo { | |||
sampler: **sampler, | |||
image_view: **image_view, | |||
image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, | |||
}, | |||
)); | |||
} | |||
let mut write_descriptors = Vec::with_capacity(sets.len() * 3); | |||
for (dst_set, infos) in sets.iter().zip(&write_infos) { | |||
write_descriptors.push(vk::WriteDescriptorSet { | |||
dst_set: *dst_set, | |||
dst_binding: misc::UFM_BIND_IDEN, | |||
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER, | |||
descriptor_count: 1, | |||
p_buffer_info: &infos.0, | |||
..Default::default() | |||
}); | |||
write_descriptors.push(vk::WriteDescriptorSet { | |||
dst_set: *dst_set, | |||
dst_binding: misc::BON_BIND_IDEN, | |||
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER, | |||
descriptor_count: 1, | |||
p_buffer_info: &infos.1, | |||
..Default::default() | |||
}); | |||
write_descriptors.push(vk::WriteDescriptorSet { | |||
dst_set: *dst_set, | |||
dst_binding: misc::SMP_BIND_IDEN, | |||
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, | |||
descriptor_count: 1, | |||
p_image_info: &infos.2, | |||
..Default::default() | |||
}); | |||
} | |||
unsafe { | |||
layout.get_device().update_descriptor_sets(&write_descriptors, &[]); | |||
@@ -1,7 +1,7 @@ | |||
use crate::{ | |||
data::image::MipImage, | |||
render::{ | |||
dev_size_of, Buffer, CommandPool, Device, ErrAllocMem, GetDevice, | |||
misc::dev_size_of, Buffer, CommandPool, Device, ErrAllocMem, GetDevice, | |||
Swapchain, | |||
}, | |||
}; | |||
@@ -0,0 +1,88 @@ | |||
use crate::data::{uniforms::Uniforms, vertex::Vertex}; | |||
use ash::vk; | |||
use glam::Mat4; | |||
use std::mem::size_of; | |||
/// Returns the size of `data` as a `vk::DeviceSize`. | |||
pub const fn dev_size_of<T>(data: &[T]) -> ash::vk::DeviceSize { | |||
(size_of::<T>() * data.len()) as ash::vk::DeviceSize | |||
} | |||
pub const UFM_BIND_SIZE: vk::DeviceSize = size_of::<Uniforms>() as _; | |||
pub const BON_BIND_SIZE: vk::DeviceSize = size_of::<[Mat4; 128]>() as _; | |||
pub const UFM_BIND_IDEN: u32 = 0; | |||
pub const BON_BIND_IDEN: u32 = 1; | |||
pub const SMP_BIND_IDEN: u32 = 2; | |||
pub const DSC_BIND_DESC: [vk::DescriptorSetLayoutBinding; 3] = [ | |||
vk::DescriptorSetLayoutBinding { | |||
binding: UFM_BIND_IDEN, | |||
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER, | |||
descriptor_count: 1, | |||
stage_flags: vk::ShaderStageFlags::VERTEX, | |||
p_immutable_samplers: std::ptr::null(), | |||
}, | |||
vk::DescriptorSetLayoutBinding { | |||
binding: BON_BIND_IDEN, | |||
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER, | |||
descriptor_count: 1, | |||
stage_flags: vk::ShaderStageFlags::VERTEX, | |||
p_immutable_samplers: std::ptr::null(), | |||
}, | |||
vk::DescriptorSetLayoutBinding { | |||
binding: SMP_BIND_IDEN, | |||
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, | |||
descriptor_count: 1, | |||
stage_flags: vk::ShaderStageFlags::FRAGMENT, | |||
p_immutable_samplers: std::ptr::null(), | |||
}, | |||
]; | |||
pub const VTX_BIND_DESC: [vk::VertexInputBindingDescription; 1] = | |||
[vk::VertexInputBindingDescription { | |||
binding: 0, | |||
stride: size_of::<Vertex>() as u32, | |||
input_rate: vk::VertexInputRate::VERTEX, | |||
}]; | |||
pub const VTX_ATTR_DESC: [vk::VertexInputAttributeDescription; 6] = [ | |||
vk::VertexInputAttributeDescription { | |||
location: 0, | |||
binding: 0, | |||
format: vk::Format::R32G32B32_SFLOAT, | |||
offset: 0, | |||
}, | |||
vk::VertexInputAttributeDescription { | |||
location: 1, | |||
binding: 0, | |||
format: vk::Format::R32G32B32_SFLOAT, | |||
offset: 16, | |||
}, | |||
vk::VertexInputAttributeDescription { | |||
location: 2, | |||
binding: 0, | |||
format: vk::Format::R32G32B32_SFLOAT, | |||
offset: 32, | |||
}, | |||
vk::VertexInputAttributeDescription { | |||
location: 3, | |||
binding: 0, | |||
format: vk::Format::R32G32B32A32_SFLOAT, | |||
offset: 48, | |||
}, | |||
vk::VertexInputAttributeDescription { | |||
location: 4, | |||
binding: 0, | |||
format: vk::Format::R32G32B32A32_SFLOAT, | |||
offset: 64, | |||
}, | |||
vk::VertexInputAttributeDescription { | |||
location: 5, | |||
binding: 0, | |||
format: vk::Format::R32G32B32A32_SFLOAT, | |||
offset: 80, | |||
}, | |||
]; | |||
// EOF |
@@ -3,6 +3,7 @@ use crate::{ | |||
render::{Buffer, CommandPool, Device, ErrAllocMem, GetDevice}, | |||
}; | |||
use ash::{version::DeviceV1_0, vk}; | |||
use glam::Mat4; | |||
use std::rc::Rc; | |||
#[derive(Error, Debug)] | |||
@@ -74,6 +75,18 @@ impl Model { | |||
Err(ErrModelDraw::NoMesh(mesh.to_owned())) | |||
} | |||
} | |||
pub fn frame_matrices(&self, frame: usize) -> [Mat4; 128] { | |||
let mut matrices = [Mat4::identity(); 128]; | |||
let mut joint = 0; | |||
while let Some(mat) = self.model.frame(joint, frame) { | |||
matrices[joint] = mat; | |||
joint += 1; | |||
} | |||
matrices | |||
} | |||
} | |||
// EOF |
@@ -1,6 +1,5 @@ | |||
use crate::{ | |||
data::vertex::Vertex, | |||
render::{Device, GetDevice, PipelineLayout, RenderPass, ShaderModule}, | |||
use crate::render::{ | |||
misc, Device, GetDevice, PipelineLayout, RenderPass, ShaderModule, | |||
}; | |||
use ash::{version::DeviceV1_0, vk}; | |||
use std::rc::Rc; | |||
@@ -87,10 +86,10 @@ impl Pipeline { | |||
]; | |||
let vertex_input_state = vk::PipelineVertexInputStateCreateInfo { | |||
vertex_binding_description_count: Vertex::BIND_DESC.len() as u32, | |||
p_vertex_binding_descriptions: Vertex::BIND_DESC.as_ptr(), | |||
vertex_attribute_description_count: Vertex::ATTR_DESC.len() as u32, | |||
p_vertex_attribute_descriptions: Vertex::ATTR_DESC.as_ptr(), | |||
vertex_binding_description_count: misc::VTX_BIND_DESC.len() as u32, | |||
p_vertex_binding_descriptions: misc::VTX_BIND_DESC.as_ptr(), | |||
vertex_attribute_description_count: misc::VTX_ATTR_DESC.len() as u32, | |||
p_vertex_attribute_descriptions: misc::VTX_ATTR_DESC.as_ptr(), | |||
..Default::default() | |||
}; | |||
@@ -15,17 +15,6 @@ impl GetDevice for Sampler { | |||
} | |||
impl Sampler { | |||
pub const BIND_IDEN: u32 = 1; | |||
pub const BIND_DESC: vk::DescriptorSetLayoutBinding = | |||
vk::DescriptorSetLayoutBinding { | |||
binding: Self::BIND_IDEN, | |||
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, | |||
descriptor_count: 1, | |||
stage_flags: vk::ShaderStageFlags::FRAGMENT, | |||
p_immutable_samplers: std::ptr::null(), | |||
}; | |||
pub fn create( | |||
device: Rc<Device>, | |||
conf: &Conf, | |||
@@ -1,24 +0,0 @@ | |||
use ash::vk; | |||
use glam::Mat4; | |||
#[repr(C)] | |||
pub struct Uniforms { | |||
pub object: Mat4, | |||
pub camera: Mat4, | |||
pub projection: Mat4, | |||
} | |||
impl Uniforms { | |||
pub const BIND_IDEN: u32 = 0; | |||
pub const BIND_DESC: vk::DescriptorSetLayoutBinding = | |||
vk::DescriptorSetLayoutBinding { | |||
binding: Self::BIND_IDEN, | |||
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER, | |||
descriptor_count: 1, | |||
stage_flags: vk::ShaderStageFlags::VERTEX, | |||
p_immutable_samplers: std::ptr::null(), | |||
}; | |||
} | |||
// EOF |
@@ -4,11 +4,11 @@ use blonkus_fw::{ | |||
data::{self, vfs}, | |||
hal, lg, log, meta, | |||
render::{ | |||
self, Buffer, CommandBuffers, CommandPool, DescriptorPool, | |||
self, misc, Buffer, CommandBuffers, CommandPool, DescriptorPool, | |||
DescriptorSetLayout, Device, ErrAllocMem, Fence, Framebuffer, GetDevice, | |||
Image, ImageView, IndepImage, Instance, Model, PhysicalDevice, Pipeline, | |||
PipelineLayout, Queue, QueueFamilyInfo, RenderPass, Sampler, Semaphore, | |||
ShaderModule, Spir, Surface, Swapchain, Uniforms, | |||
ShaderModule, Spir, Surface, Swapchain, | |||
}, | |||
}; | |||
use glam::{Mat4, Quat, Vec3, Vec4}; | |||
@@ -52,6 +52,8 @@ impl GetDevice for SwapchainData<'_, '_> { | |||
impl<'a> SwapchainData<'a, '_> { | |||
fn create(sc_info: SwapchainInfo<'a>) -> Result<Self, ErrAllocMem> { | |||
let device = sc_info.get_device(); | |||
let swapchain = Swapchain::create( | |||
sc_info.queue_graphics.clone(), | |||
sc_info.queue_surface.clone(), | |||
@@ -74,7 +76,7 @@ impl<'a> SwapchainData<'a, '_> { | |||
let depth_view = ImageView::create(depth_buffer.clone())?; | |||
let render_pass = RenderPass::create( | |||
sc_info.get_device().clone(), | |||
device.clone(), | |||
swapchain.format, | |||
depth_buffer.info().format, | |||
)?; | |||
@@ -96,8 +98,13 @@ impl<'a> SwapchainData<'a, '_> { | |||
let ufm_buffers = framebuffers | |||
.iter() | |||
.map(|_| Buffer::create_uniform(sc_info.get_device().clone())) | |||
.collect::<Result<_, _>>()?; | |||
.map(|_| { | |||
Ok(( | |||
Buffer::create_uniform(device.clone(), misc::UFM_BIND_SIZE)?, | |||
Buffer::create_uniform(device.clone(), misc::BON_BIND_SIZE)?, | |||
)) | |||
}) | |||
.collect::<Result<Vec<(Rc<Buffer>, Rc<Buffer>)>, ErrAllocMem>>()?; | |||
let descriptor_pool = DescriptorPool::create( | |||
sc_info.layout.descriptor.clone(), | |||
@@ -132,7 +139,7 @@ impl<'a> SwapchainData<'a, '_> { | |||
let begin_info = vk::CommandBufferBeginInfo::default(); | |||
unsafe { | |||
sc_info.get_device().begin_command_buffer(buf, &begin_info)?; | |||
device.begin_command_buffer(buf, &begin_info)?; | |||
let clear_values = [ | |||
vk::ClearValue { | |||
@@ -160,19 +167,19 @@ impl<'a> SwapchainData<'a, '_> { | |||
..Default::default() | |||
}; | |||
sc_info.get_device().cmd_begin_render_pass( | |||
device.cmd_begin_render_pass( | |||
buf, | |||
&begin_info, | |||
vk::SubpassContents::INLINE, | |||
); | |||
sc_info.get_device().cmd_bind_pipeline( | |||
device.cmd_bind_pipeline( | |||
buf, | |||
vk::PipelineBindPoint::GRAPHICS, | |||
**pipeline, | |||
); | |||
sc_info.get_device().cmd_bind_descriptor_sets( | |||
device.cmd_bind_descriptor_sets( | |||
buf, | |||
vk::PipelineBindPoint::GRAPHICS, | |||
**sc_info.layout, | |||
@@ -184,9 +191,9 @@ impl<'a> SwapchainData<'a, '_> { | |||
// TODO | |||
sc_info.model.draw(buf, "mesh0").unwrap(); | |||
sc_info.get_device().cmd_end_render_pass(buf); | |||
device.cmd_end_render_pass(buf); | |||
sc_info.get_device().end_command_buffer(buf)?; | |||
device.end_command_buffer(buf)?; | |||
} | |||
} | |||
@@ -238,21 +245,21 @@ fn draw_frame<'b>( | |||
let time_1 = time_ms as f32 / 1_000.0; | |||
let pos = Vec3::new(0.0, f32::sin(time_1 / 2.0) * 8.0, 0.0); | |||
let pos = Vec3::new(0.0, /*f32::sin(time_1 / 2.0) * 0.5*/ 2.0, 0.0); | |||
let object = Mat4::from_scale_rotation_translation( | |||
Vec3::new(0.025, 0.025, 0.025), | |||
Quat::from_rotation_z(PI * 2.0 * time_1 / 10.0), | |||
Quat::from_rotation_z(PI/*PI * 2.0 * time_1 / 10.0*/), | |||
pos, | |||
); | |||
let camera = Mat4::look_at_rh( | |||
Vec3::new(1.0, 1.0, 1.0), | |||
Vec3::new(1.0, 1.0, 2.0), | |||
pos, | |||
Vec3::new(0.0, 0.0, 1.0), | |||
); | |||
let projection = Mat4::perspective_rh_gl( | |||
let projec = Mat4::perspective_rh_gl( | |||
PI * 2.0 / 4.0, | |||
sc_data.swapchain.extent.width as f32 | |||
/ sc_data.swapchain.extent.height as f32, | |||
@@ -265,9 +272,13 @@ fn draw_frame<'b>( | |||
Vec4::new(0.0, 0.0, 0.0, 1.0), | |||
); | |||
let uniforms = Uniforms { object, camera, projection }; | |||
let uniforms = data::uniforms::Uniforms { object, camera, projec }; | |||
sc_data.descriptor_pool.buffers[image_index].write_data(&[uniforms])?; | |||
let (ufm_buf, bon_buf) = &sc_data.descriptor_pool.buffers[image_index]; | |||
ufm_buf.write_data(&[uniforms])?; | |||
bon_buf.write_data( | |||
&sc_data.info.model.frame_matrices((time_ms / 500 % 30) as usize), | |||
)?; | |||
let wait_semaphores = [**image_avail_s]; | |||
let wait_stages = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT]; | |||
@@ -379,7 +390,9 @@ pub fn run( | |||
let cmd_pool = CommandPool::create(queue_graphics.clone())?; | |||
let img = { | |||
let arc = vfs::Arc::read_tar(&mut vfs.get("combine.texture")?.data())?; | |||
let arc = vfs::Arc::read_tar( | |||
&mut vfs.get("scientist/hltex000.texture")?.data(), | |||
)?; | |||
let img = data::image::MipImage::read(&*arc)?; | |||
Image::from_indep(IndepImage::create(&cmd_pool, &img)?) | |||
}; | |||
@@ -389,7 +402,7 @@ pub fn run( | |||
let img_sampler = Sampler::create(device.clone(), &conf.render)?; | |||
let model = data::model::Model::read(&mut Cursor::new( | |||
vfs.get("combine.iqm")?.data(), | |||
vfs.get("scientist/scientist.iqm")?.data(), | |||
))?; | |||
let model = Model::create(&cmd_pool, model.0, model.1)?; | |||