diff --git a/crabs.txt b/crabs.txt new file mode 100644 index 0000000..aecc062 --- /dev/null +++ b/crabs.txt @@ -0,0 +1 @@ +sorry no crabs here diff --git a/shaders/world.frag b/shaders/world.frag new file mode 100644 index 0000000..e07b5e1 --- /dev/null +++ b/shaders/world.frag @@ -0,0 +1,15 @@ +#version 150 core + +in vec3 v_normal; +in vec2 v_uv; +flat in uint v_tex_index; +out vec4 color; +uniform sampler2DArray tex; + +void main() { + // base color from texture + color = texture(tex, vec3(v_uv, v_tex_index)); + //basic "lighting" + float light = abs(v_normal.x) + .8 * abs(v_normal.y) + .6 * abs(v_normal.z); + color *= vec4(vec3(light), 1.); +} diff --git a/shaders/world.vert b/shaders/world.vert new file mode 100644 index 0000000..955ca12 --- /dev/null +++ b/shaders/world.vert @@ -0,0 +1,25 @@ +#version 150 core + +//TODO pack this data: +// uint position_normal_uv +// XXYYZZNU +// wehere Normal and Uv are enums +// maybe somehow pack in tex index too + +in vec3 position; +in vec3 normal; +in vec2 uv; +in uint tex_index; +out vec2 v_uv; +out vec3 v_normal; +flat out uint v_tex_index; +uniform vec2 position_offset; +uniform mat4 perspective; +uniform mat4 view; + +void main() { + v_normal = normal; + v_tex_index = tex_index; + v_uv = uv; + gl_Position = perspective * view * (vec4(position, 1.0) + vec4(position_offset.x, 0., position_offset.y, 0.)); +} diff --git a/src/main.rs b/src/main.rs index 1f10005..c683f6b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -62,6 +62,9 @@ fn main() { *control_flow = ControlFlow::Poll; match event { Event::WindowEvent { event, .. } => match event { + WindowEvent::Resized(size) => { + // todo ... + } WindowEvent::CloseRequested => { log::info!("exit requested"); *control_flow = ControlFlow::Exit; diff --git a/src/prefabs.rs b/src/prefabs.rs index 66fe6be..8b33afe 100644 --- a/src/prefabs.rs +++ b/src/prefabs.rs @@ -1,11 +1,15 @@ use shipyard::{World, NonSendSync, UniqueView, Unique}; use strum::{EnumIter, IntoEnumIterator}; -use rayon::prelude::*; -use glium::{texture::{SrgbTexture2dArray, RawImage2d}, backend::Facade}; -use std::{fs::File, path::PathBuf, io::BufReader}; +use glium::{texture::{SrgbTexture2dArray, RawImage2d}, backend::Facade, Program}; use crate::rendering::Rederer; -trait AssetPaths { +mod texture; +mod shaders; + +use texture::load_texture2darray_prefab; +use shaders::include_shader_prefab; + +pub trait AssetPaths { fn file_name(self) -> &'static str; } @@ -46,43 +50,27 @@ impl AssetPaths for BlockTextures { } } -fn load_texture2darray_prefab(directory: PathBuf, facade: &E) -> SrgbTexture2dArray { - //Load raw images - let tex_files: Vec<&'static str> = T::iter().map(|x| x.file_name()).collect(); - let raw_images: Vec> = tex_files.par_iter().map(|&file_name| { - log::info!("loading texture {}", file_name); - //Get path to the image and open the file - let reader = { - let path = directory.join(file_name); - BufReader::new(File::open(path).expect("Failed to open texture file")) - }; - //Parse image data - let (image_data, dimensions) = { - let image =image::load( - reader, - image::ImageFormat::Png - ).unwrap().to_rgba8(); - let dimensions = image.dimensions(); - (image.into_raw(), dimensions) - }; - //Create a glium RawImage - RawImage2d::from_raw_rgba_reversed( - &image_data, - dimensions - ) - }).collect(); - log::info!("done loading texture files, uploading to the gpu"); - //Upload images to the GPU - SrgbTexture2dArray::new(facade, raw_images) - .expect("Failed to upload texture array to GPU") -} + #[derive(Unique)] pub struct BlockTexturesPrefab(SrgbTexture2dArray); +#[derive(Unique)] +pub struct ChunkShaderPrefab(Program); + pub fn load_prefabs(world: &World) { let renderer = world.borrow::>>().unwrap(); world.add_unique_non_send_sync(BlockTexturesPrefab( - load_texture2darray_prefab::("./assets/blocks/".into(), &renderer.display) + load_texture2darray_prefab::( + "./assets/blocks/".into(), + &renderer.display + ) + )); + world.add_unique_non_send_sync(ChunkShaderPrefab( + include_shader_prefab!( + "../shaders/world.vert", + "../shaders/world.frag", + &renderer.display + ) )); } diff --git a/src/prefabs/shaders.rs b/src/prefabs/shaders.rs new file mode 100644 index 0000000..5f7ed07 --- /dev/null +++ b/src/prefabs/shaders.rs @@ -0,0 +1,29 @@ +use glium::{Program, backend::Facade}; + +macro_rules! include_shader_prefab { + ($vert: literal, $frag: literal, $geom: literal, $facade: expr) => { + { + log::info!("↓↓↓ compiling shader prefab ↓↓↓"); + log::info!("{} {} {}", $vert, $frag, $geom); + Program::from_source( + &*$facade, + include_str!($vert), + include_str!($frag), + Some(include_str!($geom)), + ).expect("Failed to compile gpu program") + } + }; + ($vert: literal, $frag: literal, $facade: expr) => { + { + log::info!("↓↓↓ compiling shader prefab ↓↓↓"); + log::info!("{} {}", $vert, $frag); + Program::from_source( + &*$facade, + include_str!($vert), + include_str!($frag), + None, + ).expect("Failed to compile gpu program") + } + }; +} +pub(crate) use include_shader_prefab; diff --git a/src/prefabs/texture.rs b/src/prefabs/texture.rs new file mode 100644 index 0000000..7bfda57 --- /dev/null +++ b/src/prefabs/texture.rs @@ -0,0 +1,40 @@ +use strum::IntoEnumIterator; +use rayon::prelude::*; +use std::{fs::File, path::PathBuf, io::BufReader}; +use glium::{texture::{SrgbTexture2dArray, RawImage2d}, backend::Facade}; +use super::AssetPaths; + +pub fn load_texture2darray_prefab( + directory: PathBuf, + facade: &E +) -> SrgbTexture2dArray { + log::info!("↓↓↓ loading textures {} ↓↓↓", directory.as_os_str().to_str().unwrap()); + //Load raw images + let tex_files: Vec<&'static str> = T::iter().map(|x| x.file_name()).collect(); + let raw_images: Vec> = tex_files.par_iter().map(|&file_name| { + log::info!("loading texture {}", file_name); + //Get path to the image and open the file + let reader = { + let path = directory.join(file_name); + BufReader::new(File::open(path).expect("Failed to open texture file")) + }; + //Parse image data + let (image_data, dimensions) = { + let image =image::load( + reader, + image::ImageFormat::Png + ).unwrap().to_rgba8(); + let dimensions = image.dimensions(); + (image.into_raw(), dimensions) + }; + //Create a glium RawImage + RawImage2d::from_raw_rgba_reversed( + &image_data, + dimensions + ) + }).collect(); + log::info!("done loading texture files, uploading to the gpu"); + //Upload images to the GPU + SrgbTexture2dArray::new(facade, raw_images) + .expect("Failed to upload texture array to GPU") +} diff --git a/src/world.rs b/src/world.rs index a21d2bf..c780f13 100644 --- a/src/world.rs +++ b/src/world.rs @@ -3,6 +3,7 @@ use hashbrown::HashMap; pub mod chunk; pub mod block; +pub mod render; use chunk::Chunk; diff --git a/src/world/chunk.rs b/src/world/chunk.rs index d47b680..d4af7d1 100644 --- a/src/world/chunk.rs +++ b/src/world/chunk.rs @@ -1,6 +1,6 @@ use glam::IVec3; use glium::{VertexBuffer, IndexBuffer}; -use super::block::Block; +use super::{block::Block, render::ChunkVertex}; pub const CHUNK_SIZE: usize = 32; @@ -26,9 +26,9 @@ pub struct ChunkMesh { pub enum ChunkState { ToUnload, //desired only Nothing, - Loading, //current only + Loading, //current only Loaded, - Meshing, //current only + Meshing, //current only Rendered } diff --git a/src/world/render.rs b/src/world/render.rs new file mode 100644 index 0000000..9ae11b1 --- /dev/null +++ b/src/world/render.rs @@ -0,0 +1,10 @@ +use glium::implement_vertex; + +#[derive(Clone, Copy)] +pub struct ChunkVertex { + pub position: [f32; 3], + pub normal: [f32; 3], + pub uv: [f32; 2], + pub tex_index: u8, +} +implement_vertex!(ChunkVertex, position, normal, uv, tex_index);