wip skybox loading

This commit is contained in:
2025-11-02 12:29:00 -05:00
parent b40fce40a5
commit 3ed3fbd38a
6 changed files with 59 additions and 32 deletions

BIN
assets/sky-test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -4,7 +4,8 @@
@group(0) @binding(1) var output: texture_storage_2d<rgba32float, write>; @group(0) @binding(1) var output: texture_storage_2d<rgba32float, write>;
@group(0) @binding(2) var<uniform> config: TracerUniforms; @group(0) @binding(2) var<uniform> config: TracerUniforms;
@group(0) @binding(3) var skybox_texture: texture_cube<f32>;
@group(0) @binding(4) var skybox_sampler: sampler;
struct View { struct View {
view_proj: mat4x4<f32>, view_proj: mat4x4<f32>,

View File

@@ -36,7 +36,12 @@ impl Plugin for Blackhole {
} }
} }
fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>, window: Single<&Window, With<PrimaryWindow>>) { fn setup(
mut commands: Commands,
mut images: ResMut<Assets<Image>>,
window: Single<&Window, With<PrimaryWindow>>,
asset_server: Res<AssetServer>,
) {
commands.spawn(( commands.spawn((
PerfUiRoot::default(), PerfUiRoot::default(),
PerfUiEntryFPS::default(), PerfUiEntryFPS::default(),
@@ -70,6 +75,7 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>, window: Sing
let img0 = images.add(image.clone()); let img0 = images.add(image.clone());
let img1 = images.add(image); let img1 = images.add(image);
let skybox = asset_server.load("sky-test.png");
commands.spawn(( commands.spawn((
Name::new("Render Sprite"), Name::new("Render Sprite"),
Sprite { Sprite {
@@ -97,5 +103,9 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>, window: Sing
)) ))
.insert(Camera { order: -1, ..default() }); .insert(Camera { order: -1, ..default() });
commands.insert_resource(TracerRenderTextures(img0, img1)); commands.insert_resource(TracerRenderTextures {
main: img0,
secondary: img1,
skybox,
});
} }

View File

@@ -1,4 +1,4 @@
use bevy::{prelude::*, render::render_resource::encase::private::ShaderType}; use bevy::prelude::*;
#[derive(Component)] #[derive(Component)]
pub struct RTCamera; pub struct RTCamera;

View File

@@ -7,7 +7,7 @@ use bevy::{
}, },
}; };
use crate::render::pipeline::{TracerImageBindGroups, TracerPipeline}; use crate::render::pipeline::{TracerImageBindGroups, TracerPipeline, TracerRenderTextures};
use crate::{SHADER_ASSET_PATH, WORKGROUP_SIZE}; use crate::{SHADER_ASSET_PATH, WORKGROUP_SIZE};
pub enum TracerState { pub enum TracerState {
@@ -36,16 +36,21 @@ impl render_graph::Node for TracerNode {
// if the corresponding pipeline has loaded, transition to the next stage // if the corresponding pipeline has loaded, transition to the next stage
match self.state { match self.state {
TracerState::Loading => { TracerState::Loading => {
match pipeline_cache.get_compute_pipeline_state(pipeline.init_pipeline) { let shader_loaded = match pipeline_cache.get_compute_pipeline_state(pipeline.init_pipeline) {
CachedPipelineState::Ok(_) => { CachedPipelineState::Ok(_) => true,
self.state = TracerState::Init;
}
// If the shader hasn't loaded yet, just wait. // If the shader hasn't loaded yet, just wait.
CachedPipelineState::Err(PipelineCacheError::ShaderNotLoaded(_)) => {} CachedPipelineState::Err(PipelineCacheError::ShaderNotLoaded(_)) => false,
CachedPipelineState::Err(err) => { CachedPipelineState::Err(err) => {
panic!("Initializing assets/{SHADER_ASSET_PATH}:\n{err}") panic!("Initializing assets/{SHADER_ASSET_PATH}:\n{err}")
} }
_ => {} _ => false,
};
let tex = world.resource::<TracerRenderTextures>();
let asset_server = world.resource::<AssetServer>();
let load_state = asset_server.get_load_state(tex.skybox.id()).unwrap();
if load_state.is_loaded() && shader_loaded {
self.state = TracerState::Init;
} }
} }
TracerState::Init => { TracerState::Init => {

View File

@@ -4,15 +4,14 @@ use bevy::{
prelude::*, prelude::*,
render::{ render::{
Render, RenderApp, RenderSet, Render, RenderApp, RenderSet,
camera::CameraProjection,
extract_resource::{ExtractResource, ExtractResourcePlugin}, extract_resource::{ExtractResource, ExtractResourcePlugin},
render_asset::RenderAssets, render_asset::RenderAssets,
render_graph::{RenderGraph, RenderLabel}, render_graph::{RenderGraph, RenderLabel},
render_resource::{ render_resource::{
BindGroup, BindGroupEntries, BindGroupLayout, BindGroupLayoutEntries, CachedComputePipelineId, BindGroup, BindGroupEntries, BindGroupLayout, BindGroupLayoutEntries, CachedComputePipelineId,
ComputePipelineDescriptor, PipelineCache, ShaderStages, ShaderType, StorageTextureAccess, TextureFormat, ComputePipelineDescriptor, PipelineCache, SamplerBindingType, ShaderStages, ShaderType,
UniformBuffer, StorageTextureAccess, TextureFormat, TextureSampleType, UniformBuffer,
binding_types::{texture_storage_2d, uniform_buffer}, binding_types::{sampler, texture_cube, texture_storage_2d, uniform_buffer},
}, },
renderer::{RenderDevice, RenderQueue}, renderer::{RenderDevice, RenderQueue},
texture::GpuImage, texture::GpuImage,
@@ -26,7 +25,11 @@ pub struct TracerLabel;
#[derive(Resource, Reflect, ExtractResource, Clone)] #[derive(Resource, Reflect, ExtractResource, Clone)]
#[reflect(Resource)] #[reflect(Resource)]
pub struct TracerRenderTextures(pub Handle<Image>, pub Handle<Image>); pub struct TracerRenderTextures {
pub main: Handle<Image>,
pub secondary: Handle<Image>,
pub skybox: Handle<Image>,
}
#[derive(Resource, Clone, ExtractResource, ShaderType, Default)] #[derive(Resource, Clone, ExtractResource, ShaderType, Default)]
pub struct TracerUniforms { pub struct TracerUniforms {
@@ -64,10 +67,10 @@ impl Plugin for TracerPipelinePlugin {
} }
fn switch_textures(images: Res<TracerRenderTextures>, mut sprite: Single<&mut Sprite>) { fn switch_textures(images: Res<TracerRenderTextures>, mut sprite: Single<&mut Sprite>) {
if sprite.image == images.0 { if sprite.image == images.main {
sprite.image = images.1.clone(); sprite.image = images.secondary.clone();
} else { } else {
sprite.image = images.0.clone(); sprite.image = images.main.clone();
} }
} }
@@ -90,6 +93,8 @@ impl FromWorld for TracerPipeline {
texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::ReadOnly), texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::ReadOnly),
texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::WriteOnly), texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::WriteOnly),
uniform_buffer::<TracerUniforms>(false), uniform_buffer::<TracerUniforms>(false),
texture_cube(TextureSampleType::Float { filterable: true }),
sampler(SamplerBindingType::Filtering),
), ),
), ),
); );
@@ -138,6 +143,8 @@ fn init_pipeline(
texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::ReadOnly), texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::ReadOnly),
texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::WriteOnly), texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::WriteOnly),
uniform_buffer::<TracerUniforms>(false), uniform_buffer::<TracerUniforms>(false),
texture_cube(TextureSampleType::Float { filterable: true }),
sampler(SamplerBindingType::Filtering),
), ),
), ),
); );
@@ -177,21 +184,12 @@ fn update_tracer_uniforms(
rt_camera: Single<(&GlobalTransform, &Camera), With<RTCamera>>, rt_camera: Single<(&GlobalTransform, &Camera), With<RTCamera>>,
) { ) {
let (transform, cam) = rt_camera.into_inner(); let (transform, cam) = rt_camera.into_inner();
/*
let clip_from_view = cam.clip_from_view();
let world_from_clip = clip_from_view.inverse() * transform.compute_matrix().inverse();
*/
let clip_from_view = cam.clip_from_view(); let clip_from_view = cam.clip_from_view();
let world_from_clip = transform.compute_matrix() * clip_from_view.inverse(); let world_from_clip = transform.compute_matrix() * clip_from_view.inverse();
// cam.ndc_to_world(camera_transform, ndc)
tracer_uniforms.world_from_clip = world_from_clip; tracer_uniforms.world_from_clip = world_from_clip;
tracer_uniforms.world_position = transform.translation(); tracer_uniforms.world_position = transform.translation();
// info!("clip_from_view = {:?}", clip_from_view);
// info!("world_from_clip = {:?}", world_from_clip);
} }
fn prepare_bind_groups( fn prepare_bind_groups(
@@ -203,8 +201,9 @@ fn prepare_bind_groups(
render_device: Res<RenderDevice>, render_device: Res<RenderDevice>,
queue: Res<RenderQueue>, queue: Res<RenderQueue>,
) { ) {
let view_a = gpu_images.get(&tracer_images.0).unwrap(); let view_a = gpu_images.get(&tracer_images.main).unwrap();
let view_b = gpu_images.get(&tracer_images.1).unwrap(); let view_b = gpu_images.get(&tracer_images.secondary).unwrap();
let skybox = gpu_images.get(&tracer_images.skybox).unwrap();
// Uniform buffer is used here to demonstrate how to set up a uniform in a compute shader // Uniform buffer is used here to demonstrate how to set up a uniform in a compute shader
// Alternatives such as storage buffers or push constants may be more suitable for your use case // Alternatives such as storage buffers or push constants may be more suitable for your use case
@@ -214,12 +213,24 @@ fn prepare_bind_groups(
let bind_group_0 = render_device.create_bind_group( let bind_group_0 = render_device.create_bind_group(
None, None,
&pipeline.texture_bind_group_layout, &pipeline.texture_bind_group_layout,
&BindGroupEntries::sequential((&view_a.texture_view, &view_b.texture_view, &uniform_buffer)), &BindGroupEntries::sequential((
&view_a.texture_view,
&view_b.texture_view,
&uniform_buffer,
&skybox.texture_view,
&skybox.sampler,
)),
); );
let bind_group_1 = render_device.create_bind_group( let bind_group_1 = render_device.create_bind_group(
None, None,
&pipeline.texture_bind_group_layout, &pipeline.texture_bind_group_layout,
&BindGroupEntries::sequential((&view_b.texture_view, &view_a.texture_view, &uniform_buffer)), &BindGroupEntries::sequential((
&view_b.texture_view,
&view_a.texture_view,
&uniform_buffer,
&skybox.texture_view,
&skybox.sampler,
)),
); );
commands.insert_resource(TracerImageBindGroups([bind_group_0, bind_group_1])); commands.insert_resource(TracerImageBindGroups([bind_group_0, bind_group_1]));
} }