1import bevy_pbr::render::{forward_io::VertexOutput, mesh_bindings::mesh};2import bevy_render::bindless::{bindless_samplers_filtering, bindless_textures_2d};4/// The custom data that we extract from the ECS and expose to this shader.5struct CustomMaterialData {6 /// The tint color for the mesh.7 color: vec3<f32>,8 /// Padding to pad this out to a multiple of 16 bytes.9 pad: u32,10}12/// The array of material data that Bevy supplies.13///14/// We need to declare this type because15/// `binding_array<array<CustomMaterialData>>` isn't currently accepted by Naga.16/// We have to factor the `array<CustomMaterialData>` out into a separate type.17struct CustomMaterialDataArray {18 data_array: array<CustomMaterialData>,19}21@if(BINDLESS) {23/// The bindings table for bindless mode.24///25/// These are indexes into the various arrays.26struct CustomMaterialBindings {27 material: u32, // 028 /// The index of the data for this instance in the `CustomMaterialDataArray`.29 data: u32, // 130 /// The index of the color texture for this instance in the31 /// `bindless_textures_2d`.32 color_texture: u32, // 233 /// The index of the sampler for this instance in the34 /// `bindless_samplers_filtering`.35 color_texture_sampler: u32, // 336}38@group(constants::MATERIAL_BIND_GROUP) @binding(0) var<storage> material_indices:39 array<CustomMaterialBindings>;40@group(constants::MATERIAL_BIND_GROUP) @binding(4) var<storage> material_data:41 binding_array<CustomMaterialDataArray>;43} @else {45@group(constants::MATERIAL_BIND_GROUP) @binding(1) var<storage> material_data: CustomMaterialDataArray;46@group(constants::MATERIAL_BIND_GROUP) @binding(2) var color_texture: texture_2d<f32>;47@group(constants::MATERIAL_BIND_GROUP) @binding(3) var color_texture_sampler: sampler;49}51@fragment52fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {53 // The tag stores the index of the data in the data array.54 let tag = mesh[in.instance_index].tag;56@if(BINDLESS) {58 // Look up the bindless slot for this mesh.59 let slot = mesh[in.instance_index].material_and_lightmap_bind_group_slot & 0xffffu;61 // Unpack the bindless indices.62 let data_index = material_indices[slot].data;63 let color_texture_index = material_indices[slot].color_texture;64 let color_texture_sampler_index = material_indices[slot].color_texture_sampler;66 // Grab the color from the material data array.67 //68 // Note that there are two levels of arrays here: the binding array and the69 // data array. The binding array should only have one element in this case,70 // but Bevy still supplies a binding array because it's legal for different71 // materials to have different `ShaderBuffer` bindings, even though in our72 // case all materials are bound to the same buffer. The data array contains73 // all of the instance data and is indexed by the tag.74 let color = material_data[data_index].data_array[tag].color;76 // Sample from the appropriate texture in the bindless textures array.77 let texture_color = textureSample(78 bindless_textures_2d[color_texture_index],79 bindless_samplers_filtering[color_texture_sampler_index],80 in.uv81 ).rgb;83} @else {85 // In non-bindless mode, we only have one buffer, so we simply use the tag86 // as an index into the array.87 let color = material_data.data_array[tag].color;89 let texture_color = textureSample(color_texture, color_texture_sampler, in.uv).rgb;91}93 // Modulate the texture by the appropriate tint color.94 return vec4<f32>(color * texture_color, 1.0);95}