diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b31e7b7..af48f0a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [ main, style_checks ] + branches: [ master, main, style_checks ] pull_request: - branches: [ main, style_checks ] + branches: [ master, main, style_checks ] env: CARGO_TERM_COLOR: always diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index c3cfd4d..317ba7f 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -2,9 +2,9 @@ name: Style on: push: - branches: [ main, style_checks ] + branches: [ master, main, style_checks ] pull_request: - branches: [ main, style_checks ] + branches: [ master, main, style_checks ] jobs: check_clippy: diff --git a/README.md b/README.md index f967263..c819619 100644 --- a/README.md +++ b/README.md @@ -33,10 +33,10 @@ cargo run --release We are using GLSL shaders. There is no auto-compilation to SPV right now, so please use `glslc`: ``` -glslc -fshader-stage=vertex src/models/shaders/only_mesh.vert.glsl -o src/models/shaders/only_mesh.vert.spv -glslc -fshader-stage=fragment src/models/shaders/only_mesh.frag.glsl -o src/models/shaders/only_mesh.frag.spv -glslc -fshader-stage=vertex src/models/shaders/skin_mesh.vert.glsl -o src/models/shaders/skin_mesh.vert.spv -glslc -fshader-stage=fragment src/models/shaders/skin_mesh.frag.glsl -o src/models/shaders/skin_mesh.frag.spv +glslc -fshader-stage=vertex src/models/shaders/only_mesh.vert -o src/models/shaders/only_mesh.vert.spv +glslc -fshader-stage=fragment src/models/shaders/only_mesh.frag -o src/models/shaders/only_mesh.frag.spv +glslc -fshader-stage=vertex src/models/shaders/skin_mesh.vert -o src/models/shaders/skin_mesh.vert.spv +glslc -fshader-stage=fragment src/models/shaders/skin_mesh.frag -o src/models/shaders/skin_mesh.frag.spv ``` ## Sponsors diff --git a/src/graphics/vulkan.rs b/src/graphics/vulkan.rs index c1c442a..8df31b9 100644 --- a/src/graphics/vulkan.rs +++ b/src/graphics/vulkan.rs @@ -579,6 +579,27 @@ impl Gpu { self.device.vk_device.destroy_buffer(buffer, None); } + /// # Safety + /// + /// This function requires valid Vulkan entities + #[inline(always)] + pub unsafe fn create_sampler( + &self, + sampler_create_info: &vk::SamplerCreateInfo, + ) -> Result { + self.device + .vk_device + .create_sampler(sampler_create_info, None) + } + + /// # Safety + /// + /// This function requires valid Vulkan entities + #[inline(always)] + pub unsafe fn destroy_sampler(&self, sampler: vk::Sampler) { + self.device.vk_device.destroy_sampler(sampler, None); + } + /// # Safety /// /// This function requires valid Vulkan entities @@ -1035,6 +1056,27 @@ impl Gpu { ) } + /// # Safety + /// + /// This function requires valid Vulkan entities + #[allow(clippy::too_many_arguments)] + pub unsafe fn cmd_copy_buffer_to_image( + &self, + command_buffer: vk::CommandBuffer, + src_buffer: vk::Buffer, + dst_image: vk::Image, + dst_image_layout: vk::ImageLayout, + regions: &[vk::BufferImageCopy], + ) { + self.device.vk_device.cmd_copy_buffer_to_image( + command_buffer, + src_buffer, + dst_image, + dst_image_layout, + regions, + ); + } + // Utils pub fn find_memory_type_index( &self, diff --git a/src/models/materials.rs b/src/models/materials.rs index af307ac..4778d0c 100644 --- a/src/models/materials.rs +++ b/src/models/materials.rs @@ -2,6 +2,9 @@ use super::{Color, Image}; use crate::loaders::Asset; use crate::utils::Id; +// NOTE: 1:albedo_map, 2:occlusion_map, 3:metallic_map, 4:normal_map, 5:roughness_map +pub const MAX_MATERIAL_IMAGES: u32 = 5; + /// Material component #[derive(Debug)] pub struct Material { @@ -51,10 +54,10 @@ pub struct MaterialUniform { pub color: [f32; 4], /// Order: ambient_occlusion, metallic, roughness pub options: [f32; 4], - /// Indices of PBR maps in the buffer - /// Order: ambient_occlusion, metallic, normal, roughness - pub maps_1: [u32; 4], /// Index of Color map in the buffer + 3 reserved value¨ + pub maps_1: [u32; 4], + /// Indice2 of PBR maps in the buffer + /// Order: ambient_occlusion, metallic, normal, roughness pub maps_2: [u32; 4], } diff --git a/src/models/renderer.rs b/src/models/renderer.rs index e4f6e0c..19b09e6 100644 --- a/src/models/renderer.rs +++ b/src/models/renderer.rs @@ -5,11 +5,11 @@ use std::io::Cursor; use crate::graphics::vk; use crate::graphics::{Buffer, RenderPass}; use crate::loaders::Assets; -use crate::math::{Mat4, Vec3}; +use crate::models::materials::MAX_MATERIAL_IMAGES; use crate::utils::Id; use crate::world::{Camera, Entity, World}; use crate::{log, VertexJoints, VertexWeights}; -use crate::{Any, Asset, Display, Extent2D, Frame, Gpu, Ref, Task}; +use crate::{Any, Asset, Display, Extent2D, Frame, Gpu, Image, Ref, Task}; use super::materials::MaterialUniform; use super::{ @@ -21,8 +21,6 @@ use super::{ pub struct LayoutInBuffer { /// Offset inside of the buffer in bytes pub offset: u64, - /// Size of the buffer used for the mesh data - pub size: u64, /// Offset of the first item (vertex or index) pub base: u32, /// Number of items (vertices or indices) @@ -102,6 +100,23 @@ pub struct RenderModels { material_buffer_index: HashMap, u32>, /// Materials buffer data material_buffer_data: Vec, + /// Material sampler + material_sampler: vk::Sampler, + /// Material image view + material_image_view: vk::ImageView, + /// Material image memory + material_image_memory: vk::DeviceMemory, + /// Material image + material_image: vk::Image, + /// Buffer to copy material images to material_image + material_staging_buffer: Buffer, + /// Number of layers in material image buffer + material_layer_count: u32, + material_layer_size: Extent2D, + /// Material layer index in the material_image + material_layer_index: HashMap, usize>, + /// Usage of layers in material image buffer + material_layer_usage: u32, /// Mesh layouts of non-rigged models mesh_registry: HashMap, MeshLayout>, /// descriptor sets @@ -166,6 +181,18 @@ impl Drop for RenderModels { self.instance_buffer.free_memory_and_destroy(&self.gpu); self.material_buffer.free_memory_and_destroy(&self.gpu); self.transform_buffer.free_memory_and_destroy(&self.gpu); + self.material_staging_buffer + .free_memory_and_destroy(&self.gpu); + + // samplers + self.gpu.destroy_sampler(self.material_sampler); + + // image views + self.gpu.destroy_image_view(self.material_image_view); + + // images and memory + self.gpu.free_memory(self.material_image_memory); + self.gpu.destroy_image(self.material_image); // descriptors for &descriptor_set_layout in self.desc_set_layouts.iter() { @@ -398,6 +425,101 @@ impl RenderModels { Self::load_shader_module(&gpu, include_bytes!("shaders/skin_mesh.frag.spv")) .expect("Failed to load skin-mesh fragment shader module") }; + let material_sampler_create_info = vk::SamplerCreateInfo { + mag_filter: vk::Filter::LINEAR, + min_filter: vk::Filter::LINEAR, + mipmap_mode: vk::SamplerMipmapMode::LINEAR, + address_mode_u: vk::SamplerAddressMode::MIRRORED_REPEAT, + address_mode_v: vk::SamplerAddressMode::MIRRORED_REPEAT, + address_mode_w: vk::SamplerAddressMode::MIRRORED_REPEAT, + max_anisotropy: 1.0, + border_color: vk::BorderColor::FLOAT_OPAQUE_WHITE, + compare_op: vk::CompareOp::NEVER, + ..Default::default() + }; + + let material_sampler = unsafe { + gpu.create_sampler(&material_sampler_create_info) + .expect("Failed to create materials sampler") + }; + + let material_layer_count = setup.material_count * MAX_MATERIAL_IMAGES; + + let material_image_create_info = vk::ImageCreateInfo { + image_type: vk::ImageType::TYPE_2D, + format: vk::Format::R8G8B8A8_UNORM, + extent: vk::Extent3D { + width: setup.material_image_size.width, + height: setup.material_image_size.height, + depth: 1, + }, + mip_levels: 1, + array_layers: material_layer_count, + samples: vk::SampleCountFlags::TYPE_1, + tiling: vk::ImageTiling::OPTIMAL, + usage: vk::ImageUsageFlags::TRANSFER_DST | vk::ImageUsageFlags::SAMPLED, + sharing_mode: vk::SharingMode::EXCLUSIVE, + ..Default::default() + }; + let material_image = unsafe { + gpu.create_image(&material_image_create_info) + .expect("Failed to create material image") + }; + let material_image_memory_req = + unsafe { gpu.get_image_memory_requirements(material_image) }; + let material_image_memory_index = gpu + .find_memory_type_index( + &material_image_memory_req, + vk::MemoryPropertyFlags::DEVICE_LOCAL, + ) + .expect("Unable to find suitable memory index for depth image."); + + let material_image_allocate_info = vk::MemoryAllocateInfo { + allocation_size: material_image_memory_req.size, + memory_type_index: material_image_memory_index, + ..Default::default() + }; + let material_image_memory = unsafe { + gpu.allocate_memory(&material_image_allocate_info) + .expect("Failed to allocate material image") + }; + unsafe { + gpu.bind_image_memory(material_image, material_image_memory, 0) + .expect("Unable to bind depth image memory"); + }; + + let material_image_view_info = vk::ImageViewCreateInfo { + view_type: vk::ImageViewType::TYPE_2D_ARRAY, + format: material_image_create_info.format, + components: vk::ComponentMapping { + r: vk::ComponentSwizzle::R, + g: vk::ComponentSwizzle::G, + b: vk::ComponentSwizzle::B, + a: vk::ComponentSwizzle::A, + }, + subresource_range: vk::ImageSubresourceRange { + aspect_mask: vk::ImageAspectFlags::COLOR, + level_count: 1, + layer_count: material_layer_count, + ..Default::default() + }, + image: material_image, + ..Default::default() + }; + let material_image_view = unsafe { + gpu.create_image_view(&material_image_view_info) + .expect("Failed to create material image view") + }; + + let material_staging_buffer_size = MAX_MATERIAL_IMAGES + * setup.material_image_size.width + * setup.material_image_size.height + * std::mem::size_of::() as u32; + + let material_staging_buffer = unsafe { + Self::create_transfer_buffer(&gpu, material_staging_buffer_size as u64) + .expect("Could not allocate material staging buffer") + }; // bindings layout let descriptor_sizes = [ @@ -421,10 +543,11 @@ impl RenderModels { ty: vk::DescriptorType::STORAGE_BUFFER, descriptor_count: 1, }, - // vk::DescriptorPoolSize { - // ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, - // descriptor_count: 1, - // }, + // Materials textures sampler + vk::DescriptorPoolSize { + ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, + descriptor_count: 1, + }, ]; let descriptor_pool_info = vk::DescriptorPoolCreateInfo::default() .pool_sizes(&descriptor_sizes) @@ -445,7 +568,7 @@ impl RenderModels { binding: 1, descriptor_type: vk::DescriptorType::STORAGE_BUFFER, descriptor_count: 1, - stage_flags: vk::ShaderStageFlags::VERTEX, + stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT, ..Default::default() }, // Material @@ -453,7 +576,7 @@ impl RenderModels { binding: 2, descriptor_type: vk::DescriptorType::STORAGE_BUFFER, descriptor_count: 1, - stage_flags: vk::ShaderStageFlags::VERTEX, + stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT, ..Default::default() }, // Transform @@ -464,14 +587,14 @@ impl RenderModels { stage_flags: vk::ShaderStageFlags::VERTEX, ..Default::default() }, - // Materials - //vk::DescriptorSetLayoutBinding { - // binding: 1, - // descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, - // descriptor_count: 1, - // stage_flags: vk::ShaderStageFlags::FRAGMENT, - // ..Default::default() - //}, + // Materials textures sampler + vk::DescriptorSetLayoutBinding { + binding: 4, + descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, + descriptor_count: 1, + stage_flags: vk::ShaderStageFlags::FRAGMENT, + ..Default::default() + }, ]; let descriptor_info = vk::DescriptorSetLayoutCreateInfo::default().bindings(&desc_layout_bindings); @@ -507,11 +630,11 @@ impl RenderModels { offset: 0, range: transform_buffer.size, }; - // let tex_descriptor = vk::DescriptorImageInfo { - // image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, - // image_view: tex_image_view, - // sampler, - // }; + let tex_descriptor = vk::DescriptorImageInfo { + image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, + image_view: material_image_view, + sampler: material_sampler, + }; let only_mesh_write_desc_sets = [ vk::WriteDescriptorSet { @@ -546,14 +669,14 @@ impl RenderModels { p_buffer_info: &transform_storage_buffer_descriptor, ..Default::default() }, - //vk::WriteDescriptorSet { - // dst_set: descriptor_sets[0], - // dst_binding: 1, - // descriptor_count: 1, - // descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, - // p_image_info: &tex_descriptor, - // ..Default::default() - //}, + vk::WriteDescriptorSet { + dst_binding: 4, + dst_set: descriptor_sets[0], + descriptor_count: 1, + descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, + p_image_info: &tex_descriptor, + ..Default::default() + }, ]; unsafe { @@ -598,6 +721,15 @@ impl RenderModels { transform_buffer, material_buffer_index: HashMap::new(), material_buffer_data: Vec::new(), + material_sampler, + material_image_view, + material_image, + material_image_memory, + material_staging_buffer, + material_layer_count, + material_layer_usage: 0, + material_layer_index: HashMap::new(), + material_layer_size: setup.material_image_size, mesh_registry: HashMap::new(), descriptor_pool, desc_set_layouts, @@ -983,7 +1115,6 @@ impl RenderModels { }); if let Some((vertex_data, vertex_size, has_skin)) = vertex_data_and_skin_info { - let data_size = vertex_data.len() as u64; let vertex_offset = if has_skin { self.vertex_buffer_skin_mesh_usage } else { @@ -994,13 +1125,11 @@ impl RenderModels { let mesh_layout = MeshLayout { vertices: LayoutInBuffer { offset: vertex_offset, - size: data_size, base: (vertex_offset / vertex_size) as u32, count: mesh.count_vertices() as u32, }, indices: index_data.map(|data| LayoutInBuffer { offset: self.index_buffer_usage, - size: (data.len() * std::mem::size_of::()) as u64, base: (self.index_buffer_usage / (std::mem::size_of::() as u64)) as u32, count: data.len() as u32, @@ -1072,21 +1201,212 @@ impl RenderModels { } fn register_material(&mut self, material_id: Id, assets: &Assets) -> Option { - assets.get(material_id).and_then(|material| { - self.material_buffer_index - .get(&material_id) - .cloned() - .or_else(|| { - let index = self.material_buffer_index.len() as u32; - self.material_buffer_data.push(MaterialUniform::default()); - self.material_buffer_index.insert(material_id, index); - Some(index) - }) - .map(|material_index| { - self.material_buffer_data[material_index as usize] = material.into(); - material_index + let material_uniform: MaterialUniform = if let Some(material) = assets.get(material_id) { + let mut staging_layer_count: u32 = 0; + let (albedo_map_index, base_array_layer) = assets + .get(material.albedo_map) + .map(|image| { + let base_array_layer = self.material_layer_index.len(); + if !self.material_layer_index.contains_key(&material.albedo_map) { + // write to buffer + // TODO: verify material extent + unsafe { + self.material_staging_buffer.map_and_write_to_device_memory( + &self.gpu, + (staging_layer_count + * self.material_layer_size.width + * self.material_layer_size.height + * std::mem::size_of::() as u32) + as u64, + image.data(), + ); + }; + self.material_layer_index + .insert(material.albedo_map, base_array_layer); + staging_layer_count += 1; + } + let albedo_map_index = self + .material_layer_index + .get(&material.albedo_map) + .cloned() + .expect("Layer index must be inserted at this stage") + as u32; + (albedo_map_index, base_array_layer) }) - }) + .unwrap_or((0, 0)); + // flush material staging buffer + unsafe { + self.flush_material_staging_buffer(staging_layer_count, base_array_layer as u32); + }; + let mut material_uniform: MaterialUniform = material.into(); + material_uniform.maps_1 = [ + albedo_map_index, + std::u32::MAX, + std::u32::MAX, + std::u32::MAX, + ]; + material_uniform.maps_2 = [std::u32::MAX; 4]; + material_uniform + } else { + return None; + }; + // NOTE: most likely there will be need of having an index for relations + // between Id and material layer index + self.material_buffer_index + .get(&material_id) + .cloned() + .map(|material_index| { + self.material_buffer_data[material_index as usize] = material_uniform; + material_index + }) + .or_else(|| { + let material_index = self.material_buffer_index.len() as u32; + self.material_buffer_data.push(material_uniform); + self.material_buffer_index + .insert(material_id, material_index); + Some(material_index) + }) + } + + unsafe fn flush_material_staging_buffer( + &self, + staging_layer_count: u32, + base_array_layer: u32, + ) { + if staging_layer_count == 0 { + return; + } + log::debug!("copy material to vk:Image ({} layers)", staging_layer_count); + // begin + self.gpu + .wait_for_fences(&[self.command_buffer_setup_reuse_fence], true, u64::MAX) + .expect("Wait for fence failed."); + + self.gpu + .reset_fences(&[self.command_buffer_setup_reuse_fence]) + .expect("Reset fences failed."); + + self.gpu + .reset_command_buffer( + self.command_buffer_setup, + vk::CommandBufferResetFlags::RELEASE_RESOURCES, + ) + .expect("Reset command buffer failed."); + + let command_buffer_begin_info = vk::CommandBufferBeginInfo::default() + .flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT); + + self.gpu + .begin_command_buffer(self.command_buffer_setup, &command_buffer_begin_info) + .expect("Begin commandbuffer"); + + // Command buffer + // let buffer_copy_regions = (0..staging_layer_count) + // .into_iter() + // .map(|_| { + // vk::BufferImageCopy::default() + // .image_subresource( + // vk::ImageSubresourceLayers::default() + // .aspect_mask(vk::ImageAspectFlags::COLOR) + // .base_array_layer(base_array_layer) + // .layer_count(1), + // ) + // .image_extent(vk::Extent3D { + // width: self.material_layer_size.width, + // height: self.material_layer_size.height, + // depth: 1, + // }) + // }) + // .collect::>(); + let buffer_copy_regions = [vk::BufferImageCopy::default() + .image_subresource( + vk::ImageSubresourceLayers::default() + .aspect_mask(vk::ImageAspectFlags::COLOR) + .base_array_layer(base_array_layer) + .layer_count(staging_layer_count), + ) + .image_extent(vk::Extent3D { + width: self.material_layer_size.width, + height: self.material_layer_size.height, + depth: 1, + })]; + let texture_barrier = vk::ImageMemoryBarrier { + dst_access_mask: vk::AccessFlags::TRANSFER_WRITE, + new_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL, + image: self.material_image, + subresource_range: vk::ImageSubresourceRange { + aspect_mask: vk::ImageAspectFlags::COLOR, + level_count: 1, + layer_count: self.material_layer_count, // TODO: shouldn't there be total number? + ..Default::default() + }, + ..Default::default() + }; + self.gpu.cmd_pipeline_barrier( + self.command_buffer_setup, + vk::PipelineStageFlags::BOTTOM_OF_PIPE, + vk::PipelineStageFlags::TRANSFER, + vk::DependencyFlags::empty(), + &[], + &[], + &[texture_barrier], + ); + self.gpu.cmd_copy_buffer_to_image( + self.command_buffer_setup, + self.material_staging_buffer.handle, + self.material_image, + vk::ImageLayout::TRANSFER_DST_OPTIMAL, + buffer_copy_regions.as_slice(), + ); + let texture_barrier_end = vk::ImageMemoryBarrier { + src_access_mask: vk::AccessFlags::TRANSFER_WRITE, + dst_access_mask: vk::AccessFlags::SHADER_READ, + old_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL, + new_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, // TODO: shouldn't there be total number? + image: self.material_image, + subresource_range: vk::ImageSubresourceRange { + aspect_mask: vk::ImageAspectFlags::COLOR, + level_count: 1, + layer_count: self.material_layer_count, + ..Default::default() + }, + ..Default::default() + }; + self.gpu.cmd_pipeline_barrier( + self.command_buffer_setup, + vk::PipelineStageFlags::TRANSFER, + vk::PipelineStageFlags::FRAGMENT_SHADER, + vk::DependencyFlags::empty(), + &[], + &[], + &[texture_barrier_end], + ); + // end + self.gpu + .end_command_buffer(self.command_buffer_setup) + .expect("End commandbuffer"); + + let command_buffers = vec![self.command_buffer_setup]; + let wait_semaphores = []; + let wait_mask = []; + let signal_semaphores = []; + + let submit_info = vk::SubmitInfo::default() + .wait_semaphores(&wait_semaphores) + .wait_dst_stage_mask(&wait_mask) + .command_buffers(&command_buffers) + .signal_semaphores(&signal_semaphores); + + log::debug!("submit image copy"); + self.gpu + .submit_queue(&[submit_info], self.command_buffer_setup_reuse_fence) + .expect("queue submit failed."); + // wait + let fences = [self.command_buffer_setup_reuse_fence]; + self.gpu + .wait_for_fences(&fences, true, std::u64::MAX) + .expect("Failed to wait until end of textures bufering"); + log::debug!("wait_for_fences: done"); } /// Returns Buffer, binded memory and allocated size @@ -1145,6 +1465,17 @@ impl RenderModels { Buffer::create_and_allocate(gpu, &buffer_create_info) } + unsafe fn create_transfer_buffer(gpu: &Gpu, size: u64) -> Result { + let buffer_create_info = vk::BufferCreateInfo { + size, + usage: vk::BufferUsageFlags::TRANSFER_SRC, + sharing_mode: vk::SharingMode::EXCLUSIVE, + ..Default::default() + }; + + Buffer::create_and_allocate(gpu, &buffer_create_info) + } + unsafe fn load_shader_module(gpu: &Gpu, bytes: &[u8]) -> Result { // let bytes = include_bytes!("shaders/non-rigged.frag.spv"); let mut cursor = Cursor::new(bytes); @@ -1745,6 +2076,8 @@ pub struct RenderModelsSetup { instance_buffer_size: u64, material_buffer_size: u64, transform_buffer_size: u64, + material_count: u32, + material_image_size: Extent2D, } impl Default for RenderModelsSetup { @@ -1760,6 +2093,11 @@ impl Default for RenderModelsSetup { instance_buffer_size: 1000 * std::mem::size_of::() as u64, material_buffer_size: 1000 * std::mem::size_of::() as u64, transform_buffer_size: 1000 * std::mem::size_of::() as u64, + material_count: 2, + material_image_size: Extent2D { + width: 1024, + height: 1024, + }, } } } diff --git a/src/models/shaders/only_mesh.frag.glsl b/src/models/shaders/only_mesh.frag similarity index 54% rename from src/models/shaders/only_mesh.frag.glsl rename to src/models/shaders/only_mesh.frag index 3e624e1..c267d24 100644 --- a/src/models/shaders/only_mesh.frag.glsl +++ b/src/models/shaders/only_mesh.frag @@ -2,21 +2,24 @@ #extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_shading_language_420pack : enable -layout (location = 0) in vec3 world_position; -layout (location = 1) in vec3 world_normal; -layout (location = 2) in vec4 vertex_color; -layout (location = 0) out vec4 o_frag_color; +layout(location = 0) in vec3 world_position; +layout(location = 1) in vec3 world_normal; +layout(location = 2) in vec4 vertex_color; +layout(location = 3) in vec3 vertex_texture; +layout(location = 0) out vec4 o_frag_color; +layout(binding = 4) uniform sampler2DArray dtx_material_sampler; void main() { vec3 ambient_light = vec3(0.5, 0.5, 0.5); vec4 color = vec4(0.0, 0.0, 0.0, 0.0); vec3 light_color = vec3(1.0, 1.0, 1.0); - vec3 light_position = vec3(10.0, 10.0, 10.0); + vec3 light_position = vec3(10.0, 10.0, 10.0); vec3 normal = normalize(world_normal); vec3 light_direction = normalize(light_position - world_position); vec3 diffuse = max(dot(normal, light_direction), 0.0) * light_color; + vec4 texture_color = texture(dtx_material_sampler, vertex_texture); - o_frag_color = vec4((ambient_light + diffuse), 1.0) * vertex_color; + o_frag_color = vec4((ambient_light + diffuse), 1.0) * vertex_color * texture_color; } diff --git a/src/models/shaders/only_mesh.frag.spv b/src/models/shaders/only_mesh.frag.spv index 2727349..d74515c 100644 Binary files a/src/models/shaders/only_mesh.frag.spv and b/src/models/shaders/only_mesh.frag.spv differ diff --git a/src/models/shaders/only_mesh.vert.glsl b/src/models/shaders/only_mesh.vert similarity index 100% rename from src/models/shaders/only_mesh.vert.glsl rename to src/models/shaders/only_mesh.vert diff --git a/src/models/shaders/skin_mesh.frag.glsl b/src/models/shaders/skin_mesh.frag similarity index 54% rename from src/models/shaders/skin_mesh.frag.glsl rename to src/models/shaders/skin_mesh.frag index 3e624e1..6f97913 100644 --- a/src/models/shaders/skin_mesh.frag.glsl +++ b/src/models/shaders/skin_mesh.frag @@ -2,21 +2,25 @@ #extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_shading_language_420pack : enable -layout (location = 0) in vec3 world_position; -layout (location = 1) in vec3 world_normal; -layout (location = 2) in vec4 vertex_color; -layout (location = 0) out vec4 o_frag_color; +layout(location = 0) in vec3 world_position; +layout(location = 1) in vec3 world_normal; +layout(location = 2) in vec4 vertex_color; +layout(location = 3) in vec3 vertex_texture; +layout(location = 0) out vec4 o_frag_color; + +layout(binding = 4) uniform sampler2DArray dtx_material_sampler; void main() { vec3 ambient_light = vec3(0.5, 0.5, 0.5); vec4 color = vec4(0.0, 0.0, 0.0, 0.0); vec3 light_color = vec3(1.0, 1.0, 1.0); - vec3 light_position = vec3(10.0, 10.0, 10.0); + vec3 light_position = vec3(10.0, 10.0, 10.0); vec3 normal = normalize(world_normal); vec3 light_direction = normalize(light_position - world_position); vec3 diffuse = max(dot(normal, light_direction), 0.0) * light_color; + vec4 texture_color = texture(dtx_material_sampler, vertex_texture); - o_frag_color = vec4((ambient_light + diffuse), 1.0) * vertex_color; + o_frag_color = vec4((ambient_light + diffuse), 1.0) * vertex_color * texture_color; } diff --git a/src/models/shaders/skin_mesh.frag.spv b/src/models/shaders/skin_mesh.frag.spv index 2727349..d74515c 100644 Binary files a/src/models/shaders/skin_mesh.frag.spv and b/src/models/shaders/skin_mesh.frag.spv differ diff --git a/src/models/shaders/skin_mesh.vert.glsl b/src/models/shaders/skin_mesh.vert similarity index 66% rename from src/models/shaders/skin_mesh.vert.glsl rename to src/models/shaders/skin_mesh.vert index 12d9a22..71e6071 100644 --- a/src/models/shaders/skin_mesh.vert.glsl +++ b/src/models/shaders/skin_mesh.vert @@ -2,13 +2,13 @@ #extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_shading_language_420pack : enable -layout (location = 0) in vec3 pos; -layout (location = 1) in vec3 normal; -layout (location = 2) in vec2 texture; -layout (location = 3) in vec4 weights; -layout (location = 4) in uvec4 joints; +layout(location = 0) in vec3 pos; +layout(location = 1) in vec3 normal; +layout(location = 2) in vec2 texture; +layout(location = 3) in vec4 weights; +layout(location = 4) in uvec4 joints; -layout (binding = 0) uniform DtxGlobals { +layout(binding = 0) uniform DtxGlobals { mat4 proj; mat4 view; } dtx_globals; @@ -42,30 +42,33 @@ layout(std430, binding = 3) buffer DtxTransformsLayout mat4 dtx_transform[]; }; -layout (location = 0) out vec3 o_world_position; -layout (location = 1) out vec3 o_world_normal; -layout (location = 2) out vec4 o_color; +layout(location = 0) out vec3 o_world_position; +layout(location = 1) out vec3 o_world_normal; +layout(location = 2) out vec4 o_color; +layout(location = 3) out vec3 o_texture; void main() { uint transform_index = dtx_instance[gl_InstanceIndex].transform_index; uint armature_index = dtx_instance[gl_InstanceIndex].armature_index; uint material_index = dtx_instance[gl_InstanceIndex].material_index; mat4 model_transform = dtx_transform[transform_index]; vec4 material_color = dtx_material[material_index].color; + float albedo_layer = float(dtx_material[material_index].maps_1.x); mat4 skin_transform = mat4(1.0); if (armature_index != 0) { skin_transform = weights.x * dtx_transform[armature_index + joints.x] + - weights.y * dtx_transform[armature_index + joints.y] + - weights.z * dtx_transform[armature_index + joints.z] + - weights.w * dtx_transform[armature_index + joints.w]; + weights.y * dtx_transform[armature_index + joints.y] + + weights.z * dtx_transform[armature_index + joints.z] + + weights.w * dtx_transform[armature_index + joints.w]; } mat4 proj_view = dtx_globals.proj * dtx_globals.view; o_world_position = vec3(model_transform * skin_transform * vec4(pos, 1.0)); o_world_normal = vec3(model_transform * vec4(normal, 1.0)); o_color = vec4(material_color); + o_texture = vec3(texture, albedo_layer); gl_Position = proj_view * vec4(o_world_position, 1.0); } diff --git a/src/models/shaders/skin_mesh.vert.spv b/src/models/shaders/skin_mesh.vert.spv index 2e136c7..418ef84 100644 Binary files a/src/models/shaders/skin_mesh.vert.spv and b/src/models/shaders/skin_mesh.vert.spv differ