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"] }
|
glam = { version = "0.22", features = ["debug-glam-assert", "mint", "fast-math"] }
|
||||||
hashbrown = "0.13"
|
hashbrown = "0.13"
|
||||||
simdnoise = "3.1"
|
simdnoise = "3.1"
|
||||||
|
rayon = "1.6"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
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 std::{fs, io, path::PathBuf, sync::atomic::AtomicU16};
|
||||||
use glium::texture::{RawImage2d, SrgbTexture2d};
|
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 {
|
fn load_png(file_path: &str, display: &glium::Display) -> SrgbTexture2d {
|
||||||
log::info!("loading texture {}", file_path);
|
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()
|
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 struct Textures {
|
||||||
pub block_atlas: SrgbTexture2d
|
pub blocks: SrgbTexture2dArray
|
||||||
}
|
}
|
||||||
impl Textures {
|
impl Textures {
|
||||||
/// Load textures synchronously, one by one and upload them to the GPU
|
/// Load textures synchronously, one by one and upload them to the GPU
|
||||||
pub fn load_sync(display: &glium::Display) -> Self {
|
pub fn load_sync(display: &glium::Display) -> Self {
|
||||||
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 position: [f32; 3],
|
||||||
pub normal: [f32; 3],
|
pub normal: [f32; 3],
|
||||||
pub uv: [f32; 2],
|
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 = include_str!("./glsl/chunk.vert");
|
||||||
pub const VERTEX_SHADER: &str = r#"
|
pub const FRAGMENT_SHADER: &str = include_str!("./glsl/chunk.frag");
|
||||||
#version 150 core
|
|
||||||
|
|
||||||
in vec3 position;
|
// pub const VERTEX_SHADER: &str = r#"
|
||||||
in vec3 normal;
|
// #version 150 core
|
||||||
in vec2 uv;
|
|
||||||
out vec3 v_normal;
|
|
||||||
out vec2 v_uv;
|
|
||||||
uniform mat4 perspective;
|
|
||||||
uniform mat4 view;
|
|
||||||
uniform mat4 model;
|
|
||||||
|
|
||||||
void main() {
|
// in vec3 position;
|
||||||
mat4 modelview = view * model;
|
// in vec3 normal;
|
||||||
//v_normal = transpose(inverse(mat3(modelview))) * normal;
|
// in vec2 uv;
|
||||||
v_normal = normal;
|
// out vec3 v_normal;
|
||||||
v_uv = uv;
|
// out vec2 v_uv;
|
||||||
gl_Position = perspective * modelview * vec4(position, 1.0);
|
// uniform mat4 perspective;
|
||||||
}
|
// uniform mat4 view;
|
||||||
"#;
|
// uniform mat4 model;
|
||||||
pub const FRAGMENT_SHADER: &str = r#"
|
|
||||||
#version 150 core
|
|
||||||
|
|
||||||
in vec2 v_uv;
|
// void main() {
|
||||||
in vec3 v_normal;
|
// mat4 modelview = view * model;
|
||||||
out vec4 color;
|
// //v_normal = transpose(inverse(mat3(modelview))) * normal;
|
||||||
uniform sampler2D tex;
|
// v_normal = normal;
|
||||||
|
// v_uv = uv;
|
||||||
void main() {
|
// gl_Position = perspective * modelview * vec4(position, 1.0);
|
||||||
// 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.);
|
|
||||||
}
|
|
||||||
"#;
|
|
||||||
|
|
|
@ -6,22 +6,5 @@ pub struct Vertex {
|
||||||
}
|
}
|
||||||
implement_vertex!(Vertex, position);
|
implement_vertex!(Vertex, position);
|
||||||
|
|
||||||
pub const VERTEX_SHADER: &str = r#"
|
pub const VERTEX_SHADER: &str = include_str!("./glsl/colored2d.vert");
|
||||||
#version 150 core
|
pub const FRAGMENT_SHADER: &str = include_str!("./glsl/colored2d.frag");
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
"#;
|
|
||||||
|
|
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,
|
view: view,
|
||||||
perspective: perspective,
|
perspective: perspective,
|
||||||
tex: Sampler(&assets.textures.block_atlas, sampler)
|
tex: Sampler(&assets.textures.blocks, sampler)
|
||||||
},
|
},
|
||||||
&draw_parameters
|
&draw_parameters
|
||||||
).unwrap();
|
).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(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.)],
|
[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., 1., 0.],
|
||||||
[0., 0., -1.],
|
[0., 0., -1.],
|
||||||
[-1., 0., 0.],
|
[-1., 0., 0.],
|
||||||
|
@ -38,7 +38,14 @@ pub const CUBE_FACE_NORMALS: [[f32; 3]; 6] = [
|
||||||
[0., 0., 1.],
|
[0., 0., 1.],
|
||||||
[0., -1., 0.]
|
[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)]
|
#[derive(Default)]
|
||||||
struct MeshBuilder {
|
struct MeshBuilder {
|
||||||
|
@ -51,7 +58,7 @@ impl MeshBuilder {
|
||||||
Self::default()
|
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 coord = coord.as_vec3a();
|
||||||
let face_index = face as usize;
|
let face_index = face as usize;
|
||||||
|
|
||||||
|
@ -63,7 +70,8 @@ impl MeshBuilder {
|
||||||
self.vertex_buffer.push(Vertex {
|
self.vertex_buffer.push(Vertex {
|
||||||
position: (coord + vert[i]).to_array(),
|
position: (coord + vert[i]).to_array(),
|
||||||
normal: norm,
|
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 {
|
if show {
|
||||||
let texures = descriptor.render.unwrap().1;
|
let texures = descriptor.render.unwrap().1;
|
||||||
let texture_id = match face {
|
let texture_index = match face {
|
||||||
CubeFace::Top => texures.top,
|
CubeFace::Top => texures.top,
|
||||||
CubeFace::Front => texures.front,
|
CubeFace::Front => texures.front,
|
||||||
CubeFace::Left => texures.left,
|
CubeFace::Left => texures.left,
|
||||||
|
@ -120,22 +128,7 @@ pub fn generate_mesh(position: IVec2, chunk_data: ChunkData, neighbors: [ChunkDa
|
||||||
CubeFace::Back => texures.back,
|
CubeFace::Back => texures.back,
|
||||||
CubeFace::Bottom => texures.bottom,
|
CubeFace::Bottom => texures.bottom,
|
||||||
};
|
};
|
||||||
//TODO replace with a proper texture resolver (or calculate uvs in a shader!)
|
builer.add_face(face, coord, texture_index);
|
||||||
//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),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|