From c04fc4d36d70d68c23157e2d2e9383c6e817e74a Mon Sep 17 00:00:00 2001 From: Dani Smith Date: Sat, 22 Aug 2026 12:33:01 +0200 Subject: [PATCH 1/3] add ColorTexture::CubeMap implementation --- examples/environment/src/main.rs | 54 ++++++++++++++++++++++++++++++++ src/core/texture.rs | 22 ++++++++++--- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/examples/environment/src/main.rs b/examples/environment/src/main.rs index e24e5d916..ad3c25a2d 100644 --- a/examples/environment/src/main.rs +++ b/examples/environment/src/main.rs @@ -186,6 +186,60 @@ pub async fn run() { .write(|| gui.render()) .unwrap(); + let secondary_viewport = Viewport { + x: viewport.x, + y: viewport.y, + width: 200, + height: 100, + }; + camera.set_viewport(secondary_viewport); + frame_input.screen().apply_screen_effect( + &CopyEffect::default(), + &camera, + &[], + Some(ColorTexture::CubeMap { + texture: skybox.texture(), + sides: &[], + }), + None, + ); + + let secondary_viewport = Viewport { + x: viewport.x, + y: viewport.y + 100, + width: 200, + height: 100, + }; + camera.set_viewport(secondary_viewport); + frame_input.screen().apply_screen_effect( + &CopyEffect::default(), + &camera, + &[], + Some(ColorTexture::CubeMap { + texture: &light.environment.as_ref().unwrap().irradiance_map, + sides: &[], + }), + None, + ); + + let secondary_viewport = Viewport { + x: viewport.x, + y: viewport.y + 200, + width: 200, + height: 100, + }; + camera.set_viewport(secondary_viewport); + frame_input.screen().apply_screen_effect( + &CopyEffect::default(), + &camera, + &[], + Some(ColorTexture::CubeMap { + texture: &light.environment.as_ref().unwrap().prefilter_map, + sides: &[], + }), + None, + ); + FrameOutput::default() }); } diff --git a/src/core/texture.rs b/src/core/texture.rs index c8c17c8f0..2f9365b2f 100644 --- a/src/core/texture.rs +++ b/src/core/texture.rs @@ -137,7 +137,21 @@ impl ColorTexture<'_> { return texture(colorMap, vec3(uv, colorLayers[index])); }" .to_owned(), - Self::CubeMap { .. } => todo!(), + // Equirectangular projection + // SOURCE: https://stackoverflow.com/a/57544913 + Self::CubeMap { .. } => " + #define PI 3.1415926 + uniform samplerCube cubeMap; + vec4 sample_color(vec2 uv) { + float phi=uv.s*PI*2; + float theta=(uv.t-0.5)*PI; + + vec3 dir = vec3(cos(phi)*cos(theta),sin(theta),sin(phi)*cos(theta)); + + return texture(cubeMap, dir); + } + " + .to_owned(), } } @@ -148,9 +162,7 @@ impl ColorTexture<'_> { match self { Self::Single { .. } => 1u16 << 3, Self::Array { .. } => 10u16 << 3, - Self::CubeMap { .. } => { - todo!() - } + Self::CubeMap { .. } => 100u16 << 3, } } @@ -169,7 +181,7 @@ impl ColorTexture<'_> { program.use_uniform_array("colorLayers", &la); program.use_texture_array("colorMap", texture); } - Self::CubeMap { .. } => todo!(), + Self::CubeMap { texture, .. } => program.use_texture_cube("cubeMap", texture), } } } From 1890991363752c83a3ff0d8f96dfa8506952e34b Mon Sep 17 00:00:00 2001 From: Dani Smith Date: Sun, 23 Aug 2026 03:27:08 +0200 Subject: [PATCH 2/3] fix dpi of debug outputs, rearrange, add brdf --- examples/environment/src/main.rs | 37 +++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/examples/environment/src/main.rs b/examples/environment/src/main.rs index ad3c25a2d..5204f0ece 100644 --- a/examples/environment/src/main.rs +++ b/examples/environment/src/main.rs @@ -189,8 +189,8 @@ pub async fn run() { let secondary_viewport = Viewport { x: viewport.x, y: viewport.y, - width: 200, - height: 100, + width: (200.0 * frame_input.device_pixel_ratio) as u32, + height: (100.0 * frame_input.device_pixel_ratio) as u32, }; camera.set_viewport(secondary_viewport); frame_input.screen().apply_screen_effect( @@ -206,9 +206,9 @@ pub async fn run() { let secondary_viewport = Viewport { x: viewport.x, - y: viewport.y + 100, - width: 200, - height: 100, + y: viewport.y + (100.0 * frame_input.device_pixel_ratio) as i32, + width: (200.0 * frame_input.device_pixel_ratio) as u32, + height: (100.0 * frame_input.device_pixel_ratio) as u32, }; camera.set_viewport(secondary_viewport); frame_input.screen().apply_screen_effect( @@ -216,7 +216,7 @@ pub async fn run() { &camera, &[], Some(ColorTexture::CubeMap { - texture: &light.environment.as_ref().unwrap().irradiance_map, + texture: &light.environment.as_ref().unwrap().prefilter_map, sides: &[], }), None, @@ -224,9 +224,9 @@ pub async fn run() { let secondary_viewport = Viewport { x: viewport.x, - y: viewport.y + 200, - width: 200, - height: 100, + y: viewport.y + (200.0 * frame_input.device_pixel_ratio) as i32, + width: (200.0 * frame_input.device_pixel_ratio) as u32, + height: (100.0 * frame_input.device_pixel_ratio) as u32, }; camera.set_viewport(secondary_viewport); frame_input.screen().apply_screen_effect( @@ -234,12 +234,29 @@ pub async fn run() { &camera, &[], Some(ColorTexture::CubeMap { - texture: &light.environment.as_ref().unwrap().prefilter_map, + texture: &light.environment.as_ref().unwrap().irradiance_map, sides: &[], }), None, ); + let secondary_viewport = Viewport { + x: viewport.x, + y: viewport.y + (300.0 * frame_input.device_pixel_ratio) as i32, + width: (200.0 * frame_input.device_pixel_ratio) as u32, + height: (200.0 * frame_input.device_pixel_ratio) as u32, + }; + camera.set_viewport(secondary_viewport); + frame_input.screen().apply_screen_effect( + &CopyEffect::default(), + &camera, + &[], + Some(ColorTexture::Single( + &light.environment.as_ref().unwrap().brdf_map, + )), + None, + ); + FrameOutput::default() }); } From 643a939190554dfca4c0e0edcde74e1586ad6c86 Mon Sep 17 00:00:00 2001 From: Dani Smith Date: Sun, 23 Aug 2026 03:32:34 +0200 Subject: [PATCH 3/3] add checkbox to show environment map debug --- examples/environment/src/main.rs | 138 ++++++++++++++++--------------- 1 file changed, 71 insertions(+), 67 deletions(-) diff --git a/examples/environment/src/main.rs b/examples/environment/src/main.rs index 5204f0ece..fb0062684 100644 --- a/examples/environment/src/main.rs +++ b/examples/environment/src/main.rs @@ -72,6 +72,7 @@ pub async fn run() { // main loop let mut color = [1.0; 4]; + let mut show_debug = false; window.render_loop(move |mut frame_input| { let mut panel_width = 0.0; gui.update( @@ -83,6 +84,7 @@ pub async fn run() { use three_d::egui::*; Panel::left("side_panel").show_inside(ui, |ui| { ui.heading("Debug Panel"); + ui.checkbox(&mut show_debug, "Show debug"); ui.label("Material"); ui.add(Slider::new(&mut model.material.metallic, 0.0..=1.0).text("Metallic")); @@ -186,76 +188,78 @@ pub async fn run() { .write(|| gui.render()) .unwrap(); - let secondary_viewport = Viewport { - x: viewport.x, - y: viewport.y, - width: (200.0 * frame_input.device_pixel_ratio) as u32, - height: (100.0 * frame_input.device_pixel_ratio) as u32, - }; - camera.set_viewport(secondary_viewport); - frame_input.screen().apply_screen_effect( - &CopyEffect::default(), - &camera, - &[], - Some(ColorTexture::CubeMap { - texture: skybox.texture(), - sides: &[], - }), - None, - ); + if show_debug { + let secondary_viewport = Viewport { + x: viewport.x, + y: viewport.y, + width: (200.0 * frame_input.device_pixel_ratio) as u32, + height: (100.0 * frame_input.device_pixel_ratio) as u32, + }; + camera.set_viewport(secondary_viewport); + frame_input.screen().apply_screen_effect( + &CopyEffect::default(), + &camera, + &[], + Some(ColorTexture::CubeMap { + texture: skybox.texture(), + sides: &[], + }), + None, + ); - let secondary_viewport = Viewport { - x: viewport.x, - y: viewport.y + (100.0 * frame_input.device_pixel_ratio) as i32, - width: (200.0 * frame_input.device_pixel_ratio) as u32, - height: (100.0 * frame_input.device_pixel_ratio) as u32, - }; - camera.set_viewport(secondary_viewport); - frame_input.screen().apply_screen_effect( - &CopyEffect::default(), - &camera, - &[], - Some(ColorTexture::CubeMap { - texture: &light.environment.as_ref().unwrap().prefilter_map, - sides: &[], - }), - None, - ); + let secondary_viewport = Viewport { + x: viewport.x, + y: viewport.y + (100.0 * frame_input.device_pixel_ratio) as i32, + width: (200.0 * frame_input.device_pixel_ratio) as u32, + height: (100.0 * frame_input.device_pixel_ratio) as u32, + }; + camera.set_viewport(secondary_viewport); + frame_input.screen().apply_screen_effect( + &CopyEffect::default(), + &camera, + &[], + Some(ColorTexture::CubeMap { + texture: &light.environment.as_ref().unwrap().prefilter_map, + sides: &[], + }), + None, + ); - let secondary_viewport = Viewport { - x: viewport.x, - y: viewport.y + (200.0 * frame_input.device_pixel_ratio) as i32, - width: (200.0 * frame_input.device_pixel_ratio) as u32, - height: (100.0 * frame_input.device_pixel_ratio) as u32, - }; - camera.set_viewport(secondary_viewport); - frame_input.screen().apply_screen_effect( - &CopyEffect::default(), - &camera, - &[], - Some(ColorTexture::CubeMap { - texture: &light.environment.as_ref().unwrap().irradiance_map, - sides: &[], - }), - None, - ); + let secondary_viewport = Viewport { + x: viewport.x, + y: viewport.y + (200.0 * frame_input.device_pixel_ratio) as i32, + width: (200.0 * frame_input.device_pixel_ratio) as u32, + height: (100.0 * frame_input.device_pixel_ratio) as u32, + }; + camera.set_viewport(secondary_viewport); + frame_input.screen().apply_screen_effect( + &CopyEffect::default(), + &camera, + &[], + Some(ColorTexture::CubeMap { + texture: &light.environment.as_ref().unwrap().irradiance_map, + sides: &[], + }), + None, + ); - let secondary_viewport = Viewport { - x: viewport.x, - y: viewport.y + (300.0 * frame_input.device_pixel_ratio) as i32, - width: (200.0 * frame_input.device_pixel_ratio) as u32, - height: (200.0 * frame_input.device_pixel_ratio) as u32, - }; - camera.set_viewport(secondary_viewport); - frame_input.screen().apply_screen_effect( - &CopyEffect::default(), - &camera, - &[], - Some(ColorTexture::Single( - &light.environment.as_ref().unwrap().brdf_map, - )), - None, - ); + let secondary_viewport = Viewport { + x: viewport.x, + y: viewport.y + (300.0 * frame_input.device_pixel_ratio) as i32, + width: (200.0 * frame_input.device_pixel_ratio) as u32, + height: (200.0 * frame_input.device_pixel_ratio) as u32, + }; + camera.set_viewport(secondary_viewport); + frame_input.screen().apply_screen_effect( + &CopyEffect::default(), + &camera, + &[], + Some(ColorTexture::Single( + &light.environment.as_ref().unwrap().brdf_map, + )), + None, + ); + } FrameOutput::default() });