Move basic rendering context to RenderContext
This way they can be passed around much more easily
This commit is contained in:
parent
a3236f610a
commit
bfa7a48483
6 changed files with 442 additions and 420 deletions
|
@ -8,6 +8,7 @@ mod time;
|
|||
mod uniforms;
|
||||
mod vertex;
|
||||
mod world;
|
||||
mod render_context;
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
use wgpu::SwapChainError;
|
||||
|
|
7
src/render_context.rs
Normal file
7
src/render_context.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
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,
|
||||
}
|
|
@ -3,7 +3,7 @@ use wgpu::{
|
|||
CommandEncoder, Device, Queue, SwapChainDescriptor, SwapChainTexture,
|
||||
};
|
||||
|
||||
use crate::{texture::Texture, vertex::Vertex};
|
||||
use crate::{render_context::RenderContext, texture::Texture, vertex::Vertex};
|
||||
|
||||
const UI_SCALE_X: f32 = 0.0045;
|
||||
const UI_SCALE_Y: f32 = 0.008;
|
||||
|
@ -16,31 +16,29 @@ pub struct HudState {
|
|||
}
|
||||
|
||||
impl HudState {
|
||||
pub fn new(
|
||||
render_device: &Device,
|
||||
render_queue: &Queue,
|
||||
swap_chain_descriptor: &SwapChainDescriptor,
|
||||
) -> Self {
|
||||
let (texture_bind_group_layout, texture_bind_group) =
|
||||
Self::create_textures(render_device, render_queue);
|
||||
pub fn new(render_context: &RenderContext) -> Self {
|
||||
let (texture_bind_group_layout, texture_bind_group) = Self::create_textures(render_context);
|
||||
|
||||
let render_pipeline = Self::create_render_pipeline(
|
||||
&render_device,
|
||||
&swap_chain_descriptor,
|
||||
&[&texture_bind_group_layout],
|
||||
);
|
||||
let render_pipeline =
|
||||
Self::create_render_pipeline(render_context, &[&texture_bind_group_layout]);
|
||||
|
||||
let crosshair_vertex_buffer = render_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: Some("HUD crosshair vertex buffer"),
|
||||
contents: bytemuck::cast_slice(&CROSSHAIR_VERTICES),
|
||||
usage: wgpu::BufferUsage::VERTEX,
|
||||
});
|
||||
let crosshair_vertex_buffer =
|
||||
render_context
|
||||
.device
|
||||
.create_buffer_init(&BufferInitDescriptor {
|
||||
label: Some("HUD crosshair vertex buffer"),
|
||||
contents: bytemuck::cast_slice(&CROSSHAIR_VERTICES),
|
||||
usage: wgpu::BufferUsage::VERTEX,
|
||||
});
|
||||
|
||||
let crosshair_index_buffer = render_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: Some("HUD crosshair index buffer"),
|
||||
contents: bytemuck::cast_slice(CROSSHAIR_INDICES),
|
||||
usage: wgpu::BufferUsage::INDEX,
|
||||
});
|
||||
let crosshair_index_buffer =
|
||||
render_context
|
||||
.device
|
||||
.create_buffer_init(&BufferInitDescriptor {
|
||||
label: Some("HUD crosshair index buffer"),
|
||||
contents: bytemuck::cast_slice(CROSSHAIR_INDICES),
|
||||
usage: wgpu::BufferUsage::INDEX,
|
||||
});
|
||||
|
||||
Self {
|
||||
texture_bind_group,
|
||||
|
@ -81,119 +79,126 @@ impl HudState {
|
|||
Ok(CROSSHAIR_INDICES.len() / 3)
|
||||
}
|
||||
|
||||
fn create_textures(
|
||||
render_device: &wgpu::Device,
|
||||
render_queue: &wgpu::Queue,
|
||||
) -> (wgpu::BindGroupLayout, wgpu::BindGroup) {
|
||||
fn create_textures(render_context: &RenderContext) -> (wgpu::BindGroupLayout, wgpu::BindGroup) {
|
||||
let texture = Texture::from_bytes(
|
||||
render_device,
|
||||
render_queue,
|
||||
render_context,
|
||||
include_bytes!("../../assets/gui/widgets.png"),
|
||||
"Texture GUI widgets",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let sampler = render_device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
mag_filter: wgpu::FilterMode::Nearest,
|
||||
min_filter: wgpu::FilterMode::Linear,
|
||||
..wgpu::SamplerDescriptor::default()
|
||||
});
|
||||
let sampler = render_context
|
||||
.device
|
||||
.create_sampler(&wgpu::SamplerDescriptor {
|
||||
mag_filter: wgpu::FilterMode::Nearest,
|
||||
min_filter: wgpu::FilterMode::Linear,
|
||||
..wgpu::SamplerDescriptor::default()
|
||||
});
|
||||
|
||||
let bind_group_layout =
|
||||
render_device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("GUI texture bind group layout"),
|
||||
render_context
|
||||
.device
|
||||
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("GUI texture bind group layout"),
|
||||
entries: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
comparison: false,
|
||||
filtering: true,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let bind_group = render_context
|
||||
.device
|
||||
.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: Some("GUI texture bind group"),
|
||||
layout: &bind_group_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
comparison: false,
|
||||
filtering: true,
|
||||
},
|
||||
count: None,
|
||||
resource: wgpu::BindingResource::Sampler(&sampler),
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
resource: wgpu::BindingResource::TextureView(&texture.view),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let bind_group = render_device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: Some("GUI texture bind group"),
|
||||
layout: &bind_group_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Sampler(&sampler),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::TextureView(&texture.view),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
(bind_group_layout, bind_group)
|
||||
}
|
||||
|
||||
fn create_render_pipeline(
|
||||
render_device: &wgpu::Device,
|
||||
swap_chain_descriptor: &SwapChainDescriptor,
|
||||
render_context: &RenderContext,
|
||||
bind_group_layouts: &[&wgpu::BindGroupLayout],
|
||||
) -> wgpu::RenderPipeline {
|
||||
let module = &render_device.create_shader_module(&wgpu::ShaderModuleDescriptor {
|
||||
label: Some("UI shader"),
|
||||
flags: wgpu::ShaderFlags::all(),
|
||||
source: wgpu::ShaderSource::Wgsl(include_str!("../shaders/ui.wgsl").into()),
|
||||
});
|
||||
|
||||
let pipeline_layout =
|
||||
render_device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("UI render pipeline layout"),
|
||||
bind_group_layouts,
|
||||
push_constant_ranges: &[],
|
||||
let module = &render_context
|
||||
.device
|
||||
.create_shader_module(&wgpu::ShaderModuleDescriptor {
|
||||
label: Some("UI shader"),
|
||||
flags: wgpu::ShaderFlags::all(),
|
||||
source: wgpu::ShaderSource::Wgsl(include_str!("../shaders/ui.wgsl").into()),
|
||||
});
|
||||
|
||||
render_device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("UI render pipeline"),
|
||||
layout: Some(&pipeline_layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module,
|
||||
entry_point: "main",
|
||||
buffers: &[Vertex::desc()],
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module,
|
||||
entry_point: "main",
|
||||
targets: &[wgpu::ColorTargetState {
|
||||
format: swap_chain_descriptor.format,
|
||||
blend: Some(wgpu::BlendState::ALPHA_BLENDING),
|
||||
write_mask: wgpu::ColorWrite::ALL,
|
||||
}],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
strip_index_format: None,
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: None,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
clamp_depth: false,
|
||||
conservative: false,
|
||||
},
|
||||
depth_stencil: None,
|
||||
multisample: wgpu::MultisampleState {
|
||||
count: 1,
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
})
|
||||
let pipeline_layout =
|
||||
render_context
|
||||
.device
|
||||
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("UI render pipeline layout"),
|
||||
bind_group_layouts,
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
render_context
|
||||
.device
|
||||
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("UI render pipeline"),
|
||||
layout: Some(&pipeline_layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module,
|
||||
entry_point: "main",
|
||||
buffers: &[Vertex::desc()],
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module,
|
||||
entry_point: "main",
|
||||
targets: &[wgpu::ColorTargetState {
|
||||
format: render_context.swap_chain_descriptor.format,
|
||||
blend: Some(wgpu::BlendState::ALPHA_BLENDING),
|
||||
write_mask: wgpu::ColorWrite::ALL,
|
||||
}],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
strip_index_format: None,
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: None,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
clamp_depth: false,
|
||||
conservative: false,
|
||||
},
|
||||
depth_stencil: None,
|
||||
multisample: wgpu::MultisampleState {
|
||||
count: 1,
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ pub mod world_state;
|
|||
use std::time::Duration;
|
||||
|
||||
use winit::{
|
||||
dpi::PhysicalSize,
|
||||
event::{DeviceEvent, ElementState, KeyboardInput, VirtualKeyCode},
|
||||
window::Window,
|
||||
};
|
||||
|
@ -11,15 +12,11 @@ use winit::{
|
|||
use hud_state::HudState;
|
||||
use world_state::WorldState;
|
||||
|
||||
use crate::render_context::RenderContext;
|
||||
|
||||
pub struct State {
|
||||
pub window_size: winit::dpi::PhysicalSize<u32>,
|
||||
render_surface: wgpu::Surface,
|
||||
render_device: wgpu::Device,
|
||||
render_queue: wgpu::Queue,
|
||||
|
||||
swap_chain_descriptor: wgpu::SwapChainDescriptor,
|
||||
swap_chain: wgpu::SwapChain,
|
||||
|
||||
pub window_size: PhysicalSize<u32>,
|
||||
render_context: RenderContext,
|
||||
world_state: WorldState,
|
||||
hud_state: HudState,
|
||||
|
||||
|
@ -87,17 +84,21 @@ impl State {
|
|||
let (swap_chain_descriptor, swap_chain) =
|
||||
Self::create_swap_chain(window, &render_adapter, &render_device, &render_surface);
|
||||
|
||||
let world_state = WorldState::new(&render_device, &render_queue, &swap_chain_descriptor);
|
||||
let hud_state = HudState::new(&render_device, &render_queue, &swap_chain_descriptor);
|
||||
|
||||
Self {
|
||||
window_size,
|
||||
render_surface,
|
||||
render_device,
|
||||
render_queue,
|
||||
let render_context = RenderContext {
|
||||
surface: render_surface,
|
||||
device: render_device,
|
||||
queue: render_queue,
|
||||
|
||||
swap_chain_descriptor,
|
||||
swap_chain,
|
||||
};
|
||||
|
||||
let world_state = WorldState::new(&render_context);
|
||||
let hud_state = HudState::new(&render_context);
|
||||
|
||||
Self {
|
||||
window_size,
|
||||
render_context,
|
||||
|
||||
world_state,
|
||||
hud_state,
|
||||
|
@ -106,25 +107,25 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
|
||||
pub fn resize(&mut self, new_size: PhysicalSize<u32>) {
|
||||
println!("resizing to {:?}", new_size);
|
||||
self.window_size = new_size;
|
||||
self.swap_chain_descriptor.width = new_size.width;
|
||||
self.swap_chain_descriptor.height = new_size.height;
|
||||
self.render_context.swap_chain_descriptor.width = new_size.width;
|
||||
self.render_context.swap_chain_descriptor.height = new_size.height;
|
||||
|
||||
self.world_state
|
||||
.resize(&self.render_device, &self.swap_chain_descriptor, new_size);
|
||||
self.world_state.resize(&self.render_context, new_size);
|
||||
|
||||
self.swap_chain = self
|
||||
.render_device
|
||||
.create_swap_chain(&self.render_surface, &self.swap_chain_descriptor);
|
||||
self.render_context.swap_chain = self.render_context.device.create_swap_chain(
|
||||
&self.render_context.surface,
|
||||
&self.render_context.swap_chain_descriptor,
|
||||
);
|
||||
}
|
||||
|
||||
fn input_keyboard(&mut self, key_code: &VirtualKeyCode, state: &ElementState) {
|
||||
match key_code {
|
||||
VirtualKeyCode::F1 if state == &ElementState::Pressed => self
|
||||
.world_state
|
||||
.toggle_wireframe(&self.render_device, &self.swap_chain_descriptor),
|
||||
VirtualKeyCode::F1 if state == &ElementState::Pressed => {
|
||||
self.world_state.toggle_wireframe(&self.render_context)
|
||||
}
|
||||
_ => self.world_state.input_keyboard(key_code, state),
|
||||
}
|
||||
}
|
||||
|
@ -148,29 +149,30 @@ impl State {
|
|||
state: ElementState::Pressed,
|
||||
} if self.mouse_grabbed => self
|
||||
.world_state
|
||||
.input_mouse_button(*button, &self.render_device),
|
||||
.input_mouse_button(*button, &self.render_context),
|
||||
DeviceEvent::MouseMotion { delta: (dx, dy) } => self.input_mouse(*dx, *dy),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, dt: Duration) {
|
||||
self.world_state
|
||||
.update(dt, &self.render_device, &self.render_queue);
|
||||
self.world_state.update(dt, &self.render_context);
|
||||
}
|
||||
|
||||
pub fn render(&mut self) -> anyhow::Result<usize> {
|
||||
let frame = self.swap_chain.get_current_frame()?.output;
|
||||
let frame = self.render_context.swap_chain.get_current_frame()?.output;
|
||||
|
||||
let mut render_encoder = self
|
||||
.render_device
|
||||
.render_context
|
||||
.device
|
||||
.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)?;
|
||||
|
||||
self.render_queue
|
||||
self.render_context
|
||||
.queue
|
||||
.submit(std::iter::once(render_encoder.finish()));
|
||||
|
||||
Ok(triangle_count)
|
||||
|
|
|
@ -14,6 +14,7 @@ use winit::{
|
|||
use crate::{
|
||||
camera::{Camera, Projection},
|
||||
chunk::{Block, BlockType, CHUNK_SIZE},
|
||||
render_context::RenderContext,
|
||||
texture::{Texture, TextureManager},
|
||||
time::Time,
|
||||
uniforms::Uniforms,
|
||||
|
@ -48,15 +49,13 @@ pub struct WorldState {
|
|||
}
|
||||
|
||||
impl WorldState {
|
||||
fn create_textures(render_device: &wgpu::Device, render_queue: &wgpu::Queue) -> TextureManager {
|
||||
let mut texture_manager = TextureManager::new(render_device);
|
||||
texture_manager
|
||||
.load_all(render_device, render_queue)
|
||||
.unwrap();
|
||||
fn create_textures(render_context: &RenderContext) -> TextureManager {
|
||||
let mut texture_manager = TextureManager::new(&render_context.device);
|
||||
texture_manager.load_all(render_context).unwrap();
|
||||
texture_manager
|
||||
}
|
||||
|
||||
fn create_camera(swap_chain_descriptor: &wgpu::SwapChainDescriptor) -> (Camera, Projection) {
|
||||
fn create_camera(render_context: &RenderContext) -> (Camera, Projection) {
|
||||
let camera = Camera::new(
|
||||
(-10.0, 140.0, -10.0).into(),
|
||||
cgmath::Deg(45.0).into(),
|
||||
|
@ -64,8 +63,8 @@ impl WorldState {
|
|||
);
|
||||
|
||||
let projection = Projection::new(
|
||||
swap_chain_descriptor.width,
|
||||
swap_chain_descriptor.height,
|
||||
render_context.swap_chain_descriptor.width,
|
||||
render_context.swap_chain_descriptor.height,
|
||||
cgmath::Deg(45.0),
|
||||
0.1,
|
||||
5000.0,
|
||||
|
@ -77,7 +76,7 @@ impl WorldState {
|
|||
fn create_uniforms(
|
||||
camera: &Camera,
|
||||
projection: &Projection,
|
||||
render_device: &wgpu::Device,
|
||||
render_context: &RenderContext,
|
||||
) -> (
|
||||
Uniforms,
|
||||
wgpu::Buffer,
|
||||
|
@ -87,35 +86,42 @@ impl WorldState {
|
|||
let mut uniforms = Uniforms::new();
|
||||
uniforms.update_view_projection(camera, projection);
|
||||
|
||||
let uniform_buffer = render_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: Some("uniform_buffer"),
|
||||
contents: bytemuck::cast_slice(&[uniforms]),
|
||||
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
});
|
||||
|
||||
let uniform_bind_group_layout =
|
||||
render_device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
label: Some("uniform_bind_group_layout"),
|
||||
let uniform_buffer = render_context
|
||||
.device
|
||||
.create_buffer_init(&BufferInitDescriptor {
|
||||
label: Some("uniform_buffer"),
|
||||
contents: bytemuck::cast_slice(&[uniforms]),
|
||||
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
});
|
||||
|
||||
let uniform_bind_group = render_device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &uniform_bind_group_layout,
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: uniform_buffer.as_entire_binding(),
|
||||
}],
|
||||
label: Some("uniform_bind_group"),
|
||||
});
|
||||
let uniform_bind_group_layout =
|
||||
render_context
|
||||
.device
|
||||
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
label: Some("uniform_bind_group_layout"),
|
||||
});
|
||||
|
||||
let uniform_bind_group =
|
||||
render_context
|
||||
.device
|
||||
.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &uniform_bind_group_layout,
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: uniform_buffer.as_entire_binding(),
|
||||
}],
|
||||
label: Some("uniform_bind_group"),
|
||||
});
|
||||
|
||||
(
|
||||
uniforms,
|
||||
|
@ -126,91 +132,98 @@ impl WorldState {
|
|||
}
|
||||
|
||||
fn create_time(
|
||||
render_device: &wgpu::Device,
|
||||
render_context: &RenderContext,
|
||||
) -> (Time, wgpu::Buffer, wgpu::BindGroupLayout, wgpu::BindGroup) {
|
||||
let time = Time::new();
|
||||
|
||||
let buffer = render_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: Some("time_buffer"),
|
||||
contents: bytemuck::cast_slice(&[time]),
|
||||
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
});
|
||||
|
||||
let bind_group_layout =
|
||||
render_device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
label: Some("time_bind_group_layout"),
|
||||
let buffer = render_context
|
||||
.device
|
||||
.create_buffer_init(&BufferInitDescriptor {
|
||||
label: Some("time_buffer"),
|
||||
contents: bytemuck::cast_slice(&[time]),
|
||||
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
});
|
||||
|
||||
let bind_group = render_device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_group_layout,
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: buffer.as_entire_binding(),
|
||||
}],
|
||||
label: Some("time_bind_group"),
|
||||
});
|
||||
let bind_group_layout =
|
||||
render_context
|
||||
.device
|
||||
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
label: Some("time_bind_group_layout"),
|
||||
});
|
||||
|
||||
let bind_group = render_context
|
||||
.device
|
||||
.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_group_layout,
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: buffer.as_entire_binding(),
|
||||
}],
|
||||
label: Some("time_bind_group"),
|
||||
});
|
||||
|
||||
(time, buffer, bind_group_layout, bind_group)
|
||||
}
|
||||
|
||||
fn create_render_pipeline(
|
||||
render_device: &wgpu::Device,
|
||||
swap_chain_descriptor: &wgpu::SwapChainDescriptor,
|
||||
render_context: &RenderContext,
|
||||
shader: &wgpu::ShaderModule,
|
||||
pipeline_layout: &wgpu::PipelineLayout,
|
||||
wireframe: bool,
|
||||
) -> wgpu::RenderPipeline {
|
||||
render_device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("Render Pipeline"),
|
||||
layout: Some(&pipeline_layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module: &shader,
|
||||
entry_point: "main",
|
||||
buffers: &[Vertex::desc()],
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: "main",
|
||||
targets: &[wgpu::ColorTargetState {
|
||||
format: swap_chain_descriptor.format,
|
||||
blend: Some(wgpu::BlendState {
|
||||
alpha: wgpu::BlendComponent::REPLACE,
|
||||
color: wgpu::BlendComponent::REPLACE,
|
||||
}),
|
||||
write_mask: wgpu::ColorWrite::ALL,
|
||||
}],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
cull_mode: Some(wgpu::Face::Back),
|
||||
polygon_mode: if wireframe {
|
||||
wgpu::PolygonMode::Line
|
||||
} else {
|
||||
wgpu::PolygonMode::Fill
|
||||
render_context
|
||||
.device
|
||||
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("Render Pipeline"),
|
||||
layout: Some(&pipeline_layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module: &shader,
|
||||
entry_point: "main",
|
||||
buffers: &[Vertex::desc()],
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: Some(wgpu::DepthStencilState {
|
||||
format: Texture::DEPTH_FORMAT,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: wgpu::CompareFunction::Less,
|
||||
stencil: wgpu::StencilState::default(),
|
||||
bias: wgpu::DepthBiasState::default(),
|
||||
}),
|
||||
multisample: wgpu::MultisampleState::default(),
|
||||
})
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: "main",
|
||||
targets: &[wgpu::ColorTargetState {
|
||||
format: render_context.swap_chain_descriptor.format,
|
||||
blend: Some(wgpu::BlendState {
|
||||
alpha: wgpu::BlendComponent::REPLACE,
|
||||
color: wgpu::BlendComponent::REPLACE,
|
||||
}),
|
||||
write_mask: wgpu::ColorWrite::ALL,
|
||||
}],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
cull_mode: Some(wgpu::Face::Back),
|
||||
polygon_mode: if wireframe {
|
||||
wgpu::PolygonMode::Line
|
||||
} else {
|
||||
wgpu::PolygonMode::Fill
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: Some(wgpu::DepthStencilState {
|
||||
format: Texture::DEPTH_FORMAT,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: wgpu::CompareFunction::Less,
|
||||
stencil: wgpu::StencilState::default(),
|
||||
bias: wgpu::DepthBiasState::default(),
|
||||
}),
|
||||
multisample: wgpu::MultisampleState::default(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update_world_geometry(&mut self, render_device: &wgpu::Device) {
|
||||
pub fn update_world_geometry(&mut self, render_context: &RenderContext) {
|
||||
let instant = Instant::now();
|
||||
|
||||
let world_geometry = self.world.to_geometry(self.highlighted);
|
||||
|
@ -219,16 +232,20 @@ impl WorldState {
|
|||
self.chunk_buffers.insert(
|
||||
chunk_position,
|
||||
(
|
||||
render_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &bytemuck::cast_slice(&chunk_vertices),
|
||||
usage: wgpu::BufferUsage::VERTEX,
|
||||
}),
|
||||
render_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &bytemuck::cast_slice(&chunk_indices),
|
||||
usage: wgpu::BufferUsage::INDEX,
|
||||
}),
|
||||
render_context
|
||||
.device
|
||||
.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &bytemuck::cast_slice(&chunk_vertices),
|
||||
usage: wgpu::BufferUsage::VERTEX,
|
||||
}),
|
||||
render_context
|
||||
.device
|
||||
.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &bytemuck::cast_slice(&chunk_indices),
|
||||
usage: wgpu::BufferUsage::INDEX,
|
||||
}),
|
||||
chunk_indices.len(),
|
||||
),
|
||||
);
|
||||
|
@ -240,10 +257,9 @@ impl WorldState {
|
|||
|
||||
pub fn update_chunk_geometry(
|
||||
&mut self,
|
||||
render_device: &wgpu::Device,
|
||||
render_context: &RenderContext,
|
||||
chunk_position: Vector3<usize>,
|
||||
) {
|
||||
// println!("Updating chunk {:?}", chunk_position);
|
||||
let chunk = &mut self.world.chunks[chunk_position.y][chunk_position.z][chunk_position.x];
|
||||
let offset = chunk_position.map(|f| (f * CHUNK_SIZE) as i32);
|
||||
let (vertices, indices) = chunk.to_geometry(
|
||||
|
@ -254,53 +270,48 @@ impl WorldState {
|
|||
self.chunk_buffers.insert(
|
||||
chunk_position,
|
||||
(
|
||||
render_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &bytemuck::cast_slice(&vertices),
|
||||
usage: wgpu::BufferUsage::VERTEX,
|
||||
}),
|
||||
render_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &bytemuck::cast_slice(&indices),
|
||||
usage: wgpu::BufferUsage::INDEX,
|
||||
}),
|
||||
render_context
|
||||
.device
|
||||
.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &bytemuck::cast_slice(&vertices),
|
||||
usage: wgpu::BufferUsage::VERTEX,
|
||||
}),
|
||||
render_context
|
||||
.device
|
||||
.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &bytemuck::cast_slice(&indices),
|
||||
usage: wgpu::BufferUsage::INDEX,
|
||||
}),
|
||||
indices.len(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn toggle_wireframe(
|
||||
&mut self,
|
||||
render_device: &wgpu::Device,
|
||||
swap_chain_descriptor: &wgpu::SwapChainDescriptor,
|
||||
) {
|
||||
pub fn toggle_wireframe(&mut self, render_context: &RenderContext) {
|
||||
self.wireframe = !self.wireframe;
|
||||
self.render_pipeline = Self::create_render_pipeline(
|
||||
render_device,
|
||||
swap_chain_descriptor,
|
||||
render_context,
|
||||
&self.shader,
|
||||
&self.render_pipeline_layout,
|
||||
self.wireframe,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
render_device: &wgpu::Device,
|
||||
render_queue: &wgpu::Queue,
|
||||
swap_chain_descriptor: &wgpu::SwapChainDescriptor,
|
||||
) -> WorldState {
|
||||
pub fn new(render_context: &RenderContext) -> WorldState {
|
||||
let world = World::generate();
|
||||
|
||||
let texture_manager = Self::create_textures(render_device, render_queue);
|
||||
let texture_manager = Self::create_textures(render_context);
|
||||
|
||||
let (camera, projection) = Self::create_camera(swap_chain_descriptor);
|
||||
let (camera, projection) = Self::create_camera(render_context);
|
||||
|
||||
let (uniforms, uniform_buffer, world_uniform_layout, uniform_bind_group) =
|
||||
Self::create_uniforms(&camera, &projection, render_device);
|
||||
Self::create_uniforms(&camera, &projection, render_context);
|
||||
|
||||
let (time, time_buffer, time_layout, time_bind_group) = Self::create_time(&render_device);
|
||||
let (time, time_buffer, time_layout, time_bind_group) = Self::create_time(render_context);
|
||||
|
||||
let shader = render_device.create_shader_module(
|
||||
let shader = render_context.device.create_shader_module(
|
||||
&(wgpu::ShaderModuleDescriptor {
|
||||
label: Some("shader"),
|
||||
flags: wgpu::ShaderFlags::all(),
|
||||
|
@ -309,26 +320,22 @@ impl WorldState {
|
|||
);
|
||||
|
||||
let render_pipeline_layout =
|
||||
render_device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("render_pipeline_layout"),
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[
|
||||
&texture_manager.bind_group_layout,
|
||||
&world_uniform_layout,
|
||||
&time_layout,
|
||||
],
|
||||
});
|
||||
render_context
|
||||
.device
|
||||
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("render_pipeline_layout"),
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[
|
||||
&texture_manager.bind_group_layout,
|
||||
&world_uniform_layout,
|
||||
&time_layout,
|
||||
],
|
||||
});
|
||||
|
||||
let render_pipeline = Self::create_render_pipeline(
|
||||
&render_device,
|
||||
&swap_chain_descriptor,
|
||||
&shader,
|
||||
&render_pipeline_layout,
|
||||
false,
|
||||
);
|
||||
let render_pipeline =
|
||||
Self::create_render_pipeline(&render_context, &shader, &render_pipeline_layout, false);
|
||||
|
||||
let depth_texture =
|
||||
Texture::create_depth_texture(&render_device, &swap_chain_descriptor, "depth_texture");
|
||||
let depth_texture = Texture::create_depth_texture(render_context, "depth_texture");
|
||||
|
||||
let mut world_state = Self {
|
||||
render_pipeline,
|
||||
|
@ -357,7 +364,7 @@ impl WorldState {
|
|||
sprinting: false,
|
||||
};
|
||||
|
||||
world_state.update_world_geometry(render_device);
|
||||
world_state.update_world_geometry(render_context);
|
||||
|
||||
world_state
|
||||
}
|
||||
|
@ -428,7 +435,7 @@ impl WorldState {
|
|||
}
|
||||
}
|
||||
|
||||
fn update_aim(&mut self, render_device: &wgpu::Device) {
|
||||
fn update_aim(&mut self, render_context: &RenderContext) {
|
||||
let camera = &self.camera;
|
||||
|
||||
let old = self.highlighted;
|
||||
|
@ -443,26 +450,26 @@ impl WorldState {
|
|||
self.highlighted = new;
|
||||
|
||||
if let Some(old_chunk_) = old_chunk {
|
||||
self.update_chunk_geometry(&render_device, old_chunk_);
|
||||
self.update_chunk_geometry(render_context, old_chunk_);
|
||||
}
|
||||
|
||||
if let Some(new_chunk_) = new_chunk {
|
||||
// Don't update the same chunk twice
|
||||
if old_chunk != new_chunk {
|
||||
self.update_chunk_geometry(&render_device, new_chunk_);
|
||||
self.update_chunk_geometry(render_context, new_chunk_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn input_mouse_button(&mut self, button: u32, render_device: &wgpu::Device) {
|
||||
pub fn input_mouse_button(&mut self, button: u32, render_context: &RenderContext) {
|
||||
let camera = &self.camera;
|
||||
|
||||
let world = &mut self.world;
|
||||
if let Some((pos, axis)) = world.raycast(camera.position.to_vec(), camera.direction()) {
|
||||
if button == 1 {
|
||||
world.set_block(pos.x as isize, pos.y as isize, pos.z as isize, None);
|
||||
self.update_chunk_geometry(&render_device, pos / CHUNK_SIZE);
|
||||
self.update_chunk_geometry(render_context, pos / CHUNK_SIZE);
|
||||
} else if button == 3 {
|
||||
let new_pos = pos.cast().unwrap() - axis;
|
||||
|
||||
|
@ -475,7 +482,7 @@ impl WorldState {
|
|||
}),
|
||||
);
|
||||
|
||||
self.update_chunk_geometry(&render_device, pos / CHUNK_SIZE);
|
||||
self.update_chunk_geometry(render_context, pos / CHUNK_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -514,35 +521,28 @@ impl WorldState {
|
|||
self.camera.position += Vector3::unit_y() * self.up_speed * speed * dt_seconds;
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
dt: Duration,
|
||||
render_device: &wgpu::Device,
|
||||
render_queue: &wgpu::Queue,
|
||||
) {
|
||||
pub fn update(&mut self, dt: Duration, render_context: &RenderContext) {
|
||||
self.update_position(dt);
|
||||
self.update_aim(render_device);
|
||||
self.update_aim(render_context);
|
||||
|
||||
self.uniforms
|
||||
.update_view_projection(&self.camera, &self.projection);
|
||||
render_queue.write_buffer(
|
||||
render_context.queue.write_buffer(
|
||||
&self.uniform_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&[self.uniforms]),
|
||||
);
|
||||
|
||||
self.time.time += dt.as_secs_f32();
|
||||
render_queue.write_buffer(&self.time_buffer, 0, &bytemuck::cast_slice(&[self.time]));
|
||||
render_context.queue.write_buffer(
|
||||
&self.time_buffer,
|
||||
0,
|
||||
&bytemuck::cast_slice(&[self.time]),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn resize(
|
||||
&mut self,
|
||||
render_device: &wgpu::Device,
|
||||
swap_chain_descriptor: &wgpu::SwapChainDescriptor,
|
||||
new_size: PhysicalSize<u32>,
|
||||
) {
|
||||
pub fn resize(&mut self, render_context: &RenderContext, new_size: PhysicalSize<u32>) {
|
||||
self.projection.resize(new_size.width, new_size.height);
|
||||
self.depth_texture =
|
||||
Texture::create_depth_texture(render_device, swap_chain_descriptor, "depth_texture");
|
||||
self.depth_texture = Texture::create_depth_texture(render_context, "depth_texture");
|
||||
}
|
||||
}
|
||||
|
|
187
src/texture.rs
187
src/texture.rs
|
@ -3,6 +3,8 @@ use std::num::NonZeroU32;
|
|||
use image::EncodableLayout;
|
||||
use wgpu::Origin3d;
|
||||
|
||||
use crate::render_context::RenderContext;
|
||||
|
||||
pub struct Texture {
|
||||
pub texture: wgpu::Texture,
|
||||
pub sampler: Option<wgpu::Sampler>,
|
||||
|
@ -12,40 +14,40 @@ pub struct Texture {
|
|||
impl Texture {
|
||||
pub const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
|
||||
|
||||
pub fn create_depth_texture(
|
||||
device: &wgpu::Device,
|
||||
swap_chain_descriptor: &wgpu::SwapChainDescriptor,
|
||||
label: &str,
|
||||
) -> Self {
|
||||
pub fn create_depth_texture(render_context: &RenderContext, label: &str) -> Self {
|
||||
let size = wgpu::Extent3d {
|
||||
width: swap_chain_descriptor.width,
|
||||
height: swap_chain_descriptor.height,
|
||||
width: render_context.swap_chain_descriptor.width,
|
||||
height: render_context.swap_chain_descriptor.height,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
|
||||
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some(label),
|
||||
size,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: Self::DEPTH_FORMAT,
|
||||
usage: wgpu::TextureUsage::RENDER_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
|
||||
});
|
||||
let texture = render_context
|
||||
.device
|
||||
.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some(label),
|
||||
size,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: Self::DEPTH_FORMAT,
|
||||
usage: wgpu::TextureUsage::RENDER_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
|
||||
});
|
||||
|
||||
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
mag_filter: wgpu::FilterMode::Linear,
|
||||
min_filter: wgpu::FilterMode::Linear,
|
||||
mipmap_filter: wgpu::FilterMode::Nearest,
|
||||
compare: Some(wgpu::CompareFunction::LessEqual),
|
||||
lod_min_clamp: -100.0,
|
||||
lod_max_clamp: 100.0,
|
||||
..Default::default()
|
||||
});
|
||||
let sampler = render_context
|
||||
.device
|
||||
.create_sampler(&wgpu::SamplerDescriptor {
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
mag_filter: wgpu::FilterMode::Linear,
|
||||
min_filter: wgpu::FilterMode::Linear,
|
||||
mipmap_filter: wgpu::FilterMode::Nearest,
|
||||
compare: Some(wgpu::CompareFunction::LessEqual),
|
||||
lod_min_clamp: -100.0,
|
||||
lod_max_clamp: 100.0,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
Self {
|
||||
texture,
|
||||
|
@ -55,8 +57,7 @@ impl Texture {
|
|||
}
|
||||
|
||||
pub fn from_bytes(
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
render_context: &RenderContext,
|
||||
bytes: &[u8],
|
||||
label: &str,
|
||||
) -> anyhow::Result<Self> {
|
||||
|
@ -70,19 +71,21 @@ impl Texture {
|
|||
depth_or_array_layers: 1,
|
||||
};
|
||||
|
||||
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some(label),
|
||||
size: texture_size,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||
usage: wgpu::TextureUsage::SAMPLED
|
||||
| wgpu::TextureUsage::COPY_DST
|
||||
| wgpu::TextureUsage::COPY_SRC,
|
||||
});
|
||||
let texture = render_context
|
||||
.device
|
||||
.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some(label),
|
||||
size: texture_size,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||
usage: wgpu::TextureUsage::SAMPLED
|
||||
| wgpu::TextureUsage::COPY_DST
|
||||
| wgpu::TextureUsage::COPY_SRC,
|
||||
});
|
||||
|
||||
queue.write_texture(
|
||||
render_context.queue.write_texture(
|
||||
wgpu::ImageCopyTexture {
|
||||
texture: &texture,
|
||||
mip_level: 0,
|
||||
|
@ -165,38 +168,43 @@ impl TextureManager {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn load_all(&mut self, device: &wgpu::Device, queue: &wgpu::Queue) -> anyhow::Result<()> {
|
||||
self.load(device, queue, "assets/block/cobblestone.png")?; // 0
|
||||
self.load(device, queue, "assets/block/dirt.png")?; // 1
|
||||
self.load(device, queue, "assets/block/stone.png")?; // 2
|
||||
self.load(device, queue, "assets/grass_block_top_plains.png")?; // 3
|
||||
self.load(device, queue, "assets/grass_block_side_plains.png")?; // 4
|
||||
self.load(device, queue, "assets/block/bedrock.png")?; // 5
|
||||
self.load(device, queue, "assets/block/sand.png")?; // 6
|
||||
self.load(device, queue, "assets/block/gravel.png")?; // 7
|
||||
pub fn load_all(&mut self, render_context: &RenderContext) -> anyhow::Result<()> {
|
||||
self.load(render_context, "assets/block/cobblestone.png")?; // 0
|
||||
self.load(render_context, "assets/block/dirt.png")?; // 1
|
||||
self.load(render_context, "assets/block/stone.png")?; // 2
|
||||
self.load(render_context, "assets/grass_block_top_plains.png")?; // 3
|
||||
self.load(render_context, "assets/grass_block_side_plains.png")?; // 4
|
||||
self.load(render_context, "assets/block/bedrock.png")?; // 5
|
||||
self.load(render_context, "assets/block/sand.png")?; // 6
|
||||
self.load(render_context, "assets/block/gravel.png")?; // 7
|
||||
for i in 0..64 {
|
||||
let path = format!("assets/water_still_plains/frame-{}.png", i);
|
||||
self.load(device, queue, &path)?; // 8 - 71
|
||||
self.load(render_context, &path)?; // 8 - 71
|
||||
}
|
||||
assert_eq!(TEXTURE_COUNT, self.textures.len());
|
||||
|
||||
let texture_array = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size: wgpu::Extent3d {
|
||||
width: 512,
|
||||
height: 512,
|
||||
depth_or_array_layers: TEXTURE_COUNT as u32,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
|
||||
});
|
||||
let texture_array = render_context
|
||||
.device
|
||||
.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size: wgpu::Extent3d {
|
||||
width: 512,
|
||||
height: 512,
|
||||
depth_or_array_layers: TEXTURE_COUNT as u32,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
|
||||
});
|
||||
|
||||
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
||||
label: Some("texture copy encoder"),
|
||||
});
|
||||
let mut encoder =
|
||||
render_context
|
||||
.device
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
||||
label: Some("texture copy encoder"),
|
||||
});
|
||||
|
||||
for (i, texture) in self.textures.iter().enumerate() {
|
||||
encoder.copy_texture_to_texture(
|
||||
|
@ -222,7 +230,9 @@ impl TextureManager {
|
|||
)
|
||||
}
|
||||
|
||||
queue.submit(std::iter::once(encoder.finish()));
|
||||
render_context
|
||||
.queue
|
||||
.submit(std::iter::once(encoder.finish()));
|
||||
|
||||
let view = texture_array.create_view(&wgpu::TextureViewDescriptor {
|
||||
label: None,
|
||||
|
@ -231,32 +241,29 @@ impl TextureManager {
|
|||
..wgpu::TextureViewDescriptor::default()
|
||||
});
|
||||
|
||||
self.bind_group = Some(device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: Some(&("Block texture bind group")),
|
||||
layout: &self.bind_group_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Sampler(&self.sampler),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::TextureView(&view),
|
||||
},
|
||||
],
|
||||
}));
|
||||
self.bind_group = Some(render_context.device.create_bind_group(
|
||||
&wgpu::BindGroupDescriptor {
|
||||
label: Some(&("Block texture bind group")),
|
||||
layout: &self.bind_group_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Sampler(&self.sampler),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::TextureView(&view),
|
||||
},
|
||||
],
|
||||
},
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
path: &str,
|
||||
) -> anyhow::Result<usize> {
|
||||
pub fn load(&mut self, render_context: &RenderContext, path: &str) -> anyhow::Result<usize> {
|
||||
let bytes = std::fs::read(path)?;
|
||||
let texture = Texture::from_bytes(device, queue, &bytes, path)?;
|
||||
let texture = Texture::from_bytes(render_context, &bytes, path)?;
|
||||
|
||||
let id = self.textures.len();
|
||||
self.textures.push(texture);
|
||||
|
|
Loading…
Reference in a new issue