mirror of
https://github.com/griffi-gh/kubi.git
synced 2025-03-14 11:06:26 -05:00
Compare commits
No commits in common. "90784e21dd47d5dd87c150da9663a84edb5270bb" and "906f4882a24423b5743bbaf1b25c8ca9cb9e836a" have entirely different histories.
90784e21dd
...
906f4882a2
|
@ -1,42 +0,0 @@
|
||||||
// struct Uniforms {
|
|
||||||
// transform: mat4x4<f32>;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// @group(1) @binding(0)
|
|
||||||
// var<uniform> uniforms: Uniforms;
|
|
||||||
|
|
||||||
struct VertexInput {
|
|
||||||
@location(0) position: vec3<f32>,
|
|
||||||
@location(1) normal: vec3<f32>,
|
|
||||||
@location(2) uv: vec2<f32>,
|
|
||||||
@location(3) @interpolate(flat) tex_index: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct VertexOutput {
|
|
||||||
@builtin(position) clip_position: vec4<f32>,
|
|
||||||
@location(0) uv: vec2<f32>,
|
|
||||||
@location(1) normal: vec3<f32>,
|
|
||||||
@location(2) color: vec4<f32>,
|
|
||||||
@location(3) @interpolate(flat) tex_index: u32,
|
|
||||||
};
|
|
||||||
|
|
||||||
@vertex
|
|
||||||
fn vs_main(
|
|
||||||
in: VertexInput,
|
|
||||||
) -> VertexOutput {
|
|
||||||
var out: VertexOutput;
|
|
||||||
out.uv = in.uv;
|
|
||||||
out.clip_position = vec4<f32>(in.position, 1.0);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@group(0) @binding(0)
|
|
||||||
var t_diffuse: texture_2d_array<f32>;
|
|
||||||
|
|
||||||
@group(0) @binding(1)
|
|
||||||
var s_diffuse: sampler;
|
|
||||||
|
|
||||||
@fragment
|
|
||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
|
||||||
return textureSample(t_diffuse, s_diffuse, in.uv, in.tex_index);
|
|
||||||
}
|
|
|
@ -5,7 +5,9 @@ use kubi_shared::block::BlockTexture;
|
||||||
use crate::{filesystem::AssetManager, hui_integration::UiState, rendering::Renderer};
|
use crate::{filesystem::AssetManager, hui_integration::UiState, rendering::Renderer};
|
||||||
|
|
||||||
mod texture;
|
mod texture;
|
||||||
use texture::load_texture2darray_prefab;
|
mod shaders;
|
||||||
|
|
||||||
|
//use texture::load_texture2darray_prefab;
|
||||||
|
|
||||||
pub trait AssetPaths {
|
pub trait AssetPaths {
|
||||||
fn file_name(self) -> &'static str;
|
fn file_name(self) -> &'static str;
|
||||||
|
@ -37,7 +39,19 @@ impl AssetPaths for BlockTexture {
|
||||||
|
|
||||||
#[derive(Unique)]
|
#[derive(Unique)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct BlockDiffuseTexture(pub wgpu::Texture);
|
pub struct BlockTexturesPrefab(pub wgpu::Texture);
|
||||||
|
|
||||||
|
// #[derive(Unique)]
|
||||||
|
// #[repr(transparent)]
|
||||||
|
// pub struct ChunkShaderPrefab(pub Program);
|
||||||
|
|
||||||
|
// #[derive(Unique)]
|
||||||
|
// #[repr(transparent)]
|
||||||
|
// pub struct ColoredShaderPrefab(pub Program);
|
||||||
|
|
||||||
|
// #[derive(Unique)]
|
||||||
|
// #[repr(transparent)]
|
||||||
|
// pub struct Colored2ShaderPrefab(pub Program);
|
||||||
|
|
||||||
#[derive(Unique)]
|
#[derive(Unique)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
@ -49,14 +63,15 @@ pub fn load_prefabs(
|
||||||
mut ui: NonSendSync<UniqueViewMut<UiState>>,
|
mut ui: NonSendSync<UniqueViewMut<UiState>>,
|
||||||
assman: UniqueView<AssetManager>
|
assman: UniqueView<AssetManager>
|
||||||
) {
|
) {
|
||||||
log::info!("Loading textures...");
|
// log::info!("Loading textures...");
|
||||||
storages.add_unique_non_send_sync(BlockDiffuseTexture(
|
// storages.add_unique_non_send_sync(BlockTexturesPrefab(
|
||||||
load_texture2darray_prefab::<BlockTexture>(
|
// load_texture2darray_prefab::<BlockTexture, _>(
|
||||||
&renderer,
|
// &assman,
|
||||||
&assman,
|
// "blocks".into(),
|
||||||
"blocks".into(),
|
// &renderer.display,
|
||||||
)
|
// MipmapsOption::AutoGeneratedMipmaps
|
||||||
));
|
// )
|
||||||
|
// ));
|
||||||
|
|
||||||
log::info!("Loading the UI stuff...");
|
log::info!("Loading the UI stuff...");
|
||||||
{
|
{
|
||||||
|
|
19
kubi/src/prefabs/shaders.rs
Normal file
19
kubi/src/prefabs/shaders.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
macro_rules! include_shader_prefab {
|
||||||
|
($name: literal, $vert: literal, $frag: literal, $facade: expr) => {
|
||||||
|
{
|
||||||
|
use ::glium::{Program, program::ProgramCreationInput};
|
||||||
|
log::info!("compiling shader {}", $name);
|
||||||
|
Program::new(&*$facade, ProgramCreationInput::SourceCode {
|
||||||
|
vertex_shader: include_str!($vert),
|
||||||
|
fragment_shader: include_str!($frag),
|
||||||
|
geometry_shader: None,
|
||||||
|
tessellation_control_shader: None,
|
||||||
|
tessellation_evaluation_shader: None,
|
||||||
|
transform_feedback_varyings: None,
|
||||||
|
outputs_srgb: false,
|
||||||
|
uses_point_size: false,
|
||||||
|
}).expect("Failed to compile gpu program")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub(crate) use include_shader_prefab;
|
|
@ -1,75 +1,45 @@
|
||||||
use glam::UVec2;
|
// use strum::IntoEnumIterator;
|
||||||
use strum::IntoEnumIterator;
|
// use rayon::prelude::*;
|
||||||
use rayon::prelude::*;
|
// use std::{path::PathBuf, io::BufReader};
|
||||||
use wgpu::util::{DeviceExt, TextureDataOrder};
|
// use crate::filesystem::AssetManager;
|
||||||
use std::{io::BufReader, path::PathBuf};
|
// use super::AssetPaths;
|
||||||
use crate::{filesystem::AssetManager, rendering::Renderer};
|
|
||||||
use super::AssetPaths;
|
|
||||||
|
|
||||||
pub fn load_texture2darray_prefab<T: AssetPaths + IntoEnumIterator>(
|
// pub fn load_texture2darray_prefab<
|
||||||
renderer: &Renderer,
|
// T: AssetPaths + IntoEnumIterator,
|
||||||
assman: &AssetManager,
|
// E: Facade
|
||||||
directory: PathBuf,
|
// >(
|
||||||
) -> wgpu::Texture {
|
// assman: &AssetManager,
|
||||||
log::info!("started loading {}", directory.as_os_str().to_str().unwrap());
|
// directory: PathBuf,
|
||||||
|
// facade: &E,
|
||||||
//Load raw images
|
// mipmaps: MipmapsOption,
|
||||||
let tex_files: Vec<&'static str> = T::iter().map(|x| x.file_name()).collect();
|
// ) -> SrgbTexture2dArray {
|
||||||
let raw_images: Vec<(Vec<u8>, UVec2)> = tex_files.par_iter().map(|&file_name| {
|
// log::info!("started loading {}", directory.as_os_str().to_str().unwrap());
|
||||||
log::info!("loading texture {}", file_name);
|
// //Load raw images
|
||||||
|
// let tex_files: Vec<&'static str> = T::iter().map(|x| x.file_name()).collect();
|
||||||
//Get path to the image and open the file
|
// let raw_images: Vec<RawImage2d<u8>> = tex_files.par_iter().map(|&file_name| {
|
||||||
let reader = {
|
// log::info!("loading texture {}", file_name);
|
||||||
let path = directory.join(file_name);
|
// //Get path to the image and open the file
|
||||||
BufReader::new(assman.open_asset(&path).expect("Failed to open texture file"))
|
// let reader = {
|
||||||
};
|
// let path = directory.join(file_name);
|
||||||
|
// BufReader::new(assman.open_asset(&path).expect("Failed to open texture file"))
|
||||||
//Parse image data
|
// };
|
||||||
let (image_data, dimensions) = {
|
// //Parse image data
|
||||||
let image = image::load(
|
// let (image_data, dimensions) = {
|
||||||
reader,
|
// let image = image::load(
|
||||||
image::ImageFormat::Png
|
// reader,
|
||||||
).unwrap().to_rgba8();
|
// image::ImageFormat::Png
|
||||||
let dimensions = image.dimensions();
|
// ).unwrap().to_rgba8();
|
||||||
(image.into_raw(), dimensions)
|
// let dimensions = image.dimensions();
|
||||||
};
|
// (image.into_raw(), dimensions)
|
||||||
(image_data, UVec2::from(dimensions))
|
// };
|
||||||
}).collect();
|
// //Create a glium RawImage
|
||||||
|
// RawImage2d::from_raw_rgba_reversed(
|
||||||
assert!(!raw_images.is_empty(), "no images loaded");
|
// &image_data,
|
||||||
//TODO: check same size
|
// dimensions
|
||||||
|
// )
|
||||||
log::info!("done loading texture files, uploading to the gpu");
|
// }).collect();
|
||||||
|
// log::info!("done loading texture files, uploading to the gpu");
|
||||||
let size = raw_images[0].1;
|
// //Upload images to the GPU
|
||||||
let layers = raw_images.len() as u32;
|
// SrgbTexture2dArray::with_mipmaps(facade, raw_images, mipmaps)
|
||||||
|
// .expect("Failed to upload texture array to GPU")
|
||||||
//Concat data into a single vec
|
// }
|
||||||
let mut data = Vec::with_capacity((size.x * size.y * layers * 4) as usize);
|
|
||||||
for (layer_data, _) in raw_images {
|
|
||||||
data.extend_from_slice(&layer_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Upload images to the GPU
|
|
||||||
let desc = &wgpu::TextureDescriptor {
|
|
||||||
label: Some("block_diffuse_texture"),
|
|
||||||
size: wgpu::Extent3d {
|
|
||||||
width: size.x,
|
|
||||||
height: size.y,
|
|
||||||
depth_or_array_layers: layers,
|
|
||||||
},
|
|
||||||
dimension: wgpu::TextureDimension::D2,
|
|
||||||
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
|
||||||
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
|
||||||
mip_level_count: 1,
|
|
||||||
sample_count: 1,
|
|
||||||
view_formats: &[],
|
|
||||||
};
|
|
||||||
|
|
||||||
renderer.device().create_texture_with_data(
|
|
||||||
renderer.queue(),
|
|
||||||
desc,
|
|
||||||
TextureDataOrder::MipMajor,
|
|
||||||
&data
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
use shipyard::{AllStoragesView, AllStoragesViewMut, IntoIter, Unique, UniqueView, UniqueViewMut, View};
|
use pollster::FutureExt;
|
||||||
use winit::dpi::PhysicalSize;
|
use raw_window_handle::HasRawWindowHandle;
|
||||||
|
use shipyard::{AllStoragesView, AllStoragesViewMut, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View};
|
||||||
|
use wgpu::SurfaceTargetUnsafe;
|
||||||
|
use winit::{
|
||||||
|
event_loop::ActiveEventLoop,
|
||||||
|
window::{WindowAttributes, Fullscreen, Window},
|
||||||
|
dpi::PhysicalSize
|
||||||
|
};
|
||||||
use glam::{Vec3, UVec2};
|
use glam::{Vec3, UVec2};
|
||||||
use crate::{events::WindowResizedEvent, state::is_ingame};
|
use crate::{events::WindowResizedEvent, settings::{FullscreenMode, GameSettings}, state::is_ingame};
|
||||||
|
|
||||||
mod renderer;
|
|
||||||
pub use renderer::Renderer;
|
|
||||||
|
|
||||||
pub mod primitives;
|
pub mod primitives;
|
||||||
pub mod world;
|
pub mod world;
|
||||||
|
@ -18,20 +22,174 @@ pub struct BufferPair {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Unique)]
|
#[derive(Unique)]
|
||||||
|
#[repr(transparent)]
|
||||||
pub struct BackgroundColor(pub Vec3);
|
pub struct BackgroundColor(pub Vec3);
|
||||||
|
|
||||||
|
#[derive(Unique, Clone, Copy)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
#[deprecated = "use Renderer.size instead"]
|
||||||
|
#[allow(deprecated)]
|
||||||
|
pub struct WindowSize(pub UVec2);
|
||||||
|
|
||||||
|
#[derive(Unique)]
|
||||||
|
pub struct Renderer {
|
||||||
|
instance: wgpu::Instance,
|
||||||
|
surface: wgpu::Surface<'static>,
|
||||||
|
device: wgpu::Device,
|
||||||
|
queue: wgpu::Queue,
|
||||||
|
surface_config: wgpu::SurfaceConfiguration,
|
||||||
|
size: PhysicalSize<u32>,
|
||||||
|
// pub depth_texture: wgpu::Texture,
|
||||||
|
|
||||||
|
//must be last due to drop order
|
||||||
|
window: Window,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Renderer {
|
||||||
|
pub fn init(event_loop: &ActiveEventLoop, settings: &GameSettings) -> Self {
|
||||||
|
log::info!("initializing display");
|
||||||
|
|
||||||
|
let window_attributes = Window::default_attributes()
|
||||||
|
.with_title("kubi")
|
||||||
|
.with_maximized(true)
|
||||||
|
.with_min_inner_size(PhysicalSize::new(640, 480))
|
||||||
|
.with_fullscreen({
|
||||||
|
//this has no effect on android, so skip this pointless stuff
|
||||||
|
#[cfg(target_os = "android")] {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
|
if let Some(fs_settings) = &settings.fullscreen {
|
||||||
|
let monitor = event_loop.primary_monitor().or_else(|| {
|
||||||
|
event_loop.available_monitors().next()
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(monitor) = monitor {
|
||||||
|
log::info!("monitor: {}", monitor.name().unwrap_or_else(|| "generic".into()));
|
||||||
|
match fs_settings.mode {
|
||||||
|
FullscreenMode::Borderless => {
|
||||||
|
log::info!("starting in borderless fullscreen mode");
|
||||||
|
Some(Fullscreen::Borderless(Some(monitor)))
|
||||||
|
},
|
||||||
|
FullscreenMode::Exclusive => {
|
||||||
|
log::warn!("exclusive fullscreen mode is experimental");
|
||||||
|
log::info!("starting in exclusive fullscreen mode");
|
||||||
|
//TODO: grabbing the first video mode is probably not the best idea...
|
||||||
|
monitor.video_modes().next()
|
||||||
|
.map(|vmode| {
|
||||||
|
log::info!("video mode: {}", vmode.to_string());
|
||||||
|
Some(Fullscreen::Exclusive(vmode))
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
log::warn!("no valid video modes found, falling back to windowed mode instead");
|
||||||
|
None
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log::warn!("no monitors found, falling back to windowed mode");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log::info!("starting in windowed mode");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let window = event_loop.create_window(window_attributes).unwrap();
|
||||||
|
|
||||||
|
let size = window.inner_size();
|
||||||
|
|
||||||
|
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||||
|
backends: wgpu::Backends::BROWSER_WEBGPU | wgpu::Backends::VULKAN | wgpu::Backends::GL,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a surface with `create_surface_unsafe` to get a surface with 'static lifetime
|
||||||
|
// It should never outlive the window it's created from
|
||||||
|
let surface = unsafe {
|
||||||
|
instance.create_surface_unsafe(SurfaceTargetUnsafe::from_window(&window).unwrap()).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let adapter = instance.request_adapter(
|
||||||
|
&wgpu::RequestAdapterOptions {
|
||||||
|
power_preference: wgpu::PowerPreference::HighPerformance,
|
||||||
|
compatible_surface: Some(&surface),
|
||||||
|
force_fallback_adapter: false,
|
||||||
|
},
|
||||||
|
).block_on().unwrap();
|
||||||
|
|
||||||
|
let (device, queue) = adapter.request_device(
|
||||||
|
&wgpu::DeviceDescriptor {
|
||||||
|
label: None,
|
||||||
|
required_features: wgpu::Features::empty(),
|
||||||
|
required_limits: wgpu::Limits::downlevel_defaults(),
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
).block_on().unwrap();
|
||||||
|
|
||||||
|
let surface_config = surface.get_default_config(&adapter, size.width, size.height).unwrap();
|
||||||
|
surface.configure(&device, &surface_config);
|
||||||
|
|
||||||
|
Self { window, instance, surface, device, queue, surface_config, size }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resize(&mut self, size: PhysicalSize<u32>) {
|
||||||
|
if size.width == 0 || size.height == 0 {
|
||||||
|
log::warn!("Ignoring resize event with zero width or height");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.size == size {
|
||||||
|
log::warn!("Ignoring resize event with same size");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log::debug!("resizing surface to {:?}", size);
|
||||||
|
self.size = size;
|
||||||
|
self.surface_config.width = size.width;
|
||||||
|
self.surface_config.height = size.height;
|
||||||
|
self.surface.configure(&self.device, &self.surface_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reconfigure(&self) {
|
||||||
|
self.surface.configure(&self.device, &self.surface_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
//getters:
|
||||||
|
pub fn size(&self) -> PhysicalSize<u32> {
|
||||||
|
self.size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn window(&self) -> &Window {
|
||||||
|
&self.window
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn surface(&self) -> &wgpu::Surface<'static> {
|
||||||
|
&self.surface
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn device(&self) -> &wgpu::Device {
|
||||||
|
&self.device
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn queue(&self) -> &wgpu::Queue {
|
||||||
|
&self.queue
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn surface_config(&self) -> &wgpu::SurfaceConfiguration {
|
||||||
|
&self.surface_config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn render_master(storages: AllStoragesViewMut) {
|
pub fn render_master(storages: AllStoragesViewMut) {
|
||||||
let renderer = storages.borrow::<UniqueView<Renderer>>().unwrap();
|
let renderer = storages.borrow::<UniqueView<Renderer>>().unwrap();
|
||||||
|
|
||||||
let mut encoder = renderer.device().create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
let mut encoder = renderer.device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
||||||
label: Some("main_encoder"),
|
label: Some("main_encoder"),
|
||||||
});
|
});
|
||||||
let surface_texture = renderer.surface().get_current_texture().unwrap();
|
let surface_texture = renderer.surface().get_current_texture().unwrap();
|
||||||
let surface_view = surface_texture.texture.create_view(&wgpu::TextureViewDescriptor::default());
|
let surface_view = surface_texture.texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
|
||||||
//Main in-game render pass
|
|
||||||
if storages.run(is_ingame) {
|
if storages.run(is_ingame) {
|
||||||
let bg = storages.borrow::<UniqueView<BackgroundColor>>().unwrap().0;
|
let bg_color = storages.borrow::<UniqueView<BackgroundColor>>().unwrap();
|
||||||
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
label: Some("main0_pass"),
|
label: Some("main0_pass"),
|
||||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||||
|
@ -39,9 +197,9 @@ pub fn render_master(storages: AllStoragesViewMut) {
|
||||||
resolve_target: None,
|
resolve_target: None,
|
||||||
ops: wgpu::Operations {
|
ops: wgpu::Operations {
|
||||||
load: wgpu::LoadOp::Clear(wgpu::Color {
|
load: wgpu::LoadOp::Clear(wgpu::Color {
|
||||||
r: bg.x as f64,
|
r: bg_color.0.x as f64,
|
||||||
g: bg.y as f64,
|
g: bg_color.0.y as f64,
|
||||||
b: bg.z as f64,
|
b: bg_color.0.z as f64,
|
||||||
a: 1.0,
|
a: 1.0,
|
||||||
}),
|
}),
|
||||||
store: wgpu::StoreOp::Store,
|
store: wgpu::StoreOp::Store,
|
||||||
|
@ -54,13 +212,27 @@ pub fn render_master(storages: AllStoragesViewMut) {
|
||||||
let data = (&mut render_pass, &*renderer);
|
let data = (&mut render_pass, &*renderer);
|
||||||
|
|
||||||
storages.run_with_data(world::draw_world, data);
|
storages.run_with_data(world::draw_world, data);
|
||||||
|
|
||||||
|
// render_pass.set_pipeline(&renderer.pipeline);
|
||||||
|
// render_pass.set_bind_group(0, &renderer.bind_group, &[]);
|
||||||
|
// render_pass.set_vertex_buffer(0, renderer.vertex_buffer.slice(..));
|
||||||
|
// render_pass.set_index_buffer(renderer.index_buffer.slice(..));
|
||||||
|
// render_pass.draw_indexed(0..renderer.num_indices, 0, 0..1);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.queue().submit(std::iter::once(encoder.finish()));
|
renderer.queue().submit(std::iter::once(encoder.finish()));
|
||||||
surface_texture.present();
|
surface_texture.present();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resize the renderer when the window is resized
|
// pub fn clear_background(
|
||||||
|
// mut target: NonSendSync<UniqueViewMut<RenderTarget>>,
|
||||||
|
// color: UniqueView<BackgroundColor>,
|
||||||
|
// ) {
|
||||||
|
// target.0.clear_color_srgb_and_depth((color.0.x, color.0.y, color.0.z, 1.), 1.);
|
||||||
|
// }
|
||||||
|
|
||||||
|
//Resize the renderer
|
||||||
|
|
||||||
pub fn resize_renderer(
|
pub fn resize_renderer(
|
||||||
mut renderer: UniqueViewMut<Renderer>,
|
mut renderer: UniqueViewMut<Renderer>,
|
||||||
resize: View<WindowResizedEvent>,
|
resize: View<WindowResizedEvent>,
|
||||||
|
@ -70,15 +242,11 @@ pub fn resize_renderer(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Deprecated WindowSize thingy
|
//not sure if this belongs here
|
||||||
|
|
||||||
#[derive(Unique, Clone, Copy)]
|
pub fn init_window_size(
|
||||||
#[repr(transparent)]
|
storages: AllStoragesView,
|
||||||
#[deprecated = "use Renderer.size instead"]
|
) {
|
||||||
#[allow(deprecated)]
|
|
||||||
pub struct WindowSize(pub UVec2);
|
|
||||||
|
|
||||||
pub fn init_window_size(storages: AllStoragesView) {
|
|
||||||
let size = storages.borrow::<View<WindowResizedEvent>>().unwrap().iter().next().unwrap().0;
|
let size = storages.borrow::<View<WindowResizedEvent>>().unwrap().iter().next().unwrap().0;
|
||||||
storages.add_unique(WindowSize(size))
|
storages.add_unique(WindowSize(size))
|
||||||
}
|
}
|
||||||
|
@ -92,8 +260,8 @@ pub fn update_window_size(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn if_resized (
|
pub fn if_resized (
|
||||||
// resize: View<WindowResizedEvent>,
|
resize: View<WindowResizedEvent>,
|
||||||
// ) -> bool {
|
) -> bool {
|
||||||
// resize.len() > 0
|
resize.len() > 0
|
||||||
// }
|
}
|
||||||
|
|
|
@ -1,157 +0,0 @@
|
||||||
use pollster::FutureExt;
|
|
||||||
use shipyard::Unique;
|
|
||||||
use winit::{
|
|
||||||
event_loop::ActiveEventLoop,
|
|
||||||
window::{Fullscreen, Window},
|
|
||||||
dpi::PhysicalSize
|
|
||||||
};
|
|
||||||
use crate::settings::{GameSettings, FullscreenMode};
|
|
||||||
|
|
||||||
#[derive(Unique)]
|
|
||||||
pub struct Renderer {
|
|
||||||
instance: wgpu::Instance,
|
|
||||||
surface: wgpu::Surface<'static>,
|
|
||||||
device: wgpu::Device,
|
|
||||||
queue: wgpu::Queue,
|
|
||||||
surface_config: wgpu::SurfaceConfiguration,
|
|
||||||
size: PhysicalSize<u32>,
|
|
||||||
// pub depth_texture: wgpu::Texture,
|
|
||||||
|
|
||||||
//must be last due to drop order
|
|
||||||
window: Window,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Renderer {
|
|
||||||
pub fn init(event_loop: &ActiveEventLoop, settings: &GameSettings) -> Self {
|
|
||||||
log::info!("initializing display");
|
|
||||||
|
|
||||||
let window_attributes = Window::default_attributes()
|
|
||||||
.with_title("kubi")
|
|
||||||
.with_maximized(true)
|
|
||||||
.with_min_inner_size(PhysicalSize::new(640, 480))
|
|
||||||
.with_fullscreen({
|
|
||||||
//this has no effect on android, so skip this pointless stuff
|
|
||||||
#[cfg(target_os = "android")] {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
#[cfg(not(target_os = "android"))]
|
|
||||||
if let Some(fs_settings) = &settings.fullscreen {
|
|
||||||
let monitor = event_loop.primary_monitor().or_else(|| {
|
|
||||||
event_loop.available_monitors().next()
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(monitor) = monitor {
|
|
||||||
log::info!("monitor: {}", monitor.name().unwrap_or_else(|| "generic".into()));
|
|
||||||
match fs_settings.mode {
|
|
||||||
FullscreenMode::Borderless => {
|
|
||||||
log::info!("starting in borderless fullscreen mode");
|
|
||||||
Some(Fullscreen::Borderless(Some(monitor)))
|
|
||||||
},
|
|
||||||
FullscreenMode::Exclusive => {
|
|
||||||
log::warn!("exclusive fullscreen mode is experimental");
|
|
||||||
log::info!("starting in exclusive fullscreen mode");
|
|
||||||
//TODO: grabbing the first video mode is probably not the best idea...
|
|
||||||
monitor.video_modes().next()
|
|
||||||
.map(|vmode| {
|
|
||||||
log::info!("video mode: {}", vmode.to_string());
|
|
||||||
Some(Fullscreen::Exclusive(vmode))
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
log::warn!("no valid video modes found, falling back to windowed mode instead");
|
|
||||||
None
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log::warn!("no monitors found, falling back to windowed mode");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log::info!("starting in windowed mode");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let window = event_loop.create_window(window_attributes).unwrap();
|
|
||||||
|
|
||||||
let size = window.inner_size();
|
|
||||||
|
|
||||||
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
|
||||||
backends: wgpu::Backends::BROWSER_WEBGPU | wgpu::Backends::VULKAN | wgpu::Backends::GL,
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create a surface with `create_surface_unsafe` to get a surface with 'static lifetime
|
|
||||||
// It should never outlive the window it's created from
|
|
||||||
let surface = unsafe {
|
|
||||||
let target = wgpu::SurfaceTargetUnsafe::from_window(&window).unwrap();
|
|
||||||
instance.create_surface_unsafe(target).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let adapter = instance.request_adapter(
|
|
||||||
&wgpu::RequestAdapterOptions {
|
|
||||||
power_preference: wgpu::PowerPreference::HighPerformance,
|
|
||||||
compatible_surface: Some(&surface),
|
|
||||||
force_fallback_adapter: false,
|
|
||||||
},
|
|
||||||
).block_on().unwrap();
|
|
||||||
|
|
||||||
let (device, queue) = adapter.request_device(
|
|
||||||
&wgpu::DeviceDescriptor {
|
|
||||||
label: None,
|
|
||||||
required_features: wgpu::Features::empty(),
|
|
||||||
required_limits: wgpu::Limits::downlevel_defaults(),
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
).block_on().unwrap();
|
|
||||||
|
|
||||||
let surface_config = surface.get_default_config(&adapter, size.width, size.height).unwrap();
|
|
||||||
surface.configure(&device, &surface_config);
|
|
||||||
|
|
||||||
Self { window, instance, surface, device, queue, surface_config, size }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resize(&mut self, size: PhysicalSize<u32>) {
|
|
||||||
if size.width == 0 || size.height == 0 {
|
|
||||||
log::warn!("Ignoring resize event with zero width or height");
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if self.size == size {
|
|
||||||
log::warn!("Ignoring resize event with same size");
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log::debug!("resizing surface to {:?}", size);
|
|
||||||
self.size = size;
|
|
||||||
self.surface_config.width = size.width;
|
|
||||||
self.surface_config.height = size.height;
|
|
||||||
self.surface.configure(&self.device, &self.surface_config);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reconfigure(&self) {
|
|
||||||
self.surface.configure(&self.device, &self.surface_config);
|
|
||||||
}
|
|
||||||
|
|
||||||
//getters:
|
|
||||||
pub fn size(&self) -> PhysicalSize<u32> {
|
|
||||||
self.size
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn window(&self) -> &Window {
|
|
||||||
&self.window
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn surface(&self) -> &wgpu::Surface<'static> {
|
|
||||||
&self.surface
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn device(&self) -> &wgpu::Device {
|
|
||||||
&self.device
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn queue(&self) -> &wgpu::Queue {
|
|
||||||
&self.queue
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn surface_config(&self) -> &wgpu::SurfaceConfiguration {
|
|
||||||
&self.surface_config
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use glam::{IVec3, Vec3};
|
use glam::IVec3;
|
||||||
use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View};
|
use shipyard::{AllStoragesView, NonSendSync, Unique, UniqueView, UniqueViewMut, View};
|
||||||
use kubi_shared::{chunk::CHUNK_SIZE, transform::Transform};
|
use kubi_shared::transform::Transform;
|
||||||
use crate::{camera::Camera, settings::GameSettings, world::{ChunkMeshStorage, ChunkStorage}};
|
use crate::{camera::Camera, settings::GameSettings, world::{ChunkMeshStorage, ChunkStorage}};
|
||||||
use super::Renderer;
|
use super::Renderer;
|
||||||
|
|
||||||
|
@ -43,37 +43,7 @@ pub fn draw_world(
|
||||||
settings: UniqueView<GameSettings>,
|
settings: UniqueView<GameSettings>,
|
||||||
mut trans_queue: UniqueViewMut<TransChunkQueue>,
|
mut trans_queue: UniqueViewMut<TransChunkQueue>,
|
||||||
) {
|
) {
|
||||||
let camera = camera.iter().next().expect("No cameras in the scene");
|
//TODO
|
||||||
let camera_matrix = camera.view_matrix * camera.perspective_matrix;
|
|
||||||
|
|
||||||
for (&position, chunk) in &chunks.chunks {
|
|
||||||
if let Some(key) = chunk.mesh_index {
|
|
||||||
let mesh = meshes.get(key).expect("Mesh index pointing to nothing");
|
|
||||||
let world_position = position.as_vec3() * CHUNK_SIZE as f32;
|
|
||||||
|
|
||||||
//Skip if mesh is empty
|
|
||||||
if mesh.main.index.size() == 0 && mesh.trans.index.size() == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
//Frustum culling
|
|
||||||
let minp = world_position;
|
|
||||||
let maxp = world_position + Vec3::splat(CHUNK_SIZE as f32);
|
|
||||||
if !camera.frustum.is_box_visible(minp, maxp) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
//Draw chunk mesh
|
|
||||||
if mesh.main.index.size() > 0 {
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO trans chunks
|
|
||||||
// if mesh.trans_index_buffer.len() > 0 {
|
|
||||||
// trans_queue.0.push(position);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue