Skip to content

Commit

Permalink
Rebase of existing PBR work (#1554)
Browse files Browse the repository at this point in the history
This is a rebase of StarArawns PBR work from #261 with IngmarBitters work from #1160 cherry-picked on top.

I had to make a few minor changes to make some intermediate commits compile and the end result is not yet 100% what I expected, so there's a bit more work to do.

Co-authored-by: John Mitchell <toasterthegamer@gmail.com>
Co-authored-by: Ingmar Bitter <ingmar.bitter@gmail.com>
  • Loading branch information
3 people committed Mar 20, 2021
1 parent b6be8a5 commit 45b2db7
Show file tree
Hide file tree
Showing 28 changed files with 520 additions and 131 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ path = "examples/3d/orthographic.rs"
name = "parenting"
path = "examples/3d/parenting.rs"

[[example]]
name = "pbr"
path = "examples/3d/pbr.rs"

[[example]]
name = "spawner"
path = "examples/3d/spawner.rs"
Expand Down
7 changes: 5 additions & 2 deletions crates/bevy_gltf/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,12 @@ fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle<
load_context.set_labeled_asset(
&material_label,
LoadedAsset::new(StandardMaterial {
albedo: Color::rgba(color[0], color[1], color[2], color[3]),
albedo_texture: texture_handle,
base_color: Color::rgba(color[0], color[1], color[2], color[3]),
base_color_texture: texture_handle,
roughness: pbr.roughness_factor(),
metallic: pbr.metallic_factor(),
unlit: material.unlit(),
..Default::default()
})
.with_dependencies(dependencies),
)
Expand Down
1 change: 0 additions & 1 deletion crates/bevy_internal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ pub mod gltf {
#[cfg(feature = "bevy_pbr")]
pub mod pbr {
//! Physically based rendering.
//! **Note**: true PBR has not yet been implemented; the name `pbr` is aspirational.
pub use bevy_pbr::*;
}

Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_pbr/src/entity.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{light::Light, material::StandardMaterial, render_graph::FORWARD_PIPELINE_HANDLE};
use crate::{light::Light, material::StandardMaterial, render_graph::PBR_PIPELINE_HANDLE};
use bevy_asset::Handle;
use bevy_ecs::bundle::Bundle;
use bevy_render::{
Expand Down Expand Up @@ -27,7 +27,7 @@ impl Default for PbrBundle {
fn default() -> Self {
Self {
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new(
FORWARD_PIPELINE_HANDLE.typed(),
PBR_PIPELINE_HANDLE.typed(),
)]),
mesh: Default::default(),
visible: Default::default(),
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_pbr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ impl Plugin for PbrPlugin {
materials.set_untracked(
Handle::<StandardMaterial>::default(),
StandardMaterial {
albedo: Color::PINK,
base_color: Color::PINK,
unlit: true,
albedo_texture: None,
..Default::default()
},
);
}
Expand Down
12 changes: 10 additions & 2 deletions crates/bevy_pbr/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ pub struct Light {
pub color: Color,
pub fov: f32,
pub depth: Range<f32>,
pub intensity: f32,
pub range: f32,
}

impl Default for Light {
Expand All @@ -23,6 +25,8 @@ impl Default for Light {
color: Color::rgb(1.0, 1.0, 1.0),
depth: 0.1..50.0,
fov: f32::to_radians(60.0),
intensity: 200.0,
range: 20.0,
}
}
}
Expand All @@ -48,10 +52,14 @@ impl LightRaw {

let proj = perspective.get_projection_matrix() * global_transform.compute_matrix();
let (x, y, z) = global_transform.translation.into();

// premultiply color by intensity
// we don't use the alpha at all, so no reason to multiply only [0..3]
let color: [f32; 4] = (light.color * light.intensity).into();
LightRaw {
proj: proj.to_cols_array_2d(),
pos: [x, y, z, 1.0],
color: light.color.into(),
pos: [x, y, z, 1.0 / (light.range * light.range)], // pos.w is the attenuation.
color,
}
}
}
Expand Down
39 changes: 33 additions & 6 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,28 @@ use bevy_reflect::TypeUuid;
use bevy_render::{color::Color, renderer::RenderResources, shader::ShaderDefs, texture::Texture};

/// A material with "standard" properties used in PBR lighting
/// Standard property values with pictures here https://google.github.io/filament/Material%20Properties.pdf
#[derive(Debug, RenderResources, ShaderDefs, TypeUuid)]
#[uuid = "dace545e-4bc6-4595-a79d-c224fc694975"]
pub struct StandardMaterial {
pub albedo: Color,
/// 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`
pub base_color: Color,
#[shader_def]
pub albedo_texture: Option<Handle<Texture>>,
pub base_color_texture: Option<Handle<Texture>>,
/// Linear perceptual roughness, clamped to [0.089, 1.0] in the shader
/// Defaults to minimum of 0.089
/// If used together with a roughness/metallic texture, this is factored into the final base color
/// as `roughness * roughness_texture_value`
pub roughness: f32,
/// From [0.0, 1.0], dielectric to pure metallic
/// If used together with a roughness/metallic texture, this is factored into the final base color
/// as `metallic * metallic_texture_value`
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,
#[render_resources(ignore)]
#[shader_def]
pub unlit: bool,
Expand All @@ -17,8 +33,19 @@ pub struct StandardMaterial {
impl Default for StandardMaterial {
fn default() -> Self {
StandardMaterial {
albedo: Color::rgb(1.0, 1.0, 1.0),
albedo_texture: None,
base_color: Color::rgb(1.0, 1.0, 1.0),
base_color_texture: None,
// This is the minimum the roughness is clamped to in shader code
// See https://google.github.io/filament/Filament.html#materialsystem/parameterization/
// It's the minimum floating point value that won't be rounded down to 0 in the calculations used.
// Although technically for 32-bit floats, 0.045 could be used.
roughness: 0.089,
// Few materials are purely dielectric or metallic
// This is just a default for mostly-dielectric
metallic: 0.01,
// 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,
unlit: false,
}
}
Expand All @@ -27,7 +54,7 @@ impl Default for StandardMaterial {
impl From<Color> for StandardMaterial {
fn from(color: Color) -> Self {
StandardMaterial {
albedo: color,
base_color: color,
..Default::default()
}
}
Expand All @@ -36,7 +63,7 @@ impl From<Color> for StandardMaterial {
impl From<Handle<Texture>> for StandardMaterial {
fn from(texture: Handle<Texture>) -> Self {
StandardMaterial {
albedo_texture: Some(texture),
base_color_texture: Some(texture),
..Default::default()
}
}
Expand Down
65 changes: 0 additions & 65 deletions crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag

This file was deleted.

9 changes: 4 additions & 5 deletions crates/bevy_pbr/src/render_graph/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
mod forward_pipeline;
mod lights_node;
mod pbr_pipeline;

use bevy_ecs::world::World;
pub use forward_pipeline::*;
pub use lights_node::*;
pub use pbr_pipeline::*;

/// the names of pbr graph nodes
pub mod node {
Expand Down Expand Up @@ -50,10 +50,9 @@ pub(crate) fn add_pbr_graph(world: &mut World) {
.add_node_edge(node::LIGHTS, base::node::MAIN_PASS)
.unwrap();
}
let forward_pipeline =
build_forward_pipeline(&mut world.get_resource_mut::<Assets<Shader>>().unwrap());
let pipeline = build_pbr_pipeline(&mut world.get_resource_mut::<Assets<Shader>>().unwrap());
let mut pipelines = world
.get_resource_mut::<Assets<PipelineDescriptor>>()
.unwrap();
pipelines.set_untracked(FORWARD_PIPELINE_HANDLE, forward_pipeline);
pipelines.set_untracked(PBR_PIPELINE_HANDLE, pipeline);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ use bevy_render::{
texture::TextureFormat,
};

pub const FORWARD_PIPELINE_HANDLE: HandleUntyped =
pub const PBR_PIPELINE_HANDLE: HandleUntyped =
HandleUntyped::weak_from_u64(PipelineDescriptor::TYPE_UUID, 13148362314012771389);

pub(crate) fn build_forward_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
pub(crate) fn build_pbr_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
PipelineDescriptor {
depth_stencil: Some(DepthStencilState {
format: TextureFormat::Depth32Float,
Expand Down Expand Up @@ -48,11 +48,11 @@ pub(crate) fn build_forward_pipeline(shaders: &mut Assets<Shader>) -> PipelineDe
..PipelineDescriptor::new(ShaderStages {
vertex: shaders.add(Shader::from_glsl(
ShaderStage::Vertex,
include_str!("forward.vert"),
include_str!("pbr.vert"),
)),
fragment: Some(shaders.add(Shader::from_glsl(
ShaderStage::Fragment,
include_str!("forward.frag"),
include_str!("pbr.frag"),
))),
})
}
Expand Down
Loading

0 comments on commit 45b2db7

Please sign in to comment.