diff --git a/README.md b/README.md index 1a7a91c..5aa6878 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A framework for creative coding, mainly targeted at demoscene productions. Currently in a very early stage of development. -![screenshot](screenshot.png) +![screenshot2](screenshot2.png) ## Features @@ -27,11 +27,10 @@ The development platform is Windows, but Linux and MacOS should work as well. Anything that supports Vulkan. -Known limitations: Radeon RX cards crash in full screen. - ## License MIT +![screenshot](screenshot.png) diff --git a/crates/bitang/src/control/controls.rs b/crates/bitang/src/control/controls.rs index 47d33e4..5626538 100644 --- a/crates/bitang/src/control/controls.rs +++ b/crates/bitang/src/control/controls.rs @@ -331,6 +331,7 @@ pub enum GlobalType { ChartTime, ProjectionFromModel, LightProjectionFromModel, + LightProjectionFromWorld, ProjectionFromCamera, CameraFromModel, CameraFromWorld, @@ -352,6 +353,7 @@ impl GlobalType { "chart_time" => Ok(GlobalType::ChartTime), "projection_from_model" => Ok(GlobalType::ProjectionFromModel), "light_projection_from_model" => Ok(GlobalType::LightProjectionFromModel), + "light_projection_from_world" => Ok(GlobalType::LightProjectionFromWorld), "projection_from_camera" => Ok(GlobalType::ProjectionFromCamera), "camera_from_model" => Ok(GlobalType::CameraFromModel), "camera_from_world" => Ok(GlobalType::CameraFromWorld), @@ -395,6 +397,7 @@ impl Globals { GlobalType::ChartTime => slice::from_ref(&self.chart_time), GlobalType::ProjectionFromModel => self.projection_from_model.as_ref(), GlobalType::LightProjectionFromModel => self.light_projection_from_model.as_ref(), + GlobalType::LightProjectionFromWorld => self.light_projection_from_world.as_ref(), GlobalType::ProjectionFromCamera => self.projection_from_camera.as_ref(), GlobalType::CameraFromModel => self.camera_from_model.as_ref(), GlobalType::CameraFromWorld => self.camera_from_world.as_ref(), diff --git a/crates/bitang/src/file/resource_repository.rs b/crates/bitang/src/file/resource_repository.rs index 67aa070..106aa5a 100644 --- a/crates/bitang/src/file/resource_repository.rs +++ b/crates/bitang/src/file/resource_repository.rs @@ -145,11 +145,11 @@ impl ResourceRepository { } fn to_vec3_neg(v: &russimp::Vector3D) -> [f32; 3] { - [-v.x, -v.z, -v.y] + [v.x, v.y, -v.z] } fn to_vec3_b(v: &russimp::Vector3D) -> [f32; 3] { - [v.x, v.z, v.y] + [v.x, v.y, -v.z] } fn to_vec2(v: &russimp::Vector3D) -> [f32; 2] { [v.x, v.y] @@ -168,8 +168,8 @@ fn load_mesh_collection( PostProcess::Triangulate, PostProcess::JoinIdenticalVertices, PostProcess::SortByPrimitiveType, - PostProcess::GenerateSmoothNormals, PostProcess::FlipUVs, + PostProcess::OptimizeMeshes, ], "", )?; diff --git a/crates/bitang/src/render/chart.rs b/crates/bitang/src/render/chart.rs index 0643d33..0d495ce 100644 --- a/crates/bitang/src/render/chart.rs +++ b/crates/bitang/src/render/chart.rs @@ -44,7 +44,7 @@ impl Chart { pub fn render(&self, context: &mut RenderContext) -> Result<()> { for image in &self.images { - image.enforce_size_rule(context)?; + image.enforce_size_rule(&context.vulkan_context, context.screen_viewport.dimensions)?; } for buffer_generator in &self.buffer_generators { buffer_generator.generate()?; diff --git a/crates/bitang/src/render/image.rs b/crates/bitang/src/render/image.rs index f8fcf69..e0c29e0 100644 --- a/crates/bitang/src/render/image.rs +++ b/crates/bitang/src/render/image.rs @@ -1,4 +1,4 @@ -use crate::render::vulkan_window::RenderContext; +use crate::render::vulkan_window::VulkanContext; use anyhow::{Context, Result}; use serde::Deserialize; use std::cell::{Cell, RefCell}; @@ -146,7 +146,11 @@ impl Image { } /// Enforce the size rule. - pub fn enforce_size_rule(&self, context: &RenderContext) -> Result<()> { + pub fn enforce_size_rule( + &self, + context: &VulkanContext, + viewport_size: [f32; 2], + ) -> Result<()> { // Only attachments need to be resized. let ImageInner::SingleLevelAttachment(attachment) = &self.inner else { return Ok(()); @@ -156,12 +160,10 @@ impl Image { let size = match self.size_rule { ImageSizeRule::Fixed(w, h) => [w, h], ImageSizeRule::CanvasRelative(r) => { - let [w, h] = context.screen_viewport.dimensions; - [(w * r) as u32, (h * r) as u32] + [(viewport_size[0] * r) as u32, (viewport_size[1] * r) as u32] } ImageSizeRule::At4k(w, h) => { - let [sw, _sh] = context.screen_viewport.dimensions; - let scale = 4096.0 / sw; + let scale = 4096.0 / viewport_size[0]; [(w as f32 * scale) as u32, (h as f32 * scale) as u32] } }; @@ -176,10 +178,10 @@ impl Image { // Create a new image with the correct size. let image = AttachmentImage::with_usage( - context.vulkan_context.context.memory_allocator(), + context.context.memory_allocator(), size, self.vulkan_format, - ImageUsage::SAMPLED | ImageUsage::TRANSFER_DST, + ImageUsage::SAMPLED | ImageUsage::TRANSFER_DST | ImageUsage::TRANSFER_SRC, )?; *attachment = Some(image); self.size.set(Some((size[0], size[1]))); diff --git a/crates/bitang/src/render/vulkan_window.rs b/crates/bitang/src/render/vulkan_window.rs index d8c0f28..e7da13a 100644 --- a/crates/bitang/src/render/vulkan_window.rs +++ b/crates/bitang/src/render/vulkan_window.rs @@ -31,7 +31,7 @@ use winit::{ const START_IN_DEMO_MODE: bool = false; const BORDERLESS_FULL_SCREEN: bool = true; -pub const FRAMEDUMP_MODE: bool = !true; +pub const FRAMEDUMP_MODE: bool = false; pub const FRAMEDUMP_WIDTH: u32 = 3840; pub const FRAMEDUMP_HEIGHT: u32 = 2160; pub const FRAMEDUMP_FPS: u32 = 60; @@ -108,17 +108,11 @@ impl VulkanWindow { ); let swapchain_render_targets_by_id = if FRAMEDUMP_MODE { - let size = (FRAMEDUMP_WIDTH, FRAMEDUMP_HEIGHT); - let screen_render_target = Image::new_attachment( - SCREEN_RENDER_TARGET_ID, - ImageFormat::Rgba8U, - ImageSizeRule::Fixed(size.0, size.1), - ); - let depth_render_target = Image::new_attachment( - SCREEN_DEPTH_RENDER_TARGET_ID, - ImageFormat::Depth32F, - ImageSizeRule::Fixed(size.0, size.1), - ); + let size = ImageSizeRule::Fixed(FRAMEDUMP_WIDTH, FRAMEDUMP_HEIGHT); + let screen_render_target = + Image::new_attachment(SCREEN_RENDER_TARGET_ID, SCREEN_COLOR_FORMAT, size); + let depth_render_target = + Image::new_attachment(SCREEN_DEPTH_RENDER_TARGET_ID, DEPTH_BUFFER_FORMAT, size); HashMap::from([ (screen_render_target.id.clone(), screen_render_target), (depth_render_target.id.clone(), depth_render_target), diff --git a/crates/bitang/src/tool/demo_tool.rs b/crates/bitang/src/tool/demo_tool.rs index 01f5172..f668fca 100644 --- a/crates/bitang/src/tool/demo_tool.rs +++ b/crates/bitang/src/tool/demo_tool.rs @@ -2,6 +2,7 @@ use crate::control::controls::{ControlRepository, ControlSet}; use crate::control::{ControlId, ControlIdPartType}; use crate::file::resource_repository::ResourceRepository; use crate::render::chart::Chart; +use crate::render::image::ImageSizeRule; use crate::render::project::Project; use crate::render::vulkan_window::{ PaintResult, RenderContext, VulkanApp, VulkanContext, FRAMEDUMP_FPS, FRAMEDUMP_HEIGHT, @@ -216,9 +217,14 @@ impl DemoTool { } fn save_frame_buffer_to_file(mut content: Vec, frame_number: usize) { - // Fix the alpha channel for i in 0..content.len() / 4 { + // Fix the alpha channel content[i * 4 + 3] = 255; + + // Fix the alpha channel + let r = content[i * 4 + 0]; + content[i * 4 + 0] = content[i * 4 + 2]; + content[i * 4 + 2] = r; } let path = format!("framedump/dump-{:0>8}.png", frame_number); @@ -351,15 +357,19 @@ impl DemoTool { let target_image = vulkan_context .swapchain_render_targets_by_id .get(SCREEN_RENDER_TARGET_ID) - .unwrap() - .get_view() .unwrap(); - let size = target_image.dimensions(); + let size = match target_image.size_rule { + ImageSizeRule::Fixed(w, h) => [w, h], + _ => panic!("Screen render target must have a fixed size"), + }; let screen_viewport = Viewport { origin: [0.0, 0.0], - dimensions: [size.width() as f32, size.height() as f32], + dimensions: [size[0] as f32, size[1] as f32], depth_range: 0.0..1.0, }; + target_image + .enforce_size_rule(&vulkan_context, screen_viewport.dimensions) + .unwrap(); // Make command buffer let mut command_builder = AutoCommandBufferBuilder::primary( @@ -372,7 +382,7 @@ impl DemoTool { // Render content let mut context = RenderContext { vulkan_context, - screen_buffer: target_image, + screen_buffer: target_image.get_view().unwrap(), screen_viewport, command_builder: &mut command_builder, globals: Default::default(), diff --git a/screenshot2.png b/screenshot2.png new file mode 100644 index 0000000..27663e8 Binary files /dev/null and b/screenshot2.png differ