Allow for selecting a block to place
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Sijmen 2021-06-08 20:26:58 +02:00
parent 6c2151ffb9
commit ec6978fee9
Signed by: vijfhoek
GPG key ID: 82D05C89B28B0DAE
9 changed files with 170 additions and 66 deletions

View file

@ -1,7 +1,10 @@
use crate::texture::TextureManager;
pub struct RenderContext {
pub surface: wgpu::Surface,
pub device: wgpu::Device,
pub queue: wgpu::Queue,
pub swap_chain_descriptor: wgpu::SwapChainDescriptor,
pub swap_chain: wgpu::SwapChain,
pub texture_manager: Option<TextureManager>,
}

View file

@ -1,11 +1,13 @@
struct VertexInput {
[[location(0)]] position: vec2<f32>;
[[location(1)]] texture_coordinates: vec2<f32>;
[[location(2)]] texture_index: i32;
};
struct VertexOutput {
[[builtin(position)]] clip_position: vec4<f32>;
[[location(0)]] texture_coordinates: vec2<f32>;
[[location(1)]] texture_index: i32;
};
[[stage(vertex)]]
@ -13,13 +15,14 @@ fn main(model: VertexInput) -> VertexOutput {
var out: VertexOutput;
out.texture_coordinates = model.texture_coordinates;
out.clip_position = vec4<f32>(model.position, 0.0, 1.0);
out.texture_index = model.texture_index;
return out;
}
[[group(0), binding(0)]] var sampler: sampler;
[[group(0), binding(1)]] var texture: texture_2d<f32>;
[[group(0), binding(1)]] var texture: texture_2d_array<f32>;
[[stage(fragment)]]
fn main(in: VertexOutput) -> [[location(0)]] vec4<f32> {
return textureSample(texture, sampler, in.texture_coordinates);
return textureSample(texture, sampler, in.texture_coordinates, in.texture_index);
}

View file

