mirror of
https://github.com/bevyengine/bevy
synced 2024-12-21 02:23:08 +00:00
Make StandardMaterial
bindless. (#16644)
This commit makes `StandardMaterial` use bindless textures, as implemented in PR #16368. Non-bindless mode, as used for example in Metal and WebGL 2, remains fully supported via a plethora of `#ifdef BINDLESS` preprocessor definitions. Unfortunately, this PR introduces quite a bit of unsightliness into the PBR shaders. This is a result of the fact that WGSL supports neither passing binding arrays to functions nor passing individual *elements* of binding arrays to functions, except directly to texture sample functions. Thus we're unable to use the `sample_texture` abstraction that helped abstract over the meshlet and non-meshlet paths. I don't think there's anything we can do to help this other than to suggest improvements to upstream Naga.
This commit is contained in:
parent
7236070573
commit
7ed1f327d9
14 changed files with 574 additions and 166 deletions
|
@ -155,14 +155,32 @@ impl<B: Material, E: MaterialExtension> AsBindGroup for ExtendedMaterial<B, E> {
|
||||||
layout: &BindGroupLayout,
|
layout: &BindGroupLayout,
|
||||||
render_device: &RenderDevice,
|
render_device: &RenderDevice,
|
||||||
(base_param, extended_param): &mut SystemParamItem<'_, '_, Self::Param>,
|
(base_param, extended_param): &mut SystemParamItem<'_, '_, Self::Param>,
|
||||||
|
mut force_no_bindless: bool,
|
||||||
) -> Result<UnpreparedBindGroup<Self::Data>, AsBindGroupError> {
|
) -> Result<UnpreparedBindGroup<Self::Data>, AsBindGroupError> {
|
||||||
|
// Only allow bindless mode if both the base material and the extension
|
||||||
|
// support it.
|
||||||
|
force_no_bindless = force_no_bindless
|
||||||
|
|| B::BINDLESS_SLOT_COUNT.is_none()
|
||||||
|
|| E::BINDLESS_SLOT_COUNT.is_none();
|
||||||
|
|
||||||
// add together the bindings of the base material and the user material
|
// add together the bindings of the base material and the user material
|
||||||
let UnpreparedBindGroup {
|
let UnpreparedBindGroup {
|
||||||
mut bindings,
|
mut bindings,
|
||||||
data: base_data,
|
data: base_data,
|
||||||
} = B::unprepared_bind_group(&self.base, layout, render_device, base_param)?;
|
} = B::unprepared_bind_group(
|
||||||
let extended_bindgroup =
|
&self.base,
|
||||||
E::unprepared_bind_group(&self.extension, layout, render_device, extended_param)?;
|
layout,
|
||||||
|
render_device,
|
||||||
|
base_param,
|
||||||
|
force_no_bindless,
|
||||||
|
)?;
|
||||||
|
let extended_bindgroup = E::unprepared_bind_group(
|
||||||
|
&self.extension,
|
||||||
|
layout,
|
||||||
|
render_device,
|
||||||
|
extended_param,
|
||||||
|
force_no_bindless,
|
||||||
|
)?;
|
||||||
|
|
||||||
bindings.extend(extended_bindgroup.bindings.0);
|
bindings.extend(extended_bindgroup.bindings.0);
|
||||||
|
|
||||||
|
@ -174,13 +192,23 @@ impl<B: Material, E: MaterialExtension> AsBindGroup for ExtendedMaterial<B, E> {
|
||||||
|
|
||||||
fn bind_group_layout_entries(
|
fn bind_group_layout_entries(
|
||||||
render_device: &RenderDevice,
|
render_device: &RenderDevice,
|
||||||
|
mut force_no_bindless: bool,
|
||||||
) -> Vec<bevy_render::render_resource::BindGroupLayoutEntry>
|
) -> Vec<bevy_render::render_resource::BindGroupLayoutEntry>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
// Only allow bindless mode if both the base material and the extension
|
||||||
|
// support it.
|
||||||
|
force_no_bindless = force_no_bindless
|
||||||
|
|| B::BINDLESS_SLOT_COUNT.is_none()
|
||||||
|
|| E::BINDLESS_SLOT_COUNT.is_none();
|
||||||
|
|
||||||
// add together the bindings of the standard material and the user material
|
// add together the bindings of the standard material and the user material
|
||||||
let mut entries = B::bind_group_layout_entries(render_device);
|
let mut entries = B::bind_group_layout_entries(render_device, force_no_bindless);
|
||||||
entries.extend(E::bind_group_layout_entries(render_device));
|
entries.extend(E::bind_group_layout_entries(
|
||||||
|
render_device,
|
||||||
|
force_no_bindless,
|
||||||
|
));
|
||||||
entries
|
entries
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1062,6 +1062,7 @@ impl<M: Material> RenderAsset for PreparedMaterial<M> {
|
||||||
&pipeline.material_layout,
|
&pipeline.material_layout,
|
||||||
render_device,
|
render_device,
|
||||||
material_param,
|
material_param,
|
||||||
|
false,
|
||||||
) {
|
) {
|
||||||
Ok(unprepared) => {
|
Ok(unprepared) => {
|
||||||
bind_group_allocator.init(render_device, *material_binding_id, unprepared);
|
bind_group_allocator.init(render_device, *material_binding_id, unprepared);
|
||||||
|
|
|
@ -767,7 +767,7 @@ where
|
||||||
fn from_world(world: &mut World) -> Self {
|
fn from_world(world: &mut World) -> Self {
|
||||||
// Create a new bind group allocator.
|
// Create a new bind group allocator.
|
||||||
let render_device = world.resource::<RenderDevice>();
|
let render_device = world.resource::<RenderDevice>();
|
||||||
let bind_group_layout_entries = M::bind_group_layout_entries(render_device);
|
let bind_group_layout_entries = M::bind_group_layout_entries(render_device, false);
|
||||||
let bind_group_layout =
|
let bind_group_layout =
|
||||||
render_device.create_bind_group_layout(M::label(), &bind_group_layout_entries);
|
render_device.create_bind_group_layout(M::label(), &bind_group_layout_entries);
|
||||||
let fallback_buffers =
|
let fallback_buffers =
|
||||||
|
|
|
@ -31,6 +31,7 @@ pub enum UvChannel {
|
||||||
#[derive(Asset, AsBindGroup, Reflect, Debug, Clone)]
|
#[derive(Asset, AsBindGroup, Reflect, Debug, Clone)]
|
||||||
#[bind_group_data(StandardMaterialKey)]
|
#[bind_group_data(StandardMaterialKey)]
|
||||||
#[uniform(0, StandardMaterialUniform)]
|
#[uniform(0, StandardMaterialUniform)]
|
||||||
|
#[bindless(16)]
|
||||||
#[reflect(Default, Debug)]
|
#[reflect(Default, Debug)]
|
||||||
pub struct StandardMaterial {
|
pub struct StandardMaterial {
|
||||||
/// The color of the surface of the material before lighting.
|
/// The color of the surface of the material before lighting.
|
||||||
|
|
|
@ -494,6 +494,11 @@ where
|
||||||
shader_defs.push("HAS_PREVIOUS_MORPH".into());
|
shader_defs.push("HAS_PREVIOUS_MORPH".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If bindless mode is on, add a `BINDLESS` define.
|
||||||
|
if self.material_pipeline.bindless {
|
||||||
|
shader_defs.push("BINDLESS".into());
|
||||||
|
}
|
||||||
|
|
||||||
if key
|
if key
|
||||||
.mesh_key
|
.mesh_key
|
||||||
.contains(MeshPipelineKey::VISIBILITY_RANGE_DITHER)
|
.contains(MeshPipelineKey::VISIBILITY_RANGE_DITHER)
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
#define_import_path bevy_pbr::parallax_mapping
|
#define_import_path bevy_pbr::parallax_mapping
|
||||||
|
|
||||||
#import bevy_pbr::pbr_bindings::{depth_map_texture, depth_map_sampler}
|
#import bevy_pbr::{
|
||||||
|
pbr_bindings::{depth_map_texture, depth_map_sampler},
|
||||||
|
mesh_bindings::mesh
|
||||||
|
}
|
||||||
|
|
||||||
fn sample_depth_map(uv: vec2<f32>) -> f32 {
|
fn sample_depth_map(uv: vec2<f32>, instance_index: u32) -> f32 {
|
||||||
|
let slot = mesh[instance_index].material_bind_group_slot;
|
||||||
// We use `textureSampleLevel` over `textureSample` because the wgpu DX12
|
// We use `textureSampleLevel` over `textureSample` because the wgpu DX12
|
||||||
// backend (Fxc) panics when using "gradient instructions" inside a loop.
|
// backend (Fxc) panics when using "gradient instructions" inside a loop.
|
||||||
// It results in the whole loop being unrolled by the shader compiler,
|
// It results in the whole loop being unrolled by the shader compiler,
|
||||||
|
@ -13,7 +17,17 @@ fn sample_depth_map(uv: vec2<f32>) -> f32 {
|
||||||
// the MIP level, so no gradient instructions are used, and we can use
|
// the MIP level, so no gradient instructions are used, and we can use
|
||||||
// sample_depth_map in our loop.
|
// sample_depth_map in our loop.
|
||||||
// See https://stackoverflow.com/questions/56581141/direct3d11-gradient-instruction-used-in-a-loop-with-varying-iteration-forcing
|
// See https://stackoverflow.com/questions/56581141/direct3d11-gradient-instruction-used-in-a-loop-with-varying-iteration-forcing
|
||||||
return textureSampleLevel(depth_map_texture, depth_map_sampler, uv, 0.0).r;
|
return textureSampleLevel(
|
||||||
|
#ifdef BINDLESS
|
||||||
|
depth_map_texture[slot],
|
||||||
|
depth_map_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
|
depth_map_texture,
|
||||||
|
depth_map_sampler,
|
||||||
|
#endif // BINDLESS
|
||||||
|
uv,
|
||||||
|
0.0
|
||||||
|
).r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// An implementation of parallax mapping, see https://en.wikipedia.org/wiki/Parallax_mapping
|
// An implementation of parallax mapping, see https://en.wikipedia.org/wiki/Parallax_mapping
|
||||||
|
@ -26,6 +40,7 @@ fn parallaxed_uv(
|
||||||
original_uv: vec2<f32>,
|
original_uv: vec2<f32>,
|
||||||
// The vector from the camera to the fragment at the surface in tangent space
|
// The vector from the camera to the fragment at the surface in tangent space
|
||||||
Vt: vec3<f32>,
|
Vt: vec3<f32>,
|
||||||
|
instance_index: u32,
|
||||||
) -> vec2<f32> {
|
) -> vec2<f32> {
|
||||||
if max_layer_count < 1.0 {
|
if max_layer_count < 1.0 {
|
||||||
return original_uv;
|
return original_uv;
|
||||||
|
@ -53,7 +68,7 @@ fn parallaxed_uv(
|
||||||
var delta_uv = depth_scale * layer_depth * Vt.xy * vec2(1.0, -1.0) / view_steepness;
|
var delta_uv = depth_scale * layer_depth * Vt.xy * vec2(1.0, -1.0) / view_steepness;
|
||||||
|
|
||||||
var current_layer_depth = 0.0;
|
var current_layer_depth = 0.0;
|
||||||
var texture_depth = sample_depth_map(uv);
|
var texture_depth = sample_depth_map(uv, instance_index);
|
||||||
|
|
||||||
// texture_depth > current_layer_depth means the depth map depth is deeper
|
// texture_depth > current_layer_depth means the depth map depth is deeper
|
||||||
// than the depth the ray would be at this UV offset so the ray has not
|
// than the depth the ray would be at this UV offset so the ray has not
|
||||||
|
@ -61,7 +76,7 @@ fn parallaxed_uv(
|
||||||
for (var i: i32 = 0; texture_depth > current_layer_depth && i <= i32(layer_count); i++) {
|
for (var i: i32 = 0; texture_depth > current_layer_depth && i <= i32(layer_count); i++) {
|
||||||
current_layer_depth += layer_depth;
|
current_layer_depth += layer_depth;
|
||||||
uv += delta_uv;
|
uv += delta_uv;
|
||||||
texture_depth = sample_depth_map(uv);
|
texture_depth = sample_depth_map(uv, instance_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RELIEF_MAPPING
|
#ifdef RELIEF_MAPPING
|
||||||
|
@ -79,7 +94,7 @@ fn parallaxed_uv(
|
||||||
current_layer_depth -= delta_depth;
|
current_layer_depth -= delta_depth;
|
||||||
|
|
||||||
for (var i: u32 = 0u; i < max_steps; i++) {
|
for (var i: u32 = 0u; i < max_steps; i++) {
|
||||||
texture_depth = sample_depth_map(uv);
|
texture_depth = sample_depth_map(uv, instance_index);
|
||||||
|
|
||||||
// Halve the deltas for the next step
|
// Halve the deltas for the next step
|
||||||
delta_uv *= 0.5;
|
delta_uv *= 0.5;
|
||||||
|
@ -103,7 +118,7 @@ fn parallaxed_uv(
|
||||||
// may skip small details and result in writhing material artifacts.
|
// may skip small details and result in writhing material artifacts.
|
||||||
let previous_uv = uv - delta_uv;
|
let previous_uv = uv - delta_uv;
|
||||||
let next_depth = texture_depth - current_layer_depth;
|
let next_depth = texture_depth - current_layer_depth;
|
||||||
let previous_depth = sample_depth_map(previous_uv) - current_layer_depth + layer_depth;
|
let previous_depth = sample_depth_map(previous_uv, instance_index) - current_layer_depth + layer_depth;
|
||||||
|
|
||||||
let weight = next_depth / (next_depth - previous_depth);
|
let weight = next_depth / (next_depth - previous_depth);
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,21 @@
|
||||||
|
|
||||||
#import bevy_pbr::pbr_types::StandardMaterial
|
#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(0) var<uniform> material: StandardMaterial;
|
||||||
@group(2) @binding(1) var base_color_texture: texture_2d<f32>;
|
@group(2) @binding(1) var base_color_texture: texture_2d<f32>;
|
||||||
@group(2) @binding(2) var base_color_sampler: sampler;
|
@group(2) @binding(2) var base_color_sampler: sampler;
|
||||||
|
@ -15,23 +30,50 @@
|
||||||
@group(2) @binding(10) var normal_map_sampler: sampler;
|
@group(2) @binding(10) var normal_map_sampler: sampler;
|
||||||
@group(2) @binding(11) var depth_map_texture: texture_2d<f32>;
|
@group(2) @binding(11) var depth_map_texture: texture_2d<f32>;
|
||||||
@group(2) @binding(12) var depth_map_sampler: sampler;
|
@group(2) @binding(12) var depth_map_sampler: sampler;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
#ifdef PBR_ANISOTROPY_TEXTURE_SUPPORTED
|
#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(13) var anisotropy_texture: texture_2d<f32>;
|
||||||
@group(2) @binding(14) var anisotropy_sampler: sampler;
|
@group(2) @binding(14) var anisotropy_sampler: sampler;
|
||||||
#endif
|
#endif // BINDLESS
|
||||||
|
#endif // PBR_ANISOTROPY_TEXTURE_SUPPORTED
|
||||||
|
|
||||||
#ifdef PBR_TRANSMISSION_TEXTURES_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(15) var specular_transmission_texture: texture_2d<f32>;
|
||||||
@group(2) @binding(16) var specular_transmission_sampler: sampler;
|
@group(2) @binding(16) var specular_transmission_sampler: sampler;
|
||||||
@group(2) @binding(17) var thickness_texture: texture_2d<f32>;
|
@group(2) @binding(17) var thickness_texture: texture_2d<f32>;
|
||||||
@group(2) @binding(18) var thickness_sampler: sampler;
|
@group(2) @binding(18) var thickness_sampler: sampler;
|
||||||
@group(2) @binding(19) var diffuse_transmission_texture: texture_2d<f32>;
|
@group(2) @binding(19) var diffuse_transmission_texture: texture_2d<f32>;
|
||||||
@group(2) @binding(20) var diffuse_transmission_sampler: sampler;
|
@group(2) @binding(20) var diffuse_transmission_sampler: sampler;
|
||||||
#endif
|
#endif // BINDLESS
|
||||||
|
#endif // PBR_TRANSMISSION_TEXTURES_SUPPORTED
|
||||||
|
|
||||||
#ifdef PBR_MULTI_LAYER_MATERIAL_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(21) var clearcoat_texture: texture_2d<f32>;
|
||||||
@group(2) @binding(22) var clearcoat_sampler: sampler;
|
@group(2) @binding(22) var clearcoat_sampler: sampler;
|
||||||
@group(2) @binding(23) var clearcoat_roughness_texture: texture_2d<f32>;
|
@group(2) @binding(23) var clearcoat_roughness_texture: texture_2d<f32>;
|
||||||
@group(2) @binding(24) var clearcoat_roughness_sampler: sampler;
|
@group(2) @binding(24) var clearcoat_roughness_sampler: sampler;
|
||||||
@group(2) @binding(25) var clearcoat_normal_texture: texture_2d<f32>;
|
@group(2) @binding(25) var clearcoat_normal_texture: texture_2d<f32>;
|
||||||
@group(2) @binding(26) var clearcoat_normal_sampler: sampler;
|
@group(2) @binding(26) var clearcoat_normal_sampler: sampler;
|
||||||
#endif
|
#endif // BINDLESS
|
||||||
|
#endif // PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
|
||||||
|
|
|
@ -70,12 +70,23 @@ fn pbr_input_from_standard_material(
|
||||||
in: VertexOutput,
|
in: VertexOutput,
|
||||||
is_front: bool,
|
is_front: bool,
|
||||||
) -> pbr_types::PbrInput {
|
) -> pbr_types::PbrInput {
|
||||||
let double_sided = (pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT) != 0u;
|
#ifdef BINDLESS
|
||||||
|
let slot = mesh[in.instance_index].material_bind_group_slot;
|
||||||
|
let flags = pbr_bindings::material[slot].flags;
|
||||||
|
let base_color = pbr_bindings::material[slot].base_color;
|
||||||
|
let deferred_lighting_pass_id = pbr_bindings::material[slot].deferred_lighting_pass_id;
|
||||||
|
#else // BINDLESS
|
||||||
|
let flags = pbr_bindings::material.flags;
|
||||||
|
let base_color = pbr_bindings::material.base_color;
|
||||||
|
let deferred_lighting_pass_id = pbr_bindings::material.deferred_lighting_pass_id;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
let double_sided = (flags & pbr_types::STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT) != 0u;
|
||||||
|
|
||||||
var pbr_input: pbr_types::PbrInput = pbr_input_from_vertex_output(in, is_front, double_sided);
|
var pbr_input: pbr_types::PbrInput = pbr_input_from_vertex_output(in, is_front, double_sided);
|
||||||
pbr_input.material.flags = pbr_bindings::material.flags;
|
pbr_input.material.flags = flags;
|
||||||
pbr_input.material.base_color *= pbr_bindings::material.base_color;
|
pbr_input.material.base_color *= base_color;
|
||||||
pbr_input.material.deferred_lighting_pass_id = pbr_bindings::material.deferred_lighting_pass_id;
|
pbr_input.material.deferred_lighting_pass_id = deferred_lighting_pass_id;
|
||||||
|
|
||||||
// Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886"
|
// Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886"
|
||||||
let NdotV = max(dot(pbr_input.N, pbr_input.V), 0.0001);
|
let NdotV = max(dot(pbr_input.N, pbr_input.V), 0.0001);
|
||||||
|
@ -91,7 +102,13 @@ fn pbr_input_from_standard_material(
|
||||||
|
|
||||||
// TODO: Transforming UVs mean we need to apply derivative chain rule for meshlet mesh material pass
|
// TODO: Transforming UVs mean we need to apply derivative chain rule for meshlet mesh material pass
|
||||||
#ifdef VERTEX_UVS
|
#ifdef VERTEX_UVS
|
||||||
|
|
||||||
|
#ifdef BINDLESS
|
||||||
|
let uv_transform = pbr_bindings::material[slot].uv_transform;
|
||||||
|
#else // BINDLESS
|
||||||
let uv_transform = pbr_bindings::material.uv_transform;
|
let uv_transform = pbr_bindings::material.uv_transform;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
#ifdef VERTEX_UVS_A
|
#ifdef VERTEX_UVS_A
|
||||||
var uv = (uv_transform * vec3(in.uv, 1.0)).xy;
|
var uv = (uv_transform * vec3(in.uv, 1.0)).xy;
|
||||||
#endif
|
#endif
|
||||||
|
@ -104,7 +121,7 @@ fn pbr_input_from_standard_material(
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VERTEX_TANGENTS
|
#ifdef VERTEX_TANGENTS
|
||||||
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_DEPTH_MAP_BIT) != 0u) {
|
if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_DEPTH_MAP_BIT) != 0u) {
|
||||||
let V = pbr_input.V;
|
let V = pbr_input.V;
|
||||||
let TBN = pbr_functions::calculate_tbn_mikktspace(in.world_normal, in.world_tangent);
|
let TBN = pbr_functions::calculate_tbn_mikktspace(in.world_normal, in.world_tangent);
|
||||||
let T = TBN[0];
|
let T = TBN[0];
|
||||||
|
@ -115,28 +132,42 @@ fn pbr_input_from_standard_material(
|
||||||
#ifdef VERTEX_UVS_A
|
#ifdef VERTEX_UVS_A
|
||||||
// TODO: Transforming UVs mean we need to apply derivative chain rule for meshlet mesh material pass
|
// TODO: Transforming UVs mean we need to apply derivative chain rule for meshlet mesh material pass
|
||||||
uv = parallaxed_uv(
|
uv = parallaxed_uv(
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::material[slot].parallax_depth_scale,
|
||||||
|
pbr_bindings::material[slot].max_parallax_layer_count,
|
||||||
|
pbr_bindings::material[slot].max_relief_mapping_search_steps,
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::material.parallax_depth_scale,
|
pbr_bindings::material.parallax_depth_scale,
|
||||||
pbr_bindings::material.max_parallax_layer_count,
|
pbr_bindings::material.max_parallax_layer_count,
|
||||||
pbr_bindings::material.max_relief_mapping_search_steps,
|
pbr_bindings::material.max_relief_mapping_search_steps,
|
||||||
|
#endif // BINDLESS
|
||||||
uv,
|
uv,
|
||||||
// Flip the direction of Vt to go toward the surface to make the
|
// Flip the direction of Vt to go toward the surface to make the
|
||||||
// parallax mapping algorithm easier to understand and reason
|
// parallax mapping algorithm easier to understand and reason
|
||||||
// about.
|
// about.
|
||||||
-Vt,
|
-Vt,
|
||||||
|
in.instance_index,
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VERTEX_UVS_B
|
#ifdef VERTEX_UVS_B
|
||||||
// TODO: Transforming UVs mean we need to apply derivative chain rule for meshlet mesh material pass
|
// TODO: Transforming UVs mean we need to apply derivative chain rule for meshlet mesh material pass
|
||||||
uv_b = parallaxed_uv(
|
uv_b = parallaxed_uv(
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::material[slot].parallax_depth_scale,
|
||||||
|
pbr_bindings::material[slot].max_parallax_layer_count,
|
||||||
|
pbr_bindings::material[slot].max_relief_mapping_search_steps,
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::material.parallax_depth_scale,
|
pbr_bindings::material.parallax_depth_scale,
|
||||||
pbr_bindings::material.max_parallax_layer_count,
|
pbr_bindings::material.max_parallax_layer_count,
|
||||||
pbr_bindings::material.max_relief_mapping_search_steps,
|
pbr_bindings::material.max_relief_mapping_search_steps,
|
||||||
|
#endif // BINDLESS
|
||||||
uv_b,
|
uv_b,
|
||||||
// Flip the direction of Vt to go toward the surface to make the
|
// Flip the direction of Vt to go toward the surface to make the
|
||||||
// parallax mapping algorithm easier to understand and reason
|
// parallax mapping algorithm easier to understand and reason
|
||||||
// about.
|
// about.
|
||||||
-Vt,
|
-Vt,
|
||||||
|
in.instance_index,
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
uv_b = uv;
|
uv_b = uv;
|
||||||
|
@ -144,27 +175,47 @@ fn pbr_input_from_standard_material(
|
||||||
}
|
}
|
||||||
#endif // VERTEX_TANGENTS
|
#endif // VERTEX_TANGENTS
|
||||||
|
|
||||||
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT) != 0u) {
|
if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT) != 0u) {
|
||||||
pbr_input.material.base_color *= pbr_functions::sample_texture(
|
pbr_input.material.base_color *=
|
||||||
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleGrad(
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleBias(
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::base_color_texture[slot],
|
||||||
|
pbr_bindings::base_color_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::base_color_texture,
|
pbr_bindings::base_color_texture,
|
||||||
pbr_bindings::base_color_sampler,
|
pbr_bindings::base_color_sampler,
|
||||||
|
#endif // BINDLESS
|
||||||
#ifdef STANDARD_MATERIAL_BASE_COLOR_UV_B
|
#ifdef STANDARD_MATERIAL_BASE_COLOR_UV_B
|
||||||
uv_b,
|
uv_b,
|
||||||
#else
|
#else
|
||||||
uv,
|
uv,
|
||||||
#endif
|
#endif
|
||||||
bias,
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.ddx_uv,
|
||||||
|
bias.ddy_uv,
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.mip_bias,
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
);
|
);
|
||||||
|
|
||||||
#ifdef ALPHA_TO_COVERAGE
|
#ifdef ALPHA_TO_COVERAGE
|
||||||
// Sharpen alpha edges.
|
// Sharpen alpha edges.
|
||||||
//
|
//
|
||||||
// https://bgolus.medium.com/anti-aliased-alpha-test-the-esoteric-alpha-to-coverage-8b177335ae4f
|
// https://bgolus.medium.com/anti-aliased-alpha-test-the-esoteric-alpha-to-coverage-8b177335ae4f
|
||||||
let alpha_mode = pbr_bindings::material.flags &
|
let alpha_mode = flags & pbr_types::STANDARD_MATERIAL_FLAGS_ALPHA_MODE_RESERVED_BITS;
|
||||||
pbr_types::STANDARD_MATERIAL_FLAGS_ALPHA_MODE_RESERVED_BITS;
|
|
||||||
if alpha_mode == pbr_types::STANDARD_MATERIAL_FLAGS_ALPHA_MODE_ALPHA_TO_COVERAGE {
|
if alpha_mode == pbr_types::STANDARD_MATERIAL_FLAGS_ALPHA_MODE_ALPHA_TO_COVERAGE {
|
||||||
pbr_input.material.base_color.a = (pbr_input.material.base_color.a -
|
|
||||||
pbr_bindings::material.alpha_cutoff) /
|
#ifdef BINDLESS
|
||||||
|
let alpha_cutoff = pbr_bindings::material[slot].alpha_cutoff;
|
||||||
|
#else // BINDLESS
|
||||||
|
let alpha_cutoff = pbr_bindings::material.alpha_cutoff;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
|
pbr_input.material.base_color.a = (pbr_input.material.base_color.a - alpha_cutoff) /
|
||||||
max(fwidth(pbr_input.material.base_color.a), 0.0001) + 0.5;
|
max(fwidth(pbr_input.material.base_color.a), 0.0001) + 0.5;
|
||||||
}
|
}
|
||||||
#endif // ALPHA_TO_COVERAGE
|
#endif // ALPHA_TO_COVERAGE
|
||||||
|
@ -172,49 +223,99 @@ fn pbr_input_from_standard_material(
|
||||||
}
|
}
|
||||||
#endif // VERTEX_UVS
|
#endif // VERTEX_UVS
|
||||||
|
|
||||||
pbr_input.material.flags = pbr_bindings::material.flags;
|
pbr_input.material.flags = flags;
|
||||||
|
|
||||||
// NOTE: Unlit bit not set means == 0 is true, so the true case is if lit
|
// NOTE: Unlit bit not set means == 0 is true, so the true case is if lit
|
||||||
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_UNLIT_BIT) == 0u) {
|
if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_UNLIT_BIT) == 0u) {
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_input.material.reflectance = pbr_bindings::material[slot].reflectance;
|
||||||
|
pbr_input.material.ior = pbr_bindings::material[slot].ior;
|
||||||
|
pbr_input.material.attenuation_color = pbr_bindings::material[slot].attenuation_color;
|
||||||
|
pbr_input.material.attenuation_distance = pbr_bindings::material[slot].attenuation_distance;
|
||||||
|
pbr_input.material.alpha_cutoff = pbr_bindings::material[slot].alpha_cutoff;
|
||||||
|
#else // BINDLESS
|
||||||
pbr_input.material.reflectance = pbr_bindings::material.reflectance;
|
pbr_input.material.reflectance = pbr_bindings::material.reflectance;
|
||||||
pbr_input.material.ior = pbr_bindings::material.ior;
|
pbr_input.material.ior = pbr_bindings::material.ior;
|
||||||
pbr_input.material.attenuation_color = pbr_bindings::material.attenuation_color;
|
pbr_input.material.attenuation_color = pbr_bindings::material.attenuation_color;
|
||||||
pbr_input.material.attenuation_distance = pbr_bindings::material.attenuation_distance;
|
pbr_input.material.attenuation_distance = pbr_bindings::material.attenuation_distance;
|
||||||
pbr_input.material.alpha_cutoff = pbr_bindings::material.alpha_cutoff;
|
pbr_input.material.alpha_cutoff = pbr_bindings::material.alpha_cutoff;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
// emissive
|
// emissive
|
||||||
|
#ifdef BINDLESS
|
||||||
|
var emissive: vec4<f32> = pbr_bindings::material[slot].emissive;
|
||||||
|
#else // BINDLESS
|
||||||
var emissive: vec4<f32> = pbr_bindings::material.emissive;
|
var emissive: vec4<f32> = pbr_bindings::material.emissive;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
#ifdef VERTEX_UVS
|
#ifdef VERTEX_UVS
|
||||||
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_EMISSIVE_TEXTURE_BIT) != 0u) {
|
if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_EMISSIVE_TEXTURE_BIT) != 0u) {
|
||||||
emissive = vec4<f32>(emissive.rgb * pbr_functions::sample_texture(
|
emissive = vec4<f32>(emissive.rgb *
|
||||||
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleGrad(
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleBias(
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::emissive_texture[slot],
|
||||||
|
pbr_bindings::emissive_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::emissive_texture,
|
pbr_bindings::emissive_texture,
|
||||||
pbr_bindings::emissive_sampler,
|
pbr_bindings::emissive_sampler,
|
||||||
|
#endif // BINDLESS
|
||||||
#ifdef STANDARD_MATERIAL_EMISSIVE_UV_B
|
#ifdef STANDARD_MATERIAL_EMISSIVE_UV_B
|
||||||
uv_b,
|
uv_b,
|
||||||
#else
|
#else
|
||||||
uv,
|
uv,
|
||||||
#endif
|
#endif
|
||||||
bias,
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
).rgb, emissive.a);
|
bias.ddx_uv,
|
||||||
|
bias.ddy_uv,
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.mip_bias,
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
).rgb,
|
||||||
|
emissive.a);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
pbr_input.material.emissive = emissive;
|
pbr_input.material.emissive = emissive;
|
||||||
|
|
||||||
// metallic and perceptual roughness
|
// metallic and perceptual roughness
|
||||||
|
#ifdef BINDLESS
|
||||||
|
var metallic: f32 = pbr_bindings::material[slot].metallic;
|
||||||
|
var perceptual_roughness: f32 = pbr_bindings::material[slot].perceptual_roughness;
|
||||||
|
#else // BINDLESS
|
||||||
var metallic: f32 = pbr_bindings::material.metallic;
|
var metallic: f32 = pbr_bindings::material.metallic;
|
||||||
var perceptual_roughness: f32 = pbr_bindings::material.perceptual_roughness;
|
var perceptual_roughness: f32 = pbr_bindings::material.perceptual_roughness;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
let roughness = lighting::perceptualRoughnessToRoughness(perceptual_roughness);
|
let roughness = lighting::perceptualRoughnessToRoughness(perceptual_roughness);
|
||||||
#ifdef VERTEX_UVS
|
#ifdef VERTEX_UVS
|
||||||
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_METALLIC_ROUGHNESS_TEXTURE_BIT) != 0u) {
|
if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_METALLIC_ROUGHNESS_TEXTURE_BIT) != 0u) {
|
||||||
let metallic_roughness = pbr_functions::sample_texture(
|
let metallic_roughness =
|
||||||
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleGrad(
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleBias(
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::metallic_roughness_texture[slot],
|
||||||
|
pbr_bindings::metallic_roughness_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::metallic_roughness_texture,
|
pbr_bindings::metallic_roughness_texture,
|
||||||
pbr_bindings::metallic_roughness_sampler,
|
pbr_bindings::metallic_roughness_sampler,
|
||||||
|
#endif // BINDLESS
|
||||||
#ifdef STANDARD_MATERIAL_METALLIC_ROUGHNESS_UV_B
|
#ifdef STANDARD_MATERIAL_METALLIC_ROUGHNESS_UV_B
|
||||||
uv_b,
|
uv_b,
|
||||||
#else
|
#else
|
||||||
uv,
|
uv,
|
||||||
#endif
|
#endif
|
||||||
bias,
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.ddx_uv,
|
||||||
|
bias.ddy_uv,
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.mip_bias,
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
);
|
);
|
||||||
// Sampling from GLTF standard channels for now
|
// Sampling from GLTF standard channels for now
|
||||||
metallic *= metallic_roughness.b;
|
metallic *= metallic_roughness.b;
|
||||||
|
@ -225,75 +326,157 @@ fn pbr_input_from_standard_material(
|
||||||
pbr_input.material.perceptual_roughness = perceptual_roughness;
|
pbr_input.material.perceptual_roughness = perceptual_roughness;
|
||||||
|
|
||||||
// Clearcoat factor
|
// Clearcoat factor
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_input.material.clearcoat = pbr_bindings::material[slot].clearcoat;
|
||||||
|
#else // BINDLESS
|
||||||
pbr_input.material.clearcoat = pbr_bindings::material.clearcoat;
|
pbr_input.material.clearcoat = pbr_bindings::material.clearcoat;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
#ifdef VERTEX_UVS
|
#ifdef VERTEX_UVS
|
||||||
#ifdef PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
|
#ifdef PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
|
||||||
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_CLEARCOAT_TEXTURE_BIT) != 0u) {
|
if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_CLEARCOAT_TEXTURE_BIT) != 0u) {
|
||||||
pbr_input.material.clearcoat *= pbr_functions::sample_texture(
|
pbr_input.material.clearcoat *=
|
||||||
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleGrad(
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleBias(
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::clearcoat_texture[slot],
|
||||||
|
pbr_bindings::clearcoat_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::clearcoat_texture,
|
pbr_bindings::clearcoat_texture,
|
||||||
pbr_bindings::clearcoat_sampler,
|
pbr_bindings::clearcoat_sampler,
|
||||||
|
#endif // BINDLESS
|
||||||
#ifdef STANDARD_MATERIAL_CLEARCOAT_UV_B
|
#ifdef STANDARD_MATERIAL_CLEARCOAT_UV_B
|
||||||
uv_b,
|
uv_b,
|
||||||
#else
|
#else
|
||||||
uv,
|
uv,
|
||||||
#endif
|
#endif
|
||||||
bias,
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.ddx_uv,
|
||||||
|
bias.ddy_uv,
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.mip_bias,
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
).r;
|
).r;
|
||||||
}
|
}
|
||||||
#endif // PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
|
#endif // PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
|
||||||
#endif // VERTEX_UVS
|
#endif // VERTEX_UVS
|
||||||
|
|
||||||
// Clearcoat roughness
|
// Clearcoat roughness
|
||||||
pbr_input.material.clearcoat_perceptual_roughness = pbr_bindings::material.clearcoat_perceptual_roughness;
|
#ifdef BINDLESS
|
||||||
|
pbr_input.material.clearcoat_perceptual_roughness =
|
||||||
|
pbr_bindings::material[slot].clearcoat_perceptual_roughness;
|
||||||
|
#else // BINDLESS
|
||||||
|
pbr_input.material.clearcoat_perceptual_roughness =
|
||||||
|
pbr_bindings::material.clearcoat_perceptual_roughness;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
#ifdef VERTEX_UVS
|
#ifdef VERTEX_UVS
|
||||||
#ifdef PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
|
#ifdef PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
|
||||||
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_CLEARCOAT_ROUGHNESS_TEXTURE_BIT) != 0u) {
|
if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_CLEARCOAT_ROUGHNESS_TEXTURE_BIT) != 0u) {
|
||||||
pbr_input.material.clearcoat_perceptual_roughness *= pbr_functions::sample_texture(
|
pbr_input.material.clearcoat_perceptual_roughness *=
|
||||||
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleGrad(
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleBias(
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::clearcoat_roughness_texture[slot],
|
||||||
|
pbr_bindings::clearcoat_roughness_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::clearcoat_roughness_texture,
|
pbr_bindings::clearcoat_roughness_texture,
|
||||||
pbr_bindings::clearcoat_roughness_sampler,
|
pbr_bindings::clearcoat_roughness_sampler,
|
||||||
|
#endif // BINDLESS
|
||||||
#ifdef STANDARD_MATERIAL_CLEARCOAT_ROUGHNESS_UV_B
|
#ifdef STANDARD_MATERIAL_CLEARCOAT_ROUGHNESS_UV_B
|
||||||
uv_b,
|
uv_b,
|
||||||
#else
|
#else
|
||||||
uv,
|
uv,
|
||||||
#endif
|
#endif
|
||||||
bias,
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.ddx_uv,
|
||||||
|
bias.ddy_uv,
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.mip_bias,
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
).g;
|
).g;
|
||||||
}
|
}
|
||||||
#endif // PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
|
#endif // PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
|
||||||
#endif // VERTEX_UVS
|
#endif // VERTEX_UVS
|
||||||
|
|
||||||
|
#ifdef BINDLESS
|
||||||
|
var specular_transmission: f32 = pbr_bindings::material[slot].specular_transmission;
|
||||||
|
#else // BINDLESS
|
||||||
var specular_transmission: f32 = pbr_bindings::material.specular_transmission;
|
var specular_transmission: f32 = pbr_bindings::material.specular_transmission;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
#ifdef VERTEX_UVS
|
#ifdef VERTEX_UVS
|
||||||
#ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED
|
#ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED
|
||||||
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_SPECULAR_TRANSMISSION_TEXTURE_BIT) != 0u) {
|
if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_SPECULAR_TRANSMISSION_TEXTURE_BIT) != 0u) {
|
||||||
specular_transmission *= pbr_functions::sample_texture(
|
specular_transmission *=
|
||||||
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleGrad(
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleBias(
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::specular_transmission_texture[slot],
|
||||||
|
pbr_bindings::specular_transmission_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::specular_transmission_texture,
|
pbr_bindings::specular_transmission_texture,
|
||||||
pbr_bindings::specular_transmission_sampler,
|
pbr_bindings::specular_transmission_sampler,
|
||||||
|
#endif // BINDLESS
|
||||||
#ifdef STANDARD_MATERIAL_SPECULAR_TRANSMISSION_UV_B
|
#ifdef STANDARD_MATERIAL_SPECULAR_TRANSMISSION_UV_B
|
||||||
uv_b,
|
uv_b,
|
||||||
#else
|
#else
|
||||||
uv,
|
uv,
|
||||||
#endif
|
#endif
|
||||||
bias,
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.ddx_uv,
|
||||||
|
bias.ddy_uv,
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.mip_bias,
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
).r;
|
).r;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
pbr_input.material.specular_transmission = specular_transmission;
|
pbr_input.material.specular_transmission = specular_transmission;
|
||||||
|
|
||||||
|
#ifdef BINDLESS
|
||||||
|
var thickness: f32 = pbr_bindings::material[slot].thickness;
|
||||||
|
#else // BINDLESS
|
||||||
var thickness: f32 = pbr_bindings::material.thickness;
|
var thickness: f32 = pbr_bindings::material.thickness;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
#ifdef VERTEX_UVS
|
#ifdef VERTEX_UVS
|
||||||
#ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED
|
#ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED
|
||||||
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_THICKNESS_TEXTURE_BIT) != 0u) {
|
if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_THICKNESS_TEXTURE_BIT) != 0u) {
|
||||||
thickness *= pbr_functions::sample_texture(
|
thickness *=
|
||||||
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleGrad(
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleBias(
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::thickness_texture[slot],
|
||||||
|
pbr_bindings::thickness_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::thickness_texture,
|
pbr_bindings::thickness_texture,
|
||||||
pbr_bindings::thickness_sampler,
|
pbr_bindings::thickness_sampler,
|
||||||
|
#endif // BINDLESS
|
||||||
#ifdef STANDARD_MATERIAL_THICKNESS_UV_B
|
#ifdef STANDARD_MATERIAL_THICKNESS_UV_B
|
||||||
uv_b,
|
uv_b,
|
||||||
#else
|
#else
|
||||||
uv,
|
uv,
|
||||||
#endif
|
#endif
|
||||||
bias,
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.ddx_uv,
|
||||||
|
bias.ddy_uv,
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.mip_bias,
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
).g;
|
).g;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -307,19 +490,39 @@ fn pbr_input_from_standard_material(
|
||||||
#endif
|
#endif
|
||||||
pbr_input.material.thickness = thickness;
|
pbr_input.material.thickness = thickness;
|
||||||
|
|
||||||
|
#ifdef BINDLESS
|
||||||
|
var diffuse_transmission = pbr_bindings::material[slot].diffuse_transmission;
|
||||||
|
#else // BINDLESS
|
||||||
var diffuse_transmission = pbr_bindings::material.diffuse_transmission;
|
var diffuse_transmission = pbr_bindings::material.diffuse_transmission;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
#ifdef VERTEX_UVS
|
#ifdef VERTEX_UVS
|
||||||
#ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED
|
#ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED
|
||||||
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_DIFFUSE_TRANSMISSION_TEXTURE_BIT) != 0u) {
|
if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_DIFFUSE_TRANSMISSION_TEXTURE_BIT) != 0u) {
|
||||||
diffuse_transmission *= pbr_functions::sample_texture(
|
diffuse_transmission *=
|
||||||
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleGrad(
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleBias(
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::diffuse_transmission_texture[slot],
|
||||||
|
pbr_bindings::diffuse_transmission_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::diffuse_transmission_texture,
|
pbr_bindings::diffuse_transmission_texture,
|
||||||
pbr_bindings::diffuse_transmission_sampler,
|
pbr_bindings::diffuse_transmission_sampler,
|
||||||
|
#endif // BINDLESS
|
||||||
#ifdef STANDARD_MATERIAL_DIFFUSE_TRANSMISSION_UV_B
|
#ifdef STANDARD_MATERIAL_DIFFUSE_TRANSMISSION_UV_B
|
||||||
uv_b,
|
uv_b,
|
||||||
#else
|
#else
|
||||||
uv,
|
uv,
|
||||||
#endif
|
#endif
|
||||||
bias,
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.ddx_uv,
|
||||||
|
bias.ddy_uv,
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.mip_bias,
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
).a;
|
).a;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -329,16 +532,31 @@ fn pbr_input_from_standard_material(
|
||||||
var diffuse_occlusion: vec3<f32> = vec3(1.0);
|
var diffuse_occlusion: vec3<f32> = vec3(1.0);
|
||||||
var specular_occlusion: f32 = 1.0;
|
var specular_occlusion: f32 = 1.0;
|
||||||
#ifdef VERTEX_UVS
|
#ifdef VERTEX_UVS
|
||||||
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_OCCLUSION_TEXTURE_BIT) != 0u) {
|
if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_OCCLUSION_TEXTURE_BIT) != 0u) {
|
||||||
diffuse_occlusion *= pbr_functions::sample_texture(
|
diffuse_occlusion *=
|
||||||
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleGrad(
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleBias(
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::occlusion_texture[slot],
|
||||||
|
pbr_bindings::occlusion_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::occlusion_texture,
|
pbr_bindings::occlusion_texture,
|
||||||
pbr_bindings::occlusion_sampler,
|
pbr_bindings::occlusion_sampler,
|
||||||
|
#endif // BINDLESS
|
||||||
#ifdef STANDARD_MATERIAL_OCCLUSION_UV_B
|
#ifdef STANDARD_MATERIAL_OCCLUSION_UV_B
|
||||||
uv_b,
|
uv_b,
|
||||||
#else
|
#else
|
||||||
uv,
|
uv,
|
||||||
#endif
|
#endif
|
||||||
bias,
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.ddx_uv,
|
||||||
|
bias.ddy_uv,
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.mip_bias,
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
).r;
|
).r;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -366,24 +584,33 @@ fn pbr_input_from_standard_material(
|
||||||
|
|
||||||
#ifdef STANDARD_MATERIAL_NORMAL_MAP
|
#ifdef STANDARD_MATERIAL_NORMAL_MAP
|
||||||
|
|
||||||
let Nt = pbr_functions::sample_texture(
|
let Nt =
|
||||||
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleGrad(
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleBias(
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::normal_map_texture[slot],
|
||||||
|
pbr_bindings::normal_map_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::normal_map_texture,
|
pbr_bindings::normal_map_texture,
|
||||||
pbr_bindings::normal_map_sampler,
|
pbr_bindings::normal_map_sampler,
|
||||||
|
#endif // BINDLESS
|
||||||
#ifdef STANDARD_MATERIAL_NORMAL_MAP_UV_B
|
#ifdef STANDARD_MATERIAL_NORMAL_MAP_UV_B
|
||||||
uv_b,
|
uv_b,
|
||||||
#else
|
#else
|
||||||
uv,
|
uv,
|
||||||
#endif
|
#endif
|
||||||
bias,
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.ddx_uv,
|
||||||
|
bias.ddy_uv,
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.mip_bias,
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
).rgb;
|
).rgb;
|
||||||
|
|
||||||
pbr_input.N = pbr_functions::apply_normal_mapping(
|
pbr_input.N = pbr_functions::apply_normal_mapping(flags, TBN, double_sided, is_front, Nt);
|
||||||
pbr_bindings::material.flags,
|
|
||||||
TBN,
|
|
||||||
double_sided,
|
|
||||||
is_front,
|
|
||||||
Nt,
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif // STANDARD_MATERIAL_NORMAL_MAP
|
#endif // STANDARD_MATERIAL_NORMAL_MAP
|
||||||
|
|
||||||
|
@ -395,19 +622,34 @@ fn pbr_input_from_standard_material(
|
||||||
|
|
||||||
#ifdef STANDARD_MATERIAL_CLEARCOAT_NORMAL_MAP
|
#ifdef STANDARD_MATERIAL_CLEARCOAT_NORMAL_MAP
|
||||||
|
|
||||||
let clearcoat_Nt = pbr_functions::sample_texture(
|
let clearcoat_Nt =
|
||||||
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleGrad(
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleBias(
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::clearcoat_normal_texture[slot],
|
||||||
|
pbr_bindings::clearcoat_normal_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::clearcoat_normal_texture,
|
pbr_bindings::clearcoat_normal_texture,
|
||||||
pbr_bindings::clearcoat_normal_sampler,
|
pbr_bindings::clearcoat_normal_sampler,
|
||||||
|
#endif // BINDLESS
|
||||||
#ifdef STANDARD_MATERIAL_CLEARCOAT_NORMAL_UV_B
|
#ifdef STANDARD_MATERIAL_CLEARCOAT_NORMAL_UV_B
|
||||||
uv_b,
|
uv_b,
|
||||||
#else
|
#else
|
||||||
uv,
|
uv,
|
||||||
#endif
|
#endif
|
||||||
bias,
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.ddx_uv,
|
||||||
|
bias.ddy_uv,
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.mip_bias,
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
).rgb;
|
).rgb;
|
||||||
|
|
||||||
pbr_input.clearcoat_N = pbr_functions::apply_normal_mapping(
|
pbr_input.clearcoat_N = pbr_functions::apply_normal_mapping(
|
||||||
pbr_bindings::material.flags,
|
flags,
|
||||||
TBN,
|
TBN,
|
||||||
double_sided,
|
double_sided,
|
||||||
is_front,
|
is_front,
|
||||||
|
@ -429,20 +671,40 @@ fn pbr_input_from_standard_material(
|
||||||
#ifdef VERTEX_TANGENTS
|
#ifdef VERTEX_TANGENTS
|
||||||
#ifdef STANDARD_MATERIAL_ANISOTROPY
|
#ifdef STANDARD_MATERIAL_ANISOTROPY
|
||||||
|
|
||||||
|
#ifdef BINDLESS
|
||||||
|
var anisotropy_strength = pbr_bindings::material[slot].anisotropy_strength;
|
||||||
|
var anisotropy_direction = pbr_bindings::material[slot].anisotropy_rotation;
|
||||||
|
#else // BINDLESS
|
||||||
var anisotropy_strength = pbr_bindings::material.anisotropy_strength;
|
var anisotropy_strength = pbr_bindings::material.anisotropy_strength;
|
||||||
var anisotropy_direction = pbr_bindings::material.anisotropy_rotation;
|
var anisotropy_direction = pbr_bindings::material.anisotropy_rotation;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
// Adjust based on the anisotropy map if there is one.
|
// Adjust based on the anisotropy map if there is one.
|
||||||
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_ANISOTROPY_TEXTURE_BIT) != 0u) {
|
if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_ANISOTROPY_TEXTURE_BIT) != 0u) {
|
||||||
let anisotropy_texel = pbr_functions::sample_texture(
|
let anisotropy_texel =
|
||||||
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleGrad(
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleBias(
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::anisotropy_texture[slot],
|
||||||
|
pbr_bindings::anisotropy_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::anisotropy_texture,
|
pbr_bindings::anisotropy_texture,
|
||||||
pbr_bindings::anisotropy_sampler,
|
pbr_bindings::anisotropy_sampler,
|
||||||
|
#endif
|
||||||
#ifdef STANDARD_MATERIAL_ANISOTROPY_UV_B
|
#ifdef STANDARD_MATERIAL_ANISOTROPY_UV_B
|
||||||
uv_b,
|
uv_b,
|
||||||
#else // STANDARD_MATERIAL_ANISOTROPY_UV_B
|
#else // STANDARD_MATERIAL_ANISOTROPY_UV_B
|
||||||
uv,
|
uv,
|
||||||
#endif // STANDARD_MATERIAL_ANISOTROPY_UV_B
|
#endif // STANDARD_MATERIAL_ANISOTROPY_UV_B
|
||||||
bias,
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.ddx_uv,
|
||||||
|
bias.ddy_uv,
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.mip_bias,
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
).rgb;
|
).rgb;
|
||||||
|
|
||||||
let anisotropy_direction_from_texture = normalize(anisotropy_texel.rg * 2.0 - 1.0);
|
let anisotropy_direction_from_texture = normalize(anisotropy_texel.rg * 2.0 - 1.0);
|
||||||
|
@ -468,10 +730,14 @@ fn pbr_input_from_standard_material(
|
||||||
|
|
||||||
// TODO: Meshlet support
|
// TODO: Meshlet support
|
||||||
#ifdef LIGHTMAP
|
#ifdef LIGHTMAP
|
||||||
pbr_input.lightmap_light = lightmap(
|
|
||||||
in.uv_b,
|
#ifdef BINDLESS
|
||||||
pbr_bindings::material.lightmap_exposure,
|
let lightmap_exposure = pbr_bindings::material[slot].lightmap_exposure;
|
||||||
in.instance_index);
|
#else // BINDLESS
|
||||||
|
let lightmap_exposure = pbr_bindings::material.lightmap_exposure;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
|
pbr_input.lightmap_light = lightmap(in.uv_b, lightmap_exposure, in.instance_index);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,21 +121,6 @@ fn alpha_discard(material: pbr_types::StandardMaterial, output_color: vec4<f32>)
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Samples a texture using the appropriate biasing metric for the type of mesh
|
|
||||||
// in use (mesh vs. meshlet).
|
|
||||||
fn sample_texture(
|
|
||||||
texture: texture_2d<f32>,
|
|
||||||
samp: sampler,
|
|
||||||
uv: vec2<f32>,
|
|
||||||
bias: SampleBias,
|
|
||||||
) -> vec4<f32> {
|
|
||||||
#ifdef MESHLET_MESH_MATERIAL_PASS
|
|
||||||
return textureSampleGrad(texture, samp, uv, bias.ddx_uv, bias.ddy_uv);
|
|
||||||
#else
|
|
||||||
return textureSampleBias(texture, samp, uv, bias.mip_bias);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prepare_world_normal(
|
fn prepare_world_normal(
|
||||||
world_normal: vec3<f32>,
|
world_normal: vec3<f32>,
|
||||||
double_sided: bool,
|
double_sided: bool,
|
||||||
|
|
|
@ -76,11 +76,26 @@ fn fragment(
|
||||||
bias.mip_bias = view.mip_bias;
|
bias.mip_bias = view.mip_bias;
|
||||||
#endif // MESHLET_MESH_MATERIAL_PASS
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
|
||||||
let Nt = pbr_functions::sample_texture(
|
let Nt =
|
||||||
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleGrad(
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
textureSampleBias(
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::normal_map_texture[slot],
|
||||||
|
pbr_bindings::normal_map_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
pbr_bindings::normal_map_texture,
|
pbr_bindings::normal_map_texture,
|
||||||
pbr_bindings::normal_map_sampler,
|
pbr_bindings::normal_map_sampler,
|
||||||
|
#endif // BINDLESS
|
||||||
uv,
|
uv,
|
||||||
bias,
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.ddx_uv,
|
||||||
|
bias.ddy_uv,
|
||||||
|
#else // MESHLET_MESH_MATERIAL_PASS
|
||||||
|
bias.mip_bias,
|
||||||
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||||
).rgb;
|
).rgb;
|
||||||
let TBN = pbr_functions::calculate_tbn_mikktspace(normal, in.world_tangent);
|
let TBN = pbr_functions::calculate_tbn_mikktspace(normal, in.world_tangent);
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#import bevy_pbr::{
|
#import bevy_pbr::{
|
||||||
prepass_io::VertexOutput,
|
prepass_io::VertexOutput,
|
||||||
prepass_bindings::previous_view_uniforms,
|
prepass_bindings::previous_view_uniforms,
|
||||||
|
mesh_bindings::mesh,
|
||||||
mesh_view_bindings::view,
|
mesh_view_bindings::view,
|
||||||
pbr_bindings,
|
pbr_bindings,
|
||||||
pbr_types,
|
pbr_types,
|
||||||
|
@ -15,7 +16,12 @@ const PREMULTIPLIED_ALPHA_CUTOFF = 0.05;
|
||||||
fn prepass_alpha_discard(in: VertexOutput) {
|
fn prepass_alpha_discard(in: VertexOutput) {
|
||||||
|
|
||||||
#ifdef MAY_DISCARD
|
#ifdef MAY_DISCARD
|
||||||
|
#ifdef BINDLESS
|
||||||
|
let slot = mesh[in.instance_index].material_bind_group_slot;
|
||||||
|
var output_color: vec4<f32> = pbr_bindings::material[slot].base_color;
|
||||||
|
#else // BINDLESS
|
||||||
var output_color: vec4<f32> = pbr_bindings::material.base_color;
|
var output_color: vec4<f32> = pbr_bindings::material.base_color;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
#ifdef VERTEX_UVS
|
#ifdef VERTEX_UVS
|
||||||
#ifdef STANDARD_MATERIAL_BASE_COLOR_UV_B
|
#ifdef STANDARD_MATERIAL_BASE_COLOR_UV_B
|
||||||
|
@ -24,16 +30,38 @@ fn prepass_alpha_discard(in: VertexOutput) {
|
||||||
var uv = in.uv;
|
var uv = in.uv;
|
||||||
#endif // STANDARD_MATERIAL_BASE_COLOR_UV_B
|
#endif // STANDARD_MATERIAL_BASE_COLOR_UV_B
|
||||||
|
|
||||||
|
#ifdef BINDLESS
|
||||||
|
let uv_transform = pbr_bindings::material[slot].uv_transform;
|
||||||
|
let flags = pbr_bindings::material[slot].flags;
|
||||||
|
#else // BINDLESS
|
||||||
let uv_transform = pbr_bindings::material.uv_transform;
|
let uv_transform = pbr_bindings::material.uv_transform;
|
||||||
|
let flags = pbr_bindings::material.flags;
|
||||||
|
#endif // BINDLESS
|
||||||
|
|
||||||
uv = (uv_transform * vec3(uv, 1.0)).xy;
|
uv = (uv_transform * vec3(uv, 1.0)).xy;
|
||||||
if (pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT) != 0u {
|
if (flags & pbr_types::STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT) != 0u {
|
||||||
output_color = output_color * textureSampleBias(pbr_bindings::base_color_texture, pbr_bindings::base_color_sampler, uv, view.mip_bias);
|
output_color = output_color * textureSampleBias(
|
||||||
|
#ifdef BINDLESS
|
||||||
|
pbr_bindings::base_color_texture[slot],
|
||||||
|
pbr_bindings::base_color_sampler[slot],
|
||||||
|
#else // BINDLESS
|
||||||
|
pbr_bindings::base_color_texture,
|
||||||
|
pbr_bindings::base_color_sampler,
|
||||||
|
#endif // BINDLESS
|
||||||
|
uv,
|
||||||
|
view.mip_bias
|
||||||
|
);
|
||||||
}
|
}
|
||||||
#endif // VERTEX_UVS
|
#endif // VERTEX_UVS
|
||||||
|
|
||||||
let alpha_mode = pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_ALPHA_MODE_RESERVED_BITS;
|
let alpha_mode = flags & pbr_types::STANDARD_MATERIAL_FLAGS_ALPHA_MODE_RESERVED_BITS;
|
||||||
if alpha_mode == pbr_types::STANDARD_MATERIAL_FLAGS_ALPHA_MODE_MASK {
|
if alpha_mode == pbr_types::STANDARD_MATERIAL_FLAGS_ALPHA_MODE_MASK {
|
||||||
if output_color.a < pbr_bindings::material.alpha_cutoff {
|
#ifdef BINDLESS
|
||||||
|
let alpha_cutoff = pbr_bindings::material[slot].alpha_cutoff;
|
||||||
|
#else // BINDLESS
|
||||||
|
let alpha_cutoff = pbr_bindings::material.alpha_cutoff;
|
||||||
|
#endif // BINDLESS
|
||||||
|
if output_color.a < alpha_cutoff {
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
} else if (alpha_mode == pbr_types::STANDARD_MATERIAL_FLAGS_ALPHA_MODE_BLEND ||
|
} else if (alpha_mode == pbr_types::STANDARD_MATERIAL_FLAGS_ALPHA_MODE_BLEND ||
|
||||||
|
|
|
@ -443,7 +443,8 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
|
||||||
if render_device.features().contains(
|
if render_device.features().contains(
|
||||||
#render_path::settings::WgpuFeatures::BUFFER_BINDING_ARRAY |
|
#render_path::settings::WgpuFeatures::BUFFER_BINDING_ARRAY |
|
||||||
#render_path::settings::WgpuFeatures::TEXTURE_BINDING_ARRAY
|
#render_path::settings::WgpuFeatures::TEXTURE_BINDING_ARRAY
|
||||||
) && render_device.limits().max_storage_buffers_per_shader_stage > 0 {
|
) && render_device.limits().max_storage_buffers_per_shader_stage > 0 &&
|
||||||
|
!force_no_bindless {
|
||||||
(
|
(
|
||||||
#render_path::render_resource::BufferBindingType::Storage { read_only: true },
|
#render_path::render_resource::BufferBindingType::Storage { read_only: true },
|
||||||
#render_path::render_resource::BufferUsages::STORAGE,
|
#render_path::render_resource::BufferUsages::STORAGE,
|
||||||
|
@ -571,7 +572,8 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
|
||||||
let #actual_bindless_slot_count = if render_device.features().contains(
|
let #actual_bindless_slot_count = if render_device.features().contains(
|
||||||
#render_path::settings::WgpuFeatures::BUFFER_BINDING_ARRAY |
|
#render_path::settings::WgpuFeatures::BUFFER_BINDING_ARRAY |
|
||||||
#render_path::settings::WgpuFeatures::TEXTURE_BINDING_ARRAY
|
#render_path::settings::WgpuFeatures::TEXTURE_BINDING_ARRAY
|
||||||
) && render_device.limits().max_storage_buffers_per_shader_stage > 0 {
|
) && render_device.limits().max_storage_buffers_per_shader_stage > 0 &&
|
||||||
|
!force_no_bindless {
|
||||||
::core::num::NonZeroU32::new(#bindless_count)
|
::core::num::NonZeroU32::new(#bindless_count)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -607,6 +609,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
|
||||||
layout: &#render_path::render_resource::BindGroupLayout,
|
layout: &#render_path::render_resource::BindGroupLayout,
|
||||||
render_device: &#render_path::renderer::RenderDevice,
|
render_device: &#render_path::renderer::RenderDevice,
|
||||||
(images, fallback_image, storage_buffers): &mut #ecs_path::system::SystemParamItem<'_, '_, Self::Param>,
|
(images, fallback_image, storage_buffers): &mut #ecs_path::system::SystemParamItem<'_, '_, Self::Param>,
|
||||||
|
force_no_bindless: bool,
|
||||||
) -> Result<#render_path::render_resource::UnpreparedBindGroup<Self::Data>, #render_path::render_resource::AsBindGroupError> {
|
) -> Result<#render_path::render_resource::UnpreparedBindGroup<Self::Data>, #render_path::render_resource::AsBindGroupError> {
|
||||||
#uniform_binding_type_declarations
|
#uniform_binding_type_declarations
|
||||||
|
|
||||||
|
@ -618,7 +621,10 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bind_group_layout_entries(render_device: &#render_path::renderer::RenderDevice) -> Vec<#render_path::render_resource::BindGroupLayoutEntry> {
|
fn bind_group_layout_entries(
|
||||||
|
render_device: &#render_path::renderer::RenderDevice,
|
||||||
|
force_no_bindless: bool
|
||||||
|
) -> Vec<#render_path::render_resource::BindGroupLayoutEntry> {
|
||||||
#actual_bindless_slot_count_declaration
|
#actual_bindless_slot_count_declaration
|
||||||
#uniform_binding_type_declarations
|
#uniform_binding_type_declarations
|
||||||
|
|
||||||
|
|
|
@ -352,7 +352,7 @@ pub trait AsBindGroup {
|
||||||
param: &mut SystemParamItem<'_, '_, Self::Param>,
|
param: &mut SystemParamItem<'_, '_, Self::Param>,
|
||||||
) -> Result<PreparedBindGroup<Self::Data>, AsBindGroupError> {
|
) -> Result<PreparedBindGroup<Self::Data>, AsBindGroupError> {
|
||||||
let UnpreparedBindGroup { bindings, data } =
|
let UnpreparedBindGroup { bindings, data } =
|
||||||
Self::unprepared_bind_group(self, layout, render_device, param)?;
|
Self::unprepared_bind_group(self, layout, render_device, param, false)?;
|
||||||
|
|
||||||
let entries = bindings
|
let entries = bindings
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -372,30 +372,45 @@ pub trait AsBindGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a vec of (binding index, `OwnedBindingResource`).
|
/// Returns a vec of (binding index, `OwnedBindingResource`).
|
||||||
/// In cases where `OwnedBindingResource` is not available (as for bindless texture arrays currently),
|
///
|
||||||
/// an implementor may return `AsBindGroupError::CreateBindGroupDirectly`
|
/// In cases where `OwnedBindingResource` is not available (as for bindless
|
||||||
/// from this function and instead define `as_bind_group` directly. This may
|
/// texture arrays currently), an implementor may return
|
||||||
/// prevent certain features, such as bindless mode, from working correctly.
|
/// `AsBindGroupError::CreateBindGroupDirectly` from this function and
|
||||||
|
/// instead define `as_bind_group` directly. This may prevent certain
|
||||||
|
/// features, such as bindless mode, from working correctly.
|
||||||
|
///
|
||||||
|
/// Set `force_no_bindless` to true to require that bindless textures *not*
|
||||||
|
/// be used. `ExtendedMaterial` uses this in order to ensure that the base
|
||||||
|
/// material doesn't use bindless mode if the extension doesn't.
|
||||||
fn unprepared_bind_group(
|
fn unprepared_bind_group(
|
||||||
&self,
|
&self,
|
||||||
layout: &BindGroupLayout,
|
layout: &BindGroupLayout,
|
||||||
render_device: &RenderDevice,
|
render_device: &RenderDevice,
|
||||||
param: &mut SystemParamItem<'_, '_, Self::Param>,
|
param: &mut SystemParamItem<'_, '_, Self::Param>,
|
||||||
|
force_no_bindless: bool,
|
||||||
) -> Result<UnpreparedBindGroup<Self::Data>, AsBindGroupError>;
|
) -> Result<UnpreparedBindGroup<Self::Data>, AsBindGroupError>;
|
||||||
|
|
||||||
/// Creates the bind group layout matching all bind groups returned by [`AsBindGroup::as_bind_group`]
|
/// Creates the bind group layout matching all bind groups returned by
|
||||||
|
/// [`AsBindGroup::as_bind_group`]
|
||||||
fn bind_group_layout(render_device: &RenderDevice) -> BindGroupLayout
|
fn bind_group_layout(render_device: &RenderDevice) -> BindGroupLayout
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
render_device.create_bind_group_layout(
|
render_device.create_bind_group_layout(
|
||||||
Self::label(),
|
Self::label(),
|
||||||
&Self::bind_group_layout_entries(render_device),
|
&Self::bind_group_layout_entries(render_device, false),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a vec of bind group layout entries
|
/// Returns a vec of bind group layout entries
|
||||||
fn bind_group_layout_entries(render_device: &RenderDevice) -> Vec<BindGroupLayoutEntry>
|
///
|
||||||
|
/// Set `force_no_bindless` to true to require that bindless textures *not*
|
||||||
|
/// be used. `ExtendedMaterial` uses this in order to ensure that the base
|
||||||
|
/// material doesn't use bindless mode if the extension doesn't.
|
||||||
|
fn bind_group_layout_entries(
|
||||||
|
render_device: &RenderDevice,
|
||||||
|
force_no_bindless: bool,
|
||||||
|
) -> Vec<BindGroupLayoutEntry>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,6 +144,7 @@ impl AsBindGroup for BindlessMaterial {
|
||||||
_layout: &BindGroupLayout,
|
_layout: &BindGroupLayout,
|
||||||
_render_device: &RenderDevice,
|
_render_device: &RenderDevice,
|
||||||
_param: &mut SystemParamItem<'_, '_, Self::Param>,
|
_param: &mut SystemParamItem<'_, '_, Self::Param>,
|
||||||
|
_force_no_bindless: bool,
|
||||||
) -> Result<UnpreparedBindGroup<Self::Data>, AsBindGroupError> {
|
) -> Result<UnpreparedBindGroup<Self::Data>, AsBindGroupError> {
|
||||||
// We implement `as_bind_group`` directly because bindless texture
|
// We implement `as_bind_group`` directly because bindless texture
|
||||||
// arrays can't be owned.
|
// arrays can't be owned.
|
||||||
|
@ -152,7 +153,7 @@ impl AsBindGroup for BindlessMaterial {
|
||||||
Err(AsBindGroupError::CreateBindGroupDirectly)
|
Err(AsBindGroupError::CreateBindGroupDirectly)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bind_group_layout_entries(_: &RenderDevice) -> Vec<BindGroupLayoutEntry>
|
fn bind_group_layout_entries(_: &RenderDevice, _: bool) -> Vec<BindGroupLayoutEntry>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue