This commit allows specular highlights to be tinted with a color and for the reflectance and color tint values to vary across a model via a pair of maps. The implementation follows the [`KHR_materials_specular`] glTF extension. In order to reduce the number of samplers and textures in the default `StandardMaterial` configuration, the maps are gated behind the `pbr_specular_textures` Cargo feature. Specular tinting is currently unsupported in the deferred renderer, because I didn't want to bloat the deferred G-buffers. A possible fix for this in the future would be to make the G-buffer layout more configurable, so that specular tints could be supported on an opt-in basis. As an alternative, Bevy could force meshes with specular tints to render in forward mode. Both of these solutions require some more design, so I consider them out of scope for now. Note that the map is a *specular* map, not a *reflectance* map. In Bevy and Filament terms, the reflectance values in the specular map range from [0.0, 0.5], rather than [0.0, 1.0]. This is an unfortunate [`KHR_materials_specular`] specification requirement that stems from the fact that glTF is specified in terms of a specular strength model, not the reflectance model that Filament and Bevy use. A workaround, which is noted in the `StandardMaterial` documentation, is to set the `reflectance` value to 2.0, which spreads the specular map range from [0.0, 1.0] as normal. The glTF loader has been updated to parse the [`KHR_materials_specular`] extension. Note that, unless the non-default `pbr_specular_textures` is supplied, the maps are ignored. The `specularFactor` value is applied as usual. Note that, as with the specular map, the glTF `specularFactor` is twice Bevy's `reflectance` value. This PR adds a new example, `specular_tint`, which demonstrates the specular tint and map features. Note that this example requires the [`KHR_materials_specular`] Cargo feature. [`KHR_materials_specular`]: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_specular ## Changelog ### Added * Specular highlights can now be tinted with the `specular_tint` field in `StandardMaterial`. * Specular maps are now available in `StandardMaterial`, gated behind the `pbr_specular_textures` Cargo feature. * The `KHR_materials_specular` glTF extension is now supported, allowing for customization of specular reflectance and specular maps. Note that the latter are gated behind the `pbr_specular_textures` Cargo feature.
94 lines
5.1 KiB
WebGPU Shading Language
94 lines
5.1 KiB
WebGPU Shading Language
#define_import_path bevy_pbr::pbr_bindings
|
|
|
|
#import bevy_pbr::pbr_types::StandardMaterial
|
|
|
|
#ifdef BINDLESS
|
|
@group(2) @binding(0) var<storage> material: binding_array<StandardMaterial, 16>;
|
|
@group(2) @binding(1) var base_color_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(2) var base_color_sampler: binding_array<sampler, 16>;
|
|
@group(2) @binding(3) var emissive_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(4) var emissive_sampler: binding_array<sampler, 16>;
|
|
@group(2) @binding(5) var metallic_roughness_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(6) var metallic_roughness_sampler: binding_array<sampler, 16>;
|
|
@group(2) @binding(7) var occlusion_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(8) var occlusion_sampler: binding_array<sampler, 16>;
|
|
@group(2) @binding(9) var normal_map_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(10) var normal_map_sampler: binding_array<sampler, 16>;
|
|
@group(2) @binding(11) var depth_map_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(12) var depth_map_sampler: binding_array<sampler, 16>;
|
|
#else // BINDLESS
|
|
@group(2) @binding(0) var<uniform> material: StandardMaterial;
|
|
@group(2) @binding(1) var base_color_texture: texture_2d<f32>;
|
|
@group(2) @binding(2) var base_color_sampler: sampler;
|
|
@group(2) @binding(3) var emissive_texture: texture_2d<f32>;
|
|
@group(2) @binding(4) var emissive_sampler: sampler;
|
|
@group(2) @binding(5) var metallic_roughness_texture: texture_2d<f32>;
|
|
@group(2) @binding(6) var metallic_roughness_sampler: sampler;
|
|
@group(2) @binding(7) var occlusion_texture: texture_2d<f32>;
|
|
@group(2) @binding(8) var occlusion_sampler: sampler;
|
|
@group(2) @binding(9) var normal_map_texture: texture_2d<f32>;
|
|
@group(2) @binding(10) var normal_map_sampler: sampler;
|
|
@group(2) @binding(11) var depth_map_texture: texture_2d<f32>;
|
|
@group(2) @binding(12) var depth_map_sampler: sampler;
|
|
#endif // BINDLESS
|
|
|
|
#ifdef PBR_ANISOTROPY_TEXTURE_SUPPORTED
|
|
#ifdef BINDLESS
|
|
@group(2) @binding(13) var anisotropy_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(14) var anisotropy_sampler: binding_array<sampler, 16>;
|
|
#else // BINDLESS
|
|
@group(2) @binding(13) var anisotropy_texture: texture_2d<f32>;
|
|
@group(2) @binding(14) var anisotropy_sampler: sampler;
|
|
#endif // BINDLESS
|
|
#endif // PBR_ANISOTROPY_TEXTURE_SUPPORTED
|
|
|
|
#ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED
|
|
#ifdef BINDLESS
|
|
@group(2) @binding(15) var specular_transmission_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(16) var specular_transmission_sampler: binding_array<sampler, 16>;
|
|
@group(2) @binding(17) var thickness_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(18) var thickness_sampler: binding_array<sampler, 16>;
|
|
@group(2) @binding(19) var diffuse_transmission_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(20) var diffuse_transmission_sampler: binding_array<sampler, 16>;
|
|
#else // BINDLESS
|
|
@group(2) @binding(15) var specular_transmission_texture: texture_2d<f32>;
|
|
@group(2) @binding(16) var specular_transmission_sampler: sampler;
|
|
@group(2) @binding(17) var thickness_texture: texture_2d<f32>;
|
|
@group(2) @binding(18) var thickness_sampler: sampler;
|
|
@group(2) @binding(19) var diffuse_transmission_texture: texture_2d<f32>;
|
|
@group(2) @binding(20) var diffuse_transmission_sampler: sampler;
|
|
#endif // BINDLESS
|
|
#endif // PBR_TRANSMISSION_TEXTURES_SUPPORTED
|
|
|
|
#ifdef PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
|
|
#ifdef BINDLESS
|
|
@group(2) @binding(21) var clearcoat_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(22) var clearcoat_sampler: binding_array<sampler, 16>;
|
|
@group(2) @binding(23) var clearcoat_roughness_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(24) var clearcoat_roughness_sampler: binding_array<sampler, 16>;
|
|
@group(2) @binding(25) var clearcoat_normal_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(26) var clearcoat_normal_sampler: binding_array<sampler, 16>;
|
|
#else // BINDLESS
|
|
@group(2) @binding(21) var clearcoat_texture: texture_2d<f32>;
|
|
@group(2) @binding(22) var clearcoat_sampler: sampler;
|
|
@group(2) @binding(23) var clearcoat_roughness_texture: texture_2d<f32>;
|
|
@group(2) @binding(24) var clearcoat_roughness_sampler: sampler;
|
|
@group(2) @binding(25) var clearcoat_normal_texture: texture_2d<f32>;
|
|
@group(2) @binding(26) var clearcoat_normal_sampler: sampler;
|
|
#endif // BINDLESS
|
|
#endif // PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
|
|
|
|
#ifdef PBR_SPECULAR_TEXTURES_SUPPORTED
|
|
#ifdef BINDLESS
|
|
@group(2) @binding(27) var specular_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(28) var specular_sampler: binding_array<sampler, 16>;
|
|
@group(2) @binding(29) var specular_tint_texture: binding_array<texture_2d<f32>, 16>;
|
|
@group(2) @binding(30) var specular_tint_sampler: binding_array<sampler, 16>;
|
|
#else
|
|
@group(2) @binding(27) var specular_texture: texture_2d<f32>;
|
|
@group(2) @binding(28) var specular_sampler: sampler;
|
|
@group(2) @binding(29) var specular_tint_texture: texture_2d<f32>;
|
|
@group(2) @binding(30) var specular_tint_sampler: sampler;
|
|
#endif // BINDLESS
|
|
#endif // PBR_SPECULAR_TEXTURES_SUPPORTED
|