|
|
|
@ -2,7 +2,7 @@ use std::{collections::HashMap, iter};
|
|
|
|
|
|
|
|
|
|
use ash::{
|
|
|
|
|
khr::{surface, swapchain},
|
|
|
|
|
vk::{self, DescriptorSet},
|
|
|
|
|
vk::{self},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
@ -19,11 +19,22 @@ use super::{
|
|
|
|
|
|
|
|
|
|
/// Anything can be rendered in world
|
|
|
|
|
pub trait WorldComponent {
|
|
|
|
|
/// Return the types and number of descriptors this component wants to use
|
|
|
|
|
fn descriptors(&self) -> HashMap<vk::DescriptorType, u32>;
|
|
|
|
|
|
|
|
|
|
/// Return the layout of the descriptor set this component wants to used,
|
|
|
|
|
/// the used descriptors should match [`WorldComponent::descriptors`]
|
|
|
|
|
fn desc_layout(&self, ctx: &RenderCtx) -> vk::DescriptorSetLayout;
|
|
|
|
|
|
|
|
|
|
/// Skybox is passed in for reflections
|
|
|
|
|
/// Write to this components descriptor set, the passed descriptor set
|
|
|
|
|
/// is layed out like was requested in [`WorldComponent::desc_layout`]
|
|
|
|
|
///
|
|
|
|
|
/// Skybox is currently passed in for reflections
|
|
|
|
|
///
|
|
|
|
|
/// Note:
|
|
|
|
|
/// This api might be changed to having this functions return the
|
|
|
|
|
/// [`vk::WriteDescriptorSet`]s it wants, so that the render context
|
|
|
|
|
/// does not have to be passed in
|
|
|
|
|
fn write_desc_set(
|
|
|
|
|
&self,
|
|
|
|
|
ctx: &RenderCtx,
|
|
|
|
@ -31,8 +42,16 @@ pub trait WorldComponent {
|
|
|
|
|
skybox: (vk::ImageView, vk::Sampler),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/// Return the pipeline and pipeline layout this component wants to use,
|
|
|
|
|
/// this function is called every frame, so the component should not
|
|
|
|
|
/// contruct the pipeline in this function, but merely return an earlier
|
|
|
|
|
/// contructed pipeline
|
|
|
|
|
fn pipeline(&self) -> (vk::Pipeline, vk::PipelineLayout);
|
|
|
|
|
|
|
|
|
|
/// Return the constants that must be pushed to the shader,
|
|
|
|
|
/// camera, screen resolution and base color are provided
|
|
|
|
|
/// as they are relevant for most shaders.
|
|
|
|
|
/// Return in `(stage, offset, data)`
|
|
|
|
|
fn push_constants(
|
|
|
|
|
&self,
|
|
|
|
|
camera: &Camera,
|
|
|
|
@ -41,12 +60,19 @@ pub trait WorldComponent {
|
|
|
|
|
) -> Vec<(vk::ShaderStageFlags, u32, Vec<u8>)>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A [`WorldComponent`] and its associated [`vk::DescriptorSet`]
|
|
|
|
|
pub struct Component {
|
|
|
|
|
pub inner: Box<dyn WorldComponent>,
|
|
|
|
|
pub desc_set: DescriptorSet,
|
|
|
|
|
pub desc_set: vk::DescriptorSet,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Game<RenderAvailable> {
|
|
|
|
|
/// Start the loading of a world
|
|
|
|
|
///
|
|
|
|
|
/// FIXME: This should not remain in [`crate::render`],
|
|
|
|
|
/// the function here should be replaced with one for render
|
|
|
|
|
/// specifically and this should be moved to [`crate::game`]
|
|
|
|
|
/// and call the render specific function from there
|
|
|
|
|
pub fn start_load_world(self) -> Game<LoadingWorld> {
|
|
|
|
|
let Self {
|
|
|
|
|
state:
|
|
|
|
@ -118,6 +144,8 @@ impl Game<RenderAvailable> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Game<LoadingWorld> {
|
|
|
|
|
/// Add a component to be rendered to the world, see [`crate::render::cube`]
|
|
|
|
|
/// for an example for such a component
|
|
|
|
|
pub fn add_component<C: WorldComponent + 'static>(&mut self, component: C) {
|
|
|
|
|
let Self {
|
|
|
|
|
state:
|
|
|
|
@ -136,6 +164,12 @@ impl Game<LoadingWorld> {
|
|
|
|
|
components.push(Box::new(component));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Finish loading of a world, it is now ready for play
|
|
|
|
|
///
|
|
|
|
|
/// FIXME: This should not remain in [`crate::render`],
|
|
|
|
|
/// the function here should be replaced with one for render
|
|
|
|
|
/// specifically and this should be moved to [`crate::game`]
|
|
|
|
|
/// and call the render specific function from there
|
|
|
|
|
pub fn start_world(self) -> Game<InWorld> {
|
|
|
|
|
println!("Starting world");
|
|
|
|
|
let Self {
|
|
|
|
|