Render Ui

This commit is contained in:
Imbris 2020-12-04 00:38:26 -05:00 committed by Avi Weinstock
parent 9f399f9076
commit 617ae80d02
35 changed files with 926 additions and 337 deletions

View File

@ -11,9 +11,9 @@ uniform u_locals {
vec4 w_pos; vec4 w_pos;
}; };
layout(set = 1, binding = 1) layout(set = 2, binding = 0)
uniform texture2D t_tex; uniform texture2D t_tex;
layout(set = 1, binding = 2) layout(set = 2, binding = 1)
uniform sampler s_tex; uniform sampler s_tex;
layout(location = 0) out vec4 tgt_color; layout(location = 0) out vec4 tgt_color;

View File

@ -13,9 +13,9 @@ uniform u_locals {
vec4 w_pos; vec4 w_pos;
}; };
layout(set = 1, binding = 1) layout(set = 2, binding = 0)
uniform texture2D t_tex; uniform texture2D t_tex;
layout(set = 1, binding = 2) layout(set = 2, binding = 1)
uniform sampler s_tex; uniform sampler s_tex;
layout(location = 0) out vec2 f_uv; layout(location = 0) out vec2 f_uv;
@ -33,10 +33,10 @@ void main() {
f_uv = v_uv; f_uv = v_uv;
// Fixed scale In-game element // Fixed scale In-game element
vec4 projected_pos = /*proj_mat * view_mat*/all_mat * vec4(w_pos.xyz - focus_off.xyz, 1.0); vec4 projected_pos = /*proj_mat * view_mat*/all_mat * vec4(w_pos.xyz - focus_off.xyz, 1.0);
gl_Position = vec4(projected_pos.xy / projected_pos.w + v_pos/* * projected_pos.w*/, -1.0, /*projected_pos.w*/1.0); gl_Position = vec4(projected_pos.xy / projected_pos.w + v_pos/* * projected_pos.w*/, 0.0, /*projected_pos.w*/1.0);
} else if (v_mode == uint(3)) { } else if (v_mode == uint(3)) {
// HACK: North facing source rectangle. // HACK: North facing source rectangle.
gl_Position = vec4(v_pos, -1.0, 1.0); gl_Position = vec4(v_pos, 0.0, 1.0);
vec2 look_at_dir = normalize(vec2(-view_mat[0][2], -view_mat[1][2])); vec2 look_at_dir = normalize(vec2(-view_mat[0][2], -view_mat[1][2]));
// TODO: Consider cleaning up matrix to something more efficient (e.g. a mat3). // TODO: Consider cleaning up matrix to something more efficient (e.g. a mat3).
vec2 aspect_ratio = textureSize(sampler2D(t_tex, s_tex), 0).yx; vec2 aspect_ratio = textureSize(sampler2D(t_tex, s_tex), 0).yx;
@ -53,11 +53,11 @@ void main() {
mat2 look_at = mat2(look_at_dir.y, -look_at_dir.x, look_at_dir.x, look_at_dir.y); mat2 look_at = mat2(look_at_dir.y, -look_at_dir.x, look_at_dir.x, look_at_dir.y);
vec2 v_centered = (v_pos - v_center) / aspect_ratio; vec2 v_centered = (v_pos - v_center) / aspect_ratio;
vec2 v_rotated = look_at * v_centered; vec2 v_rotated = look_at * v_centered;
gl_Position = vec4(aspect_ratio * v_rotated + v_center, -1.0, 1.0); gl_Position = vec4(aspect_ratio * v_rotated + v_center, 0.0, 1.0);
} else { } else {
// Interface element // Interface element
f_uv = v_uv; f_uv = v_uv;
gl_Position = vec4(v_pos, -1.0, 1.0); gl_Position = vec4(v_pos, 0.0, 1.0);
} }
f_mode = v_mode; f_mode = v_mode;
} }

View File

@ -1584,7 +1584,8 @@ impl CharSelectionUi {
} }
// TODO: do we need globals? // TODO: do we need globals?
pub fn render(&self, renderer: &mut Renderer) { self.ui.render(renderer); } pub fn render(&self, renderer: &mut Renderer) { /* self.ui.render(renderer);*/
}
} }
#[derive(Default)] #[derive(Default)]

View File

@ -1,4 +1,5 @@
mod client_init; mod client_init;
mod scene;
mod ui; mod ui;
use super::char_selection::CharSelectionState; use super::char_selection::CharSelectionState;
@ -20,6 +21,7 @@ use client::{
use client_init::{ClientConnArgs, ClientInit, Error as InitError, Msg as InitMsg}; use client_init::{ClientConnArgs, ClientInit, Error as InitError, Msg as InitMsg};
use common::comp; use common::comp;
use common_base::span; use common_base::span;
use scene::Scene;
use std::{fmt::Debug, sync::Arc}; use std::{fmt::Debug, sync::Arc};
use tokio::runtime; use tokio::runtime;
use tracing::error; use tracing::error;
@ -29,6 +31,7 @@ pub struct MainMenuState {
main_menu_ui: MainMenuUi, main_menu_ui: MainMenuUi,
// Used for client creation. // Used for client creation.
client_init: Option<ClientInit>, client_init: Option<ClientInit>,
scene: Scene,
} }
impl MainMenuState { impl MainMenuState {
@ -37,6 +40,7 @@ impl MainMenuState {
Self { Self {
main_menu_ui: MainMenuUi::new(global_state), main_menu_ui: MainMenuUi::new(global_state),
client_init: None, client_init: None,
scene: Scene::new(global_state.window.renderer_mut()),
} }
} }
} }
@ -342,8 +346,18 @@ impl PlayState for MainMenuState {
fn name(&self) -> &'static str { "Title" } fn name(&self) -> &'static str { "Title" }
fn render(&mut self, renderer: &mut Renderer, _: &Settings) { fn render(&mut self, renderer: &mut Renderer, _: &Settings) {
// TODO: maybe the drawer should be passed in from above?
let mut drawer = match renderer
.start_recording_frame(self.scene.global_bind_group())
.unwrap()
{
Some(d) => d,
// Couldn't get swap chain texture this fime
None => return,
};
// Draw the UI to the screen. // Draw the UI to the screen.
self.main_menu_ui.render(renderer); self.main_menu_ui.render(&mut drawer.third_pass().draw_ui());
} }
} }

View File

@ -0,0 +1,28 @@
use crate::render::{
GlobalModel, Globals, GlobalsBindGroup, Light, LodData, Renderer, Shadow, ShadowLocals,
};
pub struct Scene {
// global_data: GlobalModel,
// lod_data: LodData,
bind_group: GlobalsBindGroup,
}
impl Scene {
pub fn new(renderer: &mut Renderer) -> Self {
let global_data = GlobalModel {
globals: renderer.create_consts(&[Globals::default()]),
lights: renderer.create_consts(&[Light::default(); 32]),
shadows: renderer.create_consts(&[Shadow::default(); 32]),
shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]),
};
let lod_data = LodData::dummy(renderer);
let bind_group = renderer.bind_globals(&global_data, &lod_data);
Self { bind_group }
}
pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.bind_group }
}

View File

@ -6,7 +6,7 @@ mod servers;
use crate::{ use crate::{
i18n::{LanguageMetadata, LocalizationHandle}, i18n::{LanguageMetadata, LocalizationHandle},
render::Renderer, render::UiDrawer,
ui::{ ui::{
self, self,
fonts::IcedFonts as Fonts, fonts::IcedFonts as Fonts,
@ -477,7 +477,7 @@ pub struct MainMenuUi {
controls: Controls, controls: Controls,
} }
impl<'a> MainMenuUi { impl MainMenuUi {
pub fn new(global_state: &mut GlobalState) -> Self { pub fn new(global_state: &mut GlobalState) -> Self {
// Load language // Load language
let i18n = &global_state.i18n.read(); let i18n = &global_state.i18n.read();
@ -582,5 +582,5 @@ impl<'a> MainMenuUi {
events events
} }
pub fn render(&self, renderer: &mut Renderer) { self.ui.render(renderer); } pub fn render<'a>(&'a self, drawer: &mut UiDrawer<'_, 'a>) { self.ui.render(drawer); }
} }

View File

@ -2,7 +2,7 @@ use bytemuck::Pod;
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
pub struct Buffer<T: Copy + Pod> { pub struct Buffer<T: Copy + Pod> {
pub buf: wgpu::Buffer, pub(super) buf: wgpu::Buffer,
// Size in number of elements // Size in number of elements
// TODO: determine if this is a good name // TODO: determine if this is a good name
len: usize, len: usize,

View File

@ -37,11 +37,12 @@ pub use self::{
ui::{ ui::{
create_quad as create_ui_quad, create_quad as create_ui_quad,
create_quad_vert_gradient as create_ui_quad_vert_gradient, create_tri as create_ui_tri, create_quad_vert_gradient as create_ui_quad_vert_gradient, create_tri as create_ui_tri,
Locals as UiLocals, Mode as UiMode, Vertex as UiVertex, Locals as UiLocals, LocalsBindGroup as UiLocalsBindGroup, Mode as UiMode,
TextureBindGroup as UiTextureBindGroup, Vertex as UiVertex,
}, },
GlobalModel, Globals, GlobalsLayouts, Light, Shadow, GlobalModel, Globals, GlobalsBindGroup, GlobalsLayouts, Light, Shadow,
}, },
renderer::{ColLightInfo, Renderer}, renderer::{ColLightInfo, Drawer, Renderer, UiDrawer},
texture::Texture, texture::Texture,
}; };
pub use wgpu::{AddressMode, FilterMode}; pub use wgpu::{AddressMode, FilterMode};

View File

@ -13,7 +13,7 @@ pub struct SubModel<'a, V: Vertex> {
} }
impl<'a, V: Vertex> SubModel<'a, V> { impl<'a, V: Vertex> SubModel<'a, V> {
pub fn buf(&self) -> &wgpu::Buffer { self.buf } pub(super) fn buf(&self) -> &wgpu::Buffer { self.buf }
} }
/// Represents a mesh that has been sent to the GPU. /// Represents a mesh that has been sent to the GPU.
@ -38,7 +38,7 @@ impl<V: Vertex> Model<V> {
} }
} }
pub fn buf(&self) -> &wgpu::Buffer { &self.vbuf.buf } pub(super) fn buf(&self) -> &wgpu::Buffer { &self.vbuf.buf }
pub fn len(&self) -> usize { self.vbuf.len() } pub fn len(&self) -> usize { self.vbuf.len() }
} }

View File

