Compare commits
2 commits
e589fd881c
...
a5a3c63214
Author | SHA1 | Date | |
---|---|---|---|
a5a3c63214 | |||
32bba75aa7 |
9 changed files with 314 additions and 14 deletions
|
@ -34,7 +34,7 @@ chrono = { version = "0.4.35", features = ["serde"] }
|
|||
anyhow = { version = "1.0.86", features = ["backtrace"] }
|
||||
indexmap = { version = "2.2.6", features = ["rayon"] }
|
||||
shaderc = { version = "0.8.3", features = ["build-from-source"] }
|
||||
rusqlite = { version = "0.32.0", features = ["bundled"] }
|
||||
rusqlite = { version = "0.33.0", features = ["bundled"] }
|
||||
cgmath = "0.18.0"
|
||||
http = "1.1.0"
|
||||
iterchunks = "0.5.0"
|
||||
|
@ -57,6 +57,7 @@ syn = { version = "2.0.67", features = ["extra-traits", "full"] }
|
|||
quote = "1.0.35"
|
||||
proc-macro2 = "1.0.86"
|
||||
downcast-rs = "1.2.1"
|
||||
plexus = { version = "0.0.11", default-features = false }
|
||||
|
||||
utilities = { git = "https://gavania.de/hodasemi/utilities.git" }
|
||||
vulkan-rs = { git = "https://gavania.de/hodasemi/vulkan_lib.git" }
|
||||
|
|
|
@ -218,7 +218,7 @@ impl Rasterizer {
|
|||
)
|
||||
.add_sub_pass(
|
||||
SubPass::builder(width, height)
|
||||
.set_prepared_targets(images, 0, [0.1, 0.1, 0.1, 1.0], true)
|
||||
.set_prepared_targets(images, 0, None)
|
||||
.build(device)?,
|
||||
)
|
||||
.build(device)?;
|
||||
|
|
|
@ -7,16 +7,16 @@ use utilities::prelude::cgmath::{Vector3, Zero};
|
|||
|
||||
use super::{
|
||||
super::{
|
||||
ExtensionCheck, RenderingFrontEnd,
|
||||
shared::{
|
||||
bufferhandler::*, position_buffer_reader::PositionBuffer,
|
||||
safecommandbuffer::SafeCommandBuffer,
|
||||
},
|
||||
ExtensionCheck, RenderingFrontEnd,
|
||||
},
|
||||
SceneInfo,
|
||||
lights::light_wrapper::{LightData, LightHandler},
|
||||
pipelines::RasterizerPipelines,
|
||||
rasterizershader::RasterizerShader,
|
||||
SceneInfo,
|
||||
};
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
@ -126,7 +126,10 @@ impl TraditionalRasterizer {
|
|||
render_scale: f32,
|
||||
sample_count: VkSampleCountFlags,
|
||||
) -> Result<(RenderTarget, usize)> {
|
||||
assert_eq!(render_scale, 1.0, "Traditional Rasterizer: render_scale needs an in between image to render to, then blit this into swapchain image");
|
||||
assert_eq!(
|
||||
render_scale, 1.0,
|
||||
"Traditional Rasterizer: render_scale needs an in between image to render to, then blit this into swapchain image"
|
||||
);
|
||||
|
||||
let width = (screen_width * render_scale) as u32;
|
||||
let height = (screen_height * render_scale) as u32;
|
||||
|
@ -142,7 +145,7 @@ impl TraditionalRasterizer {
|
|||
.add_sub_pass(
|
||||
SubPass::builder(width, height)
|
||||
// swapchain color target
|
||||
.set_prepared_targets(images, 0, [0.0, 0.0, 0.0, 0.0], true)
|
||||
.set_prepared_targets(images, 0, None)
|
||||
// position target
|
||||
.add_target_info(CustomTarget {
|
||||
usage: VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
|
||||
|
|
|
@ -6,6 +6,9 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
plexus.workspace = true
|
||||
utilities.workspace = true
|
||||
|
||||
ecs = { path = "../ecs" }
|
||||
context = { path = "../context" }
|
||||
engine = { path = "../engine" }
|
||||
|
|
53
skybox/build.rs
Normal file
53
skybox/build.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
use std::{fs, path::Path, process::Command};
|
||||
|
||||
const FILE_ENDINGS: &'static [&'static str] = &[
|
||||
"vert", "frag", "geom", "comp", "rchit", "rmiss", "rgen", "rahit",
|
||||
];
|
||||
|
||||
fn find_shader_files(path: impl AsRef<Path>) -> Vec<String> {
|
||||
let mut v = Vec::new();
|
||||
|
||||
if !path.as_ref().is_dir() {
|
||||
panic!("path ({:?}) is not a directory!", path.as_ref());
|
||||
}
|
||||
|
||||
for entry in fs::read_dir(path).unwrap() {
|
||||
let child_path = entry.unwrap().path();
|
||||
|
||||
if child_path.is_dir() {
|
||||
v.extend(find_shader_files(child_path));
|
||||
} else if child_path.is_file() {
|
||||
for ending in FILE_ENDINGS.iter() {
|
||||
if child_path.extension().unwrap() == *ending {
|
||||
v.push(child_path.to_str().unwrap().to_string());
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v
|
||||
}
|
||||
|
||||
fn compile_shader(shader_files: &[String]) {
|
||||
Command::new("glslangValidator")
|
||||
.arg("--help")
|
||||
.output()
|
||||
.expect("Failed to execute glslangValidator. Maybe you need to install it first?");
|
||||
|
||||
for shader in shader_files {
|
||||
Command::new("glslangValidator")
|
||||
.arg("-V")
|
||||
.arg(shader)
|
||||
.arg("-o")
|
||||
.arg(&format!("{}.spv", shader))
|
||||
.output()
|
||||
.expect(&format!("Failed to compile {}", shader));
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let shader_files = find_shader_files("shader");
|
||||
compile_shader(&shader_files);
|
||||
}
|
12
skybox/shader/skybox.frag
Normal file
12
skybox/shader/skybox.frag
Normal file
|
@ -0,0 +1,12 @@
|
|||
#version 450
|
||||
|
||||
layout (binding = 1) uniform samplerCube sampler_cube_map;
|
||||
|
||||
layout (location = 0) in vec3 in_uvw;
|
||||
|
||||
layout (location = 0) out vec4 out_frag_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
out_frag_color = texture(sampler_cube_map, in_uvw);
|
||||
}
|
27
skybox/shader/skybox.vert
Normal file
27
skybox/shader/skybox.vert
Normal file
|
@ -0,0 +1,27 @@
|
|||
#version 450
|
||||
|
||||
layout (location = 0) in vec3 in_position;
|
||||
|
||||
layout (set = 0, binding = 0) uniform CameraProperties
|
||||
{
|
||||
mat4 view;
|
||||
mat4 proj;
|
||||
mat4 vp;
|
||||
|
||||
mat4 inv_view;
|
||||
mat4 inv_proj;
|
||||
} globals;
|
||||
|
||||
layout (location = 0) out vec3 out_uvw;
|
||||
|
||||
void main()
|
||||
{
|
||||
out_uvw = in_position;
|
||||
|
||||
// Convert cubemap coordinates into Vulkan coordinate space
|
||||
out_uvw.xy *= -1.0;
|
||||
|
||||
// Remove translation from view matrix
|
||||
mat4 view_mat = mat4(mat3(globals.view));
|
||||
gl_Position = globals.proj * view_mat * vec4(in_position, 1.0);
|
||||
}
|
|
@ -1,8 +1,16 @@
|
|||
mod vertex;
|
||||
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
use anyhow::Result;
|
||||
use context::prelude::*;
|
||||
use ecs::*;
|
||||
use engine::prelude::{shader_type::*, *};
|
||||
use plexus::primitive::{
|
||||
cube::{Bounds, Cube},
|
||||
decompose::Triangulate,
|
||||
generate::PolygonsWithPosition,
|
||||
};
|
||||
use vertex::VertexPoint;
|
||||
|
||||
pub struct SkyBoxImages {
|
||||
left: PathBuf,
|
||||
|
@ -29,15 +37,29 @@ impl<T: ExactSizeIterator<Item = PathBuf>> From<T> for SkyBoxImages {
|
|||
}
|
||||
|
||||
pub struct SkyBox {
|
||||
cube_map: Arc<Image>,
|
||||
_cube_map: Arc<Image>,
|
||||
cube_buffer: Arc<Buffer<VertexPoint>>,
|
||||
|
||||
vertex_shader: Arc<ShaderModule<Vertex>>,
|
||||
fragment_shader: Arc<ShaderModule<Fragment>>,
|
||||
|
||||
render_target: TargetMode<RenderTarget>,
|
||||
pipeline: TargetMode<Arc<Pipeline>>,
|
||||
descriptor_set: Arc<DescriptorSet>,
|
||||
}
|
||||
|
||||
impl SkyBox {
|
||||
pub fn new(world: &mut WorldBuilder, images: impl Into<SkyBoxImages>) -> Result<()> {
|
||||
let images = images.into();
|
||||
let context = world.resources.get_mut::<Context>();
|
||||
let sample_count = world
|
||||
.resources
|
||||
.get::<EngineSettings>()
|
||||
.graphics_info()?
|
||||
.sample_count;
|
||||
|
||||
let context = world.resources.get_mut_unchecked::<Context>();
|
||||
context.render_core_mut().add_render_routine::<Self>(1);
|
||||
|
||||
let images = images.into();
|
||||
let cube_map = Image::cube_map([
|
||||
images.left.try_into()?,
|
||||
images.right.try_into()?,
|
||||
|
@ -51,22 +73,170 @@ impl SkyBox {
|
|||
.attach_pretty_sampler(context.device())?
|
||||
.build(context.device(), context.queue())?;
|
||||
|
||||
let me = Self { cube_map };
|
||||
let descriptor_set_layout = DescriptorSetLayout::builder()
|
||||
.add_layout_binding(
|
||||
0,
|
||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
VK_SHADER_STAGE_VERTEX_BIT,
|
||||
0,
|
||||
)
|
||||
.add_layout_binding(
|
||||
1,
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
0,
|
||||
)
|
||||
.build(context.device().clone())?;
|
||||
|
||||
let render_target = Self::create_render_target(context, sample_count)?;
|
||||
|
||||
let pipeline_layout = PipelineLayout::builder()
|
||||
.add_descriptor_set_layout(&descriptor_set_layout)
|
||||
.build(context.device().clone())?;
|
||||
|
||||
let pipeline =
|
||||
Self::create_pipeline(context, sample_count, &render_target, &pipeline_layout)?;
|
||||
|
||||
let descriptor_pool = DescriptorPool::builder()
|
||||
.set_layout(descriptor_set_layout)
|
||||
.build(context.device().clone())?;
|
||||
let descriptor_set = descriptor_pool.prepare_set().allocate()?;
|
||||
|
||||
let scene = world.resources.get::<Scene>();
|
||||
let view = scene.view();
|
||||
|
||||
descriptor_set.update(&[
|
||||
DescriptorWrite::uniform_buffers(0, &[view.buffer()]),
|
||||
DescriptorWrite::combined_samplers(1, &[&cube_map]),
|
||||
])?;
|
||||
|
||||
let cube_mesh = Cube::new()
|
||||
.polygons_with_position_from(Bounds::unit_radius())
|
||||
.triangulate()
|
||||
.map(|d| {
|
||||
vec![
|
||||
[d.a.0.into_inner(), d.a.1.into_inner(), d.a.2.into_inner()],
|
||||
[d.b.0.into_inner(), d.b.1.into_inner(), d.b.2.into_inner()],
|
||||
[d.c.0.into_inner(), d.c.1.into_inner(), d.c.2.into_inner()],
|
||||
]
|
||||
})
|
||||
.flatten()
|
||||
.map(|t| VertexPoint::new(t[0] as f32, t[1] as f32, t[2] as f32))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let cube_buffer = Buffer::builder()
|
||||
.set_memory_usage(MemoryUsage::GpuOnly)
|
||||
.set_sharing_mode(VK_SHARING_MODE_EXCLUSIVE)
|
||||
.set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
||||
.set_data(&cube_mesh)
|
||||
.build(context.device().clone())?;
|
||||
|
||||
let me = Self {
|
||||
_cube_map: cube_map,
|
||||
cube_buffer,
|
||||
|
||||
render_target,
|
||||
pipeline,
|
||||
descriptor_set,
|
||||
};
|
||||
world.resources.insert(me);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_render_target(
|
||||
context: &Context,
|
||||
sample_count: VkSampleCountFlags,
|
||||
) -> Result<TargetMode<RenderTarget>> {
|
||||
context.images().execute(|images| {
|
||||
let first = images.first().unwrap();
|
||||
|
||||
let width = first.width();
|
||||
let height = first.height();
|
||||
let format = first.vk_format();
|
||||
|
||||
if sample_count == VK_SAMPLE_COUNT_1_BIT {
|
||||
RenderTarget::builder()
|
||||
.add_sub_pass(
|
||||
SubPass::builder(width, height)
|
||||
// render directly into swapchain target if there is no multi sampling
|
||||
.set_prepared_targets(images, 0, None)
|
||||
.use_queue(context.queue().clone())
|
||||
.build(context.device())?,
|
||||
)
|
||||
.build(context.device())
|
||||
} else {
|
||||
RenderTarget::builder()
|
||||
.add_sub_pass(
|
||||
SubPass::builder(width, height)
|
||||
// render into multi sampled images
|
||||
.add_target_info(CustomTarget {
|
||||
usage: VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT.into(),
|
||||
format,
|
||||
clear_on_load: true,
|
||||
store_on_save: true,
|
||||
attach_sampler: false,
|
||||
use_as_input: false,
|
||||
clear_value: ClearValue::Color([0.0, 0.0, 0.0, 0.0]),
|
||||
})
|
||||
.set_sample_count(sample_count)
|
||||
// resolve multi sampling into swapchain image
|
||||
.add_resolve_targets((images, false))
|
||||
.use_queue(context.queue().clone())
|
||||
.build(context.device())?,
|
||||
)
|
||||
.build(context.device())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn create_pipeline(
|
||||
context: &Context,
|
||||
sample_count: VkSampleCountFlags,
|
||||
render_target: &TargetMode<RenderTarget>,
|
||||
pipeline_layout: &Arc<PipelineLayout>,
|
||||
) -> Result<TargetMode<Arc<Pipeline>>> {
|
||||
render_target.execute(|render_target| {
|
||||
Pipeline::new_graphics()
|
||||
.default_multisample(sample_count)
|
||||
.default_rasterization(VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE)
|
||||
.build(
|
||||
context.device().clone(),
|
||||
pipeline_layout,
|
||||
render_target.render_pass(),
|
||||
0,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TScene for SkyBox {
|
||||
fn process(
|
||||
&mut self,
|
||||
buffer_recorder: &mut CommandBufferRecorder<'_>,
|
||||
images: &TargetMode<Vec<Arc<Image>>>,
|
||||
_images: &TargetMode<Vec<Arc<Image>>>,
|
||||
indices: &TargetMode<usize>,
|
||||
world: &World,
|
||||
_world: &World,
|
||||
) -> Result<()> {
|
||||
todo!()
|
||||
self.render_target
|
||||
.chain(indices)
|
||||
.chain(&self.pipeline)
|
||||
.unfold()
|
||||
.execute(|(render_target, index, pipeline)| {
|
||||
render_target.begin(buffer_recorder, VK_SUBPASS_CONTENTS_INLINE, ***index);
|
||||
|
||||
buffer_recorder.bind_pipeline(pipeline)?;
|
||||
buffer_recorder.bind_descriptor_sets_minimal(&[&self.descriptor_set]);
|
||||
|
||||
buffer_recorder.bind_vertex_buffer(&self.cube_buffer);
|
||||
buffer_recorder.draw_complete_single_instance(self.cube_buffer.size() as u32);
|
||||
|
||||
render_target.end(buffer_recorder);
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn resize(
|
||||
|
|
31
skybox/src/vertex.rs
Normal file
31
skybox/src/vertex.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use engine::prelude::*;
|
||||
use utilities::impl_reprc;
|
||||
|
||||
impl_reprc!(
|
||||
pub struct VertexPoint {
|
||||
#[assume_reprc]
|
||||
v: [f32; 4],
|
||||
}
|
||||
);
|
||||
|
||||
impl VertexPoint {
|
||||
pub fn new(x: impl Into<f32>, y: impl Into<f32>, z: impl Into<f32>) -> Self {
|
||||
VertexPoint {
|
||||
v: [x.into(), y.into(), z.into(), 1.0],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VertexInputDescription for VertexPoint {
|
||||
fn attributes() -> Vec<VkVertexInputAttributeDescription> {
|
||||
vec![
|
||||
// position
|
||||
VkVertexInputAttributeDescription {
|
||||
location: 0,
|
||||
binding: 0,
|
||||
format: VK_FORMAT_R32G32B32_SFLOAT,
|
||||
offset: 0,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue