Skip to content

Commit e4e3a7b

Browse files
committed
Add item rendering
1 parent 0bb69da commit e4e3a7b

File tree

11 files changed

+152
-61
lines changed

11 files changed

+152
-61
lines changed

assets/shaders/model.frag

+6-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,10 @@ const vec3 SUN_DIRECTION = normalize(vec3(0, 1, 0.5));
1010
const float SUN_FRACTION = 0.3;
1111

1212
void main() {
13-
ColorBuffer = occl * vec4(v_Rgb, 1.0) * (1.0 - SUN_FRACTION + SUN_FRACTION * abs(dot(v_Norm, SUN_DIRECTION)));
13+
/* VARIOUS BRIGHTNESS FACTORS */
14+
float normal_factor = 1.0 - SUN_FRACTION + SUN_FRACTION * min(0.0, dot(v_Norm, SUN_DIRECTION));
15+
float total_factor = occl * normal_factor;
16+
17+
/* OUTPUT */
18+
ColorBuffer = vec4(v_Rgb * total_factor, 1.0);
1419
}

assets/shaders/model.vert

+6-20
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,21 @@ layout(location = 2) out vec3 v_Rgb;
1212

1313

1414
vec3 get_normal(uint id) {
15-
if(id == 0u) {
15+
if (id == 0u) {
1616
return vec3(1.0, 0.0, 0.0);
17-
} else if(id == 1u) {
17+
} else if (id == 1u) {
1818
return vec3(-1.0, 0.0, 0.0);
19-
} else if(id == 2u) {
19+
} else if (id == 2u) {
2020
return vec3(0.0, 1.0, 0.0);
21-
} else if(id == 3u) {
21+
} else if (id == 3u) {
2222
return vec3(0.0, -1.0, 0.0);
23-
} else if(id == 4u) {
23+
} else if (id == 4u) {
2424
return vec3(0.0, 0.0, 1.0);
2525
} else {
2626
return vec3(0.0, 0.0, -1.0);
2727
}
2828
}
2929

30-
vec3 srgbEncode(vec3 color){
31-
float r = color.r < 0.0031308 ? 12.92 * color.r : 1.055 * pow(color.r, 1.0/2.4) - 0.055;
32-
float g = color.g < 0.0031308 ? 12.92 * color.g : 1.055 * pow(color.g, 1.0/2.4) - 0.055;
33-
float b = color.b < 0.0031308 ? 12.92 * color.b : 1.055 * pow(color.b, 1.0/2.4) - 0.055;
34-
return vec3(r, g, b);
35-
}
36-
37-
vec3 srgbDecode(vec3 color){
38-
float r = color.r < 0.04045 ? (1.0 / 12.92) * color.r : pow((color.r + 0.055) * (1.0 / 1.055), 2.4);
39-
float g = color.g < 0.04045 ? (1.0 / 12.92) * color.g : pow((color.g + 0.055) * (1.0 / 1.055), 2.4);
40-
float b = color.b < 0.04045 ? (1.0 / 12.92) * color.b : pow((color.b + 0.055) * (1.0 / 1.055), 2.4);
41-
return vec3(r, g, b);
42-
}
43-
4430
void main() {
4531
gl_Position = u_ViewProj * u_Model * vec4(a_Pos, 1.0);
4632

@@ -67,6 +53,6 @@ void main() {
6753
float gg = float(g)/255.0;
6854
float bb = float(b)/255.0;
6955

70-
v_Rgb = srgbDecode(vec3(rr,gg,bb));
56+
v_Rgb = vec3(rr,gg,bb);
7157

7258
}

client/src/singleplayer.rs

+7
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,13 @@ impl State for SinglePlayer {
321321
pos_z: 0.0,
322322
scale: 0.3,
323323
});
324+
models_to_draw.push(crate::render::Model {
325+
mesh_id: self.model_registry.get_id_by_name(&"item:ingot_iron".to_owned()).unwrap(),
326+
pos_x: 30.0,
327+
pos_y: 55.0,
328+
pos_z: 30.0,
329+
scale: 1.0/32.0,
330+
});
324331
// Draw chunks
325332
self.world_renderer.render(
326333
device,

common/src/block/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pub type BlockId = u16;
88
#[derive(Debug, Clone, Deserialize)]
99
#[serde(rename = "Block")]
1010
pub enum BlockType {
11-
Air,
11+
Air, // TODO: skip when deserializing
1212
NormalCube { face_textures: Vec<String> },
1313
}
1414

common/src/data/mod.rs

+79-39
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::fs;
1313
use std::io::Read;
1414
use std::path::PathBuf;
1515
use texture_packer::{TexturePacker, TexturePackerConfig};
16+
use crate::item::ItemType;
1617

1718
#[derive(Debug, Clone)]
1819
pub struct Data {
@@ -92,48 +93,25 @@ pub fn load_data(data_directory: PathBuf) -> Result<Data> {
9293
let model_knight = load_voxel_model("data/model/chr_knight.vox").unwrap();
9394
models.register("knight".to_owned(), model_knight)?;
9495

95-
// Load blocks
96-
let mut block_datas: Vec<(String, BlockType)> = Vec::new();
97-
let blocks_directory = data_directory.join("blocks");
98-
info!(
99-
"Loading blocks from directory {}",
100-
blocks_directory.display()
101-
);
102-
for dir_entry in fs::read_dir(blocks_directory).context("couldn't read block directory")? {
103-
let dir_entry = dir_entry.context("failed to read directory entry")?;
104-
if dir_entry
105-
.file_type()
106-
.context("failed to get file type")?
107-
.is_file()
108-
{
109-
let file_path = dir_entry.path();
96+
// Load items
97+
let items_directory = data_directory.join("items");
98+
let item_datas: Vec<(String, ItemType)> = load_files_from_folder(items_directory);
11099

111-
match file_path.extension() {
112-
None => panic!("No file extension"),
113-
Some(ext) => {
114-
if ext == "ron" {
115-
let mut file = fs::File::open(file_path.clone())
116-
.context("couldn't open .ron block file")?;
117-
let mut buffer = String::new();
118-
file.read_to_string(&mut buffer)?;
119-
block_datas.push((
120-
file_path
121-
.file_stem()
122-
.context("failed to get file stem")?
123-
.to_str()
124-
.unwrap()
125-
.to_owned(),
126-
ron::de::from_str(&buffer)
127-
.context("failed to parse .ron block file")?,
128-
));
129-
} else {
130-
panic!("Unsupported file extension");
131-
}
132-
}
100+
// Generate item models
101+
for (name, ty) in item_datas.into_iter() {
102+
match ty {
103+
ItemType::NormalItem { texture } => {
104+
let texture_rect = texture_rects[texture_registry.get_id_by_name(&texture).unwrap() as usize];
105+
let model = self::vox::item::generate_item_model(texture_rect, &texture_atlas);
106+
models.register(format!("item:{}", name), model).expect("Failed to register item model");
133107
}
134108
}
135109
}
136110

111+
// Load blocks
112+
let blocks_directory = data_directory.join("blocks");
113+
let block_datas: Vec<(String, BlockType)> = load_files_from_folder(blocks_directory);
114+
137115
info!("Processing collected block and texture data");
138116
let mut blocks = Registry::default();
139117
let mut meshes = Vec::new();
@@ -144,7 +122,7 @@ pub fn load_data(data_directory: PathBuf) -> Result<Data> {
144122
name: "air".to_owned(),
145123
block_type: BlockType::Air,
146124
},
147-
)?;
125+
).expect("Couldn't register air in the registry.");
148126
meshes.push(BlockMesh::Empty);
149127

150128
for (name, block_type) in block_datas.into_iter() {
@@ -189,7 +167,7 @@ pub struct TextureRect {
189167
pub height: f32,
190168
}
191169

192-
const MAX_TEXTURE_SIZE: u32 = 2048;
170+
pub const MAX_TEXTURE_SIZE: u32 = 2048;
193171

194172
const TEXTURE_PACKER_CONFIG: TexturePackerConfig = TexturePackerConfig {
195173
max_width: MAX_TEXTURE_SIZE,
@@ -244,3 +222,65 @@ fn load_textures(
244222
.collect(),
245223
))
246224
}
225+
226+
/// Load all <name>.ron files from a given folder and parse them into type `T`.
227+
fn load_files_from_folder<T: serde::de::DeserializeOwned>(
228+
directory: PathBuf,
229+
) -> Vec<(String, T)> {
230+
let mut result = Vec::new();
231+
info!(
232+
"Loading objects of type {} from directory {}",
233+
std::any::type_name::<T>(),
234+
directory.display(),
235+
);
236+
for dir_entry in fs::read_dir(directory).expect("Failed to read from directory") {
237+
let dir_entry = dir_entry.expect("Failed to read directory entry");
238+
if dir_entry
239+
.file_type()
240+
.expect("Failed to get file type")
241+
.is_file()
242+
{
243+
let file_path = dir_entry.path();
244+
245+
match file_path.extension() {
246+
None => log::warn!("No file extension for file {}, skipping...", file_path.display()),
247+
Some(ext) => {
248+
if ext == "ron" {
249+
log::info!("Attempting to read file {}", file_path.display());
250+
let mut file = fs::File::open(file_path.clone())
251+
.expect("Failed to open file");
252+
let mut buffer = String::new();
253+
file.read_to_string(&mut buffer).expect("Failed to read from file");
254+
let file_stem = file_path
255+
.file_stem()
256+
.expect("Failed to get file stem")
257+
.to_str()
258+
.unwrap()
259+
.to_owned();
260+
261+
let parsed_file = {
262+
if ext == "ron" {
263+
match ron::de::from_str(&buffer) {
264+
Ok(x) => x,
265+
Err(e) => {
266+
log::error!("Failed to parse RON: {}, skipping...", e);
267+
continue
268+
}
269+
}
270+
} else {
271+
unreachable!("No parser for file format");
272+
}
273+
};
274+
result.push((
275+
file_stem,
276+
parsed_file,
277+
));
278+
} else {
279+
log::warn!("Unsupported file extension {:?}, skipping...", ext); // TODO: display instead of debug
280+
}
281+
}
282+
}
283+
}
284+
}
285+
result
286+
}

common/src/data/vox/item.rs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use crate::data::{TextureRect, MAX_TEXTURE_SIZE};
2+
use image::{ImageBuffer, Rgba};
3+
use crate::data::vox::VoxelModel;
4+
5+
pub fn generate_item_model(texture: TextureRect, atlas: &ImageBuffer<Rgba<u8>, Vec<u8>>) -> VoxelModel {
6+
let x = (texture.x * MAX_TEXTURE_SIZE as f32).round() as u32;
7+
let y = (texture.y * MAX_TEXTURE_SIZE as f32).round() as u32;
8+
let width = (texture.width * MAX_TEXTURE_SIZE as f32).round() as u32;
9+
let height = (texture.height * MAX_TEXTURE_SIZE as f32).round() as u32;
10+
11+
let mut full = Vec::with_capacity((width * height) as usize);
12+
let mut voxels = Vec::with_capacity((width * height) as usize);
13+
14+
for u in x..(x + width) {
15+
for v in (y..(y + height)).rev() {
16+
let rgba = atlas.get_pixel(u, v);
17+
if rgba[3] == 255 { // Not transparent
18+
full.push(true);
19+
// AGBR
20+
voxels.push(((rgba[2] as u32) << 16) + ((rgba[1] as u32) << 8) + rgba[0] as u32);
21+
} else {
22+
full.push(false);
23+
voxels.push(0);
24+
}
25+
}
26+
}
27+
28+
29+
VoxelModel {
30+
size_x: width as usize,
31+
size_y: height as usize,
32+
size_z: 1,
33+
voxels,
34+
full,
35+
}
36+
}

common/src/data/vox/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::fs::File;
22
use std::io::Read;
33
use std::str::from_utf8;
44

5+
pub mod item;
6+
57
const DEFAULT_PALETTE: [u32; 256] = [
68
0x00000000, 0xffffffff, 0xffccffff, 0xff99ffff, 0xff66ffff, 0xff33ffff, 0xff00ffff, 0xffffccff,
79
0xffccccff, 0xff99ccff, 0xff66ccff, 0xff33ccff, 0xff00ccff, 0xffff99ff, 0xffcc99ff, 0xff9999ff,

common/src/item/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use serde::Deserialize;
2+
3+
pub type ItemId = u32;
4+
5+
/// The type of an item. It contains the behavior and the texture of the item.
6+
/// This is the data provided by the creator of the item.
7+
#[derive(Debug, Clone, Deserialize)]
8+
#[serde(rename = "Block")]
9+
pub enum ItemType {
10+
NormalItem { texture: String },
11+
}

common/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ pub mod block;
22
pub mod collections;
33
pub mod data;
44
pub mod debug;
5+
pub mod item;
56
pub mod light;
67
pub mod network;
78
pub mod physics;

data/items/ingot_iron.ron

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
NormalItem(
2+
texture: "ingot_iron",
3+
)

data/textures/ingot_iron.png

776 Bytes
Loading

0 commit comments

Comments
 (0)