bevy/assets/shaders/extended_material_bindless.wgsl
Patrick Walton 8a066faea9 Add bindless support back to ExtendedMaterial. (#18025)
PR #17898 disabled bindless support for `ExtendedMaterial`. This commit
adds it back. It also adds a new example, `extended_material_bindless`,
showing how to use it.
2025-04-10 01:19:33 +02:00

108 lines
4.3 KiB
WebGPU Shading Language

// The shader that goes with `extended_material_bindless.rs`.
//
// This code demonstrates how to write shaders that are compatible with both
// bindless and non-bindless mode. See the `#ifdef BINDLESS` blocks.
#import bevy_pbr::{
forward_io::{FragmentOutput, VertexOutput},
mesh_bindings::mesh,
pbr_fragment::pbr_input_from_standard_material,
pbr_functions::{apply_pbr_lighting, main_pass_post_lighting_processing},
}
#import bevy_render::bindless::{bindless_samplers_filtering, bindless_textures_2d}
#ifdef BINDLESS
#import bevy_pbr::pbr_bindings::{material_array, material_indices}
#else // BINDLESS
#import bevy_pbr::pbr_bindings::material
#endif // BINDLESS
// Stores the indices of the bindless resources in the bindless resource arrays,
// for the `ExampleBindlessExtension` fields.
struct ExampleBindlessExtendedMaterialIndices {
// The index of the `ExampleBindlessExtendedMaterial` data in
// `example_extended_material`.
material: u32,
// The index of the texture we're going to modulate the base color with in
// the `bindless_textures_2d` array.
modulate_texture: u32,
// The index of the sampler we're going to sample the modulated texture with
// in the `bindless_samplers_filtering` array.
modulate_texture_sampler: u32,
}
// Plain data associated with this example material.
struct ExampleBindlessExtendedMaterial {
// The color that we multiply the base color, base color texture, and
// modulated texture with.
modulate_color: vec4<f32>,
}
#ifdef BINDLESS
// The indices of the bindless resources in the bindless resource arrays, for
// the `ExampleBindlessExtension` fields.
@group(2) @binding(100) var<storage> example_extended_material_indices:
array<ExampleBindlessExtendedMaterialIndices>;
// An array that holds the `ExampleBindlessExtendedMaterial` plain old data,
// indexed by `ExampleBindlessExtendedMaterialIndices.material`.
@group(2) @binding(101) var<storage> example_extended_material:
array<ExampleBindlessExtendedMaterial>;
#else // BINDLESS
// In non-bindless mode, we simply use a uniform for the plain old data.
@group(2) @binding(50) var<uniform> example_extended_material: ExampleBindlessExtendedMaterial;
@group(2) @binding(51) var modulate_texture: texture_2d<f32>;
@group(2) @binding(52) var modulate_sampler: sampler;
#endif // BINDLESS
@fragment
fn fragment(
in: VertexOutput,
@builtin(front_facing) is_front: bool,
) -> FragmentOutput {
#ifdef BINDLESS
// Fetch the material slot. We'll use this in turn to fetch the bindless
// indices from `example_extended_material_indices`.
let slot = mesh[in.instance_index].material_and_lightmap_bind_group_slot & 0xffffu;
#endif // BINDLESS
// Generate a `PbrInput` struct from the `StandardMaterial` bindings.
var pbr_input = pbr_input_from_standard_material(in, is_front);
// Calculate the UV for the texture we're about to sample.
#ifdef BINDLESS
let uv_transform = material_array[material_indices[slot].material].uv_transform;
#else // BINDLESS
let uv_transform = material.uv_transform;
#endif // BINDLESS
let uv = (uv_transform * vec3(in.uv, 1.0)).xy;
// Multiply the base color by the `modulate_texture` and `modulate_color`.
#ifdef BINDLESS
// Notice how we fetch the texture, sampler, and plain extended material
// data from the appropriate arrays.
pbr_input.material.base_color *= textureSample(
bindless_textures_2d[example_extended_material_indices[slot].modulate_texture],
bindless_samplers_filtering[
example_extended_material_indices[slot].modulate_texture_sampler
],
uv
) * example_extended_material[example_extended_material_indices[slot].material].modulate_color;
#else // BINDLESS
pbr_input.material.base_color *= textureSample(modulate_texture, modulate_sampler, uv) *
example_extended_material.modulate_color;
#endif // BINDLESS
var out: FragmentOutput;
// Apply lighting.
out.color = apply_pbr_lighting(pbr_input);
// Apply in-shader post processing (fog, alpha-premultiply, and also
// tonemapping, debanding if the camera is non-HDR). Note this does not
// include fullscreen postprocessing effects like bloom.
out.color = main_pass_post_lighting_processing(pbr_input, out.color);
return out;
}