@ -150,7 +150,6 @@ impl CloudsPipeline {
let samples = match aa_mode { let samples = match aa_mode {
AaMode::None | AaMode::Fxaa => 1, AaMode::None | AaMode::Fxaa => 1,
// TODO: Ensure sampling in the shader is exactly between the 4 texels // TODO: Ensure sampling in the shader is exactly between the 4 texels
AaMode::SsaaX4 => 1,
AaMode::MsaaX4 => 4, AaMode::MsaaX4 => 4,
AaMode::MsaaX8 => 8, AaMode::MsaaX8 => 8,
AaMode::MsaaX16 => 16, AaMode::MsaaX16 => 16,

View File

@ -143,7 +143,6 @@ impl FigureLayout {
}, },
count: None, count: None,
}, },
// TODO: does this change at the same frequency?
// col lights // col lights
wgpu::BindGroupLayoutEntry { wgpu::BindGroupLayoutEntry {
binding: 2, binding: 2,
@ -192,7 +191,6 @@ impl FigurePipeline {
let samples = match aa_mode { let samples = match aa_mode {
AaMode::None | AaMode::Fxaa => 1, AaMode::None | AaMode::Fxaa => 1,
// TODO: Ensure sampling in the shader is exactly between the 4 texels // TODO: Ensure sampling in the shader is exactly between the 4 texels
AaMode::SsaaX4 => 1,
AaMode::MsaaX4 => 4, AaMode::MsaaX4 => 4,
AaMode::MsaaX8 => 8, AaMode::MsaaX8 => 8,
AaMode::MsaaX16 => 16, AaMode::MsaaX16 => 16,

View File

@ -105,7 +105,6 @@ impl FluidPipeline {
let samples = match aa_mode { let samples = match aa_mode {
AaMode::None | AaMode::Fxaa => 1, AaMode::None | AaMode::Fxaa => 1,
// TODO: Ensure sampling in the shader is exactly between the 4 texels // TODO: Ensure sampling in the shader is exactly between the 4 texels
AaMode::SsaaX4 => 1,
AaMode::MsaaX4 => 4, AaMode::MsaaX4 => 4,
AaMode::MsaaX8 => 8, AaMode::MsaaX8 => 8,
AaMode::MsaaX16 => 16, AaMode::MsaaX16 => 16,

View File

@ -35,6 +35,25 @@ pub struct LodData {
} }
impl LodData { impl LodData {
pub fn dummy(renderer: &mut Renderer) -> Self {
let map_size = Vec2::new(1, 1);
let map_border = [0.0, 0.0, 0.0, 0.0];
let map_image = [0];
let alt_image = [0];
let horizon_image = [0x_00_01_00_01];
//let map_border = [0.0, 0.0, 0.0, 0.0];
Self::new(
renderer,
map_size,
&map_image,
&alt_image,
&horizon_image,
1,
//map_border.into(),
)
}
pub fn new( pub fn new(
renderer: &mut Renderer, renderer: &mut Renderer,
map_size: Vec2<u32>, map_size: Vec2<u32>,
@ -44,7 +63,8 @@ impl LodData {
tgt_detail: u32, tgt_detail: u32,
//border_color: gfx::texture::PackedColor, //border_color: gfx::texture::PackedColor,
) -> Self { ) -> Self {
let mut texture_info = wgpu::TextureDescriptor { let mut create_texture = |format, data| {
let texture_info = wgpu::TextureDescriptor {
label: None, label: None,
size: wgpu::Extent3d { size: wgpu::Extent3d {
width: map_size.x, width: map_size.x,
@ -54,7 +74,7 @@ impl LodData {
mip_level_count: 1, mip_level_count: 1,
sample_count: 1, sample_count: 1,
dimension: wgpu::TextureDimension::D2, dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb, format,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
}; };
@ -70,9 +90,9 @@ impl LodData {
..Default::default() ..Default::default()
}; };
let mut view_info = wgpu::TextureViewDescriptor { let view_info = wgpu::TextureViewDescriptor {
label: None, label: None,
format: Some(wgpu::TextureFormat::Rgba8UnormSrgb), format: Some(format),
dimension: Some(wgpu::TextureViewDimension::D2), dimension: Some(wgpu::TextureViewDimension::D2),
aspect: wgpu::TextureAspect::All, aspect: wgpu::TextureAspect::All,
base_mip_level: 0, base_mip_level: 0,
@ -81,28 +101,16 @@ impl LodData {
array_layer_count: None, array_layer_count: None,
}; };
let map = renderer.create_texture_with_data_raw( renderer.create_texture_with_data_raw(
&texture_info, &texture_info,
&view_info, &view_info,
&sampler_info, &sampler_info,
bytemuck::cast_slice(lod_base), bytemuck::cast_slice(data),
); )
texture_info.format = wgpu::TextureFormat::Rg16Uint; };
view_info.format = Some(wgpu::TextureFormat::Rg16Uint); let map = create_texture(wgpu::TextureFormat::Rgba8UnormSrgb, lod_base);
let alt = renderer.create_texture_with_data_raw( let alt = create_texture(wgpu::TextureFormat::Rg16Uint, lod_alt);
&texture_info, let horizon = create_texture(wgpu::TextureFormat::Rgba8Unorm, lod_horizon);
&view_info,
&sampler_info,
bytemuck::cast_slice(lod_base),
);
texture_info.format = wgpu::TextureFormat::Rgba8Unorm;
view_info.format = Some(wgpu::TextureFormat::Rg16Uint);
let horizon = renderer.create_texture_with_data_raw(
&texture_info,
&view_info,
&sampler_info,
bytemuck::cast_slice(lod_base),
);
Self { Self {
map, map,
@ -173,7 +181,6 @@ impl LodTerrainPipeline {
let samples = match aa_mode { let samples = match aa_mode {
AaMode::None | AaMode::Fxaa => 1, AaMode::None | AaMode::Fxaa => 1,
// TODO: Ensure sampling in the shader is exactly between the 4 texels // TODO: Ensure sampling in the shader is exactly between the 4 texels
AaMode::SsaaX4 => 1,
AaMode::MsaaX4 => 4, AaMode::MsaaX4 => 4,
AaMode::MsaaX8 => 8, AaMode::MsaaX8 => 8,
AaMode::MsaaX16 => 16, AaMode::MsaaX16 => 16,

View File

@ -10,7 +10,7 @@ pub mod sprite;
pub mod terrain; pub mod terrain;
pub mod ui; pub mod ui;
use super::Consts; use super::{Consts, Texture};
use crate::scene::camera::CameraMode; use crate::scene::camera::CameraMode;
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use common::terrain::BlockKind; use common::terrain::BlockKind;
@ -225,6 +225,10 @@ pub struct GlobalModel {
pub shadow_mats: Consts<shadow::Locals>, pub shadow_mats: Consts<shadow::Locals>,
} }
pub struct GlobalsBindGroup {
pub(super) bind_group: wgpu::BindGroup,
}
pub struct GlobalsLayouts { pub struct GlobalsLayouts {
pub globals: wgpu::BindGroupLayout, pub globals: wgpu::BindGroupLayout,
} }
@ -315,7 +319,7 @@ impl GlobalsLayouts {
ty: wgpu::BindingType::Sampler { comparison: false }, ty: wgpu::BindingType::Sampler { comparison: false },
count: None, count: None,
}, },
// light shadows // light shadows (ie shadows from a light?)
wgpu::BindGroupLayoutEntry { wgpu::BindGroupLayoutEntry {
binding: 9, binding: 9,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
@ -382,4 +386,96 @@ impl GlobalsLayouts {
Self { globals } Self { globals }
} }
pub fn bind(
&self,
device: &wgpu::Device,
global_model: &GlobalModel,
lod_data: &lod_terrain::LodData,
noise: &Texture,
point_shadow_map: &Texture,
directed_shadow_map: &Texture,
) -> GlobalsBindGroup {
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &self.globals,
entries: &[
// Global uniform
wgpu::BindGroupEntry {
binding: 0,
resource: global_model.globals.buf().as_entire_binding(),
},
// Noise tex
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::TextureView(&noise.view),
},
wgpu::BindGroupEntry {
binding: 2,
resource: wgpu::BindingResource::Sampler(&noise.sampler),
},
// Light uniform
wgpu::BindGroupEntry {
binding: 3,
resource: global_model.lights.buf().as_entire_binding(),
},
// Shadow uniform
wgpu::BindGroupEntry {
binding: 4,
resource: global_model.shadows.buf().as_entire_binding(),
},
// Alt texture
wgpu::BindGroupEntry {
binding: 5,
resource: wgpu::BindingResource::TextureView(&lod_data.alt.view),
},
wgpu::BindGroupEntry {
binding: 6,
resource: wgpu::BindingResource::Sampler(&lod_data.alt.sampler),
},
// Horizon texture
wgpu::BindGroupEntry {
binding: 7,
resource: wgpu::BindingResource::TextureView(&lod_data.horizon.view),
},
wgpu::BindGroupEntry {
binding: 8,
resource: wgpu::BindingResource::Sampler(&lod_data.horizon.sampler),
},
// light shadows
wgpu::BindGroupEntry {
binding: 9,
resource: global_model.shadow_mats.buf().as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 10,
resource: wgpu::BindingResource::TextureView(&point_shadow_map.view),
},
wgpu::BindGroupEntry {
binding: 11,
resource: wgpu::BindingResource::Sampler(&point_shadow_map.sampler),
},
// directed shadow maps
wgpu::BindGroupEntry {
binding: 12,
resource: wgpu::BindingResource::TextureView(&directed_shadow_map.view),
},
wgpu::BindGroupEntry {
binding: 13,
resource: wgpu::BindingResource::Sampler(&directed_shadow_map.sampler),
},
// lod map (t_map)
wgpu::BindGroupEntry {
binding: 14,
resource: wgpu::BindingResource::TextureView(&lod_data.map.view),
},
wgpu::BindGroupEntry {
binding: 15,
resource: wgpu::BindingResource::Sampler(&lod_data.map.sampler),
},
],
});
GlobalsBindGroup { bind_group }
}
} }

View File

@ -189,7 +189,6 @@ impl ParticlePipeline {
let samples = match aa_mode { let samples = match aa_mode {
AaMode::None | AaMode::Fxaa => 1, AaMode::None | AaMode::Fxaa => 1,
// TODO: Ensure sampling in the shader is exactly between the 4 texels // TODO: Ensure sampling in the shader is exactly between the 4 texels
AaMode::SsaaX4 => 1,
AaMode::MsaaX4 => 4, AaMode::MsaaX4 => 4,
AaMode::MsaaX8 => 8, AaMode::MsaaX8 => 8,
AaMode::MsaaX16 => 16, AaMode::MsaaX16 => 16,

View File

@ -146,7 +146,6 @@ impl PostProcessPipeline {
let samples = match aa_mode { let samples = match aa_mode {
AaMode::None | AaMode::Fxaa => 1, AaMode::None | AaMode::Fxaa => 1,
// TODO: Ensure sampling in the shader is exactly between the 4 texels // TODO: Ensure sampling in the shader is exactly between the 4 texels
AaMode::SsaaX4 => 1,
AaMode::MsaaX4 => 4, AaMode::MsaaX4 => 4,
AaMode::MsaaX8 => 8, AaMode::MsaaX8 => 8,
AaMode::MsaaX16 => 16, AaMode::MsaaX16 => 16,

View File

@ -22,7 +22,6 @@ impl Locals {
pub fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) } pub fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) }
// TODO: unused?
fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout {
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None, label: None,
@ -131,7 +130,6 @@ impl ShadowFigurePipeline {
let samples = match aa_mode { let samples = match aa_mode {
AaMode::None | AaMode::Fxaa => 1, AaMode::None | AaMode::Fxaa => 1,
// TODO: Ensure sampling in the shader is exactly between the 4 texels // TODO: Ensure sampling in the shader is exactly between the 4 texels
AaMode::SsaaX4 => 1,
AaMode::MsaaX4 => 4, AaMode::MsaaX4 => 4,
AaMode::MsaaX8 => 8, AaMode::MsaaX8 => 8,
AaMode::MsaaX16 => 16, AaMode::MsaaX16 => 16,
@ -214,7 +212,6 @@ impl ShadowPipeline {
let samples = match aa_mode { let samples = match aa_mode {
AaMode::None | AaMode::Fxaa => 1, AaMode::None | AaMode::Fxaa => 1,
// TODO: Ensure sampling in the shader is exactly between the 4 texels // TODO: Ensure sampling in the shader is exactly between the 4 texels
AaMode::SsaaX4 => 1,
AaMode::MsaaX4 => 4, AaMode::MsaaX4 => 4,
AaMode::MsaaX8 => 8, AaMode::MsaaX8 => 8,
AaMode::MsaaX16 => 16, AaMode::MsaaX16 => 16,

View File

@ -46,7 +46,6 @@ impl SkyboxPipeline {
let samples = match aa_mode { let samples = match aa_mode {
AaMode::None | AaMode::Fxaa => 1, AaMode::None | AaMode::Fxaa => 1,
// TODO: Ensure sampling in the shader is exactly between the 4 texels // TODO: Ensure sampling in the shader is exactly between the 4 texels
AaMode::SsaaX4 => 1,
AaMode::MsaaX4 => 4, AaMode::MsaaX4 => 4,
AaMode::MsaaX8 => 8, AaMode::MsaaX8 => 8,
AaMode::MsaaX16 => 16, AaMode::MsaaX16 => 16,

View File

@ -176,7 +176,6 @@ impl SpriteLayout {
label: None, label: None,
entries: &[ entries: &[
// locals // locals
// TODO: different freq
wgpu::BindGroupLayoutEntry { wgpu::BindGroupLayoutEntry {
binding: 0, binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
@ -239,7 +238,6 @@ impl SpritePipeline {
let samples = match aa_mode { let samples = match aa_mode {
AaMode::None | AaMode::Fxaa => 1, AaMode::None | AaMode::Fxaa => 1,
// TODO: Ensure sampling in the shader is exactly between the 4 texels // TODO: Ensure sampling in the shader is exactly between the 4 texels
AaMode::SsaaX4 => 1,
AaMode::MsaaX4 => 4, AaMode::MsaaX4 => 4,
AaMode::MsaaX8 => 8, AaMode::MsaaX8 => 8,
AaMode::MsaaX16 => 16, AaMode::MsaaX16 => 16,

View File

@ -170,7 +170,6 @@ impl TerrainLayout {
count: None, count: None,
}, },
// col lights // col lights
// TODO: same frequency?
wgpu::BindGroupLayoutEntry { wgpu::BindGroupLayoutEntry {
binding: 1, binding: 1,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
@ -218,7 +217,6 @@ impl TerrainPipeline {
let samples = match aa_mode { let samples = match aa_mode {
AaMode::None | AaMode::Fxaa => 1, AaMode::None | AaMode::Fxaa => 1,
// TODO: Ensure sampling in the shader is exactly between the 4 texels // TODO: Ensure sampling in the shader is exactly between the 4 texels
AaMode::SsaaX4 => 1,
AaMode::MsaaX4 => 4, AaMode::MsaaX4 => 4,
AaMode::MsaaX8 => 8, AaMode::MsaaX8 => 8,
AaMode::MsaaX16 => 16, AaMode::MsaaX16 => 16,

View File

@ -1,4 +1,4 @@
use super::super::{AaMode, GlobalsLayouts, Quad, Tri}; use super::super::{AaMode, Consts, GlobalsLayouts, Quad, Texture, Tri};
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use vek::*; use vek::*;
@ -80,11 +80,20 @@ impl Mode {
} }
} }
pub struct UILayout { pub struct LocalsBindGroup {
pub locals: wgpu::BindGroupLayout, pub(in super::super) bind_group: wgpu::BindGroup,
} }
impl UILayout { pub struct TextureBindGroup {
pub(in super::super) bind_group: wgpu::BindGroup,
}
pub struct UiLayout {
pub locals: wgpu::BindGroupLayout,
pub texture: wgpu::BindGroupLayout,
}
impl UiLayout {
pub fn new(device: &wgpu::Device) -> Self { pub fn new(device: &wgpu::Device) -> Self {
Self { Self {
locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
@ -100,9 +109,14 @@ impl UILayout {
}, },
count: None, count: None,
}, },
],
}),
texture: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None,
entries: &[
// texture // texture
wgpu::BindGroupLayoutEntry { wgpu::BindGroupLayoutEntry {
binding: 1, binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::SampledTexture { ty: wgpu::BindingType::SampledTexture {
component_type: wgpu::TextureComponentType::Float, component_type: wgpu::TextureComponentType::Float,
@ -112,7 +126,7 @@ impl UILayout {
count: None, count: None,
}, },
wgpu::BindGroupLayoutEntry { wgpu::BindGroupLayoutEntry {
binding: 2, binding: 1,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::Sampler { comparison: false }, ty: wgpu::BindingType::Sampler { comparison: false },
count: None, count: None,
@ -121,33 +135,64 @@ impl UILayout {
}), }),
} }
} }
pub fn bind_locals(&self, device: &wgpu::Device, locals: &Consts<Locals>) -> LocalsBindGroup {
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &self.locals,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: locals.buf().as_entire_binding(),
}],
});
LocalsBindGroup { bind_group }
} }
pub struct UIPipeline { pub fn bind_texture(&self, device: &wgpu::Device, texture: &Texture) -> TextureBindGroup {
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &self.texture,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(&texture.view),
},
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::Sampler(&texture.sampler),
},
],
});
TextureBindGroup { bind_group }
}
}
pub struct UiPipeline {
pub pipeline: wgpu::RenderPipeline, pub pipeline: wgpu::RenderPipeline,
} }
impl UIPipeline { impl UiPipeline {
pub fn new( pub fn new(
device: &wgpu::Device, device: &wgpu::Device,
vs_module: &wgpu::ShaderModule, vs_module: &wgpu::ShaderModule,
fs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule,
sc_desc: &wgpu::SwapChainDescriptor, sc_desc: &wgpu::SwapChainDescriptor,
global_layout: &GlobalsLayouts, global_layout: &GlobalsLayouts,
layout: &UILayout, layout: &UiLayout,
aa_mode: AaMode, aa_mode: AaMode,
) -> Self { ) -> Self {
let render_pipeline_layout = let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("UI pipeline layout"), label: Some("Ui pipeline layout"),
push_constant_ranges: &[], push_constant_ranges: &[],
bind_group_layouts: &[&global_layout.globals, &layout.locals], bind_group_layouts: &[&global_layout.globals, &layout.locals, &layout.texture],
}); });
let samples = match aa_mode { let samples = match aa_mode {
AaMode::None | AaMode::Fxaa => 1, AaMode::None | AaMode::Fxaa => 1,
// TODO: Ensure sampling in the shader is exactly between the 4 texels // TODO: Ensure sampling in the shader is exactly between the 4 texels
AaMode::SsaaX4 => 1,
AaMode::MsaaX4 => 4, AaMode::MsaaX4 => 4,
AaMode::MsaaX8 => 8, AaMode::MsaaX8 => 8,
AaMode::MsaaX16 => 16, AaMode::MsaaX16 => 16,

View File

@ -1,3 +1,8 @@
mod bind_group;
mod drawer;
pub use drawer::{Drawer, UiDrawer};
use super::{ use super::{
consts::Consts, consts::Consts,
instances::Instances, instances::Instances,
@ -8,8 +13,8 @@ use super::{
ui, GlobalsLayouts, ui, GlobalsLayouts,
}, },
texture::Texture, texture::Texture,
AaMode, AddressMode, CloudMode, FilterMode, FluidMode, LightingMode, RenderError, RenderMode, AaMode, AddressMode, CloudMode, FilterMode, FluidMode, GlobalsBindGroup, LightingMode,
ShadowMapMode, ShadowMode, Vertex, RenderError, RenderMode, ShadowMapMode, ShadowMode, Vertex,
}; };
use common::assets::{self, AssetExt, AssetHandle}; use common::assets::{self, AssetExt, AssetHandle};
use common_base::span; use common_base::span;
@ -20,6 +25,7 @@ use vek::*;
/// A type representing data that can be converted to an immutable texture map /// A type representing data that can be converted to an immutable texture map
/// of ColLight data (used for texture atlases created during greedy meshing). /// of ColLight data (used for texture atlases created during greedy meshing).
// TODO: revert to u16
pub type ColLightInfo = (Vec<[u8; 4]>, Vec2<u32>); pub type ColLightInfo = (Vec<[u8; 4]>, Vec2<u32>);
/// Load from a GLSL file. /// Load from a GLSL file.
@ -116,9 +122,9 @@ impl Shaders {
pub struct ShadowMapRenderer { pub struct ShadowMapRenderer {
// directed_encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>, // directed_encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
// point_encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>, // point_encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
directed_depth_stencil: Texture, directed_depth: Texture,
point_depth_stencil: Texture, point_depth: Texture,
point_pipeline: shadow::ShadowPipeline, point_pipeline: shadow::ShadowPipeline,
terrain_directed_pipeline: shadow::ShadowPipeline, terrain_directed_pipeline: shadow::ShadowPipeline,
@ -128,6 +134,7 @@ pub struct ShadowMapRenderer {
/// A type that stores all the layouts associated with this renderer. /// A type that stores all the layouts associated with this renderer.
pub struct Layouts { pub struct Layouts {
// TODO: pub(self)??
pub(self) global: GlobalsLayouts, pub(self) global: GlobalsLayouts,
pub(self) clouds: clouds::CloudsLayout, pub(self) clouds: clouds::CloudsLayout,
@ -137,7 +144,7 @@ pub struct Layouts {
pub(self) shadow: shadow::ShadowLayout, pub(self) shadow: shadow::ShadowLayout,
pub(self) sprite: sprite::SpriteLayout, pub(self) sprite: sprite::SpriteLayout,
pub(self) terrain: terrain::TerrainLayout, pub(self) terrain: terrain::TerrainLayout,
pub(self) ui: ui::UILayout, pub(self) ui: ui::UiLayout,
} }
/// A type that encapsulates rendering state. `Renderer` is central to Voxygen's /// A type that encapsulates rendering state. `Renderer` is central to Voxygen's
@ -156,7 +163,7 @@ pub struct Renderer {
win_depth_view: wgpu::TextureView, win_depth_view: wgpu::TextureView,
tgt_color_view: wgpu::TextureView, tgt_color_view: wgpu::TextureView,
tgt_depth_stencil_view: wgpu::TextureView, tgt_depth_view: wgpu::TextureView,
// TODO: rename // TODO: rename
tgt_color_pp_view: wgpu::TextureView, tgt_color_pp_view: wgpu::TextureView,
@ -177,7 +184,7 @@ pub struct Renderer {
skybox_pipeline: skybox::SkyboxPipeline, skybox_pipeline: skybox::SkyboxPipeline,
sprite_pipeline: sprite::SpritePipeline, sprite_pipeline: sprite::SpritePipeline,
terrain_pipeline: terrain::TerrainPipeline, terrain_pipeline: terrain::TerrainPipeline,
ui_pipeline: ui::UIPipeline, ui_pipeline: ui::UiPipeline,
shaders: AssetHandle<Shaders>, shaders: AssetHandle<Shaders>,
@ -273,7 +280,7 @@ impl Renderer {
let shadow = shadow::ShadowLayout::new(&device); let shadow = shadow::ShadowLayout::new(&device);
let sprite = sprite::SpriteLayout::new(&device); let sprite = sprite::SpriteLayout::new(&device);
let terrain = terrain::TerrainLayout::new(&device); let terrain = terrain::TerrainLayout::new(&device);
let ui = ui::UILayout::new(&device); let ui = ui::UiLayout::new(&device);
Layouts { Layouts {
global, global,
@ -313,7 +320,7 @@ impl Renderer {
shadow_views.is_some(), shadow_views.is_some(),
)?; )?;
let (tgt_color_view, tgt_depth_stencil_view, tgt_color_pp_view, win_depth_view) = let (tgt_color_view, tgt_depth_view, tgt_color_pp_view, win_depth_view) =
Self::create_rt_views(&device, (dims.width, dims.height), &mode)?; Self::create_rt_views(&device, (dims.width, dims.height), &mode)?;
let shadow_map = if let ( let shadow_map = if let (
@ -327,16 +334,16 @@ impl Renderer {
figure_directed_shadow_pipeline, figure_directed_shadow_pipeline,
shadow_views, shadow_views,
) { ) {
let (point_depth_stencil, directed_depth_stencil) = shadow_views; let (point_depth, directed_depth) = shadow_views;
let layout = shadow::ShadowLayout::new(&device); let layout = shadow::ShadowLayout::new(&device);
Some(ShadowMapRenderer { Some(ShadowMapRenderer {
directed_depth_stencil, directed_depth,
// point_encoder: factory.create_command_buffer().into(), // point_encoder: factory.create_command_buffer().into(),
// directed_encoder: factory.create_command_buffer().into(), // directed_encoder: factory.create_command_buffer().into(),
point_depth_stencil, point_depth,
point_pipeline, point_pipeline,
terrain_directed_pipeline, terrain_directed_pipeline,
@ -378,7 +385,7 @@ impl Renderer {
win_depth_view, win_depth_view,
tgt_color_view, tgt_color_view,
tgt_depth_stencil_view, tgt_depth_view,
tgt_color_pp_view, tgt_color_pp_view,
sampler, sampler,
@ -411,7 +418,7 @@ impl Renderer {
/// before post-processing. /// before post-processing.
#[allow(dead_code)] #[allow(dead_code)]
pub fn tgt_views(&self) -> (&wgpu::TextureView, &wgpu::TextureView) { pub fn tgt_views(&self) -> (&wgpu::TextureView, &wgpu::TextureView) {
(&self.tgt_color_view, &self.tgt_depth_stencil_view) (&self.tgt_color_view, &self.tgt_depth_view)
} }
/// Get references to the internal render target views that get displayed /// Get references to the internal render target views that get displayed
@ -446,19 +453,19 @@ impl Renderer {
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc); self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
// Resize other render targets // Resize other render targets
let (tgt_color_view, tgt_depth_stencil_view, tgt_color_pp_view, win_depth_view) = let (tgt_color_view, tgt_depth_view, tgt_color_pp_view, win_depth_view) =
Self::create_rt_views(&mut self.device, (dims.x, dims.y), &self.mode)?; Self::create_rt_views(&mut self.device, (dims.x, dims.y), &self.mode)?;
self.win_depth_view = win_depth_view; self.win_depth_view = win_depth_view;
self.tgt_color_view = tgt_color_view; self.tgt_color_view = tgt_color_view;
self.tgt_depth_stencil_view = tgt_depth_stencil_view; self.tgt_depth_view = tgt_depth_view;
self.tgt_color_pp_view = tgt_color_pp_view; self.tgt_color_pp_view = tgt_color_pp_view;
if let (Some(shadow_map), ShadowMode::Map(mode)) = if let (Some(shadow_map), ShadowMode::Map(mode)) =
(self.shadow_map.as_mut(), self.mode.shadow) (self.shadow_map.as_mut(), self.mode.shadow)
{ {
match Self::create_shadow_views(&mut self.device, (dims.x, dims.y), &mode) { match Self::create_shadow_views(&mut self.device, (dims.x, dims.y), &mode) {
Ok((point_depth_stencil, directed_depth_stencil)) => { Ok((point_depth, directed_depth)) => {
shadow_map.point_depth_stencil = point_depth_stencil; shadow_map.point_depth = point_depth;
shadow_map.directed_depth_stencil = directed_depth_stencil; shadow_map.directed_depth = directed_depth;
}, },
Err(err) => { Err(err) => {
warn!("Could not create shadow map views: {:?}", err); warn!("Could not create shadow map views: {:?}", err);
@ -496,7 +503,7 @@ impl Renderer {
}; };
let levels = 1; let levels = 1;
let mut color_view = || { let color_view = || {
let tex = device.create_texture(&wgpu::TextureDescriptor { let tex = device.create_texture(&wgpu::TextureDescriptor {
label: None, label: None,
size: wgpu::Extent3d { size: wgpu::Extent3d {
@ -527,7 +534,7 @@ impl Renderer {
let tgt_color_view = color_view(); let tgt_color_view = color_view();
let tgt_color_pp_view = color_view(); let tgt_color_pp_view = color_view();
let tgt_depth_stencil_tex = device.create_texture(&wgpu::TextureDescriptor { let tgt_depth_tex = device.create_texture(&wgpu::TextureDescriptor {
label: None, label: None,
size: wgpu::Extent3d { size: wgpu::Extent3d {
width, width,
@ -540,8 +547,7 @@ impl Renderer {
format: wgpu::TextureFormat::Depth24Plus, format: wgpu::TextureFormat::Depth24Plus,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT,
}); });
let tgt_depth_stencil_view = let tgt_depth_view = tgt_depth_tex.create_view(&wgpu::TextureViewDescriptor {
tgt_depth_stencil_tex.create_view(&wgpu::TextureViewDescriptor {
label: None, label: None,
format: Some(wgpu::TextureFormat::Depth24Plus), format: Some(wgpu::TextureFormat::Depth24Plus),
dimension: Some(wgpu::TextureViewDimension::D2), dimension: Some(wgpu::TextureViewDimension::D2),
@ -565,7 +571,7 @@ impl Renderer {
format: wgpu::TextureFormat::Depth24Plus, format: wgpu::TextureFormat::Depth24Plus,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT, usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
}); });
let win_depth_view = tgt_depth_stencil_tex.create_view(&wgpu::TextureViewDescriptor { let win_depth_view = tgt_depth_tex.create_view(&wgpu::TextureViewDescriptor {
label: None, label: None,
format: Some(wgpu::TextureFormat::Depth24Plus), format: Some(wgpu::TextureFormat::Depth24Plus),
dimension: Some(wgpu::TextureViewDimension::D2), dimension: Some(wgpu::TextureViewDimension::D2),
@ -578,7 +584,7 @@ impl Renderer {
Ok(( Ok((
tgt_color_view, tgt_color_view,
tgt_depth_stencil_view, tgt_depth_view,
tgt_color_pp_view, tgt_color_pp_view,
win_depth_view, win_depth_view,
)) ))
@ -656,7 +662,7 @@ impl Renderer {
}; };
//TODO: (0, levels - 1), ?? from master //TODO: (0, levels - 1), ?? from master
let mut point_shadow_view = wgpu::TextureViewDescriptor { let point_shadow_view = wgpu::TextureViewDescriptor {
label: None, label: None,
format: Some(wgpu::TextureFormat::Depth24Plus), format: Some(wgpu::TextureFormat::Depth24Plus),
dimension: Some(wgpu::TextureViewDimension::Cube), dimension: Some(wgpu::TextureViewDimension::Cube),
@ -723,8 +729,8 @@ impl Renderer {
pub fn get_shadow_resolution(&self) -> (Vec2<u32>, Vec2<u32>) { pub fn get_shadow_resolution(&self) -> (Vec2<u32>, Vec2<u32>) {
if let Some(shadow_map) = &self.shadow_map { if let Some(shadow_map) = &self.shadow_map {
( (
shadow_map.point_depth_stencil.get_dimensions().xy(), shadow_map.point_depth.get_dimensions().xy(),
shadow_map.directed_depth_stencil.get_dimensions().xy(), shadow_map.directed_depth.get_dimensions().xy(),
) )
} else { } else {
(Vec2::new(1, 1), Vec2::new(1, 1)) (Vec2::new(1, 1), Vec2::new(1, 1))
@ -741,10 +747,10 @@ impl Renderer {
// if let Some(shadow_map) = self.shadow_map.as_mut() { // if let Some(shadow_map) = self.shadow_map.as_mut() {
// // let point_encoder = &mut shadow_map.point_encoder; // // let point_encoder = &mut shadow_map.point_encoder;
// let point_encoder = &mut self.encoder; // let point_encoder = &mut self.encoder;
// point_encoder.clear_depth(&shadow_map.point_depth_stencil_view, 1.0); // point_encoder.clear_depth(&shadow_map.point_depth_view, 1.0);
// // let directed_encoder = &mut shadow_map.directed_encoder; // // let directed_encoder = &mut shadow_map.directed_encoder;
// let directed_encoder = &mut self.encoder; // let directed_encoder = &mut self.encoder;
// directed_encoder.clear_depth(&shadow_map.directed_depth_stencil_view, // directed_encoder.clear_depth(&shadow_map.directed_depth_view,
// 1.0); } // 1.0); }
// } // }
@ -802,51 +808,20 @@ impl Renderer {
// } // }
// } // }
/// Perform all queued draw calls for this frame and clean up discarded /// Start recording the frame
/// items. /// When the returned `Drawer` is dropped the recorded draw calls will be
pub fn flush(&mut self) -> Result<(), RenderError> { /// submitted to the queue
span!(_guard, "flush", "Renderer::flush"); /// If there is an intermittent issue with the swap chain then Ok(None) will
let frame = match self.swap_chain.get_current_frame() { /// be returned
Ok(frame) => frame.output, pub fn start_recording_frame<'a>(
// If lost recreate the swap chain &'a mut self,
Err(err @ wgpu::SwapChainError::Lost) => { globals: &'a GlobalsBindGroup,
warn!("{}. Recreating swap chain. A frame will be missed", err); ) -> Result<Option<Drawer<'a>>, RenderError> {
return self.on_resize(self.resolution); span!(
}, _guard,
Err(err @ wgpu::SwapChainError::Timeout) => { "start_recording_frame",
warn!("{}. This will probably be resolved on the next frame", err); "Renderer::start_recording_frame"
return Ok(()); );
},
Err(err @ wgpu::SwapChainError::Outdated) => {
warn!("{}. This will probably be resolved on the next frame", err);
return Ok(());
},
Err(err @ wgpu::SwapChainError::OutOfMemory) => return Err(err.into()),
};
let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("A render encoder"),
});
{
let _render_pas = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &frame.view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
r: 0.1,
g: 0.7,
b: 0.3,
a: 1.0,
}),
store: true,
},
}],
depth_stencil_attachment: None,
});
}
self.queue.submit(std::iter::once(encoder.finish()));
self.device.poll(wgpu::Maintain::Poll); self.device.poll(wgpu::Maintain::Poll);
@ -855,7 +830,30 @@ impl Renderer {
self.recreate_pipelines(); self.recreate_pipelines();
} }
Ok(()) let tex = match self.swap_chain.get_current_frame() {
Ok(frame) => frame.output,
// If lost recreate the swap chain
Err(err @ wgpu::SwapChainError::Lost) => {
warn!("{}. Recreating swap chain. A frame will be missed", err);
return self.on_resize(self.resolution).map(|()| None);
},
Err(err @ wgpu::SwapChainError::Timeout) => {
warn!("{}. This will probably be resolved on the next frame", err);
return Ok(None);
},
Err(err @ wgpu::SwapChainError::Outdated) => {
warn!("{}. This will probably be resolved on the next frame", err);
return Ok(None);
},
Err(err @ wgpu::SwapChainError::OutOfMemory) => return Err(err.into()),
};
let encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("A render encoder"),
});
Ok(Some(Drawer::new(encoder, self, tex, globals)))
} }
/// Recreate the pipelines /// Recreate the pipelines
@ -916,14 +914,10 @@ impl Renderer {
} }
/// Create a new set of constants with the provided values. /// Create a new set of constants with the provided values.
pub fn create_consts<T: Copy + bytemuck::Pod>( pub fn create_consts<T: Copy + bytemuck::Pod>(&mut self, vals: &[T]) -> Consts<T> {
&mut self,
vals: &[T],
// TODO: don't use result here
) -> Result<Consts<T>, RenderError> {
let mut consts = Consts::new(&self.device, vals.len()); let mut consts = Consts::new(&self.device, vals.len());
consts.update(&self.device, &self.queue, vals, 0); consts.update(&self.device, &self.queue, vals, 0);
Ok(consts) consts
} }
/// Update a set of constants with the provided values. /// Update a set of constants with the provided values.
@ -1134,8 +1128,8 @@ impl Renderer {
// self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(),
// lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(),
// lod.horizon.sampler.clone()), tgt_color: // lod.horizon.sampler.clone()), tgt_color:
// self.tgt_color_view.clone(), tgt_depth_stencil: // self.tgt_color_view.clone(), tgt_depth:
// (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, // (self.tgt_depth_view.clone()/* , (1, 1) */), },
// ); // );
// } // }
@ -1193,8 +1187,8 @@ impl Renderer {
// self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(),
// lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(),
// lod.horizon.sampler.clone()), tgt_color: // lod.horizon.sampler.clone()), tgt_color:
// self.tgt_color_view.clone(), tgt_depth_stencil: // self.tgt_color_view.clone(), tgt_depth:
// (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, // (self.tgt_depth_view.clone()/* , (1, 1) */), },
// ); // );
// } // }
@ -1253,8 +1247,8 @@ impl Renderer {
// self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(),
// lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(),
// lod.horizon.sampler.clone()), tgt_color: // lod.horizon.sampler.clone()), tgt_color:
// self.tgt_color_view.clone(), tgt_depth_stencil: // self.tgt_color_view.clone(), tgt_depth:
// (self.tgt_depth_stencil_view.clone()/* , (0, 0) */), }, // (self.tgt_depth_view.clone()/* , (0, 0) */), },
// ); */ // ); */
// } // }
@ -1312,8 +1306,8 @@ impl Renderer {
// self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(),
// lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(),
// lod.horizon.sampler.clone()), tgt_color: // lod.horizon.sampler.clone()), tgt_color:
// self.tgt_color_view.clone(), tgt_depth_stencil: // self.tgt_color_view.clone(), tgt_depth:
// (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, // (self.tgt_depth_view.clone()/* , (1, 1) */), },
// ); // );
// } // }
@ -1371,8 +1365,8 @@ impl Renderer {
// self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(),
// lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(),
// lod.horizon.sampler.clone()), tgt_color: // lod.horizon.sampler.clone()), tgt_color:
// self.tgt_color_view.clone(), tgt_depth_stencil: // self.tgt_color_view.clone(), tgt_depth:
// (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, // (self.tgt_depth_view.clone()/* , (1, 1) */), },
// ); // );
// } // }
@ -1414,7 +1408,7 @@ impl Renderer {
// // Shadow stuff // // Shadow stuff
// light_shadows: locals.buf.clone(), // light_shadows: locals.buf.clone(),
// tgt_depth_stencil: shadow_map.point_depth_stencil_view.clone(), // tgt_depth: shadow_map.point_depth_view.clone(),
// }, // },
// ); // );
// } // }
@ -1457,8 +1451,8 @@ impl Renderer {
// // Shadow stuff // // Shadow stuff
// light_shadows: locals.buf.clone(), // light_shadows: locals.buf.clone(),
// tgt_depth_stencil: // tgt_depth:
// shadow_map.directed_depth_stencil_view.clone(), }, // shadow_map.directed_depth_view.clone(), },
// ); // );
// } // }
@ -1503,8 +1497,8 @@ impl Renderer {
// // Shadow stuff // // Shadow stuff
// light_shadows: locals.buf.clone(), // light_shadows: locals.buf.clone(),
// tgt_depth_stencil: // tgt_depth:
// shadow_map.directed_depth_stencil_view.clone(), }, // shadow_map.directed_depth_view.clone(), },
// ); // );
// } // }
@ -1560,8 +1554,8 @@ impl Renderer {
// noise: (self.noise_tex.srv.clone(), // noise: (self.noise_tex.srv.clone(),
// self.noise_tex.sampler.clone()), waves: (waves.srv.clone(), // self.noise_tex.sampler.clone()), waves: (waves.srv.clone(),
// waves.sampler.clone()), tgt_color: // waves.sampler.clone()), tgt_color:
// self.tgt_color_view.clone(), tgt_depth_stencil: // self.tgt_color_view.clone(), tgt_depth:
// (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, // (self.tgt_depth_view.clone()/* , (1, 1) */), },
// ); // );
// } // }
@ -1625,8 +1619,8 @@ impl Renderer {
// self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(),
// lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(),
// lod.horizon.sampler.clone()), tgt_color: // lod.horizon.sampler.clone()), tgt_color:
// self.tgt_color_view.clone(), tgt_depth_stencil: // self.tgt_color_view.clone(), tgt_depth:
// (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, // (self.tgt_depth_view.clone()/* , (1, 1) */), },
// ); // );
// } // }
@ -1657,8 +1651,8 @@ impl Renderer {
// lod.map.sampler.clone()), alt: (lod.alt.srv.clone(), // lod.map.sampler.clone()), alt: (lod.alt.srv.clone(),
// lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(),
// lod.horizon.sampler.clone()), tgt_color: // lod.horizon.sampler.clone()), tgt_color:
// self.tgt_color_view.clone(), tgt_depth_stencil: // self.tgt_color_view.clone(), tgt_depth:
// (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, // (self.tgt_depth_view.clone()/* , (1, 1) */), },
// ); // );
// } // }
@ -1711,8 +1705,8 @@ impl Renderer {
// self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(),
// lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(),
// lod.horizon.sampler.clone()), tgt_color: // lod.horizon.sampler.clone()), tgt_color:
// self.tgt_color_view.clone(), tgt_depth_stencil: // self.tgt_color_view.clone(), tgt_depth:
// (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, // (self.tgt_depth_view.clone()/* , (1, 1) */), },
// ); // );
// } // }
@ -1836,7 +1830,7 @@ fn create_pipelines(
fluid::FluidPipeline, fluid::FluidPipeline,
sprite::SpritePipeline, sprite::SpritePipeline,
particle::ParticlePipeline, particle::ParticlePipeline,
ui::UIPipeline, ui::UiPipeline,
lod_terrain::LodTerrainPipeline, lod_terrain::LodTerrainPipeline,
clouds::CloudsPipeline, clouds::CloudsPipeline,
postprocess::PostProcessPipeline, postprocess::PostProcessPipeline,
@ -2029,7 +2023,7 @@ fn create_pipelines(
); );
// Construct a pipeline for rendering UI elements // Construct a pipeline for rendering UI elements
let ui_pipeline = ui::UIPipeline::new( let ui_pipeline = ui::UiPipeline::new(
device, device,
&create_shader("ui-vert", ShaderKind::Vertex)?, &create_shader("ui-vert", ShaderKind::Vertex)?,
&create_shader("ui-frag", ShaderKind::Fragment)?, &create_shader("ui-frag", ShaderKind::Fragment)?,
@ -2077,7 +2071,7 @@ fn create_pipelines(
// let player_shadow_pipeline = create_pipeline( // let player_shadow_pipeline = create_pipeline(
// factory, // factory,
// figure::pipe::Init { // figure::pipe::Init {
// tgt_depth_stencil: (gfx::preset::depth::PASS_TEST/*, // tgt_depth: (gfx::preset::depth::PASS_TEST/*,
// Stencil::new( // Stencil::new(
// Comparison::Equal, // Comparison::Equal,
// 0xff, // 0xff,

View File

@ -0,0 +1,38 @@
use super::{
super::{
consts::Consts,
pipelines::{lod_terrain, ui, GlobalModel, GlobalsBindGroup},
texture::Texture,
},
Renderer,
};
impl Renderer {
pub fn bind_globals(
&self,
global_model: &GlobalModel,
lod_data: &lod_terrain::LodData,
) -> GlobalsBindGroup {
let (point_shadow_map, directed_shadow_map) = match &self.shadow_map {
Some(shadow_map) => (&shadow_map.point_depth, &shadow_map.directed_depth),
None => (&self.noise_tex, &self.noise_tex),
};
self.layouts.global.bind(
&self.device,
global_model,
lod_data,
&self.noise_tex,
point_shadow_map,
directed_shadow_map,
)
}
pub fn ui_bind_locals(&self, locals: &Consts<ui::Locals>) -> ui::LocalsBindGroup {
self.layouts.ui.bind_locals(&self.device, locals)
}
pub fn ui_bind_texture(&self, texture: &Texture) -> ui::TextureBindGroup {
self.layouts.ui.bind_texture(&self.device, texture)
}
}

View File

@ -0,0 +1,360 @@
use super::{
super::{
buffer::Buffer,
consts::Consts,
instances::Instances,
model::{DynamicModel, Model},
pipelines::{
figure, fluid, postprocess, sprite, terrain, ui, GlobalsBindGroup, Light, Shadow,
},
},
Renderer,
};
use std::ops::Range;
use vek::Aabr;
pub struct Drawer<'a> {
encoder: Option<wgpu::CommandEncoder>,
renderer: &'a mut Renderer,
tex: wgpu::SwapChainTexture,
globals: &'a GlobalsBindGroup,
//pub(super) postprocess_locals: wgpu::BindGroup,
}
impl<'a> Drawer<'a> {
pub fn new(
encoder: wgpu::CommandEncoder,
renderer: &'a mut Renderer,
tex: wgpu::SwapChainTexture,
globals: &'a GlobalsBindGroup,
) -> Self {
Self {
encoder: Some(encoder),
renderer,
tex,
globals,
}
}
/*pub fn first_pass(&mut self) -> FirstPassDrawer {
let render_pass =
self.encoder
.as_mut()
.unwrap()
.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &self.renderer.tgt_color_view,
resolve_target: None,
load_op: wgpu::LoadOp::Clear,
store_op: wgpu::StoreOp::Store,
clear_color: wgpu::Color::TRANSPARENT,
}],
depth_stencil_attachment: Some(
wgpu::RenderPassDepthStencilAttachmentDescriptor {
attachment: &self.renderer.depth_stencil_texture.view,
depth_load_op: wgpu::LoadOp::Clear,
depth_store_op: wgpu::StoreOp::Store,
clear_depth: 1.0,
stencil_load_op: wgpu::LoadOp::Clear,
stencil_store_op: wgpu::StoreOp::Store,
clear_stencil: 0,
},
),
});
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
FirstPassDrawer {
render_pass,
renderer: &self.renderer,
}
}
pub fn second_pass(&mut self) -> SecondPassDrawer {
let render_pass =
self.encoder
.as_mut()
.unwrap()
.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &self.renderer.tgt_color_pp_view,
resolve_target: None,
load_op: wgpu::LoadOp::Clear,
store_op: wgpu::StoreOp::Store,
clear_color: wgpu::Color::TRANSPARENT,
}],
depth_stencil_attachment: None,
});
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
SecondPassDrawer {
render_pass,
renderer: &self.renderer,
}
}*/
pub fn third_pass(&mut self) -> ThirdPassDrawer {
let mut render_pass =
self.encoder
.as_mut()
.unwrap()
.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &self.tex.view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
r: 1.0,
g: 0.25,
b: 0.5,
a: 0.5,
}),
store: true,
},
}],
// TODO: do we need this?
depth_stencil_attachment: Some(
wgpu::RenderPassDepthStencilAttachmentDescriptor {
attachment: &self.renderer.win_depth_view,
depth_ops: Some(wgpu::Operations {
load: wgpu::LoadOp::Clear(1.0),
store: true,
}),
stencil_ops: None,
},
),
});
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
ThirdPassDrawer {
render_pass,
renderer: &self.renderer,
//postprocess_locals: &self.postprocess_locals,
}
}
}
impl<'a> Drop for Drawer<'a> {
fn drop(&mut self) {
self.renderer
.queue
.submit(std::iter::once(self.encoder.take().unwrap().finish()));
}
}
/*pub struct FirstPassDrawer<'a> {
pub(super) render_pass: wgpu::RenderPass<'a>,
pub renderer: &'a Renderer,
}
impl<'a> FirstPassDrawer<'a> {
pub fn draw_skybox<'b: 'a>(
&mut self,
model: &'b Model,
globals: &'b Consts<Globals>,
verts: Range<u32>,
) {
self.render_pass
.set_pipeline(&self.renderer.skybox_pipeline.pipeline);
self.render_pass.set_bind_group(0, &globals.bind_group, &[]);
self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0);
self.render_pass.draw(verts, 0..1);
}
pub fn draw_figure<'b: 'a>(
&mut self,
model: &'b Model,
locals: &'b Consts<figure::Locals>,
bones: &'b Consts<figure::BoneData>,
globals: &'b Consts<Globals>,
lights: &'b Consts<Light>,
shadows: &'b Consts<Shadow>,
verts: Range<u32>,
) {
self.render_pass
.set_pipeline(&self.renderer.figure_pipeline.pipeline);
self.render_pass.set_bind_group(0, &globals.bind_group, &[]);
self.render_pass.set_bind_group(1, &lights.bind_group, &[]);
self.render_pass.set_bind_group(2, &shadows.bind_group, &[]);
self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
self.render_pass.set_bind_group(4, &bones.bind_group, &[]);
self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0);
self.render_pass.draw(verts, 0..1);
}
pub fn draw_terrain<'b: 'a>(
&mut self,
model: &'b Model,
locals: &'b Consts<terrain::Locals>,
globals: &'b Consts<Globals>,
lights: &'b Consts<Light>,
shadows: &'b Consts<Shadow>,
verts: Range<u32>,
) {
self.render_pass
.set_pipeline(&self.renderer.terrain_pipeline.pipeline);
self.render_pass.set_bind_group(0, &globals.bind_group, &[]);
self.render_pass.set_bind_group(1, &lights.bind_group, &[]);
self.render_pass.set_bind_group(2, &shadows.bind_group, &[]);
self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0);
self.render_pass.draw(verts, 0..1)
}
pub fn draw_fluid<'b: 'a>(
&mut self,
model: &'b Model,
locals: &'b Consts<terrain::Locals>,
waves: &'b Consts<fluid::Locals>,
globals: &'b Consts<Globals>,
lights: &'b Consts<Light>,
shadows: &'b Consts<Shadow>,
verts: Range<u32>,
) {
self.render_pass
.set_pipeline(&self.renderer.fluid_pipeline.pipeline);
self.render_pass.set_bind_group(0, &globals.bind_group, &[]);
self.render_pass.set_bind_group(1, &lights.bind_group, &[]);
self.render_pass.set_bind_group(2, &shadows.bind_group, &[]);
self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
self.render_pass.set_bind_group(4, &waves.bind_group, &[]);
self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0);
self.render_pass.draw(verts, 0..1);
}
pub fn draw_sprite<'b: 'a>(
&mut self,
model: &'b Model,
instances: &'a Instances<sprite::Instance>,
globals: &'b Consts<Globals>,
lights: &'b Consts<Light>,
shadows: &'b Consts<Shadow>,
verts: Range<u32>,
) {
self.render_pass
.set_pipeline(&self.renderer.sprite_pipeline.pipeline);
self.render_pass.set_bind_group(0, &globals.bind_group, &[]);
self.render_pass.set_bind_group(1, &lights.bind_group, &[]);
self.render_pass.set_bind_group(2, &shadows.bind_group, &[]);
self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0);
self.render_pass.set_vertex_buffer(1, &instances.ibuf, 0, 0);
self.render_pass.draw(verts, 0..instances.count() as u32);
}
}
pub struct SecondPassDrawer<'a> {
pub(super) render_pass: wgpu::RenderPass<'a>,
pub renderer: &'a Renderer,
}
impl<'a> SecondPassDrawer<'a> {
pub fn draw_post_process<'b: 'a>(
&mut self,
model: &'b Model,
globals: &'b Consts<Globals>,
verts: Range<u32>,
) {
self.render_pass
.set_pipeline(&self.renderer.postprocess_pipeline.pipeline);
self.render_pass.set_bind_group(0, &globals.bind_group, &[]);
self.render_pass
.set_bind_group(1, self.postprocess_locals, &[]);
self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0);
self.render_pass.draw(verts, 0..1);
}
}*/
pub struct ThirdPassDrawer<'a> {
render_pass: wgpu::RenderPass<'a>,
renderer: &'a Renderer,
//postprocess_locals: &'a wgpu::BindGroup,
}
impl<'a> ThirdPassDrawer<'a> {
pub fn draw_post_process<'b: 'a>(
&mut self,
model: &'b Model<postprocess::Vertex>,
verts: Range<u32>,
) {
self.render_pass
.set_pipeline(&self.renderer.postprocess_pipeline.pipeline);
//self.render_pass
// .set_bind_group(1, self.postprocess_locals, &[]);
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
self.render_pass.draw(verts, 0..1);
}
pub fn draw_ui<'c>(&'c mut self) -> UiDrawer<'c, 'a> {
self.render_pass
.set_pipeline(&self.renderer.ui_pipeline.pipeline);
UiDrawer {
render_pass: &mut self.render_pass,
}
}
}
pub struct UiDrawer<'pass_ref, 'pass: 'pass_ref> {
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
}
pub struct PreparedUiDrawer<'pass_ref, 'pass: 'pass_ref> {
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
}
impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> {
/// Set vertex buffer, initial scissor, and locals
/// These can be changed later but this ensures that they don't have to be
/// set with every draw call
pub fn prepare<'data: 'pass>(
&mut self,
locals: &'data ui::LocalsBindGroup,
//texture: &'b ui::TextureBindGroup,
buf: &'data DynamicModel<ui::Vertex>,
scissor: Aabr<u16>,
) -> PreparedUiDrawer<'_, 'pass> {
// Note: not actually prepared yet
// we do this to avoid having to write extra code for the set functions
let mut prepared = PreparedUiDrawer {
render_pass: self.render_pass,
};
// Prepare
prepared.set_locals(locals);
//prepared.set_texture(texture);
prepared.set_model(buf);
prepared.set_scissor(scissor);
prepared
}
}
impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> {
pub fn set_locals<'data: 'pass>(&mut self, locals: &'data ui::LocalsBindGroup) {
self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
}
//pub fn set_texture<'b: 'a>(&mut self, texture: &'b ui::TextureBindGroup) {
// self.render_pass.set_bind_group(1, &texture.bind_group, &[]);
//}
pub fn set_model<'data: 'pass>(&mut self, model: &'data DynamicModel<ui::Vertex>) {
self.render_pass.set_vertex_buffer(0, model.buf().slice(..))
}
pub fn set_scissor<'data: 'pass>(&mut self, scissor: Aabr<u16>) {
let Aabr { min, max } = scissor;
//self.render_pass.set_scissor_rect(
// min.x as u32,
// min.y as u32,
// (max.x - min.x) as u32,
// (max.y - min.y) as u32,
//);
}
pub fn draw<'data: 'pass>(&mut self, texture: &'data ui::TextureBindGroup, verts: Range<u32>) {
self.render_pass.set_bind_group(2, &texture.bind_group, &[]);
self.render_pass.draw(verts, 0..1);
}
}

View File

@ -179,7 +179,7 @@ impl Texture {
data: &[u8], data: &[u8],
) { ) {
// Note: we only accept 4 bytes per pixel // Note: we only accept 4 bytes per pixel
// (enforce this is API?) // (enforce this in API?)
debug_assert_eq!(data.len(), size[0] as usize * size[1] as usize * 4); debug_assert_eq!(data.len(), size[0] as usize * size[1] as usize * 4);
// TODO: Only works for 2D images // TODO: Only works for 2D images
queue.write_texture( queue.write_texture(

View File

@ -176,7 +176,7 @@ fn handle_main_events_cleared(
last.render(renderer, &global_state.settings); last.render(renderer, &global_state.settings);
// Finish the frame. // Finish the frame.
// TODO: do this as part of dropping rendering thing // TODO: do this as part of dropping rendering thing
global_state.window.renderer_mut().flush().unwrap(); //global_state.window.renderer_mut().flush().unwrap();
// // Display the frame on the window. // // Display the frame on the window.
// global_state // global_state
// .window // .window

View File

@ -8,13 +8,13 @@ use crate::{
ecs::comp::Interpolated, ecs::comp::Interpolated,
render::{ render::{
pipelines, ColLightInfo, Consts, FigureBoneData, FigureLocals, FigureModel, GlobalModel, pipelines, ColLightInfo, Consts, FigureBoneData, FigureLocals, FigureModel, GlobalModel,
Mesh, RenderError, Renderer, SubModel, TerrainVertex, Texture, LodData, Mesh, RenderError, Renderer, SubModel, TerrainVertex, Texture,
}, },
scene::{ scene::{
camera::{Camera, CameraMode, Dependents}, camera::{Camera, CameraMode, Dependents},
math, math,
terrain::Terrain, terrain::Terrain,
LodData, SceneData, SceneData,
}, },
}; };
use anim::{ use anim::{
@ -5352,8 +5352,8 @@ impl<S: Skeleton> FigureState<S> {
let bone_consts = figure_bone_data_from_anim(&buf); let bone_consts = figure_bone_data_from_anim(&buf);
Self { Self {
meta: FigureStateMeta { meta: FigureStateMeta {
bone_consts: renderer.create_consts(bone_consts).unwrap(), bone_consts: renderer.create_consts(bone_consts),
locals: renderer.create_consts(&[FigureLocals::default()]).unwrap(), locals: renderer.create_consts(&[FigureLocals::default()]),
lantern_offset, lantern_offset,
state_time: 0.0, state_time: 0.0,
last_ori: Ori::default().into(), last_ori: Ori::default().into(),

View File

@ -17,8 +17,8 @@ use crate::{
audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend}, audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend},
render::{ render::{
create_clouds_mesh, create_pp_mesh, create_skybox_mesh, CloudsLocals, CloudsVertex, Consts, create_clouds_mesh, create_pp_mesh, create_skybox_mesh, CloudsLocals, CloudsVertex, Consts,
GlobalModel, Globals, Light, LodData, Model, PostProcessLocals, PostProcessVertex, GlobalModel, Globals, Light, Model, PostProcessLocals, PostProcessVertex, Renderer, Shadow,
Renderer, Shadow, ShadowLocals, SkyboxVertex, ShadowLocals, SkyboxVertex,
}, },
settings::Settings, settings::Settings,
window::{AnalogGameInput, Event}, window::{AnalogGameInput, Event},
@ -277,16 +277,11 @@ impl Scene {
Self { Self {
data: GlobalModel { data: GlobalModel {
globals: renderer.create_consts(&[Globals::default()]).unwrap(), globals: renderer.create_consts(&[Globals::default()]),
lights: renderer lights: renderer.create_consts(&[Light::default(); MAX_LIGHT_COUNT]),
.create_consts(&[Light::default(); MAX_LIGHT_COUNT]) shadows: renderer.create_consts(&[Shadow::default(); MAX_SHADOW_COUNT]),
.unwrap(),
shadows: renderer
.create_consts(&[Shadow::default(); MAX_SHADOW_COUNT])
.unwrap(),
shadow_mats: renderer shadow_mats: renderer
.create_consts(&[ShadowLocals::default(); MAX_LIGHT_COUNT * 6 + 6]) .create_consts(&[ShadowLocals::default(); MAX_LIGHT_COUNT * 6 + 6]),
.unwrap(),
}, },
camera: Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson), camera: Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson),
camera_input_state: Vec2::zero(), camera_input_state: Vec2::zero(),
@ -297,13 +292,11 @@ impl Scene {
}, },
clouds: Clouds { clouds: Clouds {
model: renderer.create_model(&create_clouds_mesh()).unwrap(), model: renderer.create_model(&create_clouds_mesh()).unwrap(),
locals: renderer.create_consts(&[CloudsLocals::default()]).unwrap(), locals: renderer.create_consts(&[CloudsLocals::default()]),
}, },
postprocess: PostProcess { postprocess: PostProcess {
model: renderer.create_model(&create_pp_mesh()).unwrap(), model: renderer.create_model(&create_pp_mesh()).unwrap(),
locals: renderer locals: renderer.create_consts(&[PostProcessLocals::default()]),
.create_consts(&[PostProcessLocals::default()])
.unwrap(),
}, },
terrain: Terrain::new(renderer, sprite_render_context), terrain: Terrain::new(renderer, sprite_render_context),
lod: Lod::new(renderer, client, settings), lod: Lod::new(renderer, client, settings),

View File

@ -2,14 +2,13 @@ use crate::{
mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain}, mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain},
render::{ render::{
create_clouds_mesh, create_pp_mesh, create_skybox_mesh, BoneMeshes, CloudsLocals, create_clouds_mesh, create_pp_mesh, create_skybox_mesh, BoneMeshes, CloudsLocals,
CloudsVertex, Consts, FigureModel, GlobalModel, Globals, Light, Mesh, Model, CloudsVertex, Consts, FigureModel, GlobalModel, Globals, Light, LodData, Mesh, Model,
PostProcessLocals, PostProcessVertex, Renderer, Shadow, ShadowLocals, SkyboxVertex, PostProcessLocals, PostProcessVertex, Renderer, Shadow, ShadowLocals, SkyboxVertex,
TerrainVertex, TerrainVertex,
}, },
scene::{ scene::{
camera::{self, Camera, CameraMode}, camera::{self, Camera, CameraMode},
figure::{load_mesh, FigureColLights, FigureModelCache, FigureModelEntry, FigureState}, figure::{load_mesh, FigureColLights, FigureModelCache, FigureModelEntry, FigureState},
LodData,
}, },
window::{Event, PressState}, window::{Event, PressState},
}; };
@ -110,10 +109,6 @@ impl Scene {
client.world_data().min_chunk_alt(), client.world_data().min_chunk_alt(),
client.world_data().max_chunk_alt(), client.world_data().max_chunk_alt(),
); );
let map_border = [0.0, 0.0, 0.0, 0.0];
let map_image = [0];
let alt_image = [0];
let horizon_image = [0x_00_01_00_01];
let mut camera = Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson); let mut camera = Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson);
camera.set_focus_pos(Vec3::unit_z() * 1.5); camera.set_focus_pos(Vec3::unit_z() * 1.5);
@ -124,12 +119,10 @@ impl Scene {
Self { Self {
data: GlobalModel { data: GlobalModel {
globals: renderer.create_consts(&[Globals::default()]).unwrap(), globals: renderer.create_consts(&[Globals::default()]),
lights: renderer.create_consts(&[Light::default(); 32]).unwrap(), lights: renderer.create_consts(&[Light::default(); 32]),
shadows: renderer.create_consts(&[Shadow::default(); 32]).unwrap(), shadows: renderer.create_consts(&[Shadow::default(); 32]),
shadow_mats: renderer shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]),
.create_consts(&[ShadowLocals::default(); 6])
.unwrap(),
}, },
skybox: Skybox { skybox: Skybox {
@ -137,23 +130,13 @@ impl Scene {
}, },
clouds: Clouds { clouds: Clouds {
model: renderer.create_model(&create_clouds_mesh()).unwrap(), model: renderer.create_model(&create_clouds_mesh()).unwrap(),
locals: renderer.create_consts(&[CloudsLocals::default()]).unwrap(), locals: renderer.create_consts(&[CloudsLocals::default()]),
}, },
postprocess: PostProcess { postprocess: PostProcess {
model: renderer.create_model(&create_pp_mesh()).unwrap(), model: renderer.create_model(&create_pp_mesh()).unwrap(),
locals: renderer locals: renderer.create_consts(&[PostProcessLocals::default()]),
.create_consts(&[PostProcessLocals::default()])
.unwrap(),
}, },
lod: LodData::new( lod: LodData::dummy(renderer),
renderer,
Vec2::new(1, 1),
&map_image,
&alt_image,
&horizon_image,
1,
//map_border.into(),
),
map_bounds, map_bounds,
figure_model_cache: FigureModelCache::new(), figure_model_cache: FigureModelCache::new(),

View File

@ -8,13 +8,13 @@ use crate::{
terrain::{generate_mesh, SUNLIGHT}, terrain::{generate_mesh, SUNLIGHT},
}, },
render::{ render::{
pipelines, ColLightInfo, Consts, FluidVertex, GlobalModel, Instances, Mesh, Model, pipelines, ColLightInfo, Consts, FluidVertex, GlobalModel, Instances, LodData, Mesh, Model,
RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex, TerrainLocals, RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex, TerrainLocals,
TerrainVertex, Texture, TerrainVertex, Texture,
}, },
}; };
use super::{math, LodData, SceneData}; use super::{math, SceneData};
use common::{ use common::{
assets::{self, AssetExt, DotVoxAsset}, assets::{self, AssetExt, DotVoxAsset},
figure::Segment, figure::Segment,
@ -517,9 +517,7 @@ impl SpriteRenderContext {
offset, offset,
}| { }| {
SpriteData { SpriteData {
locals: renderer locals: renderer.create_consts(&locals_buffer),
.create_consts(&locals)
.expect("Failed to upload sprite locals to the GPU!"),
model: renderer.create_model(&model).expect( model: renderer.create_model(&model).expect(
"Failed to upload sprite model data to the GPU!", "Failed to upload sprite model data to the GPU!",
), ),
@ -1161,8 +1159,7 @@ impl<V: RectRasterableVol> Terrain<V> {
light_map: mesh.light_map, light_map: mesh.light_map,
glow_map: mesh.glow_map, glow_map: mesh.glow_map,
sprite_instances, sprite_instances,
locals: renderer locals: renderer.create_consts(&[TerrainLocals {
.create_consts(&[TerrainLocals {
model_offs: Vec3::from( model_offs: Vec3::from(
response.pos.map2(VolGrid2d::<V>::chunk_size(), |e, sz| { response.pos.map2(VolGrid2d::<V>::chunk_size(), |e, sz| {
e as f32 * sz as f32 e as f32 * sz as f32
@ -1177,8 +1174,7 @@ impl<V: RectRasterableVol> Terrain<V> {
) )
.into_array(), .into_array(),
load_time, load_time,
}]) }]),
.expect("Failed to upload chunk locals to the GPU!"),
visible: Visibility { visible: Visibility {
in_range: false, in_range: false,
in_frustum: false, in_frustum: false,

View File

@ -3,7 +3,7 @@ mod renderer;
pub use renderer::{SampleStrat, Transform}; pub use renderer::{SampleStrat, Transform};
use crate::render::{Renderer, Texture}; use crate::render::{Renderer, Texture, UiTextureBindGroup};
use common::figure::Segment; use common::figure::Segment;
use guillotiere::{size2, SimpleAtlasAllocator}; use guillotiere::{size2, SimpleAtlasAllocator};
use hashbrown::{hash_map::Entry, HashMap}; use hashbrown::{hash_map::Entry, HashMap};
@ -139,7 +139,7 @@ pub struct GraphicCache {
// Atlases with the index of their texture in the textures vec // Atlases with the index of their texture in the textures vec
atlases: Vec<(SimpleAtlasAllocator, usize)>, atlases: Vec<(SimpleAtlasAllocator, usize)>,
textures: Vec<Texture>, textures: Vec<(Texture, UiTextureBindGroup)>,
// Stores the location of graphics rendered at a particular resolution and cached on the cpu // Stores the location of graphics rendered at a particular resolution and cached on the cpu
cache_map: HashMap<Parameters, CachedDetails>, cache_map: HashMap<Parameters, CachedDetails>,
} }
@ -184,7 +184,7 @@ impl GraphicCache {
pub fn get_graphic(&self, id: Id) -> Option<&Graphic> { self.graphic_map.get(&id) } pub fn get_graphic(&self, id: Id) -> Option<&Graphic> { self.graphic_map.get(&id) }
/// Used to acquire textures for rendering /// Used to acquire textures for rendering
pub fn get_tex(&self, id: TexId) -> &Texture { pub fn get_tex(&self, id: TexId) -> &(Texture, UiTextureBindGroup) {
self.textures.get(id.0).expect("Invalid TexId used") self.textures.get(id.0).expect("Invalid TexId used")
} }
@ -284,7 +284,7 @@ impl GraphicCache {
// color. // color.
assert!(border.is_none()); assert!(border.is_none());
// Transfer to the gpu // Transfer to the gpu
upload_image(renderer, aabr, &textures[idx], &image); upload_image(renderer, aabr, &textures[idx].0, &image);
} }
return Some((transformed_aabr(aabr.map(|e| e as f64)), TexId(idx))); return Some((transformed_aabr(aabr.map(|e| e as f64)), TexId(idx)));
@ -324,7 +324,7 @@ impl GraphicCache {
valid: true, valid: true,
aabr, aabr,
}); });
upload_image(renderer, aabr, &textures[texture_idx], &image); upload_image(renderer, aabr, &textures[texture_idx].0, &image);
break; break;
} }
} }
@ -344,7 +344,7 @@ impl GraphicCache {
let atlas_idx = atlases.len(); let atlas_idx = atlases.len();
textures.push(texture); textures.push(texture);
atlases.push((atlas, tex_idx)); atlases.push((atlas, tex_idx));
upload_image(renderer, aabr, &textures[tex_idx], &image); upload_image(renderer, aabr, &textures[tex_idx].0, &image);
CachedDetails::Atlas { CachedDetails::Atlas {
atlas_idx, atlas_idx,
valid: true, valid: true,
@ -354,7 +354,11 @@ impl GraphicCache {
} }
} else { } else {
// Create a texture just for this // Create a texture just for this
let texture = renderer.create_dynamic_texture(dims.map(|e| e as u32)); let texture = {
let tex = renderer.create_dynamic_texture(dims.map(|e| e as u32));
let bind = renderer.ui_bind_texture(&tex);
(tex, bind)
};
// NOTE: All mutations happen only after the texture creation succeeds! // NOTE: All mutations happen only after the texture creation succeeds!
let index = textures.len(); let index = textures.len();
textures.push(texture); textures.push(texture);
@ -365,7 +369,7 @@ impl GraphicCache {
// Note texture should always match the cached dimensions // Note texture should always match the cached dimensions
max: dims, max: dims,
}, },
&textures[index], &textures[index].0,
&image, &image,
); );
CachedDetails::Texture { index, valid: true } CachedDetails::Texture { index, valid: true }
@ -419,11 +423,18 @@ fn atlas_size(renderer: &Renderer) -> Vec2<u32> {
}) })
} }
fn create_atlas_texture(renderer: &mut Renderer) -> (SimpleAtlasAllocator, Texture) { fn create_atlas_texture(
renderer: &mut Renderer,
) -> (SimpleAtlasAllocator, (Texture, UiTextureBindGroup)) {
let size = atlas_size(renderer); let size = atlas_size(renderer);
// Note: here we assume the atlas size is under i32::MAX // Note: here we assume the atlas size is under i32::MAX
let atlas = SimpleAtlasAllocator::new(size2(size.x as i32, size.y as i32)); let atlas = SimpleAtlasAllocator::new(size2(size.x as i32, size.y as i32));
let texture = renderer.create_dynamic_texture(size); let texture = {
let tex = renderer.create_dynamic_texture(size);
let bind = renderer.ui_bind_texture(&tex);
(tex, bind)
};
(atlas, texture) (atlas, texture)
} }
@ -449,8 +460,12 @@ fn upload_image(renderer: &mut Renderer, aabr: Aabr<u16>, tex: &Texture, image:
); );
} }
fn create_image(renderer: &mut Renderer, image: RgbaImage, border_color: Rgba<f32>) -> Texture { fn create_image(
renderer renderer: &mut Renderer,
image: RgbaImage,
border_color: Rgba<f32>,
) -> (Texture, UiTextureBindGroup) {
let tex = renderer
.create_texture( .create_texture(
&DynamicImage::ImageRgba8(image), &DynamicImage::ImageRgba8(image),
None, None,
@ -458,5 +473,8 @@ fn create_image(renderer: &mut Renderer, image: RgbaImage, border_color: Rgba<f3
// Some(border_color.into_array().into()), // Some(border_color.into_array().into()),
Some(wgpu::AddressMode::ClampToBorder), Some(wgpu::AddressMode::ClampToBorder),
) )
.expect("create_texture only panics is non ImageRbga8 is passed") .expect("create_texture only panics is non ImageRbga8 is passed");
let bind = renderer.ui_bind_texture(&tex);
(tex, bind)
} }

View File

@ -1,6 +1,6 @@
use super::graphic::{Graphic, GraphicCache, Id as GraphicId}; use super::graphic::{Graphic, GraphicCache, Id as GraphicId};
use crate::{ use crate::{
render::{Renderer, Texture}, render::{Renderer, Texture, UiTextureBindGroup},
Error, Error,
}; };
use common::assets::{self, AssetExt}; use common::assets::{self, AssetExt};
@ -46,7 +46,7 @@ pub struct FontId(pub(super) glyph_brush::FontId);
pub struct Cache { pub struct Cache {
glyph_brush: RefCell<GlyphBrush>, glyph_brush: RefCell<GlyphBrush>,
glyph_cache_tex: Texture, glyph_cache_tex: (Texture, UiTextureBindGroup),
graphic_cache: GraphicCache, graphic_cache: GraphicCache,
} }
@ -66,16 +66,22 @@ impl Cache {
.draw_cache_position_tolerance(POSITION_TOLERANCE) .draw_cache_position_tolerance(POSITION_TOLERANCE)
.build(); .build();
let glyph_cache_tex = {
let tex = renderer.create_dynamic_texture(glyph_cache_dims);
let bind = renderer.ui_bind_texture(&tex);
(tex, bind)
};
Ok(Self { Ok(Self {
glyph_brush: RefCell::new(glyph_brush), glyph_brush: RefCell::new(glyph_brush),
glyph_cache_tex: renderer.create_dynamic_texture(glyph_cache_dims), glyph_cache_tex,
graphic_cache: GraphicCache::new(renderer), graphic_cache: GraphicCache::new(renderer),
}) })
} }
pub fn glyph_cache_tex(&self) -> &Texture { &self.glyph_cache_tex } pub fn glyph_cache_tex(&self) -> &(Texture, UiTextureBindGroup) { &self.glyph_cache_tex }
pub fn glyph_cache_mut_and_tex(&mut self) -> (&mut GlyphBrush, &Texture) { pub fn glyph_cache_mut_and_tex(&mut self) -> (&mut GlyphBrush, &(Texture, UiTextureBindGroup)) {
(self.glyph_brush.get_mut(), &self.glyph_cache_tex) (self.glyph_brush.get_mut(), &self.glyph_cache_tex)
} }
@ -117,6 +123,7 @@ impl Cache {
self.graphic_cache.replace_graphic(id, graphic) self.graphic_cache.replace_graphic(id, graphic)
} }
// TODO: combine resize functions
// Resizes and clears the GraphicCache // Resizes and clears the GraphicCache
pub fn resize_graphic_cache(&mut self, renderer: &mut Renderer) { pub fn resize_graphic_cache(&mut self, renderer: &mut Renderer) {
self.graphic_cache.clear_cache(renderer); self.graphic_cache.clear_cache(renderer);
@ -134,7 +141,12 @@ impl Cache {
.initial_cache_size((cache_dims.x, cache_dims.y)) .initial_cache_size((cache_dims.x, cache_dims.y))
.build(); .build();
self.glyph_cache_tex = renderer.create_dynamic_texture(cache_dims); self.glyph_cache_tex = {
let tex = renderer.create_dynamic_texture(cache_dims);
let bind = renderer.ui_bind_texture(&tex);
(tex, bind)
};
Ok(()) Ok(())
} }
} }

View File

@ -14,7 +14,11 @@ use super::{
graphic::{self, Graphic}, graphic::{self, Graphic},
scale::{Scale, ScaleMode}, scale::{Scale, ScaleMode},
}; };
use crate::{render::Renderer, window::Window, Error}; use crate::{
render::{Renderer, UiDrawer},
window::Window,
Error,
};
use common_base::span; use common_base::span;
use iced::{mouse, Cache, Size, UserInterface}; use iced::{mouse, Cache, Size, UserInterface};
use iced_winit::Clipboard; use iced_winit::Clipboard;
@ -212,5 +216,5 @@ impl IcedUi {
(messages, mouse_interaction) (messages, mouse_interaction)
} }
pub fn render(&self, renderer: &mut Renderer) { self.renderer.render(renderer, None); } pub fn render<'a>(&'a self, drawer: &mut UiDrawer<'_, 'a>) { self.renderer.render(drawer); }
} }

View File

@ -15,8 +15,8 @@ use super::{
}; };
use crate::{ use crate::{
render::{ render::{
create_ui_quad, create_ui_quad_vert_gradient, Consts, DynamicModel, Globals, Mesh, create_ui_quad, create_ui_quad_vert_gradient, Consts, DynamicModel, Mesh, Renderer,
Renderer, UiLocals, UiMode, UiVertex, UiDrawer, UiLocals, UiLocalsBindGroup, UiMode, UiVertex,
}, },
Error, Error,
}; };
@ -85,10 +85,10 @@ pub struct IcedRenderer {
// Model for drawing the ui // Model for drawing the ui
model: DynamicModel<UiVertex>, model: DynamicModel<UiVertex>,
// Consts to specify positions of ingame elements (e.g. Nametags) // Consts to specify positions of ingame elements (e.g. Nametags)
ingame_locals: Vec<Consts<UiLocals>>, ingame_locals: Vec<(Consts<UiLocals>, UiLocalsBindGroup)>,
// Consts for default ui drawing position (ie the interface) // Consts for default ui drawing position (ie the interface)
interface_locals: Consts<UiLocals>, interface_locals: (Consts<UiLocals>, UiLocalsBindGroup),
default_globals: Consts<Globals>, //default_globals: Consts<Globals>,
// Used to delay cache resizing until after current frame is drawn // Used to delay cache resizing until after current frame is drawn
//need_cache_resize: bool, //need_cache_resize: bool,
@ -125,12 +125,18 @@ impl IcedRenderer {
let (half_res, align, p_scale) = let (half_res, align, p_scale) =
Self::calculate_resolution_dependents(physical_resolution, scaled_resolution); Self::calculate_resolution_dependents(physical_resolution, scaled_resolution);
let interface_locals = {
let locals = renderer.create_consts(&[UiLocals::default()]);
let bind = renderer.ui_bind_locals(&locals);
(locals, bind)
};
Ok(Self { Ok(Self {
cache: Cache::new(renderer, default_font)?, cache: Cache::new(renderer, default_font)?,
draw_commands: Vec::new(), draw_commands: Vec::new(),
model: renderer.create_dynamic_model(100), model: renderer.create_dynamic_model(100),
interface_locals: renderer.create_consts(&[UiLocals::default()])?, interface_locals,
default_globals: renderer.create_consts(&[Globals::default()])?, //default_globals: renderer.create_consts(&[Globals::default()]),
ingame_locals: Vec::new(), ingame_locals: Vec::new(),
mesh: Mesh::new(), mesh: Mesh::new(),
glyphs: Vec::new(), glyphs: Vec::new(),
@ -222,7 +228,7 @@ impl IcedRenderer {
.push(DrawCommand::plain(self.start..self.mesh.vertices().len()));*/ .push(DrawCommand::plain(self.start..self.mesh.vertices().len()));*/
// Fill in placeholder glyph quads // Fill in placeholder glyph quads
let (glyph_cache, cache_tex) = self.cache.glyph_cache_mut_and_tex(); let (glyph_cache, (cache_tex, _)) = self.cache.glyph_cache_mut_and_tex();
let half_res = self.half_res; let half_res = self.half_res;
let brush_result = glyph_cache.process_queued( let brush_result = glyph_cache.process_queued(
@ -542,6 +548,7 @@ impl IcedRenderer {
Some((aabr, tex_id)) => { Some((aabr, tex_id)) => {
let cache_dims = graphic_cache let cache_dims = graphic_cache
.get_tex(tex_id) .get_tex(tex_id)
.0
.get_dimensions() .get_dimensions()
.xy() .xy()
.map(|e| e as f32); .map(|e| e as f32);
@ -763,28 +770,32 @@ impl IcedRenderer {
} }
} }
pub fn render(&self, renderer: &mut Renderer, maybe_globals: Option<&Consts<Globals>>) { pub fn render<'pass_ref, 'pass: 'pass_ref, 'data: 'pass>(
&'data self,
drawer: &mut UiDrawer<'pass_ref, 'pass>, /* maybe_globals: Option<&Consts<Globals>> */
) {
span!(_guard, "render", "IcedRenderer::render"); span!(_guard, "render", "IcedRenderer::render");
let mut scissor = self.window_scissor; let mut drawer = drawer.prepare(&self.interface_locals.1, &self.model, self.window_scissor);
let globals = maybe_globals.unwrap_or(&self.default_globals); //let mut scissor = self.window_scissor;
let mut locals = &self.interface_locals; //let globals = maybe_globals.unwrap_or(&self.default_globals);
//let mut locals = &self.interface_locals.1;
for draw_command in self.draw_commands.iter() { for draw_command in self.draw_commands.iter() {
match draw_command { match draw_command {
DrawCommand::Scissor(new_scissor) => { DrawCommand::Scissor(new_scissor) => {
scissor = *new_scissor; drawer.set_scissor(*new_scissor);
}, },
DrawCommand::WorldPos(index) => { DrawCommand::WorldPos(index) => {
locals = index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]); drawer.set_locals(
index.map_or(&self.interface_locals.1, |i| &self.ingame_locals[i].1),
);
}, },
DrawCommand::Draw { kind, verts } => { DrawCommand::Draw { kind, verts } => {
// TODO: don't make these assert!(!verts.is_empty());
let tex = match kind { let tex = match kind {
DrawKind::Image(tex_id) => self.cache.graphic_cache().get_tex(*tex_id), DrawKind::Image(tex_id) => self.cache.graphic_cache().get_tex(*tex_id),
DrawKind::Plain => self.cache.glyph_cache_tex(), DrawKind::Plain => self.cache.glyph_cache_tex(),
}; };
let model = self.model.submodel(verts.clone()); drawer.draw(&tex.1, verts.clone()); // Note: trivial clone
// TODO
//renderer.render_ui_element(model, tex, scissor, globals,
// locals);
}, },
} }
} }

View File

@ -163,8 +163,8 @@ impl Ui {
draw_commands: Vec::new(), draw_commands: Vec::new(),
mesh: Mesh::new(), mesh: Mesh::new(),
model: renderer.create_dynamic_model(100), model: renderer.create_dynamic_model(100),
interface_locals: renderer.create_consts(&[UiLocals::default()])?, interface_locals: renderer.create_consts(&[UiLocals::default()]),
default_globals: renderer.create_consts(&[Globals::default()])?, default_globals: renderer.create_consts(&[Globals::default()]),
ingame_locals: Vec::new(), ingame_locals: Vec::new(),
window_resized: None, window_resized: None,
scale_factor_changed: None, scale_factor_changed: None,
@ -812,6 +812,7 @@ impl Ui {
Some((aabr, tex_id)) => { Some((aabr, tex_id)) => {
let cache_dims = graphic_cache let cache_dims = graphic_cache
.get_tex(tex_id) .get_tex(tex_id)
.0
.get_dimensions() .get_dimensions()
.xy() .xy()
.map(|e| e as f32); .map(|e| e as f32);
@ -953,7 +954,7 @@ impl Ui {
) )
} else { } else {
self.ingame_locals self.ingame_locals
.push(renderer.create_consts(&[world_pos.into()]).unwrap()); .push(renderer.create_consts(&[world_pos.into()]));
} }
self.draw_commands self.draw_commands
.push(DrawCommand::WorldPos(Some(ingame_local_index))); .push(DrawCommand::WorldPos(Some(ingame_local_index)));
@ -1019,11 +1020,12 @@ impl Ui {
locals = index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]); locals = index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]);
}, },
DrawCommand::Draw { kind, verts } => { DrawCommand::Draw { kind, verts } => {
let tex = match kind { //let tex = match kind {
DrawKind::Image(tex_id) => self.cache.graphic_cache().get_tex(*tex_id), // DrawKind::Image(tex_id) =>
DrawKind::Plain => self.cache.glyph_cache_tex(), // self.cache.graphic_cache().get_tex(*tex_id),
}; // DrawKind::Plain => self.cache.glyph_cache_tex(),
let model = self.model.submodel(verts.clone()); //};
//let model = self.model.submodel(verts.clone());
// TODO // TODO
//renderer.render_ui_element(model, tex, scissor, globals, //renderer.render_ui_element(model, tex, scissor, globals,
// locals); // locals);