Compare commits

...

5 Commits

5 changed files with 136 additions and 13 deletions

View File

@ -2,6 +2,8 @@
name = "rust-game-engine" name = "rust-game-engine"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
authors = ["phito", "endmove"]
repository = "https://git.endmove.eu/phito/rust-game-engine.git"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -10,4 +12,10 @@ bytemuck = "1.14.0"
env_logger = "0.10.0" env_logger = "0.10.0"
pollster = "0.3.0" pollster = "0.3.0"
wgpu = "0.17.0" wgpu = "0.17.0"
winit = "0.28.6" winit = "0.28.6"
criterion = { version = "0.5.1", features = ["html_reports"] }
[[bench]]
name = "voxel_map_benchmark"
harness = false

BIN
assets/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,37 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
const MAP_WIDTH: usize = 100;
const MAP_HEIGHT: usize = 100;
const MAP_DEPTH: usize = 100;
#[derive(Clone, Copy, Debug)]
struct Voxel {
r: u8, g: u8, b: u8
}
fn voxel_vec_1d(data: Vec<Voxel>) -> Voxel {
const X: usize = 0;
const Y: usize = 0;
const Z: usize = 0;
data[X + Y * MAP_WIDTH + Z * MAP_WIDTH * MAP_HEIGHT]
}
fn voxel_vec_3d(data: Vec<Vec<Vec<Voxel>>>) -> Voxel {
const X: usize = 0;
const Y: usize = 0;
const Z: usize = 0;
data[X][Y][Z]
}
fn criterion_benchmark(c: &mut Criterion) {
let vec_1d = vec![Voxel { r: 0, g: 0, b: 0 }; MAP_WIDTH * MAP_HEIGHT * MAP_DEPTH];
let vec_3d = vec![vec![vec![Voxel { r: 0, g: 0, b: 0 }; MAP_DEPTH]; MAP_HEIGHT]; MAP_WIDTH];
c.bench_function("voxels in 1d vector", |b| b.iter(|| voxel_vec_1d(black_box(vec_1d.clone()))));
c.bench_function("voxels in 3d vector", |b| b.iter(|| voxel_vec_3d(black_box(vec_3d.clone()))));
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

View File

@ -1,23 +1,27 @@
mod voxel;
use std::borrow::Cow; use std::borrow::Cow;
use winit::{ use winit::{
event::{Event, WindowEvent}, event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop}, event_loop::{ControlFlow, EventLoop},
window::Window, window::{WindowBuilder, Window},
}; };
async fn run(event_loop: EventLoop<()>, window: Window) { async fn run(event_loop: EventLoop<()>, window: Window) {
let size = window.inner_size(); let size = window.inner_size();
let instance = wgpu::Instance::default(); let instance = wgpu::Instance::default();
let surface = unsafe { instance.create_surface(&window) }
.expect("Failed to create surface");
let adapter_options = wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
force_fallback_adapter: false,
compatible_surface: None,
};
let surface = unsafe { instance.create_surface(&window) }.unwrap();
let adapter = instance let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions { .request_adapter(&adapter_options)
power_preference: wgpu::PowerPreference::default(),
force_fallback_adapter: false,
// Request an adapter which can render to our surface
compatible_surface: Some(&surface),
})
.await .await
.expect("Failed to find an appropriate adapter"); .expect("Failed to find an appropriate adapter");
@ -38,12 +42,12 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
// Load the shaders from disk // Load the shaders from disk
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None, label: Some("Shader"),
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))), source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))),
}); });
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: None, label: Some("Pipeline Layout"),
bind_group_layouts: &[], bind_group_layouts: &[],
push_constant_ranges: &[], push_constant_ranges: &[],
}); });
@ -52,7 +56,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
let swapchain_format = swapchain_capabilities.formats[0]; let swapchain_format = swapchain_capabilities.formats[0];
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None, label: Some("Render Pipeline"),
layout: Some(&pipeline_layout), layout: Some(&pipeline_layout),
vertex: wgpu::VertexState { vertex: wgpu::VertexState {
module: &shader, module: &shader,
@ -140,8 +144,23 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
} }
fn main() { fn main() {
// Instantiate event loop and win builder
let event_loop = EventLoop::new(); let event_loop = EventLoop::new();
let window = winit::window::Window::new(&event_loop).unwrap(); let win_builder = WindowBuilder::new();
// Create and configure window
let window_def_size = winit::dpi::LogicalSize::new(640, 360);
// let window_icon = Icon::from_path("../assets/icon.ico", None).expect("Failed to load icon");
let window = win_builder.with_title("Rust Game Engine")
.with_inner_size(window_def_size)
.with_min_inner_size(window_def_size)
.with_resizable(true)
.with_enabled_buttons(winit::window::WindowButtons::from_bits(3).unwrap())
.with_transparent(true)
// .with_window_icon(Some(window_icon))
.build(&event_loop)
.unwrap();
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
{ {
env_logger::init(); env_logger::init();

59
src/voxel.rs Normal file
View File

@ -0,0 +1,59 @@
#[derive(PartialEq, Clone, Copy, Debug)]
struct Voxel {
r: u8, g: u8, b: u8
}
const AIR_VOXEL: Voxel = Voxel { r: 0, g: 0, b: 0 };
struct VoxelMap {
data: Vec<Voxel>,
width: usize,
height: usize,
depth: usize
}
impl VoxelMap {
fn new(width: usize, height: usize, depth: usize) -> Self {
Self {
data: vec![AIR_VOXEL; width * height * depth],
width,
height,
depth
}
}
fn set(&mut self, x: usize, y: usize, z: usize, voxel: Voxel) {
if x < self.width && y < self.height && z < self.depth {
self.data[x + y * self.width + z * self.width * self.height] = voxel;
}
}
fn get(&self, x: usize, y: usize, z: usize) -> Voxel {
if x < self.width && y < self.height && z < self.depth {
self.data[x + y * self.width + z * self.width * self.height]
} else {
AIR_VOXEL
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_voxel_map() {
let mut map = VoxelMap::new(10, 10, 10);
map.set(0, 0, 0, Voxel { r: 255, g: 0, b: 0 });
assert_eq!(map.get(0, 0, 0), Voxel { r: 255, g: 0, b: 0 });
assert_eq!(map.get(1, 0, 0), AIR_VOXEL);
assert_eq!(map.get(0, 1, 0), AIR_VOXEL);
assert_eq!(map.get(0, 0, 1), AIR_VOXEL);
assert_eq!(map.get(10, 0, 0), AIR_VOXEL);
assert_eq!(map.get(0, 10, 0), AIR_VOXEL);
assert_eq!(map.get(0, 0, 10), AIR_VOXEL);
// out of bounds
assert_eq!(map.get(0, 0, 11), AIR_VOXEL);
}
}