Fix wesl in wasm and webgl2 (#18591)

# Objective

- feature `shader_format_wesl` doesn't compile in Wasm
- once fixed, example `shader_material_wesl` doesn't work in WebGL2

## Solution

- remove special path handling when loading shaders. this seems like a
way to escape the asset folder which we don't want to allow, and can't
compile on android or wasm, and can't work on iOS (filesystem is rooted
there)
- pad material so that it's 16 bits. I couldn't get conditional
compilation to work in wesl for type declaration, it fails to parse
- the shader renders the color `(0.0, 0.0, 0.0, 0.0)` when it's not a
polka dot. this renders as black on WebGPU/metal/..., and white on
WebGL2. change it to `(0.0, 0.0, 0.0, 1.0)` so that it's black
everywhere
This commit is contained in:
François Mockers 2025-03-28 22:45:02 +01:00 committed by François Mockers
parent a143a499c2
commit 0ab477e266
4 changed files with 11 additions and 27 deletions

View File

@ -6,7 +6,8 @@ struct VertexOutput {
}
struct CustomMaterial {
time: f32,
// Needed for 16-bit alignment on WebGL2
time: vec4<f32>,
}
@group(2) @binding(0) var<uniform> material: CustomMaterial;
@ -15,5 +16,5 @@ struct CustomMaterial {
fn fragment(
mesh: VertexOutput,
) -> @location(0) vec4<f32> {
return make_polka_dots(mesh.uv, material.time);
}
return make_polka_dots(mesh.uv, material.time.x);
}

View File

@ -40,5 +40,5 @@ fn make_polka_dots(pos: vec2<f32>, time: f32) -> vec4<f32> {
is_dot = step(dist_from_center, 0.3 + wave_normalized * 0.2);
}
return vec4<f32>(dot_color * is_dot, is_dot);
}
return vec4<f32>(dot_color * is_dot, 1.0);
}

View File

@ -163,26 +163,8 @@ impl Shader {
match import_path {
ShaderImport::AssetPath(asset_path) => {
let asset_path = std::path::PathBuf::from(&asset_path);
// 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();
base_path.push("assets");
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);
let shader_path = std::path::Path::new("/").join(&asset_path);
// Convert to a string with forward slashes and without extension
let import_path_str = shader_path

View File

@ -59,7 +59,7 @@ fn setup(
commands.spawn((
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(CustomMaterial {
time: 0.0,
time: Vec4::ZERO,
party_mode: false,
})),
Transform::from_xyz(0.0, 0.5, 0.0),
@ -80,7 +80,7 @@ fn update(
) {
for (material, mut transform) in query.iter_mut() {
let material = materials.get_mut(material).unwrap();
material.time = time.elapsed_secs();
material.time.x = time.elapsed_secs();
if keys.just_pressed(KeyCode::Space) {
material.party_mode = !material.party_mode;
}
@ -95,8 +95,9 @@ fn update(
#[derive(Asset, TypePath, AsBindGroup, Clone)]
#[bind_group_data(CustomMaterialKey)]
struct CustomMaterial {
// Needed for 16 bit alignment in WebGL2
#[uniform(0)]
time: f32,
time: Vec4,
party_mode: bool,
}