From bfad6a844f1bc50274547651e0475037a67493c9 Mon Sep 17 00:00:00 2001 From: Joshua Simmons Date: Sun, 13 Nov 2022 17:20:15 +0100 Subject: [PATCH] Multiple Shark Zone --- narcissus-core/src/rand.rs | 8 ++ narcissus/src/main.rs | 131 ++++++++++++++++++++------ narcissus/src/shaders/basic.vert.glsl | 25 +++-- narcissus/src/shaders/basic.vert.spv | Bin 1416 -> 2372 bytes 4 files changed, 131 insertions(+), 33 deletions(-) diff --git a/narcissus-core/src/rand.rs b/narcissus-core/src/rand.rs index e6eccbe..ac64dfb 100644 --- a/narcissus-core/src/rand.rs +++ b/narcissus-core/src/rand.rs @@ -42,6 +42,14 @@ impl Pcg64 { let (_, carry) = fraction.overflowing_add(hi); result + carry as u64 } + + /// Generates a uniformly distributed random float in the range `-1.0..1.0` + #[inline] + #[must_use] + pub fn next_f32(&mut self) -> f32 { + let value = (self.next_u64() >> (64 - 25)) as i64 as f32; + value * 5.960_464_5e-8 // 0x1p-24f + } } impl Default for Pcg64 { diff --git a/narcissus/src/main.rs b/narcissus/src/main.rs index d452b2c..fa969ee 100644 --- a/narcissus/src/main.rs +++ b/narcissus/src/main.rs @@ -1,7 +1,7 @@ use std::{path::Path, time::Instant}; use narcissus_app::{create_app, Event, Key, WindowDesc}; -use narcissus_core::{cstr, default, obj, Image}; +use narcissus_core::{cstr, default, obj, rand::Pcg64, Image}; use narcissus_gpu::{ create_vulkan_device, Bind, BindGroupLayoutDesc, BindGroupLayoutEntryDesc, BindingType, Buffer, BufferDesc, BufferUsageFlags, ClearValue, CompareOp, CullingMode, Device, FrontFace, @@ -10,7 +10,12 @@ use narcissus_gpu::{ TextureDesc, TextureDimension, TextureFormat, TextureUsageFlags, ThreadToken, Topology, TypedBind, Viewport, }; -use narcissus_maths::{sin_cos_pi_f32, Deg, Mat4, Point3, Vec2, Vec3, Vec4}; +use narcissus_maths::{ + sin_cos_pi_f32, Affine3, Deg, HalfTurn, Mat3, Mat4, Point3, Vec2, Vec3, Vec4, +}; + +const MAX_SHARKS: usize = 262_144; +const NUM_SHARKS: usize = 10; /// Marker trait indicates it's safe to convert a given type directly to an array of bytes. /// @@ -20,11 +25,11 @@ use narcissus_maths::{sin_cos_pi_f32, Deg, Mat4, Point3, Vec2, Vec3, Vec4}; unsafe trait Blittable: Sized {} #[allow(unused)] -struct Uniform { +struct Uniforms { clip_from_model: Mat4, } -unsafe impl Blittable for Uniform {} +unsafe impl Blittable for Uniforms {} #[allow(unused)] struct Vertex { @@ -35,6 +40,7 @@ struct Vertex { unsafe impl Blittable for Vertex {} unsafe impl Blittable for u16 {} +unsafe impl Blittable for Affine3 {} fn load_obj>(path: P) -> (Vec, Vec) { #[derive(Default)] @@ -137,17 +143,17 @@ where buffer } -struct UniformBufferMap<'a> { +struct MappedBuffer<'a> { device: &'a dyn Device, buffer: Buffer, slice: &'a mut [u8], } -impl<'a> UniformBufferMap<'a> { - pub fn new(device: &'a dyn Device, len: usize) -> Self { +impl<'a> MappedBuffer<'a> { + pub fn new(device: &'a dyn Device, usage: BufferUsageFlags, len: usize) -> Self { let buffer = device.create_buffer(&BufferDesc { memory_location: MemoryLocation::PreferHost, - usage: BufferUsageFlags::UNIFORM, + usage, size: len, }); unsafe { @@ -177,9 +183,20 @@ impl<'a> UniformBufferMap<'a> { self.slice.copy_from_slice(src) } } + + pub fn write_slice(&mut self, values: &[T]) + where + T: Blittable, + { + unsafe { + let len = values.len() * std::mem::size_of::(); + let src = std::slice::from_raw_parts(values.as_ptr() as *const u8, len); + self.slice[..len].copy_from_slice(src) + } + } } -impl<'a> Drop for UniformBufferMap<'a> { +impl<'a> Drop for MappedBuffer<'a> { fn drop(&mut self) { // Safety: Make sure we don't have the slice outlive the mapping. unsafe { @@ -218,12 +235,20 @@ pub fn main() { }); let storage_bind_group_layout = device.create_bind_group_layout(&BindGroupLayoutDesc { - entries: &[BindGroupLayoutEntryDesc { - slot: 0, - stages: ShaderStageFlags::ALL, - binding_type: BindingType::StorageBuffer, - count: 1, - }], + entries: &[ + BindGroupLayoutEntryDesc { + slot: 0, + stages: ShaderStageFlags::ALL, + binding_type: BindingType::StorageBuffer, + count: 1, + }, + BindGroupLayoutEntryDesc { + slot: 1, + stages: ShaderStageFlags::ALL, + binding_type: BindingType::StorageBuffer, + count: 1, + }, + ], }); let pipeline = device.create_graphics_pipeline(&GraphicsPipelineDesc { @@ -266,12 +291,38 @@ pub fn main() { blåhaj_indices.as_slice(), ); - let mut uniforms = UniformBufferMap::new(device.as_ref(), std::mem::size_of::()); + let mut uniforms = MappedBuffer::new( + device.as_ref(), + BufferUsageFlags::UNIFORM, + std::mem::size_of::(), + ); + + let mut transforms = MappedBuffer::new( + device.as_ref(), + BufferUsageFlags::STORAGE, + std::mem::size_of::() * MAX_SHARKS, + ); let mut depth_width = 0; let mut depth_height = 0; let mut depth_image = default(); + let shark_distance = 8.0; + + let mut rng = Pcg64::new(); + + let mut shark_transforms = Vec::new(); + for z in 0..NUM_SHARKS { + for x in 0..NUM_SHARKS { + let x = x as f32 * shark_distance - NUM_SHARKS as f32 / 2.0 * shark_distance; + let z = z as f32 * shark_distance - NUM_SHARKS as f32 / 2.0 * shark_distance; + shark_transforms.push(Affine3 { + matrix: Mat3::from_axis_rotation(Vec3::Y, HalfTurn::new(rng.next_f32())), + translate: Vec3::new(x, 0.0, z), + }) + } + } + let start_time = Instant::now(); 'main: loop { let frame = device.begin_frame(); @@ -305,16 +356,28 @@ pub fn main() { device.acquire_swapchain(&frame, main_window, TextureFormat::BGRA8_SRGB); let frame_start = Instant::now() - start_time; - let frame_start = frame_start.as_secs_f32() * 0.5; + let frame_start = frame_start.as_secs_f32() * 0.125; + + for (i, transform) in shark_transforms.iter_mut().enumerate() { + let direction = if i & 1 == 0 { 1.0 } else { -1.0 }; + let (s, _) = sin_cos_pi_f32(frame_start + (i as f32) * 0.125); + transform.translate.y = 0.0 + s; + transform.matrix *= Mat3::from_axis_rotation(Vec3::Y, HalfTurn::new(0.005 * direction)) + } + + transforms.write_slice(&shark_transforms); let (s, c) = sin_cos_pi_f32(frame_start); - let camera_from_model = - Mat4::look_at(Point3::new(s * 5.0, 1.0, c * 5.0), Point3::ZERO, -Vec3::Y); + let camera_height = c * 5.0; + let camera_radius = 50.0; + let eye = Point3::new(s * camera_radius, camera_height, c * camera_radius); + let center = Point3::ZERO; + let camera_from_model = Mat4::look_at(eye, center, -Vec3::Y); let clip_from_camera = - Mat4::perspective_rev_inf_zo(Deg::new(90.0).into(), width as f32 / height as f32, 0.01); + Mat4::perspective_rev_inf_zo(Deg::new(45.0).into(), width as f32 / height as f32, 0.01); let clip_from_model = clip_from_camera * camera_from_model; - uniforms.write(Uniform { clip_from_model }); + uniforms.write(Uniforms { clip_from_model }); if width != depth_width || height != depth_height { device.destroy_texture(&frame, depth_image); @@ -356,11 +419,18 @@ pub fn main() { &mut cmd_buffer, storage_bind_group_layout, 1, - &[Bind { - binding: 0, - array_element: 0, - typed: TypedBind::StorageBuffer(&[blåhaj_vertex_buffer]), - }], + &[ + Bind { + binding: 0, + array_element: 0, + typed: TypedBind::StorageBuffer(&[blåhaj_vertex_buffer]), + }, + Bind { + binding: 1, + array_element: 0, + typed: TypedBind::StorageBuffer(&[transforms.buffer()]), + }, + ], ); device.cmd_set_index_buffer(&mut cmd_buffer, blåhaj_index_buffer, 0, IndexType::U16); @@ -413,7 +483,14 @@ pub fn main() { }], ); - device.cmd_draw_indexed(&mut cmd_buffer, blåhaj_indices.len() as u32, 1, 0, 0, 0); + device.cmd_draw_indexed( + &mut cmd_buffer, + blåhaj_indices.len() as u32, + shark_transforms.len() as u32, + 0, + 0, + 0, + ); device.cmd_end_rendering(&mut cmd_buffer); diff --git a/narcissus/src/shaders/basic.vert.glsl b/narcissus/src/shaders/basic.vert.glsl index aaad3a8..a869c90 100644 --- a/narcissus/src/shaders/basic.vert.glsl +++ b/narcissus/src/shaders/basic.vert.glsl @@ -4,21 +4,34 @@ layout(set = 0, binding = 0) uniform uniformBuffer { mat4 viewProj; }; -struct Vertex { +struct VertexData { vec4 position; vec4 normal; vec4 texcoord; }; +struct TransformData { + vec4 transform[3]; +}; + layout(std430, set = 1, binding = 0) readonly buffer vertexBuffer { - Vertex vertices[]; + VertexData vertices[]; +}; + +layout(std430, set = 1, binding = 1) readonly buffer transformBuffer { + TransformData transforms[]; }; layout(location = 0) out vec3 fragColor; void main() { - Vertex vertex = vertices[gl_VertexIndex]; - vec3 pos = vertex.position.xyz; - gl_Position = vec4(pos, 1.0) * viewProj; - fragColor = vertex.normal.xyz * 0.5 + 0.5; + TransformData td = transforms[gl_InstanceIndex]; + VertexData vd = vertices[gl_VertexIndex]; + + vec4 posLocal = vec4(vd.position.xyz, 1.0); + vec3 posWorld = mat4x3(td.transform[0], td.transform[1], td.transform[2]) * posLocal; + vec4 posClip = vec4(posWorld, 1.0) * viewProj; + + gl_Position = posClip; + fragColor = vd.normal.xyz * 0.5 + 0.5; } diff --git a/narcissus/src/shaders/basic.vert.spv b/narcissus/src/shaders/basic.vert.spv index c0b9e8836507d7d05133227e0344c4ef867c9d00..9ab0390c3198ae6a94929ecbae33b973d52bdce9 100644 GIT binary patch literal 2372 zcmZ9MS+7)85QV?)bGk2sGRUaH4U^0eWH2NK5fttPE^rYNnUqlpq6~rfCJ|5{4g6bP zOvqPV6?ZsEr%$b_UA3xeo!t#LPca^_h!6RP$+Mgx17I=Z_@9}(IJfudv%7l_9@=Nb z61oU9W+@-Udk_3}>;6NH6~G!`3-B56BXAG+6_}xC2`~nh0ke!)8W~`7{u`su7z@tQ zvpjuk^GwcZOQtJ>;dI`ghz82CoIIAhFex|pZ)T|*x|IA3$EqGv(Q z-e*_Z3$y+@dKN*P5u2t99%A~`o--+*+7nw(7dzJWjQVot8|e86Lgiv#rmenIzI;|D zA7>*U?N!;I=U3;v#67RA{*2fEaps!T9SMRbNe2{cY*1dGAR*yF>eN_Mb;Te;!>+&({z!?nC=p^3;}#+7q+4A9C+v*49>Q z?pgnhd^f&!c_+EKue-@bY?^WC$o}P|&!2gI&i$)1>u7uD*n|H2`R-Zm2Wi`@@!IOL z?fLO!hevlaj<~-eFmZohFp56x+sCtS8OC>cBz52&;I5A`jy->p_oMpIXPkTg6vFp< z(1%{vC3b;PX!rNf@8l7)kCza*PhqbTbGL>4m6$UxUR(2SmY4hAo*I#tKI7EGj`Yb( zU3v$JRqj6$YdJhmtT?!<{SdJgCw3sQHtt|za-C-?`aG29jn}Uht#6LwIfpjyH;J`* zzfH`%b@oJJ?yazs5HoD^%_P?5n@z0EcPgB z_GnLqpNHs2{_-t+KJH|Kn_LRN0Kvn$)^XN;*WW?ZFrR0Qd&4O7e<}U$qvrKJ1m5;{ zIkC3CD~Yvxy$W&Oc>V767^AooZst9q9@V1v!z~E>b?W~%L=JJ!`HlaQ-@WI)q6^!& q^DKxS9zp0+jrzz@PXA_)PatCazF#Ev6ax4AH>dZ6*nbQ-%z$?yLUYpq literal 1416 zcmYk5*=iI~6h&8!9TJlmV+KK+#3&Al?UY18V-p-Y4*?awK=8!}ebEolACP>mFM_O7 z=R#j7s?NS=*mv(+O}#gwuUKT6cMNNdnhIE=kN52S)A{7b&o7h1qeo_}&_tp+t1QNM z3w-gsu1@;9D8kD8Bjf1Nt&c4>l_JvM1VPxalRjXCNo-!UBv5Sa6Q z#5_-leczx7U&P0$w?6IAvI6m~FE29I1NS#*!)s@&=YGa($=CWTx#yj*-dK;!cYh;$ zIa~hM@_wkh{q61JvcKQzWBqm7(9ZLUjp;*s&m^X7PE@%UIv^!+r0z-zEPr=g79KXMXd*W6JqxKlaSqSolB1md(8c~q_%rDJJF#hSApEeWzKQ*#;yD%n0ZiyJ A^#A|> -- 2.49.0