From 35bf9753e8c5c619f3b759c652508011149bfe54 Mon Sep 17 00:00:00 2001 From: charlotte Date: Mon, 17 Mar 2025 15:29:29 -0700 Subject: [PATCH] Fixes for WESL on Windows (#18373) # Objective WESL was broken on windows. ## Solution - Upgrade to `wesl_rs` 1.2. - Fix path handling on windows. - Improve example for khronos demo this week. --- assets/shaders/custom_material.wesl | 2 +- assets/shaders/util.wesl | 43 +++++++++++++------ crates/bevy_render/Cargo.toml | 2 +- .../bevy_render/src/render_resource/shader.rs | 41 +++++++++++------- examples/shader/shader_material_wesl.rs | 8 +++- 5 files changed, 63 insertions(+), 33 deletions(-) diff --git a/assets/shaders/custom_material.wesl b/assets/shaders/custom_material.wesl index 35340811d9..2fd32fc923 100644 --- a/assets/shaders/custom_material.wesl +++ b/assets/shaders/custom_material.wesl @@ -1,4 +1,4 @@ -import super::shaders::util::make_polka_dots; +import super::util::make_polka_dots; struct VertexOutput { @builtin(position) position: vec4, diff --git a/assets/shaders/util.wesl b/assets/shaders/util.wesl index dbb74c3520..52461fca48 100644 --- a/assets/shaders/util.wesl +++ b/assets/shaders/util.wesl @@ -1,29 +1,44 @@ fn make_polka_dots(pos: vec2, time: f32) -> vec4 { - // Create repeating circles let scaled_pos = pos * 6.0; let cell = vec2(fract(scaled_pos.x), fract(scaled_pos.y)); - let dist_from_center = distance(cell, vec2(0.5)); - - // Make dots alternate between pink and purple + var dist_from_center = distance(cell, vec2(0.5)); + let is_even = (floor(scaled_pos.x) + floor(scaled_pos.y)) % 2.0; var dot_color = vec3(0.0); + var is_dot = 0.0; + @if(!PARTY_MODE) { let color1 = vec3(1.0, 0.4, 0.8); // pink let color2 = vec3(0.6, 0.2, 1.0); // purple dot_color = mix(color1, color2, is_even); - } - // Animate the colors in party mode - @if(PARTY_MODE) { - let color1 = vec3(1.0, 0.2, 0.2); // red - let color2 = vec3(0.2, 0.2, 1.0); // blue - let oscillation = (sin(time * 10.0) + 1.0) * 0.5; - let animated_color1 = mix(color1, color2, oscillation); - let animated_color2 = mix(color2, color1, oscillation); + is_dot = step(dist_from_center, 0.3); + } @else { + let grid_x = floor(scaled_pos.x); + let grid_y = floor(scaled_pos.y); + let wave_speed = 3.0; + let wave_phase = time * wave_speed; + + let diagonal_pos = (grid_x + grid_y) * 0.5; + let wave_value = sin(diagonal_pos + wave_phase); + + let wave_normalized = (wave_value + 1.0) * 0.5; + + let color1 = vec3(1.0, 0.3, 0.7); + let color2 = vec3(0.5, 0.1, 1.0); + let intense_color1 = vec3(1.0, 0.1, 0.9); + let intense_color2 = vec3(0.8, 0.0, 1.0); + + let animated_color1 = mix(color1, intense_color1, wave_normalized); + let animated_color2 = mix(color2, intense_color2, wave_normalized); + dot_color = mix(animated_color1, animated_color2, is_even); + + let size_mod = 0.15 * wave_value; + dist_from_center = dist_from_center * (1.0 - size_mod); + // Animate whether something is a dot by position but also time + is_dot = step(dist_from_center, 0.3 + wave_normalized * 0.2); } - // Draw the dot - let is_dot = step(dist_from_center, 0.3); return vec4(dot_color * is_dot, is_dot); } \ No newline at end of file diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 7730cf4217..9a7f8e51bd 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -113,7 +113,7 @@ tracing = { version = "0.1", default-features = false, features = ["std"] } indexmap = { version = "2" } fixedbitset = { version = "0.5" } bitflags = "2" -wesl = { version = "0.1.0", optional = true } +wesl = { version = "0.1.2", optional = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] # Omit the `glsl` feature in non-WebAssembly by default. diff --git a/crates/bevy_render/src/render_resource/shader.rs b/crates/bevy_render/src/render_resource/shader.rs index efc33aa7f9..62849a2f28 100644 --- a/crates/bevy_render/src/render_resource/shader.rs +++ b/crates/bevy_render/src/render_resource/shader.rs @@ -164,23 +164,34 @@ impl Shader { match import_path { ShaderImport::AssetPath(asset_path) => { let asset_path = std::path::PathBuf::from(&asset_path); - // Resolve and normalize the path - let asset_path = asset_path.canonicalize().unwrap_or(asset_path); - // Strip the asset root + + // Get the base path and canonicalize it to match the format of the asset path let mut base_path = bevy_asset::io::file::FileAssetReader::get_base_path(); - // TODO: integrate better with the asset system rather than hard coding this base_path.push("assets"); - let asset_path = asset_path - .strip_prefix(&base_path) - .unwrap_or_else(|_| &asset_path); - // Wesl paths are provided as absolute relative to the asset root - let asset_path = std::path::Path::new("/").join(asset_path); - // And with a striped file name - let asset_path = asset_path.with_extension(""); - let asset_path = asset_path.to_str().unwrap_or_else(|| { - panic!("Failed to convert path to string: {:?}", asset_path) - }); - let import_path = ShaderImport::AssetPath(asset_path.to_string()); + let base_path = base_path.canonicalize().unwrap_or(base_path); + + // Try to make the path relative to the base path + let relative_path = match asset_path.canonicalize() { + Ok(canonical_asset_path) => { + match canonical_asset_path.strip_prefix(&base_path) { + Ok(rel_path) => rel_path.to_path_buf(), + Err(_) => canonical_asset_path, + } + } + Err(_) => asset_path, + }; + + // Create the shader import path - always starting with "/" + let shader_path = std::path::Path::new("/").join(&relative_path); + + // Convert to a string with forward slashes and without extension + let import_path_str = shader_path + .with_extension("") + .to_string_lossy() + .replace('\\', "/"); + + let import_path = ShaderImport::AssetPath(import_path_str.to_string()); + Shader { path, imports, diff --git a/examples/shader/shader_material_wesl.rs b/examples/shader/shader_material_wesl.rs index 81ee3325b0..a436d0a49e 100644 --- a/examples/shader/shader_material_wesl.rs +++ b/examples/shader/shader_material_wesl.rs @@ -70,16 +70,20 @@ fn setup( fn update( time: Res