diff --git a/resources/skybox.rif b/resources/skybox.rif new file mode 100644 index 0000000..b763a30 Binary files /dev/null and b/resources/skybox.rif differ diff --git a/shaders/frag.frag b/shaders/frag.frag index 5110430..3b185db 100644 --- a/shaders/frag.frag +++ b/shaders/frag.frag @@ -1,4 +1,7 @@ #version 450 +// vim: ft=c +// +layout(binding = 1) uniform samplerCube combined_image; layout(location = 0) out vec4 outColor; @@ -10,7 +13,8 @@ layout(push_constant, std430) uniform pc { }; void main() { - outColor = vec4(data.rgb*(1.0+dot(normal.xyz, normalize(vec3(-0.7, -0.5, -0.1))))/2.0, 1.0); + outColor = texture(combined_image, vec3(pos_pre)); + // outColor = vec4(data.rgb*(1.0+dot(normal.xyz, normalize(vec3(-0.7, -0.5, -0.1))))/2.0, 1.0); //if(pos_post.z <= 0.0) { // outColor = vec4(1.0); //} diff --git a/shaders/frag.spv b/shaders/frag.spv index caa5771..94a38d7 100644 Binary files a/shaders/frag.spv and b/shaders/frag.spv differ diff --git a/shaders/vert.spv b/shaders/vert.spv index 5aaa550..8518aa3 100644 Binary files a/shaders/vert.spv and b/shaders/vert.spv differ diff --git a/shaders/vert.vert b/shaders/vert.vert index 5ed8c2c..b8b3a04 100644 --- a/shaders/vert.vert +++ b/shaders/vert.vert @@ -1,8 +1,13 @@ #version 450 // vim: ft=c +struct PosNorm { + vec4 pos; + vec4 norm; +}; + layout(std430, set = 0, binding = 0) buffer positions_buffer { - mat2x4 posnrm[]; + PosNorm posnrm[]; } pos; layout(push_constant, std430) uniform pc { @@ -20,16 +25,22 @@ const float TAU = PI*2.0; void main() { // assign outs - normal = pos.posnrm[gl_VertexIndex][1]; - pos_pre = pos.posnrm[gl_VertexIndex][0]; + normal = pos.posnrm[gl_VertexIndex].norm; + pos_pre = pos.posnrm[gl_VertexIndex].pos; // define constants const float zFar = 100.0; const float zNear = 0.1; // assign the transformee - gl_Position = pos.posnrm[gl_VertexIndex][0]; + gl_Position = pos.posnrm[gl_VertexIndex].pos; + mat4 fix_coordinates = mat4( + -1.0, 0.0, 0.0, 0.0, + 0.0, -1.0, 0.0, 0.0, + 0.0, 0.0, -1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 + ); mat4 view_orig = mat4( 1.0, 0.0, 0.0, cam_orig.x, 0.0, 1.0, 0.0, cam_orig.y, @@ -73,9 +84,14 @@ void main() { 0.0, 0.0, 0.0, 1.0 ); + // vulkan has inverted screen coordinates + // but we want regular mesh coordinates + // gl_Position.xyz *= -1.0 + gl_Position *= fix_coordinates; + // apply view's origin transformation //gl_Position.xyz += cam_orig.xyz; - gl_Position *= view_orig; + // gl_Position *= view_orig; // apply view's xz rotation //mat2 xz_rot; @@ -107,4 +123,5 @@ void main() { // z normalization //gl_Position.z /= zFar; gl_Position *= project_normal; + } diff --git a/src/main.rs b/src/main.rs index 7378acb..610e245 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ -#![feature(inherent_str_constructors)] #![allow(unused_variables, unused_mut)] use ash::Device; @@ -6,6 +5,7 @@ use ash::Entry; use ash::Instance; use ash::khr::{surface, swapchain}; use ash::vk; +use ash::vk::ImageCreateFlags; use sdl2::mouse::MouseUtil; use std::cmp; @@ -26,7 +26,6 @@ use sdl2::video::Window; const APP_NAME: &str = "MineClone"; const MOV_STEP: f32 = 0.05; -const ROT_STEP: f32 = 0.05; const ROT_MOUSE_SCALE: f32 = 0.001; const MAX_WIDTH: u32 = 3440; @@ -34,26 +33,123 @@ const MAX_HEIGHT: u32 = 1440; const MESH_SIZE: u64 = 36 * 2 * 4 * 4; +#[rustfmt::skip] const POSITIONS: [f32; 36 * 2 * 4] = [ // BOTTOM - -0.5, 0.5, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.5, 2.0, 1.0, 0.0, 1.0, 0.0, 0.0, -0.5, 0.5, 2.0, - 1.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.5, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.5, 2.0, 1.0, 0.0, 1.0, - 0.0, 0.0, -0.5, 0.5, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, // TOP - 0.5, -0.5, 2.0, 1.0, 0.0, -1.0, 0.0, 0.0, -0.5, -0.5, 1.0, 1.0, 0.0, -1.0, 0.0, 0.0, -0.5, - -0.5, 2.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.5, -0.5, 2.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.5, -0.5, 1.0, - 1.0, 0.0, -1.0, 0.0, 0.0, -0.5, -0.5, 1.0, 1.0, 0.0, -1.0, 0.0, 0.0, // FRONT - -0.5, -0.5, 1.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.5, 0.5, 1.0, 1.0, 0.0, 0.0, -1.0, 0.0, -0.5, 0.5, - 1.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.5, -0.5, 1.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.5, 0.5, 1.0, 1.0, - 0.0, 0.0, -1.0, 0.0, -0.5, -0.5, 1.0, 1.0, 0.0, 0.0, -1.0, 0.0, // BACK - 0.5, 0.5, 2.0, 1.0, 0.0, 0.0, 1.0, 0.0, -0.5, -0.5, 2.0, 1.0, 0.0, 0.0, 1.0, 0.0, -0.5, 0.5, - 2.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.5, 0.5, 2.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.5, -0.5, 2.0, 1.0, 0.0, - 0.0, 1.0, 0.0, -0.5, -0.5, 2.0, 1.0, 0.0, 0.0, 1.0, 0.0, // LEFT - -0.5, -0.5, 1.0, 1.0, -1.0, 0.0, 0.0, 0.0, -0.5, 0.5, 2.0, 1.0, -1.0, 0.0, 0.0, 0.0, -0.5, - -0.5, 2.0, 1.0, -1.0, 0.0, 0.0, 0.0, -0.5, 0.5, 1.0, 1.0, -1.0, 0.0, 0.0, 0.0, -0.5, 0.5, 2.0, - 1.0, -1.0, 0.0, 0.0, 0.0, -0.5, -0.5, 1.0, 1.0, -1.0, 0.0, 0.0, 0.0, // RIGHT - 0.5, 0.5, 2.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.5, -0.5, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.5, -0.5, - 2.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.5, 0.5, 2.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.5, 0.5, 1.0, 1.0, 1.0, - 0.0, 0.0, 0.0, 0.5, -0.5, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, + + -0.5, 0.5, -0.5, 1.0, + 0.0, 1.0, 0.0, 0.0, + + 0.5, 0.5, 0.5, 1.0, + 0.0, 1.0, 0.0, 0.0, + + -0.5, 0.5, 0.5, 1.0, + 0.0, 1.0, 0.0, 0.0, + + 0.5, 0.5, -0.5, 1.0, + 0.0, 1.0, 0.0, 0.0, + + 0.5, 0.5, 0.5, 1.0, + 0.0, 1.0, 0.0, 0.0, + + -0.5, 0.5, -0.5, 1.0, + 0.0, 1.0, 0.0, 0.0, + + // TOP + 0.5, -0.5, 0.5, 1.0, + 0.0, -1.0, 0.0, 0.0, + + -0.5, -0.5, -0.5, 1.0, + 0.0, -1.0, 0.0, 0.0, + + -0.5, -0.5, 0.5, 1.0, + 0.0, -1.0, 0.0, 0.0, + + 0.5, -0.5, 0.5, 1.0, + 0.0, -1.0, 0.0, 0.0, + + 0.5, -0.5, -0.5, 1.0, + 0.0, -1.0, 0.0, 0.0, + + -0.5, -0.5, -0.5, 1.0, + 0.0, -1.0, 0.0, 0.0, + + // FRONT + -0.5, -0.5, -0.5, 1.0, + 0.0, 0.0, -1.0, 0.0, + + 0.5, 0.5, -0.5, 1.0, + 0.0, 0.0, -1.0, 0.0, + + -0.5, 0.5, -0.5, 1.0, + 0.0, 0.0, -1.0, 0.0, + + 0.5, -0.5, -0.5, 1.0, + 0.0, 0.0, -1.0, 0.0, + + 0.5, 0.5, -0.5, 1.0, + 0.0, 0.0, -1.0, 0.0, + + -0.5, -0.5, -0.5, 1.0, + 0.0, 0.0, -1.0, 0.0, + + // BACK + 0.5, 0.5, 0.5, 1.0, + 0.0, 0.0, 1.0, 0.0, + + -0.5, -0.5, 0.5, 1.0, + 0.0, 0.0, 1.0, 0.0, + + -0.5, 0.5, 0.5, 1.0, + 0.0, 0.0, 1.0, 0.0, + + 0.5, 0.5, 0.5, 1.0, + 0.0, 0.0, 1.0, 0.0, + + 0.5, -0.5, 0.5, 1.0, + 0.0, 0.0, 1.0, 0.0, + + -0.5, -0.5, 0.5, 1.0, + 0.0, 0.0, 1.0, 0.0, + + // LEFT + -0.5, -0.5, -0.5, 1.0, + -1.0, 0.0, 0.0, 0.0, + + -0.5, 0.5, 0.5, 1.0, + -1.0, 0.0, 0.0, 0.0, + + -0.5, -0.5, 0.5, 1.0, + -1.0, 0.0, 0.0, 0.0, + + -0.5, 0.5, -0.5, 1.0, + -1.0, 0.0, 0.0, 0.0, + + -0.5, 0.5, 0.5, 1.0, + -1.0, 0.0, 0.0, 0.0, + + -0.5, -0.5, -0.5, 1.0, + -1.0, 0.0, 0.0, 0.0, + + // RIGHT + 0.5, 0.5, 0.5, 1.0, + 1.0, 0.0, 0.0, 0.0, + 0.5, -0.5, -0.5, 1.0, + 1.0, 0.0, 0.0, 0.0, + + 0.5, -0.5, 0.5, 1.0, + 1.0, 0.0, 0.0, 0.0, + + 0.5, 0.5, 0.5, 1.0, + 1.0, 0.0, 0.0, 0.0, + + 0.5, 0.5, -0.5, 1.0, + 1.0, 0.0, 0.0, 0.0, + + 0.5, -0.5, -0.5, 1.0, + 1.0, 0.0, 0.0, 0.0, + + ]; fn create_instance(window: &Window, entry: &Entry) -> Instance { @@ -106,7 +202,7 @@ fn find_pdev_dgpu(instance: &Instance) -> vk::PhysicalDevice { // Fix. println!( "Found discrete GPU: {}", - str::from_utf8(std::mem::transmute(props.device_name.as_slice())).unwrap() + std::str::from_utf8(std::mem::transmute(props.device_name.as_slice())).unwrap() ); return pdevs.remove(i); } @@ -339,7 +435,12 @@ fn setup_desc_layout(dev: &Device) -> vk::DescriptorSetLayout { .descriptor_type(vk::DescriptorType::STORAGE_BUFFER) .descriptor_count(1) .stage_flags(vk::ShaderStageFlags::VERTEX); - let layouts = [storage_binding]; + let image_binding = vk::DescriptorSetLayoutBinding::default() + .binding(1) + .descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER) + .descriptor_count(1) + .stage_flags(vk::ShaderStageFlags::FRAGMENT); + let layouts = [storage_binding, image_binding]; let layout_info = vk::DescriptorSetLayoutCreateInfo::default().bindings(&layouts); let layout = unsafe { @@ -453,11 +554,11 @@ fn setup_shader_stage( let vert_stage = vk::PipelineShaderStageCreateInfo::default() .stage(vk::ShaderStageFlags::VERTEX) .module(vert_shader) - .name(CStr::from_bytes_with_nul(b"main\0").unwrap()); + .name(c"main"); let frag_stage = vk::PipelineShaderStageCreateInfo::default() .stage(vk::ShaderStageFlags::FRAGMENT) .module(frag_shader) - .name(CStr::from_bytes_with_nul(b"main\0").unwrap()); + .name(c"main"); [vert_stage, frag_stage] } @@ -474,7 +575,7 @@ fn setup_pipeline( .topology(vk::PrimitiveTopology::TRIANGLE_LIST); let rasterization = vk::PipelineRasterizationStateCreateInfo::default() .polygon_mode(vk::PolygonMode::FILL) - .cull_mode(vk::CullModeFlags::BACK) + .cull_mode(vk::CullModeFlags::NONE) .front_face(vk::FrontFace::CLOCKWISE) .line_width(1.0); let multisample = vk::PipelineMultisampleStateCreateInfo::default() @@ -601,10 +702,14 @@ fn setup_swapchain( } fn setup_desc_pool(dev: &Device) -> vk::DescriptorPool { - let pool_size = vk::DescriptorPoolSize::default() + let pool_size_storage = vk::DescriptorPoolSize::default() .ty(vk::DescriptorType::STORAGE_BUFFER) .descriptor_count(1); - let pool_sizes = [pool_size]; + let pool_size_image = vk::DescriptorPoolSize::default() + .ty(vk::DescriptorType::COMBINED_IMAGE_SAMPLER) + .descriptor_count(1); + let pool_sizes = [pool_size_storage, pool_size_image]; + let pool_info = vk::DescriptorPoolCreateInfo::default() .max_sets(1) .pool_sizes(&pool_sizes); @@ -718,7 +823,13 @@ fn make_desc_sets(dev: &Device, desc_pool: &vk::DescriptorPool) -> Vec, mesh_buf: &vk::Buffer) { +fn write_desc_sets( + dev: &Device, + desc_sets: &Vec, + mesh_buf: &vk::Buffer, + image_view: vk::ImageView, + skybox_sampler: vk::Sampler +) { let buf_info = vk::DescriptorBufferInfo::default() .buffer(*mesh_buf) .offset(0) @@ -730,8 +841,21 @@ fn write_desc_sets(dev: &Device, desc_sets: &Vec, mesh_buf: & .dst_array_element(0) .descriptor_type(vk::DescriptorType::STORAGE_BUFFER) .buffer_info(&buf_infos); + + let img_info = vk::DescriptorImageInfo::default() + .image_layout(vk::ImageLayout::GENERAL) + .image_view(image_view) + .sampler(skybox_sampler); + let img_infos = &[img_info]; + let img_desc = vk::WriteDescriptorSet::default() + .dst_set(desc_sets[0]) + .dst_binding(1) + .dst_array_element(0) + .descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER) + .image_info(img_infos); + unsafe { - dev.update_descriptor_sets(&[buf_desc], &[]); + dev.update_descriptor_sets(&[buf_desc, img_desc], &[]); } } @@ -794,6 +918,8 @@ fn record_commands( pipe: &vk::Pipeline, desc_sets: &Vec, camera: &Camera, + skybox_buffer: &vk::Buffer, + skybox_image: &vk::Image, ) { let clear_vals = [ vk::ClearValue { @@ -820,6 +946,30 @@ fn record_commands( .clear_values(&clear_vals); unsafe { + let regions = (0..6) + .map(|i| { + vk::BufferImageCopy::default() + .buffer_offset(3 * 2048 * 2048 * i) + .buffer_row_length(0) + .buffer_image_height(0) + .image_offset(vk::Offset3D::default()) + .image_extent(vk::Extent3D::default().width(2048).height(2048).depth(1)) + .image_subresource( + vk::ImageSubresourceLayers::default() + .aspect_mask(vk::ImageAspectFlags::COLOR) + .mip_level(0) + .layer_count(1) + .base_array_layer(i as u32), + ) + }) + .collect::>(); + dev.cmd_copy_buffer_to_image( + *cmd_buf, + *skybox_buffer, + *skybox_image, + vk::ImageLayout::GENERAL, + ®ions, + ); dev.cmd_begin_render_pass(*cmd_buf, &render_pass_info, vk::SubpassContents::INLINE); dev.cmd_bind_pipeline(*cmd_buf, vk::PipelineBindPoint::GRAPHICS, *pipe); dev.cmd_bind_descriptor_sets( @@ -886,6 +1036,9 @@ fn record_commands( 48, base_color.as_ref(), ); + + + dev.cmd_draw(*cmd_buf, 36, 1, 0, 0); dev.cmd_end_render_pass(*cmd_buf); } @@ -993,6 +1146,10 @@ fn handle_cont_key(keycode: Keycode, camera: &mut Camera, mouse: &MouseUtil) { } } +fn decode_rif(raw: &[u8]) -> &[u8] { + &raw[17..] +} + fn main() { let sdl_context = sdl2::init().unwrap(); let video_subsystem = sdl_context.video().unwrap(); @@ -1068,6 +1225,75 @@ fn main() { unsafe { std::ptr::copy(POSITIONS.as_ptr(), mesh_mem as *mut f32, POSITIONS.len()); } + + let (skybox_image, skybox_image_view, skybox_sampler) = { + let qf_idxs = [rcs_queue_inx]; + let create_info = vk::ImageCreateInfo::default() + .flags(ImageCreateFlags::CUBE_COMPATIBLE) + .image_type(vk::ImageType::TYPE_2D) + .format(vk::Format::R8G8B8_UNORM) + .extent(vk::Extent3D::default().width(2048).height(2048).depth(1)) + .mip_levels(1) + .array_layers(6) + .samples(vk::SampleCountFlags::TYPE_1) + .tiling(vk::ImageTiling::OPTIMAL) + .usage(vk::ImageUsageFlags::TRANSFER_DST | vk::ImageUsageFlags::SAMPLED) + .sharing_mode(vk::SharingMode::EXCLUSIVE) + .initial_layout(vk::ImageLayout::UNDEFINED) + .queue_family_indices(&qf_idxs); + let image = + unsafe { dev.create_image(&create_info, None) }.expect("Failed to create image"); + + let skybox_mem_size: vk::MemoryRequirements = unsafe {dev.get_image_memory_requirements(image)}; + let skybox_dev_mem = mem_alloc(&dev, host_invisible_inx, skybox_mem_size.size); + unsafe { + dev.bind_image_memory(image, skybox_dev_mem, 0).expect("Failed to bind image memory"); + } + let create_info = vk::ImageViewCreateInfo::default() + .image(image) + .view_type(vk::ImageViewType::CUBE) + .format(vk::Format::R8G8B8_UNORM) + .components(vk::ComponentMapping::default()) + .subresource_range( + vk::ImageSubresourceRange::default() + .aspect_mask(vk::ImageAspectFlags::COLOR) + .base_mip_level(0) + .level_count(1) + .base_array_layer(0) + .layer_count(6), + ); + let image_view = unsafe { dev.create_image_view(&create_info, None) } + .expect("Failed to create image view"); + let create_info = vk::SamplerCreateInfo::default() + .mag_filter(vk::Filter::LINEAR) + .min_filter(vk::Filter::LINEAR) + .mipmap_mode(vk::SamplerMipmapMode::LINEAR) + .address_mode_u(vk::SamplerAddressMode::CLAMP_TO_EDGE) + .address_mode_v(vk::SamplerAddressMode::CLAMP_TO_EDGE) + .address_mode_w(vk::SamplerAddressMode::CLAMP_TO_EDGE) + .max_anisotropy(1.0) + .max_lod(1.0) + .border_color(vk::BorderColor::FLOAT_OPAQUE_WHITE); + let sampler = + unsafe { dev.create_sampler(&create_info, None) }.expect("Failed to create sampler"); + + + (image, image_view, sampler) + }; + + let skybox_mem = mem_alloc(&dev, host_visible_inx, 3 * 2048 * 2048 * 6); + let skybox_buf = alloc_buf( + &dev, + &skybox_mem, + 3 * 2048 * 2048 * 6, + vk::BufferUsageFlags::TRANSFER_SRC, + ); + let skybox_ptr = buf_to_ptr(&dev, &skybox_mem, &skybox_buf); + let img = std::fs::read("resources/skybox.rif").unwrap(); + let data = decode_rif(&img); + unsafe { + std::ptr::copy(data.as_ptr(), skybox_ptr as *mut u8, data.len()); + } let vert_shader_bin = std::fs::read("shaders/vert.spv").unwrap(); let frag_shader_bin = std::fs::read("shaders/frag.spv").unwrap(); @@ -1127,7 +1353,7 @@ fn main() { let desc_sets = make_desc_sets(&dev, &desc_pool); - write_desc_sets(&dev, &desc_sets, &mesh_buf); + write_desc_sets(&dev, &desc_sets, &mesh_buf, skybox_image_view, skybox_sampler); let sem_avail = make_sem(&dev); let sem_finish = make_sem(&dev); @@ -1164,7 +1390,7 @@ fn main() { .expect("Failed to wait for device idle"); swapchain_loader.destroy_swapchain(swapchain, None); } - (swapchain, extents) = setup_swapchain( + (swapchain, _) = setup_swapchain( &pdev, &dev, &surface, @@ -1202,10 +1428,9 @@ fn main() { xrel, yrel, .. - } - // We only wanna do movement if the mouse is in relative mode (ie. its pinned to - // the center of the window and hidden) - if mouse.relative_mouse_mode() => { + } if mouse.relative_mouse_mode() => { + // We only wanna do movement if the mouse is in relative mode (ie. its pinned to + // the center of the window and hidden) camera.rotation.y -= xrel as f32 * ROT_MOUSE_SCALE; camera.rotation.x -= yrel as f32 * ROT_MOUSE_SCALE; mouse.warp_mouse_in_window(&window, width as i32 / 2, height as i32 / 2); @@ -1244,6 +1469,8 @@ fn main() { &pipe, &desc_sets, &camera, + &skybox_buf, + &skybox_image, ); end_cmd_buf(&dev, &cmd_buf);