@ -1,4 +1,7 @@
use std::time::{Duration, Instant};
use std::{
convert::TryInto,
time::{Duration, Instant},
};
use cgmath::Vector3;
use wgpu::{BufferUsage, CommandEncoder, SwapChainTexture};
@ -10,6 +13,7 @@ use crate::{
text_renderer::{self, TextRenderer},
texture::Texture,
vertex::{HudVertex, Vertex},
world::block::BlockType,
};
// TODO update aspect ratio when resizing
@ -30,7 +34,10 @@ pub struct HudState {
coordinates_geometry_buffers: GeometryBuffers<u16>,
coordinates_last: Vector3<f32>,
pub hotbar_cursor_position: i32,
pub hotbar_cursor_position: usize,
hotbar_blocks: [Option<BlockType>; 9],
hotbar_block_buffers: Option<GeometryBuffers<u16>>,
}
impl HudState {
@ -55,7 +62,19 @@ impl HudState {
let coordinates_geometry_buffers =
text_renderer.string_to_buffers(&render_context, -0.98, 0.97 - text_renderer::DY, "");
Self {
let hotbar_blocks = [
Some(BlockType::Dirt),
Some(BlockType::Stone),
Some(BlockType::Sand),
None,
Some(BlockType::Grass),
None,
None,
None,
None,
];
let mut hud_state = Self {
texture_bind_group,
render_pipeline,
text_renderer,
@ -71,7 +90,17 @@ impl HudState {
coordinates_last: Vector3::new(0.0, 0.0, 0.0),
hotbar_cursor_position: 0,
}
hotbar_blocks,
hotbar_block_buffers: None,
};
hud_state.hotbar_block_buffers = Some(GeometryBuffers::from_geometry(
render_context,
&hud_state.hotbar_block_vertices(),
wgpu::BufferUsage::empty(),
));
hud_state
}
pub fn update(&mut self, render_context: &RenderContext, position: &Vector3<f32>) {
@ -106,6 +135,7 @@ impl HudState {
pub fn render(
&self,
render_context: &RenderContext,
frame: &SwapChainTexture,
render_encoder: &mut CommandEncoder,
) -> anyhow::Result<usize> {
@ -141,18 +171,65 @@ impl HudState {
self.coordinates_geometry_buffers
.draw_indexed(&mut render_pass);
// Render the blocks on the hot bar
let texture_manager = render_context.texture_manager.as_ref().unwrap();
render_pass.set_bind_group(0, texture_manager.bind_group.as_ref().unwrap(), &[]);
self.hotbar_block_buffers
.as_ref()
.unwrap()
.apply_buffers(&mut render_pass);
self.hotbar_block_buffers
.as_ref()
.unwrap()
.draw_indexed(&mut render_pass);
Ok(HUD_INDICES.len() / 3)
}
pub fn selected_block_type(&self) -> Option<BlockType> {
self.hotbar_blocks[self.hotbar_cursor_position]
}
fn hotbar_block_vertices(&self) -> Geometry<HudVertex, u16> {
let mut vertices = Vec::new();
let mut indices = Vec::new();
let mut index = 0;
for cursor_index in 0..9 {
if let Some(block) = self.hotbar_blocks[cursor_index as usize] {
let x = (-92 + 20 * cursor_index as i32) as f32;
let texture_index = block.texture_indices().2.try_into().unwrap();
#[rustfmt::skip]
vertices.extend(&[
HudVertex { position: [UI_SCALE_X * (x + 5.0), -1.0 + UI_SCALE_Y * 18.0], texture_coordinates: [0.0, 0.0], texture_index },
HudVertex { position: [UI_SCALE_X * (x + 19.0), -1.0 + UI_SCALE_Y * 18.0], texture_coordinates: [1.0, 0.0], texture_index },
HudVertex { position: [UI_SCALE_X * (x + 19.0), -1.0 + UI_SCALE_Y * 4.0], texture_coordinates: [1.0, 1.0], texture_index },
HudVertex { position: [UI_SCALE_X * (x + 5.0), -1.0 + UI_SCALE_Y * 4.0], texture_coordinates: [0.0, 1.0], texture_index },
]);
#[rustfmt::skip]
indices.extend(&[
index, 2 + index, 1 + index,
index, 3 + index, 2 + index,
]);
index += 4;
}
}
Geometry::new(vertices, indices)
}
pub fn redraw_hotbar_cursor(&self, render_context: &RenderContext) {
let x = (-92 + 20 * self.hotbar_cursor_position) as f32;
let x = (-92 + 20 * self.hotbar_cursor_position as i32) as f32;
let texture_index = 0;
#[rustfmt::skip]
let vertices = [
HudVertex { position: [UI_SCALE_X * (x ), -1.0 + UI_SCALE_Y * 23.0], texture_coordinates: [ 0.0 / 256.0, 22.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * (x + 24.0), -1.0 + UI_SCALE_Y * 23.0], texture_coordinates: [ 24.0 / 256.0, 22.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * (x + 24.0), -1.0 + UI_SCALE_Y * -1.0], texture_coordinates: [ 24.0 / 256.0, 46.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * (x ), -1.0 + UI_SCALE_Y * -1.0], texture_coordinates: [ 0.0 / 256.0, 46.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * (x ), -1.0 + UI_SCALE_Y * 23.0], texture_coordinates: [ 0.0 / 256.0, 22.0 / 256.0], texture_index },
HudVertex { position: [UI_SCALE_X * (x + 24.0), -1.0 + UI_SCALE_Y * 23.0], texture_coordinates: [ 24.0 / 256.0, 22.0 / 256.0], texture_index },
HudVertex { position: [UI_SCALE_X * (x + 24.0), -1.0 + UI_SCALE_Y * -1.0], texture_coordinates: [ 24.0 / 256.0, 46.0 / 256.0], texture_index },
HudVertex { position: [UI_SCALE_X * (x ), -1.0 + UI_SCALE_Y * -1.0], texture_coordinates: [ 0.0 / 256.0, 46.0 / 256.0], texture_index },
];
render_context.queue.write_buffer(
@ -162,13 +239,14 @@ impl HudState {
);
}
pub fn set_hotbar_cursor(&mut self, render_context: &RenderContext, i: i32) {
pub fn set_hotbar_cursor(&mut self, render_context: &RenderContext, i: usize) {
self.hotbar_cursor_position = i;
self.redraw_hotbar_cursor(render_context);
}
pub fn move_hotbar_cursor(&mut self, render_context: &RenderContext, delta: i32) {
self.hotbar_cursor_position = (self.hotbar_cursor_position + delta).rem_euclid(9);
self.hotbar_cursor_position =
(self.hotbar_cursor_position as i32 + delta).rem_euclid(9) as usize;
self.redraw_hotbar_cursor(render_context);
}
@ -208,7 +286,7 @@ impl HudState {
visibility: wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::Texture {
sample_type: wgpu::TextureSampleType::Float { filterable: true },
view_dimension: wgpu::TextureViewDimension::D2,
view_dimension: wgpu::TextureViewDimension::D2Array,
multisampled: false,
},
count: None,
@ -286,22 +364,22 @@ impl HudState {
#[rustfmt::skip]
pub const HUD_VERTICES: [HudVertex; 12] = [
// Crosshair
HudVertex { position: [UI_SCALE_X * -8.0, UI_SCALE_Y * 8.0], texture_coordinates: [240.0 / 256.0, 0.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * 8.0, UI_SCALE_Y * 8.0], texture_coordinates: [ 1.0, 0.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * 8.0, UI_SCALE_Y * -8.0], texture_coordinates: [ 1.0, 16.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * -8.0, UI_SCALE_Y * -8.0], texture_coordinates: [240.0 / 256.0, 16.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * -8.0, UI_SCALE_Y * 8.0], texture_coordinates: [240.0 / 256.0, 0.0 / 256.0], texture_index: 0 },
HudVertex { position: [UI_SCALE_X * 8.0, UI_SCALE_Y * 8.0], texture_coordinates: [ 1.0, 0.0 / 256.0], texture_index: 0 },
HudVertex { position: [UI_SCALE_X * 8.0, UI_SCALE_Y * -8.0], texture_coordinates: [ 1.0, 16.0 / 256.0], texture_index: 0 },
HudVertex { position: [UI_SCALE_X * -8.0, UI_SCALE_Y * -8.0], texture_coordinates: [240.0 / 256.0, 16.0 / 256.0], texture_index: 0 },
// Hotbar
HudVertex { position: [UI_SCALE_X * -91.0, -1.0 + UI_SCALE_Y * 22.0], texture_coordinates: [ 0.0 / 256.0, 0.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * 91.0, -1.0 + UI_SCALE_Y * 22.0], texture_coordinates: [182.0 / 256.0, 0.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * 91.0, -1.0 ], texture_coordinates: [182.0 / 256.0, 22.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * -91.0, -1.0 ], texture_coordinates: [ 0.0 / 256.0, 22.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * -91.0, -1.0 + UI_SCALE_Y * 22.0], texture_coordinates: [ 0.0 / 256.0, 0.0 / 256.0], texture_index: 0 },
HudVertex { position: [UI_SCALE_X * 91.0, -1.0 + UI_SCALE_Y * 22.0], texture_coordinates: [182.0 / 256.0, 0.0 / 256.0], texture_index: 0 },
HudVertex { position: [UI_SCALE_X * 91.0, -1.0 ], texture_coordinates: [182.0 / 256.0, 22.0 / 256.0], texture_index: 0 },
HudVertex { position: [UI_SCALE_X * -91.0, -1.0 ], texture_coordinates: [ 0.0 / 256.0, 22.0 / 256.0], texture_index: 0 },
// Hotbar cursor
HudVertex { position: [UI_SCALE_X * -92.0, -1.0 + UI_SCALE_Y * 23.0], texture_coordinates: [ 0.0 / 256.0, 22.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * -68.0, -1.0 + UI_SCALE_Y * 23.0], texture_coordinates: [ 24.0 / 256.0, 22.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * -68.0, -1.0 + UI_SCALE_Y * -1.0], texture_coordinates: [ 24.0 / 256.0, 46.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * -92.0, -1.0 + UI_SCALE_Y * -1.0], texture_coordinates: [ 0.0 / 256.0, 46.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * -92.0, -1.0 + UI_SCALE_Y * 23.0], texture_coordinates: [ 0.0 / 256.0, 22.0 / 256.0], texture_index: 0 },
HudVertex { position: [UI_SCALE_X * -68.0, -1.0 + UI_SCALE_Y * 23.0], texture_coordinates: [ 24.0 / 256.0, 22.0 / 256.0], texture_index: 0 },
HudVertex { position: [UI_SCALE_X * -68.0, -1.0 + UI_SCALE_Y * -1.0], texture_coordinates: [ 24.0 / 256.0, 46.0 / 256.0], texture_index: 0 },
HudVertex { position: [UI_SCALE_X * -92.0, -1.0 + UI_SCALE_Y * -1.0], texture_coordinates: [ 0.0 / 256.0, 46.0 / 256.0], texture_index: 0 },
];
#[rustfmt::skip]

View file

@ -13,7 +13,7 @@ use winit::{
use hud_state::HudState;
use world_state::WorldState;
use crate::render_context::RenderContext;
use crate::{render_context::RenderContext, texture::TextureManager};
pub const PRIMITIVE_STATE: wgpu::PrimitiveState = wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
@ -96,15 +96,20 @@ impl State {
let (swap_chain_descriptor, swap_chain) =
Self::create_swap_chain(window, &render_adapter, &render_device, &render_surface);
let render_context = RenderContext {
let mut render_context = RenderContext {
surface: render_surface,
device: render_device,
queue: render_queue,
swap_chain_descriptor,
swap_chain,
texture_manager: None,
};
let mut texture_manager = TextureManager::new(&render_context);
texture_manager.load_all(&render_context).unwrap();
render_context.texture_manager = Some(texture_manager);
let world_state = WorldState::new(&render_context);
let hud_state = HudState::new(&render_context);
@ -169,9 +174,11 @@ impl State {
button,
state: ElementState::Pressed,
..
} if self.mouse_grabbed => self
.world_state
.input_mouse_button(button, &self.render_context),
} if self.mouse_grabbed => self.world_state.input_mouse_button(
button,
&self.render_context,
self.hud_state.selected_block_type(),
),
WindowEvent::MouseWheel {
delta: MouseScrollDelta::LineDelta(_, delta),
@ -211,8 +218,12 @@ impl State {
.create_command_encoder(&Default::default());
let mut triangle_count = 0;
triangle_count += self.world_state.render(&frame, &mut render_encoder);
triangle_count += self.hud_state.render(&frame, &mut render_encoder)?;
triangle_count +=
self.world_state
.render(&self.render_context, &frame, &mut render_encoder);
triangle_count +=
self.hud_state
.render(&self.render_context, &frame, &mut render_encoder)?;
self.render_context
.queue

View file

@ -15,12 +15,12 @@ use crate::{
camera::{Camera, Projection},
render_context::RenderContext,
renderable::Renderable,
texture::{Texture, TextureManager},
texture::Texture,
time::Time,
utils,
vertex::{BlockVertex, Vertex},
view::View,
world::World,
world::{block::BlockType, World},
};
pub struct WorldState {
@ -28,7 +28,6 @@ pub struct WorldState {
pub view: View,
pub view_buffer: wgpu::Buffer,
pub view_bind_group: wgpu::BindGroup,
pub texture_manager: TextureManager,
pub camera: Camera,
pub projection: Projection,
pub depth_texture: Texture,
@ -52,12 +51,6 @@ pub struct WorldState {
}
impl WorldState {
fn create_textures(render_context: &RenderContext) -> TextureManager {
let mut texture_manager = TextureManager::new(&render_context);
texture_manager.load_all(render_context).unwrap();
texture_manager
}
fn create_camera(render_context: &RenderContext) -> (Camera, Projection) {
let camera = Camera::new(
(10.0, 140.0, 10.0).into(),
@ -226,8 +219,6 @@ impl WorldState {
}
pub fn new(render_context: &RenderContext) -> WorldState {
let texture_manager = Self::create_textures(render_context);
let (camera, projection) = Self::create_camera(render_context);
let (view, view_buffer, view_bind_group_layout, view_bind_group) =
@ -246,6 +237,7 @@ impl WorldState {
}),
);
let texture_manager = render_context.texture_manager.as_ref().unwrap();
let render_pipeline_layout =
render_context
.device
@ -267,7 +259,6 @@ impl WorldState {
view,
view_buffer,
view_bind_group,
texture_manager,
camera,
projection,
depth_texture,
@ -292,7 +283,12 @@ impl WorldState {
}
}
pub fn render(&self, frame: &SwapChainTexture, render_encoder: &mut CommandEncoder) -> usize {
pub fn render(
&self,
render_context: &RenderContext,
frame: &SwapChainTexture,
render_encoder: &mut CommandEncoder,
) -> usize {
let mut triangle_count = 0;
let mut render_pass = render_encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
@ -322,8 +318,8 @@ impl WorldState {
render_pass.set_pipeline(&self.render_pipeline);
let tm = &self.texture_manager;
render_pass.set_bind_group(0, tm.bind_group.as_ref().unwrap(), &[]);
let texture_manager = render_context.texture_manager.as_ref().unwrap();
render_pass.set_bind_group(0, texture_manager.bind_group.as_ref().unwrap(), &[]);
render_pass.set_bind_group(1, &self.view_bind_group, &[]);
render_pass.set_bind_group(2, &self.time_bind_group, &[]);
@ -344,11 +340,19 @@ impl WorldState {
}
}
pub fn input_mouse_button(&mut self, button: &MouseButton, render_context: &RenderContext) {
pub fn input_mouse_button(
&mut self,
button: &MouseButton,
render_context: &RenderContext,
selected: Option<BlockType>,
) {
if button == &MouseButton::Left {
self.world.break_at_crosshair(render_context, &self.camera);
} else if button == &MouseButton::Right {
self.world.place_at_crosshair(render_context, &self.camera);
if let Some(selected) = selected {
self.world
.place_at_crosshair(render_context, &self.camera, selected);
}
}
}

View file

@ -60,7 +60,7 @@ impl TextRenderer {
visibility: wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::Texture {
sample_type: wgpu::TextureSampleType::Float { filterable: true },
view_dimension: wgpu::TextureViewDimension::D2,
view_dimension: wgpu::TextureViewDimension::D2Array,
multisampled: false,
},
count: None,
@ -109,10 +109,10 @@ impl TextRenderer {
#[rustfmt::skip]
let vertices = [
HudVertex { position: [x, y ], texture_coordinates: [tx, ty ] },
HudVertex { position: [x + DX, y ], texture_coordinates: [tx + s, ty ] },
HudVertex { position: [x + DX, y - DY], texture_coordinates: [tx + s, ty + s] },
HudVertex { position: [x, y - DY], texture_coordinates: [tx, ty + s] },
HudVertex { position: [x, y ], texture_coordinates: [tx, ty ], texture_index: 0 },
HudVertex { position: [x + DX, y ], texture_coordinates: [tx + s, ty ], texture_index: 0 },
HudVertex { position: [x + DX, y - DY], texture_coordinates: [tx + s, ty + s], texture_index: 0 },
HudVertex { position: [x, y - DY], texture_coordinates: [tx, ty + s], texture_index: 0 },
];
#[rustfmt::skip]

View file

@ -102,7 +102,7 @@ impl Texture {
let view = texture.create_view(&wgpu::TextureViewDescriptor {
label: Some(&format!("texture_view_{}", label)),
dimension: Some(wgpu::TextureViewDimension::D2),
dimension: Some(wgpu::TextureViewDimension::D2Array),
..wgpu::TextureViewDescriptor::default()
});

View file

@ -38,11 +38,13 @@ impl Vertex for PlainVertex {
pub struct HudVertex {
pub position: [f32; 2],
pub texture_coordinates: [f32; 2],
pub texture_index: i32,
}
const HUD_VERTEX_ATTRIBUTES: &[VertexAttribute] = &wgpu::vertex_attr_array![
0 => Float32x2,
1 => Float32x2,
2 => Sint32,
];
impl Vertex for HudVertex {

View file

@ -249,7 +249,12 @@ impl World {
}
}
pub fn place_at_crosshair(&mut self, render_context: &RenderContext, camera: &Camera) {
pub fn place_at_crosshair(
&mut self,
render_context: &RenderContext,
camera: &Camera,
block_type: BlockType,
) {
if let Some((pos, face_normal)) = self.raycast(camera.position, camera.direction()) {
let new_pos = pos.cast().unwrap() + face_normal;
@ -257,9 +262,7 @@ impl World {
new_pos.x as isize,
new_pos.y as isize,
new_pos.z as isize,
Some(Block {
block_type: BlockType::Cobblestone,
}),
Some(Block { block_type }),
);
self.update_chunk_geometry(render_context, pos / CHUNK_ISIZE);