539 lines
22 KiB
Rust
539 lines
22 KiB
Rust
use crate::{
|
||
AlphaMode, Material, MaterialPipeline, MaterialPipelineKey, PBR_PREPASS_SHADER_HANDLE,
|
||
PBR_SHADER_HANDLE,
|
||
};
|
||
use bevy_asset::Handle;
|
||
use bevy_math::Vec4;
|
||
use bevy_reflect::{std_traits::ReflectDefault, FromReflect, Reflect, TypeUuid};
|
||
use bevy_render::{
|
||
color::Color, mesh::MeshVertexBufferLayout, render_asset::RenderAssets, render_resource::*,
|
||
texture::Image,
|
||
};
|
||
|
||
/// A material with "standard" properties used in PBR lighting
|
||
/// Standard property values with pictures here
|
||
/// <https://google.github.io/filament/Material%20Properties.pdf>.
|
||
///
|
||
/// May be created directly from a [`Color`] or an [`Image`].
|
||
#[derive(AsBindGroup, Reflect, FromReflect, Debug, Clone, TypeUuid)]
|
||
#[uuid = "7494888b-c082-457b-aacf-517228cc0c22"]
|
||
#[bind_group_data(StandardMaterialKey)]
|
||
#[uniform(0, StandardMaterialUniform)]
|
||
#[reflect(Default, Debug)]
|
||
pub struct StandardMaterial {
|
||
/// The color of the surface of the material before lighting.
|
||
///
|
||
/// Doubles as diffuse albedo for non-metallic, specular for metallic and a mix for everything
|
||
/// in between. If used together with a `base_color_texture`, this is factored into the final
|
||
/// base color as `base_color * base_color_texture_value`
|
||
///
|
||
/// Defaults to [`Color::WHITE`].
|
||
pub base_color: Color,
|
||
|
||
/// The texture component of the material's color before lighting.
|
||
/// The actual pre-lighting color is `base_color * this_texture`.
|
||
///
|
||
/// See [`base_color`] for details.
|
||
///
|
||
/// You should set `base_color` to [`Color::WHITE`] (the default)
|
||
/// if you want the texture to show as-is.
|
||
///
|
||
/// Setting `base_color` to something else than white will tint
|
||
/// the texture. For example, setting `base_color` to pure red will
|
||
/// tint the texture red.
|
||
///
|
||
/// [`base_color`]: StandardMaterial::base_color
|
||
#[texture(1)]
|
||
#[sampler(2)]
|
||
pub base_color_texture: Option<Handle<Image>>,
|
||
|
||
// Use a color for user friendliness even though we technically don't use the alpha channel
|
||
// Might be used in the future for exposure correction in HDR
|
||
/// Color the material "emits" to the camera.
|
||
///
|
||
/// This is typically used for monitor screens or LED lights.
|
||
/// Anything that can be visible even in darkness.
|
||
///
|
||
/// The emissive color is added to what would otherwise be the material's visible color.
|
||
/// This means that for a light emissive value, in darkness,
|
||
/// you will mostly see the emissive component.
|
||
///
|
||
/// The default emissive color is black, which doesn't add anything to the material color.
|
||
///
|
||
/// Note that **an emissive material won't light up surrounding areas like a light source**,
|
||
/// it just adds a value to the color seen on screen.
|
||
pub emissive: Color,
|
||
|
||
/// The emissive map, multiplies pixels with [`emissive`]
|
||
/// to get the final "emitting" color of a surface.
|
||
///
|
||
/// This color is multiplied by [`emissive`] to get the final emitted color.
|
||
/// Meaning that you should set [`emissive`] to [`Color::WHITE`]
|
||
/// if you want to use the full range of color of the emissive texture.
|
||
///
|
||
/// [`emissive`]: StandardMaterial::emissive
|
||
#[texture(3)]
|
||
#[sampler(4)]
|
||
pub emissive_texture: Option<Handle<Image>>,
|
||
|
||
/// Linear perceptual roughness, clamped to `[0.089, 1.0]` in the shader.
|
||
///
|
||
/// Defaults to `0.5`.
|
||
///
|
||
/// Low values result in a "glossy" material with specular highlights,
|
||
/// while values close to `1` result in rough materials.
|
||
///
|
||
/// If used together with a roughness/metallic texture, this is factored into the final base
|
||
/// color as `roughness * roughness_texture_value`.
|
||
///
|
||
/// 0.089 is the minimum floating point value that won't be rounded down to 0 in the
|
||
/// calculations used.
|
||
//
|
||
// Technically for 32-bit floats, 0.045 could be used.
|
||
// See <https://google.github.io/filament/Filament.html#materialsystem/parameterization/>
|
||
pub perceptual_roughness: f32,
|
||
|
||
/// How "metallic" the material appears, within `[0.0, 1.0]`.
|
||
///
|
||
/// This should be set to 0.0 for dielectric materials or 1.0 for metallic materials.
|
||
/// For a hybrid surface such as corroded metal, you may need to use in-between values.
|
||
///
|
||
/// Defaults to `0.00`, for dielectric.
|
||
///
|
||
/// If used together with a roughness/metallic texture, this is factored into the final base
|
||
/// color as `metallic * metallic_texture_value`.
|
||
pub metallic: f32,
|
||
|
||
/// Metallic and roughness maps, stored as a single texture.
|
||
///
|
||
/// The blue channel contains metallic values,
|
||
/// and the green channel contains the roughness values.
|
||
/// Other channels are unused.
|
||
///
|
||
/// Those values are multiplied by the scalar ones of the material,
|
||
/// see [`metallic`] and [`perceptual_roughness`] for details.
|
||
///
|
||
/// Note that with the default values of [`metallic`] and [`perceptual_roughness`],
|
||
/// setting this texture has no effect. If you want to exclusively use the
|
||
/// `metallic_roughness_texture` values for your material, make sure to set [`metallic`]
|
||
/// and [`perceptual_roughness`] to `1.0`.
|
||
///
|
||
/// [`metallic`]: StandardMaterial::metallic
|
||
/// [`perceptual_roughness`]: StandardMaterial::perceptual_roughness
|
||
#[texture(5)]
|
||
#[sampler(6)]
|
||
pub metallic_roughness_texture: Option<Handle<Image>>,
|
||
|
||
/// Specular intensity for non-metals on a linear scale of `[0.0, 1.0]`.
|
||
///
|
||
/// Use the value as a way to control the intensity of the
|
||
/// specular highlight of the material, i.e. how reflective is the material,
|
||
/// rather than the physical property "reflectance."
|
||
///
|
||
/// Set to `0.0`, no specular highlight is visible, the highlight is strongest
|
||
/// when `reflectance` is set to `1.0`.
|
||
///
|
||
/// Defaults to `0.5` which is mapped to 4% reflectance in the shader.
|
||
#[doc(alias = "specular_intensity")]
|
||
pub reflectance: f32,
|
||
|
||
/// The amount of light transmitted through the material (via refraction)
|
||
///
|
||
/// - When set to `0.0` (the default) no light is transmitted.
|
||
/// - When set to `1.0` all light is transmitted through the material.
|
||
///
|
||
/// The material's [`StandardMaterial::base_color`] also modulates the transmitted light.
|
||
///
|
||
/// **Important:** For transmission to have any effect, you must also set `alpha_mode` to [`AlphaMode::Blend`].
|
||
/// **Note:** Typically used in conjunction with [`StandardMaterial::thickness`] and [`StandardMaterial::ior`].
|
||
pub transmission: f32,
|
||
|
||
/// Thickness of the volume beneath the material surface.
|
||
///
|
||
/// When set to `0.0` (the default) the material appears as an infinitely-thin film,
|
||
/// transmitting light without distorting it.
|
||
///
|
||
/// When set to any other value, the material distorts light like a volumetric lens.
|
||
///
|
||
/// **Note:** Typically used in conjunction with [`StandardMaterial::transmission`] and [`StandardMaterial::ior`].
|
||
pub thickness: f32,
|
||
|
||
/// The index of refraction of the material
|
||
///
|
||
/// | Material | Index of Refraction |
|
||
/// |:----------------|:---------------------|
|
||
/// | Vacuum | 1 |
|
||
/// | Air | 1.00 |
|
||
/// | Ice | 1.31 |
|
||
/// | Water | 1.33 |
|
||
/// | Eyes | 1.38 |
|
||
/// | Quartz | 1.46 |
|
||
/// | Olive Oil | 1.47 |
|
||
/// | Honey | 1.49 |
|
||
/// | Acrylic | 1.49 |
|
||
/// | Window Glass | 1.52 |
|
||
/// | Polycarbonate | 1.58 |
|
||
/// | Flint Glass | 1.69 |
|
||
/// | Ruby | 1.71 |
|
||
/// | Glycerine | 1.74 |
|
||
/// | Saphire | 1.77 |
|
||
/// | Cubic Zirconia | 2.15 |
|
||
/// | Diamond | 2.42 |
|
||
/// | Moissanite | 2.65 |
|
||
///
|
||
/// **Note:** Typically used in conjunction with [`StandardMaterial::transmission`] and [`StandardMaterial::thickness`].
|
||
#[doc(alias = "index_of_refraction")]
|
||
#[doc(alias = "refraction_index")]
|
||
pub ior: f32,
|
||
|
||
/// Used to fake the lighting of bumps and dents on a material.
|
||
///
|
||
/// A typical usage would be faking cobblestones on a flat plane mesh in 3D.
|
||
///
|
||
/// # Notes
|
||
///
|
||
/// Normal mapping with `StandardMaterial` and the core bevy PBR shaders requires:
|
||
/// - A normal map texture
|
||
/// - Vertex UVs
|
||
/// - Vertex tangents
|
||
/// - Vertex normals
|
||
///
|
||
/// Tangents do not have to be stored in your model,
|
||
/// they can be generated using the [`Mesh::generate_tangents`] method.
|
||
/// If your material has a normal map, but still renders as a flat surface,
|
||
/// make sure your meshes have their tangents set.
|
||
///
|
||
/// [`Mesh::generate_tangents`]: bevy_render::mesh::Mesh::generate_tangents
|
||
#[texture(9)]
|
||
#[sampler(10)]
|
||
pub normal_map_texture: Option<Handle<Image>>,
|
||
|
||
/// Normal map textures authored for DirectX have their y-component flipped. Set this to flip
|
||
/// it to right-handed conventions.
|
||
pub flip_normal_map_y: bool,
|
||
|
||
/// Specifies the level of exposure to ambient light.
|
||
///
|
||
/// This is usually generated and stored automatically ("baked") by 3D-modelling software.
|
||
///
|
||
/// Typically, steep concave parts of a model (such as the armpit of a shirt) are darker,
|
||
/// because they have little exposure to light.
|
||
/// An occlusion map specifies those parts of the model that light doesn't reach well.
|
||
///
|
||
/// The material will be less lit in places where this texture is dark.
|
||
/// This is similar to ambient occlusion, but built into the model.
|
||
#[texture(7)]
|
||
#[sampler(8)]
|
||
pub occlusion_texture: Option<Handle<Image>>,
|
||
|
||
/// Support two-sided lighting by automatically flipping the normals for "back" faces
|
||
/// within the PBR lighting shader.
|
||
///
|
||
/// Defaults to `false`.
|
||
/// This does not automatically configure backface culling,
|
||
/// which can be done via `cull_mode`.
|
||
pub double_sided: bool,
|
||
|
||
/// Whether to cull the "front", "back" or neither side of a mesh.
|
||
/// If set to `None`, the two sides of the mesh are visible.
|
||
///
|
||
/// Defaults to `Some(Face::Back)`.
|
||
/// In bevy, the order of declaration of a triangle's vertices
|
||
/// in [`Mesh`] defines the triangle's front face.
|
||
///
|
||
/// When a triangle is in a viewport,
|
||
/// if its vertices appear counter-clockwise from the viewport's perspective,
|
||
/// then the viewport is seeing the triangle's front face.
|
||
/// Conversely, if the vertices appear clockwise, you are seeing the back face.
|
||
///
|
||
/// In short, in bevy, front faces winds counter-clockwise.
|
||
///
|
||
/// Your 3D editing software should manage all of that.
|
||
///
|
||
/// [`Mesh`]: bevy_render::mesh::Mesh
|
||
// TODO: include this in reflection somehow (maybe via remote types like serde https://serde.rs/remote-derive.html)
|
||
#[reflect(ignore)]
|
||
pub cull_mode: Option<Face>,
|
||
|
||
/// Whether to apply only the base color to this material.
|
||
///
|
||
/// Normals, occlusion textures, roughness, metallic, reflectance, emissive,
|
||
/// shadows, alpha mode and ambient light are ignored if this is set to `true`.
|
||
pub unlit: bool,
|
||
|
||
/// Whether to enable fog for this material.
|
||
pub fog_enabled: bool,
|
||
|
||
/// How to apply the alpha channel of the `base_color_texture`.
|
||
///
|
||
/// See [`AlphaMode`] for details. Defaults to [`AlphaMode::Opaque`].
|
||
pub alpha_mode: AlphaMode,
|
||
|
||
/// Adjust rendered depth.
|
||
///
|
||
/// A material with a positive depth bias will render closer to the
|
||
/// camera while negative values cause the material to render behind
|
||
/// other objects. This is independent of the viewport.
|
||
///
|
||
/// `depth_bias` affects render ordering and depth write operations
|
||
/// using the `wgpu::DepthBiasState::Constant` field.
|
||
///
|
||
/// [z-fighting]: https://en.wikipedia.org/wiki/Z-fighting
|
||
pub depth_bias: f32,
|
||
}
|
||
|
||
impl Default for StandardMaterial {
|
||
fn default() -> Self {
|
||
StandardMaterial {
|
||
// White because it gets multiplied with texture values if someone uses
|
||
// a texture.
|
||
base_color: Color::rgb(1.0, 1.0, 1.0),
|
||
base_color_texture: None,
|
||
emissive: Color::BLACK,
|
||
emissive_texture: None,
|
||
// Matches Blender's default roughness.
|
||
perceptual_roughness: 0.5,
|
||
// Metallic should generally be set to 0.0 or 1.0.
|
||
metallic: 0.0,
|
||
metallic_roughness_texture: None,
|
||
// Minimum real-world reflectance is 2%, most materials between 2-5%
|
||
// Expressed in a linear scale and equivalent to 4% reflectance see
|
||
// <https://google.github.io/filament/Material%20Properties.pdf>
|
||
reflectance: 0.5,
|
||
transmission: 0.0,
|
||
thickness: 0.0,
|
||
ior: 1.5,
|
||
occlusion_texture: None,
|
||
normal_map_texture: None,
|
||
flip_normal_map_y: false,
|
||
double_sided: false,
|
||
cull_mode: Some(Face::Back),
|
||
unlit: false,
|
||
fog_enabled: true,
|
||
alpha_mode: AlphaMode::Opaque,
|
||
depth_bias: 0.0,
|
||
}
|
||
}
|
||
}
|
||
|
||
impl From<Color> for StandardMaterial {
|
||
fn from(color: Color) -> Self {
|
||
StandardMaterial {
|
||
base_color: color,
|
||
alpha_mode: if color.a() < 1.0 {
|
||
AlphaMode::Blend
|
||
} else {
|
||
AlphaMode::Opaque
|
||
},
|
||
..Default::default()
|
||
}
|
||
}
|
||
}
|
||
|
||
impl From<Handle<Image>> for StandardMaterial {
|
||
fn from(texture: Handle<Image>) -> Self {
|
||
StandardMaterial {
|
||
base_color_texture: Some(texture),
|
||
..Default::default()
|
||
}
|
||
}
|
||
}
|
||
|
||
// NOTE: These must match the bit flags in bevy_pbr/src/render/pbr_types.wgsl!
|
||
bitflags::bitflags! {
|
||
/// Bitflags info about the material a shader is currently rendering.
|
||
/// This is accessible in the shader in the [`StandardMaterialUniform`]
|
||
#[repr(transparent)]
|
||
pub struct StandardMaterialFlags: u32 {
|
||
const BASE_COLOR_TEXTURE = (1 << 0);
|
||
const EMISSIVE_TEXTURE = (1 << 1);
|
||
const METALLIC_ROUGHNESS_TEXTURE = (1 << 2);
|
||
const OCCLUSION_TEXTURE = (1 << 3);
|
||
const DOUBLE_SIDED = (1 << 4);
|
||
const UNLIT = (1 << 5);
|
||
const TWO_COMPONENT_NORMAL_MAP = (1 << 6);
|
||
const FLIP_NORMAL_MAP_Y = (1 << 7);
|
||
const FOG_ENABLED = (1 << 8);
|
||
const ALPHA_MODE_RESERVED_BITS = (Self::ALPHA_MODE_MASK_BITS << Self::ALPHA_MODE_SHIFT_BITS); // ← Bitmask reserving bits for the `AlphaMode`
|
||
const ALPHA_MODE_OPAQUE = (0 << Self::ALPHA_MODE_SHIFT_BITS); // ← Values are just sequential values bitshifted into
|
||
const ALPHA_MODE_MASK = (1 << Self::ALPHA_MODE_SHIFT_BITS); // the bitmask, and can range from 0 to 7.
|
||
const ALPHA_MODE_BLEND = (2 << Self::ALPHA_MODE_SHIFT_BITS); //
|
||
const ALPHA_MODE_PREMULTIPLIED = (3 << Self::ALPHA_MODE_SHIFT_BITS); //
|
||
const ALPHA_MODE_ADD = (4 << Self::ALPHA_MODE_SHIFT_BITS); // Right now only values 0–5 are used, which still gives
|
||
const ALPHA_MODE_MULTIPLY = (5 << Self::ALPHA_MODE_SHIFT_BITS); // ← us "room" for two more modes without adding more bits
|
||
const NONE = 0;
|
||
const UNINITIALIZED = 0xFFFF;
|
||
}
|
||
}
|
||
|
||
impl StandardMaterialFlags {
|
||
const ALPHA_MODE_MASK_BITS: u32 = 0b111;
|
||
const ALPHA_MODE_SHIFT_BITS: u32 = 32 - Self::ALPHA_MODE_MASK_BITS.count_ones();
|
||
}
|
||
|
||
/// The GPU representation of the uniform data of a [`StandardMaterial`].
|
||
#[derive(Clone, Default, ShaderType)]
|
||
pub struct StandardMaterialUniform {
|
||
/// Doubles as diffuse albedo for non-metallic, specular for metallic and a mix for everything
|
||
/// in between.
|
||
pub base_color: Vec4,
|
||
// Use a color for user friendliness even though we technically don't use the alpha channel
|
||
// Might be used in the future for exposure correction in HDR
|
||
pub emissive: Vec4,
|
||
/// Linear perceptual roughness, clamped to [0.089, 1.0] in the shader
|
||
/// Defaults to minimum of 0.089
|
||
pub roughness: f32,
|
||
/// From [0.0, 1.0], dielectric to pure metallic
|
||
pub metallic: f32,
|
||
/// Specular intensity for non-metals on a linear scale of [0.0, 1.0]
|
||
/// defaults to 0.5 which is mapped to 4% reflectance in the shader
|
||
pub reflectance: f32,
|
||
/// Amount of light transmitted through the material
|
||
pub transmission: f32,
|
||
/// Thickness of the volume underneath the material surface
|
||
pub thickness: f32,
|
||
/// Index of Refraction
|
||
pub ior: f32,
|
||
/// The [`StandardMaterialFlags`] accessible in the `wgsl` shader.
|
||
pub flags: u32,
|
||
/// When the alpha mode mask flag is set, any base color alpha above this cutoff means fully opaque,
|
||
/// and any below means fully transparent.
|
||
pub alpha_cutoff: f32,
|
||
}
|
||
|
||
impl AsBindGroupShaderType<StandardMaterialUniform> for StandardMaterial {
|
||
fn as_bind_group_shader_type(&self, images: &RenderAssets<Image>) -> StandardMaterialUniform {
|
||
let mut flags = StandardMaterialFlags::NONE;
|
||
if self.base_color_texture.is_some() {
|
||
flags |= StandardMaterialFlags::BASE_COLOR_TEXTURE;
|
||
}
|
||
if self.emissive_texture.is_some() {
|
||
flags |= StandardMaterialFlags::EMISSIVE_TEXTURE;
|
||
}
|
||
if self.metallic_roughness_texture.is_some() {
|
||
flags |= StandardMaterialFlags::METALLIC_ROUGHNESS_TEXTURE;
|
||
}
|
||
if self.occlusion_texture.is_some() {
|
||
flags |= StandardMaterialFlags::OCCLUSION_TEXTURE;
|
||
}
|
||
if self.double_sided {
|
||
flags |= StandardMaterialFlags::DOUBLE_SIDED;
|
||
}
|
||
if self.unlit {
|
||
flags |= StandardMaterialFlags::UNLIT;
|
||
}
|
||
if self.fog_enabled {
|
||
flags |= StandardMaterialFlags::FOG_ENABLED;
|
||
}
|
||
let has_normal_map = self.normal_map_texture.is_some();
|
||
if has_normal_map {
|
||
if let Some(texture) = images.get(self.normal_map_texture.as_ref().unwrap()) {
|
||
match texture.texture_format {
|
||
// All 2-component unorm formats
|
||
TextureFormat::Rg8Unorm
|
||
| TextureFormat::Rg16Unorm
|
||
| TextureFormat::Bc5RgUnorm
|
||
| TextureFormat::EacRg11Unorm => {
|
||
flags |= StandardMaterialFlags::TWO_COMPONENT_NORMAL_MAP;
|
||
}
|
||
_ => {}
|
||
}
|
||
}
|
||
if self.flip_normal_map_y {
|
||
flags |= StandardMaterialFlags::FLIP_NORMAL_MAP_Y;
|
||
}
|
||
}
|
||
// NOTE: 0.5 is from the glTF default - do we want this?
|
||
let mut alpha_cutoff = 0.5;
|
||
match self.alpha_mode {
|
||
AlphaMode::Opaque => flags |= StandardMaterialFlags::ALPHA_MODE_OPAQUE,
|
||
AlphaMode::Mask(c) => {
|
||
alpha_cutoff = c;
|
||
flags |= StandardMaterialFlags::ALPHA_MODE_MASK;
|
||
}
|
||
AlphaMode::Blend => flags |= StandardMaterialFlags::ALPHA_MODE_BLEND,
|
||
AlphaMode::Premultiplied => flags |= StandardMaterialFlags::ALPHA_MODE_PREMULTIPLIED,
|
||
AlphaMode::Add => flags |= StandardMaterialFlags::ALPHA_MODE_ADD,
|
||
AlphaMode::Multiply => flags |= StandardMaterialFlags::ALPHA_MODE_MULTIPLY,
|
||
};
|
||
|
||
StandardMaterialUniform {
|
||
base_color: self.base_color.as_linear_rgba_f32().into(),
|
||
emissive: self.emissive.as_linear_rgba_f32().into(),
|
||
roughness: self.perceptual_roughness,
|
||
metallic: self.metallic,
|
||
reflectance: self.reflectance,
|
||
transmission: self.transmission,
|
||
thickness: self.thickness,
|
||
ior: self.ior,
|
||
flags: flags.bits(),
|
||
alpha_cutoff,
|
||
}
|
||
}
|
||
}
|
||
|
||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||
pub struct StandardMaterialKey {
|
||
normal_map: bool,
|
||
cull_mode: Option<Face>,
|
||
depth_bias: i32,
|
||
}
|
||
|
||
impl From<&StandardMaterial> for StandardMaterialKey {
|
||
fn from(material: &StandardMaterial) -> Self {
|
||
StandardMaterialKey {
|
||
normal_map: material.normal_map_texture.is_some(),
|
||
cull_mode: material.cull_mode,
|
||
depth_bias: material.depth_bias as i32,
|
||
}
|
||
}
|
||
}
|
||
|
||
impl Material for StandardMaterial {
|
||
fn specialize(
|
||
_pipeline: &MaterialPipeline<Self>,
|
||
descriptor: &mut RenderPipelineDescriptor,
|
||
_layout: &MeshVertexBufferLayout,
|
||
key: MaterialPipelineKey<Self>,
|
||
) -> Result<(), SpecializedMeshPipelineError> {
|
||
if key.bind_group_data.normal_map {
|
||
if let Some(fragment) = descriptor.fragment.as_mut() {
|
||
fragment
|
||
.shader_defs
|
||
.push("STANDARDMATERIAL_NORMAL_MAP".into());
|
||
}
|
||
}
|
||
descriptor.primitive.cull_mode = key.bind_group_data.cull_mode;
|
||
if let Some(label) = &mut descriptor.label {
|
||
*label = format!("pbr_{}", *label).into();
|
||
}
|
||
if let Some(depth_stencil) = descriptor.depth_stencil.as_mut() {
|
||
depth_stencil.bias.constant = key.bind_group_data.depth_bias;
|
||
}
|
||
Ok(())
|
||
}
|
||
|
||
fn prepass_fragment_shader() -> ShaderRef {
|
||
PBR_PREPASS_SHADER_HANDLE.typed().into()
|
||
}
|
||
|
||
fn fragment_shader() -> ShaderRef {
|
||
PBR_SHADER_HANDLE.typed().into()
|
||
}
|
||
|
||
#[inline]
|
||
fn alpha_mode(&self) -> AlphaMode {
|
||
self.alpha_mode
|
||
}
|
||
|
||
#[inline]
|
||
fn depth_bias(&self) -> f32 {
|
||
self.depth_bias
|
||
}
|
||
|
||
#[inline]
|
||
fn transmissive(&self) -> bool {
|
||
self.transmission > 0.0
|
||
}
|
||
}
|