diff --git a/src/app/mod.rs b/src/app/mod.rs index 633d2d2..c284826 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -5,19 +5,62 @@ use winit::{ use std::sync::Arc; mod camera_controller; use camera_controller::CameraController; +mod world_gen; use world_gen::WorldGen; use crate::renderer::Renderer; - +//use crate::renderer::BrickData; pub struct App { pub window: Window, pub renderer: Renderer, + world_gen: WorldGen, camera_controller: CameraController, } impl App { - pub fn new(window: Window, renderer: Renderer) -> Self { + pub fn new(window: Window) -> Self { + let mut renderer = futures::executor::block_on(Renderer::new(&window)); let camera_controller = CameraController::new(); - Self { window, renderer, camera_controller } + let mut world_gen = WorldGen::new(); + + + // let start = std::time::Instant::now(); + // for x in 0..128 { + // for z in 0..128 { + // // Dirt + // for y in 0..31 { + // renderer.set_voxel(x, y, z, 1); + // } + // // Grass + // renderer.set_voxel(x, 31, z, 2); + // } + // } + // println!("Generated in {}ms", start.elapsed().as_millis()); + + + let start = std::time::Instant::now(); + for bx in 0..4 { + for bz in 0..4 { + + let brick_id = renderer.brick_get_id(bx, 0, bz); + renderer.brick_mark_changed(brick_id); + for x in 0..32 { + for z in 0..32 { + // Dirt + for y in 0..31 { + renderer.brick_set_voxel(brick_id, x, y, z, 1); + } + // Grass + renderer.brick_set_voxel(brick_id, x, 31, z, 2); + } + } + + } + } + println!("Generated in {}ms", start.elapsed().as_millis()); + + + + Self { window, renderer, camera_controller, world_gen } } pub fn input(&mut self, event: Arc>) { diff --git a/src/app/world_gen.rs b/src/app/world_gen.rs new file mode 100644 index 0000000..9b147a2 --- /dev/null +++ b/src/app/world_gen.rs @@ -0,0 +1,16 @@ +use std::sync::Arc; +use crate::renderer::Renderer; + +pub struct WorldGen { + +} + +impl WorldGen { + + pub fn new() -> Self { + Self{} + } + + pub fn generate(&mut self, renderer: Renderer) { + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 2ace7f5..7c22c4f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,8 +20,7 @@ fn main() { .with_inner_size(LogicalSize::new(1280.0, 720.0)) .build(&events) .expect("Failed to create window"); - let _renderer = futures::executor::block_on(Renderer::new(&_window)); - let mut app = App::new(_window, _renderer); + let mut app = App::new(_window); // Stats let mut fps_timer = std::time::Instant::now(); diff --git a/src/renderer/buffers/brick_buffer.rs b/src/renderer/buffers/brick_buffer.rs index 202fe6a..bdba9ea 100644 --- a/src/renderer/buffers/brick_buffer.rs +++ b/src/renderer/buffers/brick_buffer.rs @@ -1,42 +1,22 @@ -use wgpu::util::DeviceExt; use std::convert::TryInto; -use rand::prelude::*; -const BRICK_SIZE : usize = 32; // 32x32x32 brick size -const BRICK_NUM : usize = 10000; // x bricks in texture - -const BRICK_LEN : usize = BRICK_SIZE*BRICK_SIZE*BRICK_SIZE; +use crate::renderer::buffers::{BRICK_SIZE, BRICK_NUM, BRICK_LEN}; const DATA_LEN : usize = BRICK_LEN * BRICK_NUM; -struct BrickData { - pub data: Box<[u8]> -} - -impl BrickData { - - pub fn new() -> Self { - let data = vec![0_u8; DATA_LEN].into_boxed_slice(); - Self { data } - } - - pub fn set(&mut self, brick: usize, x: usize, y: usize, z: usize, value: u8) - { - let local_idx = x + BRICK_SIZE * (y + BRICK_SIZE * z); - let offset = brick * BRICK_LEN; - self.data[offset + local_idx] = value; - } -} - pub struct BrickBuffer { - bricks: BrickData, + pub bricks: Box<[u8]>, + pub free_brick: usize, texture: wgpu::Texture, - size: wgpu::Extent3d, pub bind_layout: wgpu::BindGroupLayout, pub bind_group: wgpu::BindGroup } impl BrickBuffer { + + /* + * Create buffer in memory and gpu + */ pub fn new(device: &wgpu::Device) -> Self { // Create texture @@ -93,36 +73,24 @@ impl BrickBuffer { ); // Data - let mut bricks = BrickData::new(); + let mut bricks = vec![0_u8; DATA_LEN].into_boxed_slice(); + bricks[0] = 1; println!("Brick buffer size: {} MB", DATA_LEN as f32 / 1024.0 / 1024.0); - let mut rng = rand::thread_rng(); - for x in 0..32 { - for y in 0..32 { - for z in 0..32 { - let value = if rng.gen::()> 0.99 { 1 } else { 0 }; - bricks.set(0, x, y, z, value); - bricks.set(1, x, 0, z, 1); - } - } - } - bricks.set(1, 20, 5, 16, 1); - // Done - Self { bricks, texture, size, bind_layout, bind_group } + Self { bricks, texture, bind_layout, bind_group, free_brick: 0 } } /* Write brick data to gpu, should be called to apply changes offset: Brick index to copy */ - pub fn write(&mut self, queue: &wgpu::Queue, offset: usize) - { + pub fn write(&mut self, queue: &wgpu::Queue, brick: usize) { // Get first brick - let brick_offset = offset*BRICK_LEN; - let brick_bytes : [u8;BRICK_LEN] = self.bricks.data[brick_offset..brick_offset+BRICK_LEN].try_into().unwrap(); + let brick_offset = brick*BRICK_LEN; + let brick_bytes : [u8;BRICK_LEN] = self.bricks[brick_offset..brick_offset+BRICK_LEN].try_into().unwrap(); let brick_size = wgpu::Extent3d{ width: BRICK_SIZE as u32, height: BRICK_SIZE as u32, depth: BRICK_SIZE as u32 }; - let brick_origin = wgpu::Origin3d{ x:0, y:0, z: (offset*BRICK_SIZE) as u32 }; + let brick_origin = wgpu::Origin3d{ x:0, y:0, z: (brick*BRICK_SIZE) as u32 }; // Write queue.write_texture( @@ -132,4 +100,13 @@ impl BrickBuffer { brick_size ); } + + pub fn next_brick(&mut self) -> usize { + if self.free_brick >= self.bricks.len() { + panic!("No more free bricks! we should consider reusing bricks..."); + } + + self.free_brick += 1; + self.free_brick + } } \ No newline at end of file diff --git a/src/renderer/buffers/material_buffer.rs b/src/renderer/buffers/material_buffer.rs new file mode 100644 index 0000000..dee9124 --- /dev/null +++ b/src/renderer/buffers/material_buffer.rs @@ -0,0 +1,74 @@ +use wgpu::util::DeviceExt; + + +#[repr(C)] +#[derive(Default, Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +struct Material { + pub albedo: [f32; 4], +} + +impl Material { + pub fn set_albedo(&mut self, r: f32, g: f32, b:f32) + { + self.albedo[0] = r; + self.albedo[1] = g; + self.albedo[2] = b; + } +} + + +pub struct MaterialBuffer { + materials: [Material; 256], + pub buffer: wgpu::Buffer, + pub bind_layout: wgpu::BindGroupLayout, + pub bind_group: wgpu::BindGroup +} + +impl MaterialBuffer { + + pub fn new(device: &wgpu::Device) -> Self { + // Create values + let mut materials: [Material; 256] = [Default::default(); 256]; + materials[0].set_albedo(0.41,0.33,0.20); + materials[1].set_albedo(0.49,0.74,0.00); + + // Create buffer + let buffer = device.create_buffer_init( + &wgpu::util::BufferInitDescriptor { + label: Some("Materials buffer"), + contents: bytemuck::cast_slice(&materials), + usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, + } + ); + + // Create bind group + let bind_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + } + ], + label: Some("Materials buffer layout"), + }); + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &bind_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: buffer.as_entire_binding(), + } + ], + label: Some("Materials buffer group"), + }); + + // Done + MaterialBuffer { buffer, materials, bind_layout, bind_group } + } +} \ No newline at end of file diff --git a/src/renderer/buffers/mod.rs b/src/renderer/buffers/mod.rs index 48992e7..9bf5c1e 100644 --- a/src/renderer/buffers/mod.rs +++ b/src/renderer/buffers/mod.rs @@ -1,9 +1,20 @@ +// Consts + +pub const WORLD_SIZE: usize = 32; +pub const NUM_NODES: usize = (WORLD_SIZE*WORLD_SIZE*WORLD_SIZE) as usize; + +pub const BRICK_SIZE : usize = 32; // 32x32x32 brick size +pub const BRICK_NUM : usize = 32768; // max bricks in texture +pub const BRICK_LEN : usize = BRICK_SIZE*BRICK_SIZE*BRICK_SIZE; + +// Import names + mod node_buffer; pub use node_buffer::NodeBuffer; mod brick_buffer; -pub use brick_buffer::BrickBuffer; +pub use brick_buffer::{BrickBuffer}; mod uniform_buffer; pub use uniform_buffer::UniformBuffer; @@ -11,4 +22,7 @@ pub use uniform_buffer::UniformValues; mod raster_buffer; pub use raster_buffer::RasterBuffer; -pub use raster_buffer::Vertex; \ No newline at end of file +pub use raster_buffer::Vertex; + +mod material_buffer; +pub use material_buffer::MaterialBuffer; \ No newline at end of file diff --git a/src/renderer/buffers/node_buffer.rs b/src/renderer/buffers/node_buffer.rs index e4249d2..11a415e 100644 --- a/src/renderer/buffers/node_buffer.rs +++ b/src/renderer/buffers/node_buffer.rs @@ -1,31 +1,10 @@ use byteorder::{ByteOrder, LittleEndian}; use rand::prelude::*; -// 4x4x4 nodes -const WORLD_SIZE: usize = 32; -const NUM_NODES: usize = (WORLD_SIZE*WORLD_SIZE*WORLD_SIZE) as usize; - -struct NodeData { - pub data: Box<[u32]> -} - -impl NodeData { - - pub fn new() -> Self { - let data = vec![0_u32; NUM_NODES].into_boxed_slice(); - Self { data } - } - - pub fn set(&mut self, x: usize, y: usize, z: usize, value: u32) - { - let idx = x + WORLD_SIZE * (y + WORLD_SIZE * z); - self.data[idx] = value; - } -} - +use crate::renderer::buffers::{WORLD_SIZE, NUM_NODES}; pub struct NodeBuffer { - nodes: NodeData, + pub nodes: Box<[u32]>, texture: wgpu::Texture, size: wgpu::Extent3d, pub bind_layout: wgpu::BindGroupLayout, @@ -90,23 +69,8 @@ impl NodeBuffer { ); // Data - let mut nodes = NodeData::new(); - - // let mut rng = rand::thread_rng(); - // for x in 0..WORLD_SIZE { - // for y in 0..WORLD_SIZE { - // for z in 0..WORLD_SIZE { - // let value = if rng.gen::()> 0.5 { 1 } else { 0 }; - // nodes.set(x, y, z, value); - // } - // } - // } - for i in 0..WORLD_SIZE { - nodes.set(i, 0, 0, 1); - nodes.set(0, i, 0, 1); - nodes.set(0, 0, i, 1); - } - nodes.set(0, 0, 0, 2); + let nodes = vec![0_u32; NUM_NODES].into_boxed_slice(); + println!("Node buffer size: {} MB", nodes.len() as f32 * 4.0 / 1024.0 / 1024.0); // Done Self { nodes, texture, size, bind_layout, bind_group } @@ -115,7 +79,7 @@ impl NodeBuffer { pub fn write(&mut self, queue: &wgpu::Queue) { // Convert 32 bit values to 8 bit let mut bytes = [0_u8; NUM_NODES*4]; - LittleEndian::write_u32_into(&self.nodes.data, &mut bytes); + LittleEndian::write_u32_into(&self.nodes, &mut bytes); // Write queue.write_texture( diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 6710d35..fb26e3b 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -1,6 +1,8 @@ use winit::{window::Window, dpi::PhysicalSize}; -mod buffers; use buffers::{NodeBuffer, BrickBuffer, UniformBuffer, RasterBuffer, Vertex}; +mod buffers; +use buffers::{NodeBuffer, BrickBuffer, UniformBuffer, RasterBuffer, Vertex, MaterialBuffer}; + pub mod camera; use camera::Camera; @@ -16,9 +18,11 @@ pub struct Renderer { uniform_buffer: UniformBuffer, node_buffer: NodeBuffer, brick_buffer: BrickBuffer, + material_buffer: MaterialBuffer, // Other pub camera: Camera, - start: std::time::Instant + start: std::time::Instant, + changed_bricks: Vec, } impl Renderer { @@ -82,6 +86,9 @@ impl Renderer { }) } + /* + * Initializes renderer and all buffers + */ pub async fn new(window: &Window) -> Self { // Create surface and pick device @@ -107,24 +114,29 @@ impl Renderer { // Buffers let uniform_buffer = UniformBuffer::new(&device); let raster_buffer = RasterBuffer::new(&device); - - let mut node_buffer = NodeBuffer::new(&device); - node_buffer.write(&queue); - - let mut brick_buffer = BrickBuffer::new(&device); - brick_buffer.write(&queue, 0); - brick_buffer.write(&queue, 1); + let node_buffer = NodeBuffer::new(&device); + let brick_buffer = BrickBuffer::new(&device); + let material_buffer = MaterialBuffer::new(&device); // Pipeline - let pipeline = Self::create_pipeline(&device, &swapchain_desc, &[&uniform_buffer.bind_layout, &node_buffer.bind_layout, &brick_buffer.bind_layout]); - - let start = std::time::Instant::now(); + let bind_layouts = [ + &uniform_buffer.bind_layout, + &node_buffer.bind_layout, + &brick_buffer.bind_layout, + &material_buffer.bind_layout + ]; + let pipeline = Self::create_pipeline(&device, &swapchain_desc, &bind_layouts); // Save values in app println!("Initialized"); - Self { surface, device, queue, swapchain_desc, swapchain, pipeline, raster_buffer, uniform_buffer, node_buffer, brick_buffer, camera, start } + let start = std::time::Instant::now(); + let changed_bricks: Vec = Vec::new(); + Self { surface, device, queue, swapchain_desc, swapchain, pipeline, raster_buffer, uniform_buffer, node_buffer, brick_buffer, material_buffer, camera, start, changed_bricks } } + /* + * Recreates swapchain with new resolution + */ pub fn resize(&mut self, new_size: Option>) { if let Some(size) = new_size { // Minimized or manually resized to 0 @@ -139,12 +151,24 @@ impl Renderer { self.swapchain = self.device.create_swap_chain(&self.surface, &self.swapchain_desc); } + /* + * Actually renders the frame + */ pub fn render(&mut self) -> Result<(), wgpu::SwapChainError> { // Update uniform buffer self.uniform_buffer.values.update(&self.camera, self.start.elapsed().as_secs_f32()); self.queue.write_buffer(&self.uniform_buffer.buffer, 0, bytemuck::cast_slice(&[self.uniform_buffer.values])); + // Update changed nodes + if self.changed_bricks.len() > 0 { + self.node_buffer.write(&self.queue); + for node in &self.changed_bricks { + self.brick_buffer.write(&self.queue, *node); + } + self.changed_bricks.clear(); + } + // Get next frame to render to let frame = self.swapchain.get_current_frame()?.output; @@ -171,6 +195,7 @@ impl Renderer { render_pass.set_bind_group(0, &self.uniform_buffer.bind_group, &[]); render_pass.set_bind_group(1, &self.node_buffer.bind_group, &[]); render_pass.set_bind_group(2, &self.brick_buffer.bind_group, &[]); + render_pass.set_bind_group(3, &self.material_buffer.bind_group, &[]); // Vertices and indices render_pass.set_vertex_buffer(0, self.raster_buffer.vertex_buffer.slice(..)); render_pass.set_index_buffer(self.raster_buffer.index_buffer.slice(..), wgpu::IndexFormat::Uint16); @@ -183,4 +208,52 @@ impl Renderer { // Return ok Ok(()) } + + /* + * Create or update brick at given location + */ + #[allow(dead_code)] + pub fn set_voxel(&mut self, x: usize, y: usize, z:usize, value: u8) + { + let brick_id = self.brick_get_id(x/32, y/32, z/32 ); + self.brick_set_voxel(brick_id, x%32, y%32, z%32, value); + self.brick_mark_changed(brick_id); + } + + /* + * Create or update brick at given location + */ + pub fn brick_set_voxel(&mut self, brick_id:usize, x: usize, y: usize, z:usize, value: u8) + { + let voxel_id = x + buffers::BRICK_SIZE * (y + buffers::BRICK_SIZE * z); + let brick_offset = brick_id * buffers::BRICK_LEN; + self.brick_buffer.bricks[brick_offset + voxel_id] = value; + } + + /* + * Gets brick id + */ + pub fn brick_get_id(&mut self, x: usize, y: usize, z:usize) -> usize { + // Get node + let node_idx = x + buffers::WORLD_SIZE * (y + buffers::WORLD_SIZE * z); + let mut node_value = self.node_buffer.nodes[node_idx]; + + // Use new brick if neccesary + if node_value == 0 { + node_value = self.brick_buffer.next_brick() as u32; + self.node_buffer.nodes[node_idx] = node_value; + } + + // Get brick id from node value + (node_value - 1) as usize + } + + /* + * Marks brick as changed + */ + pub fn brick_mark_changed(&mut self, brick_id:usize) { + if !self.changed_bricks.contains(&brick_id) { + self.changed_bricks.push(brick_id); + } + } } \ No newline at end of file diff --git a/src/shaders/bin/shader.frag.spv b/src/shaders/bin/shader.frag.spv index 1889b63..608d6e3 100644 Binary files a/src/shaders/bin/shader.frag.spv and b/src/shaders/bin/shader.frag.spv differ diff --git a/src/shaders/raycasting.cginc b/src/shaders/raycasting.cginc index 5bc8e8d..80ce95e 100644 --- a/src/shaders/raycasting.cginc +++ b/src/shaders/raycasting.cginc @@ -1,28 +1,9 @@ -/* - point: Hit point - view: View vector (camera ray) - normal: Normal vector -*/ -vec3 solve(vec3 hitPoint, vec3 view, vec3 normal) -{ - // Lighting - vec3 light_color = vec3(1.0, 1.0, 1.0); - vec3 light_dir = normalize(hitPoint-vec3(0.0, 1.5, 4.0)); - - vec3 ambient = light_color * 0.1; - vec3 diffuse = light_color * max(1.0-dot(normal, light_dir), 0.0); - vec3 specular = light_color * pow(max(dot(view, reflect(-light_dir, normal)), 0.0), 32); - - // Combine colors - vec3 object_color = vec3(0.0, 0.1, 0.5); - return (ambient + diffuse + specular) * object_color; -} - /* * origin: Point hit on the node * dir: Camera view direction (ray direction) -* addr: Number given by node, afaik brick offset in brick array +* incAxis: Last axis that was used to increment position +* addr: Number given by node, brick offset in brick array */ vec4 castBricks(vec3 origin, vec3 start, vec3 dir, vec3 incAxis, uint addr) { @@ -38,14 +19,12 @@ vec4 castBricks(vec3 origin, vec3 start, vec3 dir, vec3 incAxis, uint addr) vec3 rayInv = 1.0/dir; vec3 raySign = sign(dir); vec3 dist = (pos-origin+0.5 + raySign*0.5) * rayInv; - ivec3 offset = ivec3(0, 0, (addr-1)*32); - vec3 tmp = abs(raySign); for(int i=0;i<110;i++) { // Get brick - uint brick = texelFetch(bricksTexture, offset+ivec3(pos), 0).r; + uint brick = texelFetch(_BricksTexture, offset+ivec3(pos), 0).r; if(brick != 0) { // Hit point @@ -55,7 +34,7 @@ vec4 castBricks(vec3 origin, vec3 start, vec3 dir, vec3 incAxis, uint addr) // Normal vector (negate previous increment axis and mult by sign) vec3 normal = -incAxis * raySign; - return vec4(solve(hitPoint, dir, normal), 1.0); + return vec4(solve(hitPoint, dir, normal, brick-1), 1.0); } // Get new closest axis to increment @@ -68,7 +47,7 @@ vec4 castBricks(vec3 origin, vec3 start, vec3 dir, vec3 incAxis, uint addr) if(pos.x > 31 || pos.y > 31 || pos.z > 31) { break; } } - return vec4(0.5,0.5,0.5, 0.0); + return vec4(1.0,0.0,0.5,0.0); } /* @@ -93,16 +72,13 @@ vec3 castNodes(vec3 origin, vec3 dir) for(int i=0;i<110;i++) { // Get node - uint node = texelFetch(nodesTexture, ivec3(pos), 0).r; + uint node = texelFetch(_NodesTexture, ivec3(pos), 0).r; if(node != 0) { // Hit point vec3 mini = (pos-origin+0.5 - raySign*0.5) * rayInv; float len = max(0.0, max(mini.x, max(mini.y, mini.z))); vec3 hitPoint = origin + dir * len; - // Normal vector (negate previous increment axis and mult by sign) - //vec3 normal = -incAxis * raySign; - //return solve(hitPoint, dir, normal); // Cast brick vec4 result = castBricks(pos, hitPoint, dir, incAxis, node); diff --git a/src/shaders/raymarching.cginc b/src/shaders/raymarching.cginc deleted file mode 100644 index c853868..0000000 --- a/src/shaders/raymarching.cginc +++ /dev/null @@ -1,91 +0,0 @@ - -// Returns nearest distance to and object id from given point -vec2 map(in vec3 pos) -{ - vec2 d1 = vec2(sdPlane(pos), 1); - vec2 d2 = vec2(sdSphere(pos - vec3(0.0, 2.0, 5.0)), 2); - vec2 d3 = vec2(sdSphere(pos - vec3(0.0, 3.0, 3.0)), 3); - return sdUnion(sdUnion(d1, d2), d3); -} - -// Returns distance to and object id that has been intersected by ray -vec2 intersect(in vec3 ro, in vec3 rd) -{ - float depth = NEAR; - for(int i=0;i 0.0) - { - // Calculate intersection point, normal vector and reflection vector - vec3 pos = ro + rd * result.x; - vec3 nor = estimateNormal(pos); - vec3 ref = reflect(rd, nor); - - // Light - vec3 light = vec3(1); - - float dif = clamp( dot( nor, ld ), 0.0, 1.0 ); - light += 2.20*dif*vec3(1.30,1.00,0.70); - - vec3 hal = normalize( ld-rd ); - float spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0); - spe *= dif; - spe *= 0.04+0.96*pow(clamp(1.0-dot(hal,ld),0.0,1.0),5.0); - light += 5.00*spe*vec3(1.30,1.00,0.70); - - //float diffuse = max(dot(norm, -ld), 0); - //color *= diffuse; - - //vec3 ldr = normalize(reflect(-ld, norm)); - //float specular = max(dot(ldr, rd), 0.0); - //specular = pow(specular, 3); - //color += vec3(0.2) * specular; - - //float scatter = pow(1.0-dot(rd, -norm), 2); - - // Calculate color - vec3 color = vec3(0); - if(result.y == 1) color = vec3(0.0, 0.1, 0.01); - else if(result.y == 2) color = vec3(0.5, 0.7, 0.05); - else if(result.y == 3) color = vec3(0.0, 0.2, 0.7); - - // Return - color *= light; - return color; - } - else - { - return vec3(0); - } -} \ No newline at end of file diff --git a/src/shaders/shader.frag b/src/shaders/shader.frag index 553360b..a805a26 100644 --- a/src/shaders/shader.frag +++ b/src/shaders/shader.frag @@ -1,38 +1,41 @@ // shader.frag #version 450 +struct Material { + vec4 albedo; +}; + // Variables layout(location=0) in vec2 vert_uv; layout(location=0) out vec4 out_color; -layout(set=0, binding=0) uniform Uniforms -{ - mat4 _viewMatrix; - mat4 _projMatrixInv; +layout(set=0,binding=0) uniform Uniforms { + mat4 _ViewMatrix; + mat4 _ProjMatrixInv; vec3 _CamPos; float _Time; }; - -//layout(set = 1, binding = 0) uniform texture3D node_tex; -//layout(set = 1, binding = 1) uniform usampler3D node_sampl; -layout(set=1,binding=0) uniform usampler3D nodesTexture; -layout(set=2,binding=0) uniform usampler3D bricksTexture; +layout(set=1,binding=0) uniform usampler3D _NodesTexture; +layout(set=2,binding=0) uniform usampler3D _BricksTexture; +layout(set=3, binding=0) uniform Materials { + Material _Materials[256]; +}; // Defines -#define PI 3.141592 -#define EPSILON 0.01 -#define NEAR 0.01 -#define MAX_STEPS 200 +// #define PI 3.141592 +// #define EPSILON 0.01 +// #define NEAR 0.01 // Include -#include "shapes.cginc" +#include "shading.cginc" #include "raycasting.cginc" + void main() { // Calculate ray direction - vec3 view_dir = (_projMatrixInv * vec4(vert_uv, 0, 1)).xyz; - vec3 ray_dir = normalize(_viewMatrix * vec4(view_dir,0)).xyz; + vec3 view_dir = (_ProjMatrixInv * vec4(vert_uv, 0, 1)).xyz; + vec3 ray_dir = normalize(_ViewMatrix * vec4(view_dir,0)).xyz; // Raycast out_color = vec4(castNodes(_CamPos, ray_dir), 1.0); diff --git a/src/shaders/shading.cginc b/src/shaders/shading.cginc new file mode 100644 index 0000000..a72a36f --- /dev/null +++ b/src/shaders/shading.cginc @@ -0,0 +1,19 @@ +/* + point: Hit point + view: View vector (camera ray) + normal: Normal vector +*/ +vec3 solve(vec3 hitPoint, vec3 view, vec3 normal, uint brick) +{ + // Lighting + vec3 light_color = vec3(1.0, 1.0, 1.0); + vec3 light_dir = normalize(hitPoint-vec3(0.0, 1.5, 4.0)); + + vec3 ambient = light_color * 0.1; + vec3 diffuse = light_color * max(1.0-dot(normal, light_dir), 0.0); + vec3 specular = light_color * pow(max(dot(view, reflect(-light_dir, normal)), 0.0), 32); + + // Combine colors + vec3 object_color = _Materials[brick].albedo.rgb;//vec3(0.0, 0.1, 0.5); + return (ambient + diffuse + specular) * object_color; +} \ No newline at end of file