Work-in-progress refactor
|
@ -12,6 +12,7 @@ strum = { version = "0.24", features = ["derive"] }
|
|||
glam = { version = "0.22", features = ["debug-glam-assert", "mint", "fast-math"] }
|
||||
hashbrown = "0.13"
|
||||
simdnoise = "3.1"
|
||||
rayon = "1.6"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
|
BIN
assets/blocks/bedrock.png
Normal file
After Width: | Height: | Size: 229 B |
BIN
assets/blocks/dirt.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
assets/blocks/grass.png
Normal file
After Width: | Height: | Size: 550 B |
BIN
assets/blocks/grass_side.png
Normal file
After Width: | Height: | Size: 386 B |
BIN
assets/blocks/leaf.png
Normal file
After Width: | Height: | Size: 347 B |
BIN
assets/blocks/sand.png
Normal file
After Width: | Height: | Size: 798 B |
BIN
assets/blocks/stone.png
Normal file
After Width: | Height: | Size: 230 B |
BIN
assets/blocks/tall_grass.png
Normal file
After Width: | Height: | Size: 401 B |
BIN
assets/blocks/torch.png
Normal file
After Width: | Height: | Size: 240 B |
BIN
assets/blocks/tree.png
Normal file
After Width: | Height: | Size: 476 B |
BIN
assets/blocks/tree_top.png
Normal file
After Width: | Height: | Size: 455 B |
Before Width: | Height: | Size: 222 KiB |
|
@ -1,5 +1,8 @@
|
|||
use std::{fs, io};
|
||||
use glium::texture::{RawImage2d, SrgbTexture2d};
|
||||
use std::{fs, io, path::PathBuf, sync::atomic::AtomicU16};
|
||||
use rayon::prelude::*;
|
||||
use glium::texture::{RawImage2d, SrgbTexture2d, SrgbTexture2dArray};
|
||||
|
||||
//This code is terrible and has a alot of duplication
|
||||
|
||||
fn load_png(file_path: &str, display: &glium::Display) -> SrgbTexture2d {
|
||||
log::info!("loading texture {}", file_path);
|
||||
|
@ -25,14 +28,53 @@ fn load_png(file_path: &str, display: &glium::Display) -> SrgbTexture2d {
|
|||
SrgbTexture2d::new(display, raw_image).unwrap()
|
||||
}
|
||||
|
||||
fn load_png_array(file_paths: &[PathBuf], display: &glium::Display) -> SrgbTexture2dArray {
|
||||
let counter = AtomicU16::new(0);
|
||||
let raw_images: Vec<RawImage2d<u8>> = file_paths.par_iter().enumerate().map(|(_, file_path)| {
|
||||
let counter = counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
|
||||
log::info!("loading texture {}/{}: {}", counter, file_paths.len(), file_path.to_str().unwrap());
|
||||
|
||||
//Load file
|
||||
let data = fs::read(file_path).expect("Failed to load texture");
|
||||
|
||||
//decode image data
|
||||
let image_data = image::load(
|
||||
io::Cursor::new(&data),
|
||||
image::ImageFormat::Png
|
||||
).unwrap().to_rgba8();
|
||||
|
||||
//Create raw glium image
|
||||
let image_dimensions = image_data.dimensions();
|
||||
let raw_image = RawImage2d::from_raw_rgba_reversed(
|
||||
&image_data.into_raw(),
|
||||
image_dimensions
|
||||
);
|
||||
|
||||
raw_image
|
||||
}).collect();
|
||||
SrgbTexture2dArray::new(display, raw_images).unwrap()
|
||||
}
|
||||
|
||||
pub struct Textures {
|
||||
pub block_atlas: SrgbTexture2d
|
||||
pub blocks: SrgbTexture2dArray
|
||||
}
|
||||
impl Textures {
|
||||
/// Load textures synchronously, one by one and upload them to the GPU
|
||||
pub fn load_sync(display: &glium::Display) -> Self {
|
||||
Self {
|
||||
block_atlas: load_png("assets/spritesheet.png", display)
|
||||
blocks: load_png_array(&[
|
||||
"./assets/blocks/stone.png".into(),
|
||||
"./assets/blocks/dirt.png".into(),
|
||||
"./assets/blocks/grass.png".into(),
|
||||
"./assets/blocks/grass_side.png".into(),
|
||||
"./assets/blocks/sand.png".into(),
|
||||
"./assets/blocks/bedrock.png".into(),
|
||||
"./assets/blocks/tree.png".into(),
|
||||
"./assets/blocks/tree_top.png".into(),
|
||||
"./assets/blocks/leaf.png".into(),
|
||||
"./assets/blocks/torch.png".into(),
|
||||
"./assets/blocks/tall_grass.png".into(),
|
||||
], display)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,43 +5,30 @@ pub struct Vertex {
|
|||
pub position: [f32; 3],
|
||||
pub normal: [f32; 3],
|
||||
pub uv: [f32; 2],
|
||||
pub tex_index: u8,
|
||||
}
|
||||
implement_vertex!(Vertex, position, normal, uv);
|
||||
implement_vertex!(Vertex, position, normal, uv, tex_index);
|
||||
|
||||
//TODO store vertex data in a more compact way
|
||||
pub const VERTEX_SHADER: &str = r#"
|
||||
#version 150 core
|
||||
pub const VERTEX_SHADER: &str = include_str!("./glsl/chunk.vert");
|
||||
pub const FRAGMENT_SHADER: &str = include_str!("./glsl/chunk.frag");
|
||||
|
||||
in vec3 position;
|
||||
in vec3 normal;
|
||||
in vec2 uv;
|
||||
out vec3 v_normal;
|
||||
out vec2 v_uv;
|
||||
uniform mat4 perspective;
|
||||
uniform mat4 view;
|
||||
uniform mat4 model;
|
||||
// pub const VERTEX_SHADER: &str = r#"
|
||||
// #version 150 core
|
||||
|
||||
void main() {
|
||||
mat4 modelview = view * model;
|
||||
//v_normal = transpose(inverse(mat3(modelview))) * normal;
|
||||
v_normal = normal;
|
||||
v_uv = uv;
|
||||
gl_Position = perspective * modelview * vec4(position, 1.0);
|
||||
}
|
||||
"#;
|
||||
pub const FRAGMENT_SHADER: &str = r#"
|
||||
#version 150 core
|
||||
// in vec3 position;
|
||||
// in vec3 normal;
|
||||
// in vec2 uv;
|
||||
// out vec3 v_normal;
|
||||
// out vec2 v_uv;
|
||||
// uniform mat4 perspective;
|
||||
// uniform mat4 view;
|
||||
// uniform mat4 model;
|
||||
|
||||
in vec2 v_uv;
|
||||
in vec3 v_normal;
|
||||
out vec4 color;
|
||||
uniform sampler2D tex;
|
||||
|
||||
void main() {
|
||||
// base color from texture
|
||||
color = texture(tex, v_uv);
|
||||
|
||||
//basic lighting
|
||||
color *= vec4(vec3(abs(v_normal.x) + .8 * abs(v_normal.y) + .6 * abs(v_normal.z)), 1.);
|
||||
}
|
||||
"#;
|
||||
// void main() {
|
||||
// mat4 modelview = view * model;
|
||||
// //v_normal = transpose(inverse(mat3(modelview))) * normal;
|
||||
// v_normal = normal;
|
||||
// v_uv = uv;
|
||||
// gl_Position = perspective * modelview * vec4(position, 1.0);
|
||||
// }
|
||||
// "#;
|
||||
|
|
|
@ -6,22 +6,5 @@ pub struct Vertex {
|
|||
}
|
||||
implement_vertex!(Vertex, position);
|
||||
|
||||
pub const VERTEX_SHADER: &str = r#"
|
||||
#version 150 core
|
||||
|
||||
in vec2 position;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(position, 0., 1.);
|
||||
}
|
||||
"#;
|
||||
pub const FRAGMENT_SHADER: &str = r#"
|
||||
#version 150 core
|
||||
|
||||
out vec4 color;
|
||||
uniform vec4 u_color;
|
||||
|
||||
void main() {
|
||||
color = u_color;
|
||||
}
|
||||
"#;
|
||||
pub const VERTEX_SHADER: &str = include_str!("./glsl/colored2d.vert");
|
||||
pub const FRAGMENT_SHADER: &str = include_str!("./glsl/colored2d.frag");
|
||||
|
|
15
src/game/shaders/glsl/chunk.frag
Normal file
|
@ -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.);
|
||||
}
|
18
src/game/shaders/glsl/chunk.vert
Normal file
|
@ -0,0 +1,18 @@
|
|||
#version 150 core
|
||||
|
||||
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 vec3 position_offset;
|
||||
uniform mat4 perspective;
|
||||
uniform mat4 view;
|
||||
|
||||
void main() {
|
||||
v_normal = normal;
|
||||
v_tex_index = tex_index;
|
||||
gl_Position = perspective * view * vec4(position, 1.0) * vec4(position_offset, 1.0);
|
||||
}
|
8
src/game/shaders/glsl/colored2d.frag
Normal file
|
@ -0,0 +1,8 @@
|
|||
#version 150 core
|
||||
|
||||
out vec4 color;
|
||||
uniform vec4 u_color;
|
||||
|
||||
void main() {
|
||||
color = u_color;
|
||||
}
|
7
src/game/shaders/glsl/colored2d.vert
Normal file
|
@ -0,0 +1,7 @@
|
|||
#version 150 core
|
||||
|
||||
in vec2 position;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(position, 0., 1.);
|
||||
}
|
|
@ -95,7 +95,7 @@ impl World {
|
|||
],
|
||||
view: view,
|
||||
perspective: perspective,
|
||||
tex: Sampler(&assets.textures.block_atlas, sampler)
|
||||
tex: Sampler(&assets.textures.blocks, sampler)
|
||||
},
|
||||
&draw_parameters
|
||||
).unwrap();
|
||||
|
|
|
@ -30,7 +30,7 @@ const CUBE_FACE_VERTICES: [[Vec3A; 4]; 6] = [
|
|||
[vec3a(1., 0., 1.), vec3a(1., 1., 1.), vec3a(0., 0., 1.), vec3a(0., 1., 1.)],
|
||||
[vec3a(0., 0., 1.), vec3a(0., 0., 0.), vec3a(1., 0., 1.), vec3a(1., 0., 0.)],
|
||||
];
|
||||
pub const CUBE_FACE_NORMALS: [[f32; 3]; 6] = [
|
||||
const CUBE_FACE_NORMALS: [[f32; 3]; 6] = [
|
||||
[0., 1., 0.],
|
||||
[0., 0., -1.],
|
||||
[-1., 0., 0.],
|
||||
|
@ -38,7 +38,14 @@ pub const CUBE_FACE_NORMALS: [[f32; 3]; 6] = [
|
|||
[0., 0., 1.],
|
||||
[0., -1., 0.]
|
||||
];
|
||||
pub const CUBE_FACE_INDICES: [u32; 6] = [0, 1, 2, 2, 1, 3];
|
||||
const CUBE_FACE_INDICES: [u32; 6] = [0, 1, 2, 2, 1, 3];
|
||||
const UV_COORDS: [[f32; 2]; 4] = [
|
||||
[0., 0.],
|
||||
[0., 1.],
|
||||
[1., 0.],
|
||||
[1., 1.],
|
||||
];
|
||||
|
||||
|
||||
#[derive(Default)]
|
||||
struct MeshBuilder {
|
||||
|
@ -51,7 +58,7 @@ impl MeshBuilder {
|
|||
Self::default()
|
||||
}
|
||||
|
||||
pub fn add_face(&mut self, face: CubeFace, coord: IVec3, uvs: [Vec2; 4]) {
|
||||
pub fn add_face(&mut self, face: CubeFace, coord: IVec3, texture: u8) {
|
||||
let coord = coord.as_vec3a();
|
||||
let face_index = face as usize;
|
||||
|
||||
|
@ -63,7 +70,8 @@ impl MeshBuilder {
|
|||
self.vertex_buffer.push(Vertex {
|
||||
position: (coord + vert[i]).to_array(),
|
||||
normal: norm,
|
||||
uv: uvs[i].to_array()
|
||||
uv: UV_COORDS[i],
|
||||
tex_index: texture
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -112,7 +120,7 @@ pub fn generate_mesh(position: IVec2, chunk_data: ChunkData, neighbors: [ChunkDa
|
|||
};
|
||||
if show {
|
||||
let texures = descriptor.render.unwrap().1;
|
||||
let texture_id = match face {
|
||||
let texture_index = match face {
|
||||
CubeFace::Top => texures.top,
|
||||
CubeFace::Front => texures.front,
|
||||
CubeFace::Left => texures.left,
|
||||
|
@ -120,22 +128,7 @@ pub fn generate_mesh(position: IVec2, chunk_data: ChunkData, neighbors: [ChunkDa
|
|||
CubeFace::Back => texures.back,
|
||||
CubeFace::Bottom => texures.bottom,
|
||||
};
|
||||
//TODO replace with a proper texture resolver (or calculate uvs in a shader!)
|
||||
//this is temporary!
|
||||
//also this can only resolve textures on the first row.
|
||||
|
||||
const TEX_WIDTH: f32 = 16. / 640.;
|
||||
const TEX_HEIGHT: f32 = 16. / 404.;
|
||||
let x1 = TEX_WIDTH * texture_id as f32;
|
||||
let x2 = x1 + TEX_WIDTH as f32;
|
||||
let y1 = 1. - TEX_HEIGHT;
|
||||
let y2 = 1.;
|
||||
builer.add_face(face, coord, [
|
||||
vec2(x1, y1),
|
||||
vec2(x1, y2),
|
||||
vec2(x2, y1),
|
||||
vec2(x2, y2),
|
||||
]);
|
||||
builer.add_face(face, coord, texture_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|