From 13c552a2688c49bfbb1cbbf5f879d132906bba30 Mon Sep 17 00:00:00 2001 From: John Mitchell Date: Sun, 7 Mar 2021 12:14:31 +0100 Subject: [PATCH 01/58] semi working pbr. --- crates/bevy_gltf/src/loader.rs | 3 +- crates/bevy_pbr/src/entity.rs | 22 +++ crates/bevy_pbr/src/lib.rs | 2 +- crates/bevy_pbr/src/light.rs | 6 +- crates/bevy_pbr/src/material.rs | 4 + .../forward_pipeline/forward.frag | 169 +++++++++++++++--- .../forward_pipeline/forward.vert | 7 +- .../src/render_graph/nodes/camera_node.rs | 2 +- .../src/render_graph/nodes/pass_node.rs | 5 +- .../bevy_render/src/shader/shader_reflect.rs | 1 + crates/bevy_sprite/src/render/sprite.vert | 1 + .../bevy_sprite/src/render/sprite_sheet.vert | 1 + crates/bevy_ui/src/render/ui.vert | 1 + examples/shader/shader_custom_material.rs | 1 + examples/shader/shader_defs.rs | 1 + 15 files changed, 193 insertions(+), 33 deletions(-) diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index dec120bc5bdfe..c7b921e360235 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -4,7 +4,7 @@ use bevy_asset::{ }; use bevy_core::Name; use bevy_ecs::world::World; -use bevy_math::Mat4; +use bevy_math::{Mat4, Vec2}; use bevy_pbr::prelude::{PbrBundle, StandardMaterial}; use bevy_render::{ camera::{ @@ -280,6 +280,7 @@ fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle< albedo: Color::rgba(color[0], color[1], color[2], color[3]), albedo_texture: texture_handle, unlit: material.unlit(), + pbr: Vec2::new(pbr.roughness_factor(), pbr.metallic_factor()), }) .with_dependencies(dependencies), ) diff --git a/crates/bevy_pbr/src/entity.rs b/crates/bevy_pbr/src/entity.rs index d03b0d89cf988..1a23e62cf479b 100644 --- a/crates/bevy_pbr/src/entity.rs +++ b/crates/bevy_pbr/src/entity.rs @@ -26,6 +26,28 @@ pub struct PbrBundle { impl Default for PbrBundle { fn default() -> Self { Self { + // render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::specialized( + // FORWARD_PIPELINE_HANDLE, + // PipelineSpecialization { + // dynamic_bindings: vec![ + // // Transform + // DynamicBinding { + // bind_group: 2, + // binding: 0, + // }, + // // StandardMaterial_albedo + // DynamicBinding { + // bind_group: 3, + // binding: 0, + // }, + // // StandardMaterial_pbr + // DynamicBinding { + // bind_group: 3, + // binding: 3, + // }, + // ], + // ..Default::default() + // }, render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new( FORWARD_PIPELINE_HANDLE.typed(), )]), diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index 73790b395f751..702e6ead910c5 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -44,7 +44,7 @@ impl Plugin for PbrPlugin { StandardMaterial { albedo: Color::PINK, unlit: true, - albedo_texture: None, + ..Default::default() }, ); } diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index 8deee5fdb9c52..0a9402a4916df 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -15,14 +15,16 @@ pub struct Light { pub color: Color, pub fov: f32, pub depth: Range, + pub attenuation: f32, } impl Default for Light { fn default() -> Self { Light { - color: Color::rgb(1.0, 1.0, 1.0), + color: Color::rgba(1.0, 1.0, 1.0, 100.0), depth: 0.1..50.0, fov: f32::to_radians(60.0), + attenuation: 100.0, } } } @@ -50,7 +52,7 @@ impl LightRaw { let (x, y, z) = global_transform.translation.into(); LightRaw { proj: proj.to_cols_array_2d(), - pos: [x, y, z, 1.0], + pos: [x, y, z, light.attenuation], // pos.w is the attenuation. color: light.color.into(), } } diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 1244d23a11364..4eb75632bdca5 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -1,4 +1,5 @@ use bevy_asset::{self, Handle}; +use bevy_math::Vec2; use bevy_reflect::TypeUuid; use bevy_render::{color::Color, renderer::RenderResources, shader::ShaderDefs, texture::Texture}; @@ -7,6 +8,8 @@ use bevy_render::{color::Color, renderer::RenderResources, shader::ShaderDefs, t #[uuid = "dace545e-4bc6-4595-a79d-c224fc694975"] pub struct StandardMaterial { pub albedo: Color, + /// Represented as roughness/metallic. + pub pbr: Vec2, #[shader_def] pub albedo_texture: Option>, #[render_resources(ignore)] @@ -18,6 +21,7 @@ impl Default for StandardMaterial { fn default() -> Self { StandardMaterial { albedo: Color::rgb(1.0, 1.0, 1.0), + pbr: Vec2::new(1.0, 0.95), albedo_texture: None, unlit: false, } diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index cf6e3bcf79deb..75fc26c0a875e 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -4,18 +4,21 @@ const int MAX_LIGHTS = 10; struct Light { mat4 proj; - vec4 pos; + vec3 pos; + float attenuation; vec4 color; }; layout(location = 0) in vec3 v_Position; layout(location = 1) in vec3 v_Normal; layout(location = 2) in vec2 v_Uv; +layout(location = 3) in vec3 w_Position; layout(location = 0) out vec4 o_Target; layout(set = 0, binding = 0) uniform CameraViewProj { mat4 ViewProj; + vec4 CameraPos; }; layout(set = 1, binding = 0) uniform Lights { @@ -24,41 +27,157 @@ layout(set = 1, binding = 0) uniform Lights { Light SceneLights[MAX_LIGHTS]; }; -layout(set = 3, binding = 0) uniform StandardMaterial_albedo { - vec4 Albedo; -}; +layout(set = 3, binding = 0) uniform StandardMaterial_albedo { vec4 Albedo; }; + +layout(set = 3, binding = 3) uniform StandardMaterial_pbr { vec2 pbr; }; -# ifdef STANDARDMATERIAL_ALBEDO_TEXTURE +#ifdef STANDARDMATERIAL_ALBEDO_TEXTURE layout(set = 3, binding = 1) uniform texture2D StandardMaterial_albedo_texture; -layout(set = 3, binding = 2) uniform sampler StandardMaterial_albedo_texture_sampler; -# endif +layout(set = 3, + binding = 2) uniform sampler StandardMaterial_albedo_texture_sampler; +#endif + +#ifndef STANDARDMATERIAL_UNLIT + +const float PI = 3.141592653589793; + +#define saturate(x) clamp(x, 0.0, 1.0) + +float pow5(float x) { + float x2 = x * x; + return x2 * x2 * x; +} + +float getRangeAttenuation(float range, float distance) { + if (range <= 0.0) { + return 1.0; + } + return max(min(1.0 - pow(distance / range, 4.0), 1.0), 0.0) / + pow(distance, 2.0); +} + +float D_GGX(float roughness, float NoH, const vec3 h) { + float oneMinusNoHSquared = 1.0 - NoH * NoH; + float a = NoH * roughness; + float k = roughness / (oneMinusNoHSquared + a * a); + float d = k * k * (1.0 / PI); + return d; +} + +float V_SmithGGXCorrelated(float roughness, float NoV, float NoL) { + float a2 = roughness * roughness; + float lambdaV = NoL * sqrt((NoV - a2 * NoV) * NoV + a2); + float lambdaL = NoV * sqrt((NoL - a2 * NoL) * NoL + a2); + float v = 0.5 / (lambdaV + lambdaL); + return v; +} + +vec3 F_Schlick(const vec3 f0, float f90, float VoH) { + return f0 + (f90 - f0) * pow5(1.0 - VoH); +} + +float F_Schlick(float f0, float f90, float VoH) { + return f0 + (f90 - f0) * pow5(1.0 - VoH); +} + +vec3 fresnel(vec3 f0, float LoH) { + float f90 = saturate(dot(f0, vec3(50.0 * 0.33))); + return F_Schlick(f0, f90, LoH); +} + +vec3 isotropicLobe(vec3 f0, float roughness, const vec3 h, float NoV, float NoL, + float NoH, float LoH) { + + float D = D_GGX(roughness, NoH, h); + float V = V_SmithGGXCorrelated(roughness, NoV, NoL); + vec3 F = fresnel(f0, LoH); + + return (D * V) * F; +} + +float Fd_Burley(float roughness, float NoV, float NoL, float LoH) { + float f90 = 0.5 + 2.0 * roughness * LoH * LoH; + float lightScatter = F_Schlick(1.0, f90, NoL); + float viewScatter = F_Schlick(1.0, f90, NoV); + return lightScatter * viewScatter * (1.0 / PI); +} + +vec3 computeDiffuseColor(const vec3 baseColor, float metallic) { + return baseColor * (1.0 - metallic); +} + +#define MIN_N_DOT_V 1e-4 + +float clampNoV(float NoV) { + // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The + // Order: 1886" + return max(NoV, MIN_N_DOT_V); +} + +#endif void main() { - vec4 output_color = Albedo; -# ifdef STANDARDMATERIAL_ALBEDO_TEXTURE - output_color *= texture( - sampler2D(StandardMaterial_albedo_texture, StandardMaterial_albedo_texture_sampler), - v_Uv); -# endif - -# ifndef STANDARDMATERIAL_UNLIT - vec3 normal = normalize(v_Normal); + vec4 output_color = Albedo; // Albedo; +#ifdef STANDARDMATERIAL_ALBEDO_TEXTURE + output_color *= texture(sampler2D(StandardMaterial_albedo_texture, + StandardMaterial_albedo_texture_sampler), + v_Uv); +#endif + +#ifndef STANDARDMATERIAL_UNLIT // accumulate color vec3 color = AmbientColor; - for (int i=0; i 1.0 - color /= max(float(NumLights.x), 1.0); + // color /= max(float(NumLights.x), 1.0); + + output_color.xyz = light_accum; - output_color.xyz *= color; -# endif + // Gamma correction. + output_color.xyz = output_color.xyz / (output_color.xyz + vec3(1.0)); + output_color.xyz = pow(output_color.xyz, vec3(1.0 / 2.2)); +#endif // multiply the light by material color o_Target = output_color; diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert index bbba55ea7c05a..14df04fdde810 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert @@ -7,9 +7,11 @@ layout(location = 2) in vec2 Vertex_Uv; layout(location = 0) out vec3 v_Position; layout(location = 1) out vec3 v_Normal; layout(location = 2) out vec2 v_Uv; +layout(location = 3) out vec3 w_Position; layout(set = 0, binding = 0) uniform CameraViewProj { mat4 ViewProj; + vec4 CameraPos; }; layout(set = 2, binding = 0) uniform Transform { @@ -18,7 +20,8 @@ layout(set = 2, binding = 0) uniform Transform { void main() { v_Normal = mat3(Model) * Vertex_Normal; - v_Position = (Model * vec4(Vertex_Position, 1.0)).xyz; + v_Position = Vertex_Position; + w_Position = (Model * vec4(Vertex_Position, 1.0)).xyz; v_Uv = Vertex_Uv; - gl_Position = ViewProj * vec4(v_Position, 1.0); + gl_Position = ViewProj * Model * vec4(v_Position, 1.0); } diff --git a/crates/bevy_render/src/render_graph/nodes/camera_node.rs b/crates/bevy_render/src/render_graph/nodes/camera_node.rs index fdf2c021e6c20..82dfa3f2d5ad4 100644 --- a/crates/bevy_render/src/render_graph/nodes/camera_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/camera_node.rs @@ -6,7 +6,7 @@ use crate::{ RenderResourceContext, }, }; -use bevy_core::AsBytes; +use bevy_core::{AsBytes, Bytes}; use bevy_ecs::{ system::{BoxedSystem, IntoSystem, Local, Query, Res, ResMut}, world::World, diff --git a/crates/bevy_render/src/render_graph/nodes/pass_node.rs b/crates/bevy_render/src/render_graph/nodes/pass_node.rs index 66fef3c857a35..3258efa934b73 100644 --- a/crates/bevy_render/src/render_graph/nodes/pass_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/pass_node.rs @@ -109,7 +109,10 @@ impl PassNode { index: 0, bind_type: BindType::Uniform { has_dynamic_offset: false, - property: UniformProperty::Struct(vec![UniformProperty::Mat4]), + property: UniformProperty::Struct(vec![ + UniformProperty::Mat4, + UniformProperty::Vec4, + ]), }, shader_stage: BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT, }], diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index 78a5f306f18fd..8ee086a779b2e 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -321,6 +321,7 @@ mod tests { layout(location = 0) out vec4 v_Position; layout(set = 0, binding = 0) uniform CameraViewProj { mat4 ViewProj; + vec4 CameraPos; }; layout(set = 1, binding = 0) uniform texture2D Texture; diff --git a/crates/bevy_sprite/src/render/sprite.vert b/crates/bevy_sprite/src/render/sprite.vert index 2a0cc68e3af18..c311dfaf7af3d 100644 --- a/crates/bevy_sprite/src/render/sprite.vert +++ b/crates/bevy_sprite/src/render/sprite.vert @@ -8,6 +8,7 @@ layout(location = 0) out vec2 v_Uv; layout(set = 0, binding = 0) uniform CameraViewProj { mat4 ViewProj; + vec4 CameraPos; }; layout(set = 2, binding = 0) uniform Transform { diff --git a/crates/bevy_sprite/src/render/sprite_sheet.vert b/crates/bevy_sprite/src/render/sprite_sheet.vert index 72e0f5de93a21..25bd5a9a5a1ce 100644 --- a/crates/bevy_sprite/src/render/sprite_sheet.vert +++ b/crates/bevy_sprite/src/render/sprite_sheet.vert @@ -9,6 +9,7 @@ layout(location = 1) out vec4 v_Color; layout(set = 0, binding = 0) uniform CameraViewProj { mat4 ViewProj; + vec4 CameraPos; }; // TODO: merge dimensions into "sprites" buffer when that is supported in the Uniforms derive abstraction diff --git a/crates/bevy_ui/src/render/ui.vert b/crates/bevy_ui/src/render/ui.vert index 3a00b11f404d8..bcfe502802f3f 100644 --- a/crates/bevy_ui/src/render/ui.vert +++ b/crates/bevy_ui/src/render/ui.vert @@ -8,6 +8,7 @@ layout(location = 0) out vec2 v_Uv; layout(set = 0, binding = 0) uniform CameraViewProj { mat4 ViewProj; + vec4 CameraPos; }; layout(set = 1, binding = 0) uniform Transform { diff --git a/examples/shader/shader_custom_material.rs b/examples/shader/shader_custom_material.rs index acd9b3146b01f..ca420a57d0960 100644 --- a/examples/shader/shader_custom_material.rs +++ b/examples/shader/shader_custom_material.rs @@ -31,6 +31,7 @@ const VERTEX_SHADER: &str = r#" layout(location = 0) in vec3 Vertex_Position; layout(set = 0, binding = 0) uniform CameraViewProj { mat4 ViewProj; + vec4 CameraPos; }; layout(set = 1, binding = 0) uniform Transform { mat4 Model; diff --git a/examples/shader/shader_defs.rs b/examples/shader/shader_defs.rs index 52827d6e955d0..1b4a928f00653 100644 --- a/examples/shader/shader_defs.rs +++ b/examples/shader/shader_defs.rs @@ -39,6 +39,7 @@ const VERTEX_SHADER: &str = r#" layout(location = 0) in vec3 Vertex_Position; layout(set = 0, binding = 0) uniform CameraViewProj { mat4 ViewProj; + vec4 CameraPos; }; layout(set = 1, binding = 0) uniform Transform { mat4 Model; From cc1a4ba722933fac025be3e3b71270ad3bbd4e60 Mon Sep 17 00:00:00 2001 From: John Mitchell Date: Thu, 4 Mar 2021 21:17:10 +0100 Subject: [PATCH 02/58] More changes. --- crates/bevy_pbr/src/material.rs | 2 +- .../forward_pipeline/forward.frag | 26 ++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 4eb75632bdca5..6064eac861a56 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -21,7 +21,7 @@ impl Default for StandardMaterial { fn default() -> Self { StandardMaterial { albedo: Color::rgb(1.0, 1.0, 1.0), - pbr: Vec2::new(1.0, 0.95), + pbr: Vec2::new(0.01, 0.08), albedo_texture: None, unlit: false, } diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 75fc26c0a875e..0b5b3439768d3 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -39,21 +39,24 @@ layout(set = 3, #ifndef STANDARDMATERIAL_UNLIT -const float PI = 3.141592653589793; - #define saturate(x) clamp(x, 0.0, 1.0) +const float PI = 3.141592653589793; float pow5(float x) { float x2 = x * x; return x2 * x2 * x; } -float getRangeAttenuation(float range, float distance) { - if (range <= 0.0) { - return 1.0; - } - return max(min(1.0 - pow(distance / range, 4.0), 1.0), 0.0) / - pow(distance, 2.0); +float getSquareFalloffAttenuation(float distanceSquare, float falloff) { + float factor = distanceSquare * falloff; + float smoothFactor = saturate(1.0 - factor * factor); + return smoothFactor * smoothFactor; +} + +float getDistanceAttenuation(const vec3 posToLight, float falloff) { + float distanceSquare = dot(posToLight, posToLight); + float attenuation = getSquareFalloffAttenuation(distanceSquare, falloff); + return attenuation * 1.0 / max(distanceSquare, 1e-4); } float D_GGX(float roughness, float NoH, const vec3 h) { @@ -147,7 +150,7 @@ void main() { vec3 L = normalize(lightDir); float rangeAttenuation = - getRangeAttenuation(light.attenuation, length(lightDir)); + getDistanceAttenuation(lightDir, light.attenuation); vec3 H = normalize(L + V); @@ -164,9 +167,8 @@ void main() { vec3 specular = isotropicLobe(F0, roughness, H, NdotV, NoL, NoH, LoH); vec3 diffuse = diffuseColor * Fd_Burley(roughness, NdotV, NoL, LoH); - light_accum += (diffuse + specular) * - NdotL; //((diffuse + specular) * light.color.xyz) * - //(light.color.w * rangeAttenuation * NdotL); + light_accum += + ((diffuse + specular) * light.color.xyz) * (light.color.w * NdotL); } // average the lights so that we will never get something with > 1.0 From 8975234ba9af581f165f06546bf8f93af8f074c2 Mon Sep 17 00:00:00 2001 From: John Mitchell Date: Wed, 19 Aug 2020 09:54:48 -0400 Subject: [PATCH 03/58] Removed unused vars. --- .../bevy_pbr/src/render_graph/forward_pipeline/forward.frag | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 0b5b3439768d3..d9682c1f291d9 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -156,10 +156,6 @@ void main() { float NdotL = clampNoV(dot(N, L)); float NdotV = clampNoV(dot(N, V)); - float NdotH = clampNoV(dot(N, H)); - float LdotH = clampNoV(dot(L, H)); - float VdotH = clampNoV(dot(V, H)); - float NoL = saturate(NdotL); float NoH = saturate(dot(N, H)); float LoH = saturate(dot(L, H)); From 13d16296a09ca0930460c583f52cfa7c3b99b731 Mon Sep 17 00:00:00 2001 From: Ingmar Bitter Date: Tue, 29 Dec 2020 17:22:10 -0500 Subject: [PATCH 04/58] example/pbr added, example/msaa restored to a simple box --- Cargo.toml | 4 ++++ examples/3d/pbr.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 examples/3d/pbr.rs diff --git a/Cargo.toml b/Cargo.toml index c1a688239d986..ee901649c3d94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs new file mode 100644 index 0000000000000..7ca4d0f4b6b38 --- /dev/null +++ b/examples/3d/pbr.rs @@ -0,0 +1,46 @@ +use bevy::prelude::*; + +/// This example shows how to configure Physically Based Rendering (PBR) parameters. +fn main() { + App::build() + .insert_resource(Msaa { samples: 4 }) + .add_plugins(DefaultPlugins) + .add_startup_system(setup.system()) + .run(); +} + +/// set up a simple 3D scene +fn setup( + commands: &mut Commands, + mut meshes: ResMut>, + mut materials: ResMut>, +) { + // add entities to the world + for y in -2..=2 { + for x in -5..=5 { + commands + // spheres + .spawn(PbrBundle { + mesh: meshes.add(Mesh::from(shape::Icosphere { + radius: 0.45, + subdivisions: 32, + })), + material: materials.add(Color::rgb(0.5, 0.4, 0.3).into()), + transform: Transform::from_translation(Vec3::new(x as f32, y as f32, 0.0)), + ..Default::default() + }); + } + } + commands + // light + .spawn(LightBundle { + transform: Transform::from_translation(Vec3::new(0.0, 1000.0, 1000.0)), + ..Default::default() + }) + // camera + .spawn(PerspectiveCameraBundle { + transform: Transform::from_translation(Vec3::new(0.0, 0.0, 8.0)) + .looking_at(Vec3::default(), Vec3::unit_y()), + ..Default::default() + }); +} From 13a9baa336510f4f2f9bd562c5a4b8bbd06967a0 Mon Sep 17 00:00:00 2001 From: Ingmar Bitter Date: Tue, 29 Dec 2020 17:39:46 -0500 Subject: [PATCH 05/58] to fix: spheres appear in default color, not the one specified in the material --- examples/3d/pbr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index 7ca4d0f4b6b38..f80ae91e81650 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -25,7 +25,7 @@ fn setup( radius: 0.45, subdivisions: 32, })), - material: materials.add(Color::rgb(0.5, 0.4, 0.3).into()), + material: materials.add(Color::rgb(0.2, 0.2, 1.0).into()), transform: Transform::from_translation(Vec3::new(x as f32, y as f32, 0.0)), ..Default::default() }); From 5ef291268ab76865db35a3328fcaf8ab91363879 Mon Sep 17 00:00:00 2001 From: Ingmar Bitter Date: Tue, 29 Dec 2020 18:05:45 -0500 Subject: [PATCH 06/58] vary key PBR parameters on a grid of spheres to show the effect --- crates/bevy_pbr/src/material.rs | 2 +- examples/3d/pbr.rs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 6064eac861a56..4eb75632bdca5 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -21,7 +21,7 @@ impl Default for StandardMaterial { fn default() -> Self { StandardMaterial { albedo: Color::rgb(1.0, 1.0, 1.0), - pbr: Vec2::new(0.01, 0.08), + pbr: Vec2::new(1.0, 0.95), albedo_texture: None, unlit: false, } diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index f80ae91e81650..55a5d91110a37 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -18,6 +18,8 @@ fn setup( // add entities to the world for y in -2..=2 { for x in -5..=5 { + let x01 = x as f32 / 10.0 + 0.5; + let y01 = y as f32 / 2.0 + 0.5; commands // spheres .spawn(PbrBundle { @@ -25,7 +27,11 @@ fn setup( radius: 0.45, subdivisions: 32, })), - material: materials.add(Color::rgb(0.2, 0.2, 1.0).into()), + material: materials.add(StandardMaterial { + albedo: Color::rgb(0.2, 0.2, 1.0), + pbr: Vec2::new(x01, y01), // vary key PBR parameters on a grid of spheres to show the effect + ..Default::default() + }), transform: Transform::from_translation(Vec3::new(x as f32, y as f32, 0.0)), ..Default::default() }); From 5a5e1ae642ea1365320268258fb3f86d0b92ccbe Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Thu, 4 Mar 2021 22:28:09 +0100 Subject: [PATCH 07/58] Improve example PBR parameter calculation --- examples/3d/pbr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index 55a5d91110a37..672c56602ec4e 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -18,8 +18,8 @@ fn setup( // add entities to the world for y in -2..=2 { for x in -5..=5 { - let x01 = x as f32 / 10.0 + 0.5; - let y01 = y as f32 / 2.0 + 0.5; + let x01 = (x + 5) as f32 / 10.0; + let y01 = (y + 2) as f32 / 4.0; commands // spheres .spawn(PbrBundle { From 1a2e02261502c403d8e6d8f2bdd456eb4bacce5c Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Thu, 4 Mar 2021 22:28:37 +0100 Subject: [PATCH 08/58] Remove unused variable and comments --- .../bevy_pbr/src/render_graph/forward_pipeline/forward.frag | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index d9682c1f291d9..ae1687aeb751a 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -120,7 +120,7 @@ float clampNoV(float NoV) { #endif void main() { - vec4 output_color = Albedo; // Albedo; + vec4 output_color = Albedo; #ifdef STANDARDMATERIAL_ALBEDO_TEXTURE output_color *= texture(sampler2D(StandardMaterial_albedo_texture, StandardMaterial_albedo_texture_sampler), @@ -128,9 +128,6 @@ void main() { #endif #ifndef STANDARDMATERIAL_UNLIT - // accumulate color - vec3 color = AmbientColor; - float roughness = pbr.x; float metallic = pbr.y; vec3 N = normalize(v_Normal); From 0ebeb11b8fb5471280db2272669393fa5fd59ead Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Thu, 4 Mar 2021 22:28:55 +0100 Subject: [PATCH 09/58] Use from_xyz --- examples/3d/pbr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index 672c56602ec4e..cf07ae1ed208b 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -32,7 +32,7 @@ fn setup( pbr: Vec2::new(x01, y01), // vary key PBR parameters on a grid of spheres to show the effect ..Default::default() }), - transform: Transform::from_translation(Vec3::new(x as f32, y as f32, 0.0)), + transform: Transform::from_xyz(x as f32, y as f32, 0.0), ..Default::default() }); } From f8c3c7caaa12c3c613b8ecfa7ef0b2a13d6530e8 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Thu, 4 Mar 2021 23:53:39 +0100 Subject: [PATCH 10/58] Correct default roughness/metallic --- crates/bevy_pbr/src/material.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 4eb75632bdca5..6064eac861a56 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -21,7 +21,7 @@ impl Default for StandardMaterial { fn default() -> Self { StandardMaterial { albedo: Color::rgb(1.0, 1.0, 1.0), - pbr: Vec2::new(1.0, 0.95), + pbr: Vec2::new(0.01, 0.08), albedo_texture: None, unlit: false, } From 96dce6680b738920dc49bace50b2fe106ffdb63f Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Thu, 4 Mar 2021 23:54:38 +0100 Subject: [PATCH 11/58] Add perceptualRoughness->roughness and clamping --- .../forward_pipeline/forward.frag | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index ae1687aeb751a..205d22a9a3ffa 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -29,8 +29,6 @@ layout(set = 1, binding = 0) uniform Lights { layout(set = 3, binding = 0) uniform StandardMaterial_albedo { vec4 Albedo; }; -layout(set = 3, binding = 3) uniform StandardMaterial_pbr { vec2 pbr; }; - #ifdef STANDARDMATERIAL_ALBEDO_TEXTURE layout(set = 3, binding = 1) uniform texture2D StandardMaterial_albedo_texture; layout(set = 3, @@ -39,6 +37,8 @@ layout(set = 3, #ifndef STANDARDMATERIAL_UNLIT +layout(set = 3, binding = 3) uniform StandardMaterial_pbr { vec2 pbr; }; + #define saturate(x) clamp(x, 0.0, 1.0) const float PI = 3.141592653589793; @@ -117,6 +117,20 @@ float clampNoV(float NoV) { return max(NoV, MIN_N_DOT_V); } +float perceptualRoughnessToRoughness(float perceptualRoughness) { + return perceptualRoughness * perceptualRoughness; +} + +#if defined(TARGET_MOBILE) +// min roughness such that (MIN_PERCEPTUAL_ROUGHNESS^4) > 0 in fp16 (i.e. +// 2^(-14/4), rounded up) +#define MIN_PERCEPTUAL_ROUGHNESS 0.089 +#define MIN_ROUGHNESS 0.007921 +#else +#define MIN_PERCEPTUAL_ROUGHNESS 0.045 +#define MIN_ROUGHNESS 0.002025 +#endif + #endif void main() { @@ -128,7 +142,11 @@ void main() { #endif #ifndef STANDARDMATERIAL_UNLIT - float roughness = pbr.x; + float perceptual_roughness = pbr.x; + perceptual_roughness = + clamp(perceptual_roughness, MIN_PERCEPTUAL_ROUGHNESS, 1.0); + float roughness = perceptualRoughnessToRoughness(perceptual_roughness); + float metallic = pbr.y; vec3 N = normalize(v_Normal); vec3 V = normalize(CameraPos.xyz - v_Position.xyz); From c9cc8583a5c4e31ca289539f71d6548f12ac6ee7 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Fri, 5 Mar 2021 07:37:50 +0100 Subject: [PATCH 12/58] Remove commented code --- crates/bevy_pbr/src/entity.rs | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/crates/bevy_pbr/src/entity.rs b/crates/bevy_pbr/src/entity.rs index 1a23e62cf479b..d03b0d89cf988 100644 --- a/crates/bevy_pbr/src/entity.rs +++ b/crates/bevy_pbr/src/entity.rs @@ -26,28 +26,6 @@ pub struct PbrBundle { impl Default for PbrBundle { fn default() -> Self { Self { - // render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::specialized( - // FORWARD_PIPELINE_HANDLE, - // PipelineSpecialization { - // dynamic_bindings: vec![ - // // Transform - // DynamicBinding { - // bind_group: 2, - // binding: 0, - // }, - // // StandardMaterial_albedo - // DynamicBinding { - // bind_group: 3, - // binding: 0, - // }, - // // StandardMaterial_pbr - // DynamicBinding { - // bind_group: 3, - // binding: 3, - // }, - // ], - // ..Default::default() - // }, render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new( FORWARD_PIPELINE_HANDLE.typed(), )]), From 56dd5856053e87ef8ad8cde3188e08abc79eae49 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Fri, 5 Mar 2021 07:54:25 +0100 Subject: [PATCH 13/58] Reorder fields --- crates/bevy_pbr/src/material.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 6064eac861a56..7b975a776e859 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -8,10 +8,10 @@ use bevy_render::{color::Color, renderer::RenderResources, shader::ShaderDefs, t #[uuid = "dace545e-4bc6-4595-a79d-c224fc694975"] pub struct StandardMaterial { pub albedo: Color, - /// Represented as roughness/metallic. - pub pbr: Vec2, #[shader_def] pub albedo_texture: Option>, + /// Represented as roughness/metallic. + pub pbr: Vec2, #[render_resources(ignore)] #[shader_def] pub unlit: bool, From 314b64f1dcaadac60f8f6c0e131b542b298ae08a Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sat, 6 Mar 2021 16:33:23 +0100 Subject: [PATCH 14/58] whitespace --- crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert index 14df04fdde810..b3e344b801109 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert @@ -20,7 +20,7 @@ layout(set = 2, binding = 0) uniform Transform { void main() { v_Normal = mat3(Model) * Vertex_Normal; - v_Position = Vertex_Position; + v_Position = Vertex_Position; w_Position = (Model * vec4(Vertex_Position, 1.0)).xyz; v_Uv = Vertex_Uv; gl_Position = ViewProj * Model * vec4(v_Position, 1.0); From e55ff3eb55e457b1ed63194081dd1834fc5f4f77 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sat, 6 Mar 2021 16:34:37 +0100 Subject: [PATCH 15/58] Use world position --- .../bevy_pbr/src/render_graph/forward_pipeline/forward.frag | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 205d22a9a3ffa..d2e2bf944835a 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -149,7 +149,7 @@ void main() { float metallic = pbr.y; vec3 N = normalize(v_Normal); - vec3 V = normalize(CameraPos.xyz - v_Position.xyz); + vec3 V = normalize(CameraPos.xyz - w_Position.xyz); vec3 F0 = vec3(0.04); F0 = mix(F0, output_color.rgb, metallic); @@ -161,7 +161,7 @@ void main() { for (int i = 0; i < int(NumLights.x) && i < MAX_LIGHTS; ++i) { Light light = SceneLights[i]; - vec3 lightDir = light.pos.xyz - v_Position.xyz; + vec3 lightDir = light.pos.xyz - w_Position.xyz; vec3 L = normalize(lightDir); float rangeAttenuation = From 3b3e33a25082a16fe229b91342406c7f1197dfb3 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sat, 6 Mar 2021 23:51:39 +0100 Subject: [PATCH 16/58] Rework, fix and document --- crates/bevy_pbr/src/light.rs | 15 +- .../forward_pipeline/forward.frag | 162 ++++++++++++------ examples/3d/pbr.rs | 15 +- 3 files changed, 133 insertions(+), 59 deletions(-) diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index 0a9402a4916df..ec519bf3abdb4 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -15,16 +15,18 @@ pub struct Light { pub color: Color, pub fov: f32, pub depth: Range, - pub attenuation: f32, + pub intensity: f32, + pub radius: f32, } impl Default for Light { fn default() -> Self { Light { - color: Color::rgba(1.0, 1.0, 1.0, 100.0), + color: Color::rgb(1.0, 1.0, 1.0), depth: 0.1..50.0, fov: f32::to_radians(60.0), - attenuation: 100.0, + intensity: 100.0, + radius: 10.0, } } } @@ -50,10 +52,13 @@ impl LightRaw { let proj = perspective.get_projection_matrix() * global_transform.compute_matrix(); let (x, y, z) = global_transform.translation.into(); + + let mut color: [f32; 4] = light.color.into(); + color[3] = light.intensity; LightRaw { proj: proj.to_cols_array_2d(), - pos: [x, y, z, light.attenuation], // pos.w is the attenuation. - color: light.color.into(), + pos: [x, y, z, 1.0 / (light.radius * light.radius)], // pos.w is the attenuation. + color, } } } diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index d2e2bf944835a..d252da7ad73bc 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -1,3 +1,37 @@ +// From the Filament design doc +// https://google.github.io/filament/Filament.html#table_symbols +// Symbol Definition +// v View unit vector +// l Incident light unit vector +// n Surface normal unit vector +// h Half unit vector between l and v +// f BRDF +// f_d Diffuse component of a BRDF +// f_r Specular component of a BRDF +// α Roughness, remapped from using input perceptualRoughness +// σ Diffuse reflectance +// Ω Spherical domain +// f0 Reflectance at normal incidence +// f90 Reflectance at grazing angle +// χ+(a) Heaviside function (1 if a>0 and 0 otherwise) +// nior Index of refraction (IOR) of an interface +// ⟨n⋅l⟩ Dot product clamped to [0..1] +// ⟨a⟩ Saturated value (clamped to [0..1]) + +// The Bidirectional Reflectance Distribution Function (BRDF) describes the surface response of a standard material +// and consists of two components, the diffuse component (f_d) and the specular component (f_r): +// f(v,l) = f_d(v,l) + f_r(v,l) +// +// The form of the microfacet model is the same for diffuse and specular +// f_r(v,l) = f_d(v,l) = 1 / { |n⋅v||n⋅l| } ∫_Ω D(m,α) G(v,l,m) f_m(v,l,m) (v⋅m) (l⋅m) dm +// +// In which: +// D, also called the Normal Distribution Function (NDF) models the distribution of the microfacets +// G models the visibility (or occlusion or shadow-masking) of the microfacets +// f_m is the microfacet BRDF and differs between specular and diffuse components +// +// The above integration needs to be approximated. + #version 450 const int MAX_LIGHTS = 10; @@ -5,8 +39,9 @@ const int MAX_LIGHTS = 10; struct Light { mat4 proj; vec3 pos; - float attenuation; - vec4 color; + float inverseRadiusSquared; + vec3 color; + float intensity; }; layout(location = 0) in vec3 v_Position; @@ -27,7 +62,9 @@ layout(set = 1, binding = 0) uniform Lights { Light SceneLights[MAX_LIGHTS]; }; -layout(set = 3, binding = 0) uniform StandardMaterial_albedo { vec4 Albedo; }; +layout(set = 3, binding = 0) uniform StandardMaterial_albedo { + vec4 Albedo; +}; #ifdef STANDARDMATERIAL_ALBEDO_TEXTURE layout(set = 3, binding = 1) uniform texture2D StandardMaterial_albedo_texture; @@ -37,9 +74,11 @@ layout(set = 3, #ifndef STANDARDMATERIAL_UNLIT -layout(set = 3, binding = 3) uniform StandardMaterial_pbr { vec2 pbr; }; +layout(set = 3, binding = 3) uniform StandardMaterial_pbr { + vec2 pbr; +}; -#define saturate(x) clamp(x, 0.0, 1.0) +# define saturate(x) clamp(x, 0.0, 1.0) const float PI = 3.141592653589793; float pow5(float x) { @@ -47,18 +86,21 @@ float pow5(float x) { return x2 * x2 * x; } -float getSquareFalloffAttenuation(float distanceSquare, float falloff) { - float factor = distanceSquare * falloff; - float smoothFactor = saturate(1.0 - factor * factor); - return smoothFactor * smoothFactor; -} - -float getDistanceAttenuation(const vec3 posToLight, float falloff) { +float getDistanceAttenuation(const vec3 posToLight, float inverseRadiusSquared) { float distanceSquare = dot(posToLight, posToLight); - float attenuation = getSquareFalloffAttenuation(distanceSquare, falloff); + float factor = distanceSquare * inverseRadiusSquared; + float smoothFactor = saturate(1.0 - factor * factor); + float attenuation = smoothFactor * smoothFactor; return attenuation * 1.0 / max(distanceSquare, 1e-4); } +// Normal distribution function (specular D) +// Based on https://google.github.io/filament/Filament.html#citation-walter07 + +// D_GGX(h,α) = α^2 / { π ((n⋅h)^2 (α2−1) + 1)^2 } + +// Simple implementation, has precision problems when using fp16 instead of fp32 +// see https://google.github.io/filament/Filament.html#listing_speculardfp16 float D_GGX(float roughness, float NoH, const vec3 h) { float oneMinusNoHSquared = 1.0 - NoH * NoH; float a = NoH * roughness; @@ -67,6 +109,13 @@ float D_GGX(float roughness, float NoH, const vec3 h) { return d; } +// Visibility function (Specular G) +// V(v,l,a) = G(v,l,α) / { 4 (n⋅v) (n⋅l) } +// such that f_r becomes +// f_r(v,l) = D(h,α) V(v,l,α) F(v,h,f0) +// where +// V(v,l,α) = 0.5 / { n⋅l sqrt((n⋅v)^2 (1−α2) + α2) + n⋅v sqrt((n⋅l)^2 (1−α2) + α2) } +// Note the two sqrt's, that may be slow on mobile, see https://google.github.io/filament/Filament.html#listing_approximatedspecularv float V_SmithGGXCorrelated(float roughness, float NoV, float NoL) { float a2 = roughness * roughness; float lambdaV = NoL * sqrt((NoV - a2 * NoV) * NoV + a2); @@ -75,6 +124,9 @@ float V_SmithGGXCorrelated(float roughness, float NoV, float NoL) { return v; } +// Fresnel function +// see https://google.github.io/filament/Filament.html#citation-schlick94 +// F_Schlick(v,h,f_0,f_90) = f_0 + (f_90 − f_0) (1 − v⋅h)^5 vec3 F_Schlick(const vec3 f0, float f90, float VoH) { return f0 + (f90 - f0) * pow5(1.0 - VoH); } @@ -84,13 +136,19 @@ float F_Schlick(float f0, float f90, float VoH) { } vec3 fresnel(vec3 f0, float LoH) { + // f_90 suitable for ambient occlusion + // see https://google.github.io/filament/Filament.html#lighting/occlusion float f90 = saturate(dot(f0, vec3(50.0 * 0.33))); return F_Schlick(f0, f90, LoH); } -vec3 isotropicLobe(vec3 f0, float roughness, const vec3 h, float NoV, float NoL, - float NoH, float LoH) { +// Specular BRDF +// https://google.github.io/filament/Filament.html#materialsystem/specularbrdf +// Cook-Torrance approximation of the microfacet model integration using Fresnel law F to model f_m +// f_r(v,l) = { D(h,α) G(v,l,α) F(v,h,f0) } / { 4 (n⋅v) (n⋅l) } +vec3 specular(vec3 f0, float roughness, const vec3 h, float NoV, float NoL, + float NoH, float LoH) { float D = D_GGX(roughness, NoH, h); float V = V_SmithGGXCorrelated(roughness, NoV, NoL); vec3 F = fresnel(f0, LoH); @@ -98,6 +156,20 @@ vec3 isotropicLobe(vec3 f0, float roughness, const vec3 h, float NoV, float NoL, return (D * V) * F; } +// Diffuse BRDF +// https://google.github.io/filament/Filament.html#materialsystem/diffusebrdf +// fd(v,l) = σ/π * 1 / { |n⋅v||n⋅l| } ∫Ω D(m,α) G(v,l,m) (v⋅m) (l⋅m) dm + +// simplest approximation +// float Fd_Lambert() { +// return 1.0 / PI; +// } +// +// vec3 Fd = diffuseColor * Fd_Lambert(); + +// Disney approximation +// See https://google.github.io/filament/Filament.html#citation-burley12 +// minimal quality difference float Fd_Burley(float roughness, float NoV, float NoL, float LoH) { float f90 = 0.5 + 2.0 * roughness * LoH * LoH; float lightScatter = F_Schlick(1.0, f90, NoL); @@ -105,32 +177,14 @@ float Fd_Burley(float roughness, float NoV, float NoL, float LoH) { return lightScatter * viewScatter * (1.0 / PI); } -vec3 computeDiffuseColor(const vec3 baseColor, float metallic) { - return baseColor * (1.0 - metallic); -} - -#define MIN_N_DOT_V 1e-4 - -float clampNoV(float NoV) { - // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The - // Order: 1886" - return max(NoV, MIN_N_DOT_V); -} - float perceptualRoughnessToRoughness(float perceptualRoughness) { - return perceptualRoughness * perceptualRoughness; + // clamp perceptual roughness to prevent precision problems + // According to Filament design 0.089 is recommended for mobile + // Filament uses 0.045 for non-mobile + float clampedPerceptualRoughness = clamp(perceptualRoughness, 0.089, 1.0); + return clampedPerceptualRoughness * clampedPerceptualRoughness; } -#if defined(TARGET_MOBILE) -// min roughness such that (MIN_PERCEPTUAL_ROUGHNESS^4) > 0 in fp16 (i.e. -// 2^(-14/4), rounded up) -#define MIN_PERCEPTUAL_ROUGHNESS 0.089 -#define MIN_ROUGHNESS 0.007921 -#else -#define MIN_PERCEPTUAL_ROUGHNESS 0.045 -#define MIN_ROUGHNESS 0.002025 -#endif - #endif void main() { @@ -143,18 +197,23 @@ void main() { #ifndef STANDARDMATERIAL_UNLIT float perceptual_roughness = pbr.x; - perceptual_roughness = - clamp(perceptual_roughness, MIN_PERCEPTUAL_ROUGHNESS, 1.0); + // calculate non-linear roughness from linear perceptualRoughness float roughness = perceptualRoughnessToRoughness(perceptual_roughness); float metallic = pbr.y; + vec3 N = normalize(v_Normal); vec3 V = normalize(CameraPos.xyz - w_Position.xyz); - vec3 F0 = vec3(0.04); - F0 = mix(F0, output_color.rgb, metallic); + // TODO reflectance material property + float reflectance = 0.02; + + // Remapping [0,1] reflectance to F0 + // See https://google.github.io/filament/Filament.html#materialsystem/parameterization/remapping + vec3 F0 = 0.16 * reflectance * reflectance * (1.0 - metallic) + output_color.rgb * metallic; - vec3 diffuseColor = computeDiffuseColor(output_color.rgb, metallic); + // Diffuse strength inversely related to metallicity + vec3 diffuseColor = output_color.rgb * (1.0 - metallic); // accumulate color vec3 light_accum = vec3(0.0); @@ -165,26 +224,25 @@ void main() { vec3 L = normalize(lightDir); float rangeAttenuation = - getDistanceAttenuation(lightDir, light.attenuation); + getDistanceAttenuation(lightDir, light.inverseRadiusSquared); vec3 H = normalize(L + V); - float NdotL = clampNoV(dot(N, L)); - float NdotV = clampNoV(dot(N, V)); - float NoL = saturate(NdotL); + // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886" + float NdotV = max(dot(N, V), 1e-4); + + float NoL = saturate(dot(N, L)); float NoH = saturate(dot(N, H)); float LoH = saturate(dot(L, H)); - vec3 specular = isotropicLobe(F0, roughness, H, NdotV, NoL, NoH, LoH); + vec3 specular = specular(F0, roughness, H, NdotV, NoL, NoH, LoH); vec3 diffuse = diffuseColor * Fd_Burley(roughness, NdotV, NoL, LoH); + // f = (f_d + f_r) * light_color * light_intensity * attenuation * ⟨n⋅l⟩ light_accum += - ((diffuse + specular) * light.color.xyz) * (light.color.w * NdotL); + ((diffuse + specular) * light.color.xyz) * (light.intensity * rangeAttenuation * NoL); } - // average the lights so that we will never get something with > 1.0 - // color /= max(float(NumLights.x), 1.0); - output_color.xyz = light_accum; // Gamma correction. diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index cf07ae1ed208b..fdd46c17f1140 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -1,4 +1,10 @@ -use bevy::prelude::*; +use bevy::{ + prelude::*, + render::{ + pipeline::{PipelineDescriptor, RenderPipeline, RenderPipelines}, + shader::ShaderStages, + }, +}; /// This example shows how to configure Physically Based Rendering (PBR) parameters. fn main() { @@ -40,7 +46,12 @@ fn setup( commands // light .spawn(LightBundle { - transform: Transform::from_translation(Vec3::new(0.0, 1000.0, 1000.0)), + light: Light { + radius: 20.0, + intensity: 100.0, + ..Default::default() + }, + transform: Transform::from_translation(Vec3::new(0.0, 10.0, 10.0)), ..Default::default() }) // camera From dd9f2bc69c07ce0799e1277634e39639d4f9ab48 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sun, 7 Mar 2021 12:21:00 +0100 Subject: [PATCH 17/58] Rename albedo->base_color, pbr->roughness/metallic --- crates/bevy_gltf/src/loader.rs | 9 ++++--- crates/bevy_pbr/src/lib.rs | 2 +- crates/bevy_pbr/src/material.rs | 20 +++++++-------- .../forward_pipeline/forward.frag | 25 ++++++++++--------- examples/3d/parenting.rs | 2 +- examples/3d/pbr.rs | 10 +++++--- examples/3d/spawner.rs | 4 +-- examples/3d/texture.rs | 10 ++++---- examples/3d/z_sort_debug.rs | 2 +- examples/asset/asset_loading.rs | 2 +- 10 files changed, 45 insertions(+), 41 deletions(-) diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index c7b921e360235..801e172ef3499 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -4,7 +4,7 @@ use bevy_asset::{ }; use bevy_core::Name; use bevy_ecs::world::World; -use bevy_math::{Mat4, Vec2}; +use bevy_math::Mat4; use bevy_pbr::prelude::{PbrBundle, StandardMaterial}; use bevy_render::{ camera::{ @@ -277,10 +277,11 @@ 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_factor: Color::rgba(color[0], color[1], color[2], color[3]), + base_color_texture: texture_handle, + roughness_factor: pbr.roughness_factor(), + metallic_factor: pbr.metallic_factor(), unlit: material.unlit(), - pbr: Vec2::new(pbr.roughness_factor(), pbr.metallic_factor()), }) .with_dependencies(dependencies), ) diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index 702e6ead910c5..ad01adeb0426d 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -42,7 +42,7 @@ impl Plugin for PbrPlugin { materials.set_untracked( Handle::::default(), StandardMaterial { - albedo: Color::PINK, + base_color_factor: Color::PINK, unlit: true, ..Default::default() }, diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 7b975a776e859..275bf731085af 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -1,5 +1,4 @@ use bevy_asset::{self, Handle}; -use bevy_math::Vec2; use bevy_reflect::TypeUuid; use bevy_render::{color::Color, renderer::RenderResources, shader::ShaderDefs, texture::Texture}; @@ -7,11 +6,11 @@ use bevy_render::{color::Color, renderer::RenderResources, shader::ShaderDefs, t #[derive(Debug, RenderResources, ShaderDefs, TypeUuid)] #[uuid = "dace545e-4bc6-4595-a79d-c224fc694975"] pub struct StandardMaterial { - pub albedo: Color, + pub base_color_factor: Color, #[shader_def] - pub albedo_texture: Option>, - /// Represented as roughness/metallic. - pub pbr: Vec2, + pub base_color_texture: Option>, + pub roughness_factor: f32, + pub metallic_factor: f32, #[render_resources(ignore)] #[shader_def] pub unlit: bool, @@ -20,9 +19,10 @@ pub struct StandardMaterial { impl Default for StandardMaterial { fn default() -> Self { StandardMaterial { - albedo: Color::rgb(1.0, 1.0, 1.0), - pbr: Vec2::new(0.01, 0.08), - albedo_texture: None, + base_color_factor: Color::rgb(1.0, 1.0, 1.0), + base_color_texture: None, + roughness_factor: 0.01, + metallic_factor: 0.08, unlit: false, } } @@ -31,7 +31,7 @@ impl Default for StandardMaterial { impl From for StandardMaterial { fn from(color: Color) -> Self { StandardMaterial { - albedo: color, + base_color_factor: color, ..Default::default() } } @@ -40,7 +40,7 @@ impl From for StandardMaterial { impl From> for StandardMaterial { fn from(texture: Handle) -> Self { StandardMaterial { - albedo_texture: Some(texture), + base_color_texture: Some(texture), ..Default::default() } } diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index d252da7ad73bc..25a3c5a226ff7 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -62,20 +62,24 @@ layout(set = 1, binding = 0) uniform Lights { Light SceneLights[MAX_LIGHTS]; }; -layout(set = 3, binding = 0) uniform StandardMaterial_albedo { - vec4 Albedo; +layout(set = 3, binding = 0) uniform StandardMaterial_base_color_factor { + vec4 base_color_factor; }; #ifdef STANDARDMATERIAL_ALBEDO_TEXTURE -layout(set = 3, binding = 1) uniform texture2D StandardMaterial_albedo_texture; +layout(set = 3, binding = 1) uniform texture2D StandardMaterial_base_color_texture; layout(set = 3, - binding = 2) uniform sampler StandardMaterial_albedo_texture_sampler; + binding = 2) uniform sampler StandardMaterial_base_color_texture_sampler; #endif #ifndef STANDARDMATERIAL_UNLIT -layout(set = 3, binding = 3) uniform StandardMaterial_pbr { - vec2 pbr; +layout(set = 3, binding = 3) uniform StandardMaterial_roughness_factor { + float perceptual_roughness; +}; + +layout(set = 3, binding = 4) uniform StandardMaterial_metallic_factor { + float metallic; }; # define saturate(x) clamp(x, 0.0, 1.0) @@ -188,20 +192,17 @@ float perceptualRoughnessToRoughness(float perceptualRoughness) { #endif void main() { - vec4 output_color = Albedo; + vec4 output_color = base_color_factor; #ifdef STANDARDMATERIAL_ALBEDO_TEXTURE - output_color *= texture(sampler2D(StandardMaterial_albedo_texture, - StandardMaterial_albedo_texture_sampler), + output_color *= texture(sampler2D(StandardMaterial_base_color_texture, + StandardMaterial_base_color_texture_sampler), v_Uv); #endif #ifndef STANDARDMATERIAL_UNLIT - float perceptual_roughness = pbr.x; // calculate non-linear roughness from linear perceptualRoughness float roughness = perceptualRoughnessToRoughness(perceptual_roughness); - float metallic = pbr.y; - vec3 N = normalize(v_Normal); vec3 V = normalize(CameraPos.xyz - w_Position.xyz); diff --git a/examples/3d/parenting.rs b/examples/3d/parenting.rs index c4b95b755fe54..589d38c841fde 100644 --- a/examples/3d/parenting.rs +++ b/examples/3d/parenting.rs @@ -29,7 +29,7 @@ fn setup( ) { let cube_handle = meshes.add(Mesh::from(shape::Cube { size: 2.0 })); let cube_material_handle = materials.add(StandardMaterial { - albedo: Color::rgb(0.8, 0.7, 0.6), + base_color_factor: Color::rgb(0.8, 0.7, 0.6), ..Default::default() }); diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index fdd46c17f1140..fb7df9652b2bb 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -17,7 +17,7 @@ fn main() { /// set up a simple 3D scene fn setup( - commands: &mut Commands, + mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, ) { @@ -34,8 +34,10 @@ fn setup( subdivisions: 32, })), material: materials.add(StandardMaterial { - albedo: Color::rgb(0.2, 0.2, 1.0), - pbr: Vec2::new(x01, y01), // vary key PBR parameters on a grid of spheres to show the effect + base_color_factor: Color::rgb(0.2, 0.2, 1.0), + // vary key PBR parameters on a grid of spheres to show the effect + metallic_factor: y01, + roughness_factor: x01, ..Default::default() }), transform: Transform::from_xyz(x as f32, y as f32, 0.0), @@ -57,7 +59,7 @@ fn setup( // camera .spawn(PerspectiveCameraBundle { transform: Transform::from_translation(Vec3::new(0.0, 0.0, 8.0)) - .looking_at(Vec3::default(), Vec3::unit_y()), + .looking_at(Vec3::default(), Vec3::Y), ..Default::default() }); } diff --git a/examples/3d/spawner.rs b/examples/3d/spawner.rs index 892933e56a7eb..d300b7ce802f7 100644 --- a/examples/3d/spawner.rs +++ b/examples/3d/spawner.rs @@ -30,7 +30,7 @@ fn move_cubes( for (mut transform, material_handle) in query.iter_mut() { let material = materials.get_mut(material_handle).unwrap(); transform.translation += Vec3::new(1.0, 0.0, 0.0) * time.delta_seconds(); - material.albedo = + material.base_color_factor = Color::BLUE * Vec3::splat((3.0 * time.seconds_since_startup() as f32).sin()); } } @@ -58,7 +58,7 @@ fn setup( commands.spawn(PbrBundle { mesh: cube_handle.clone(), material: materials.add(StandardMaterial { - albedo: Color::rgb( + base_color_factor: Color::rgb( rng.gen_range(0.0..1.0), rng.gen_range(0.0..1.0), rng.gen_range(0.0..1.0), diff --git a/examples/3d/texture.rs b/examples/3d/texture.rs index 663875f0b3f56..3ac50b7ce8d4b 100644 --- a/examples/3d/texture.rs +++ b/examples/3d/texture.rs @@ -28,22 +28,22 @@ fn setup( // this material renders the texture normally let material_handle = materials.add(StandardMaterial { - albedo_texture: Some(texture_handle.clone()), + base_color_texture: Some(texture_handle.clone()), unlit: true, ..Default::default() }); // this material modulates the texture to make it red (and slightly transparent) let red_material_handle = materials.add(StandardMaterial { - albedo: Color::rgba(1.0, 0.0, 0.0, 0.5), - albedo_texture: Some(texture_handle.clone()), + base_color_factor: Color::rgba(1.0, 0.0, 0.0, 0.5), + base_color_texture: Some(texture_handle.clone()), unlit: true, }); // and lets make this one blue! (and also slightly transparent) let blue_material_handle = materials.add(StandardMaterial { - albedo: Color::rgba(0.0, 0.0, 1.0, 0.5), - albedo_texture: Some(texture_handle), + base_color_factor: Color::rgba(0.0, 0.0, 1.0, 0.5), + base_color_texture: Some(texture_handle), unlit: true, }); diff --git a/examples/3d/z_sort_debug.rs b/examples/3d/z_sort_debug.rs index 41667cc5691e1..a83e3db683a31 100644 --- a/examples/3d/z_sort_debug.rs +++ b/examples/3d/z_sort_debug.rs @@ -36,7 +36,7 @@ fn camera_order_color_system( if let Ok(material_handle) = material_query.get(visible_entity.entity) { let material = materials.get_mut(&*material_handle).unwrap(); let value = 1.0 - (visible_entity.order.0.sqrt() - 10.0) / 7.0; - material.albedo = Color::rgb(value, value, value); + material.base_color_factor = Color::rgb(value, value, value); } } } diff --git a/examples/asset/asset_loading.rs b/examples/asset/asset_loading.rs index 51f7f63cbd34f..0d48b1c199894 100644 --- a/examples/asset/asset_loading.rs +++ b/examples/asset/asset_loading.rs @@ -39,7 +39,7 @@ fn setup( // You can also add assets directly to their Assets storage: let material_handle = materials.add(StandardMaterial { - albedo: Color::rgb(0.8, 0.7, 0.6), + base_color_factor: Color::rgb(0.8, 0.7, 0.6), ..Default::default() }); From f8e744db7c14bde2711ecfc853688e8f02b7d074 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sun, 7 Mar 2021 00:31:48 +0100 Subject: [PATCH 18/58] Add reflectance material property --- crates/bevy_gltf/src/loader.rs | 1 + crates/bevy_pbr/src/material.rs | 8 ++++++-- .../src/render_graph/forward_pipeline/forward.frag | 7 ++++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 801e172ef3499..8760daa8c2b03 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -282,6 +282,7 @@ fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle< roughness_factor: pbr.roughness_factor(), metallic_factor: pbr.metallic_factor(), unlit: material.unlit(), + ..Default::default() }) .with_dependencies(dependencies), ) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 275bf731085af..47e37a925bbc0 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -11,6 +11,7 @@ pub struct StandardMaterial { pub base_color_texture: Option>, pub roughness_factor: f32, pub metallic_factor: f32, + pub reflectance: f32, #[render_resources(ignore)] #[shader_def] pub unlit: bool, @@ -21,8 +22,11 @@ impl Default for StandardMaterial { StandardMaterial { base_color_factor: Color::rgb(1.0, 1.0, 1.0), base_color_texture: None, - roughness_factor: 0.01, - metallic_factor: 0.08, + // TODO document defaults + roughness_factor: 0.089, + metallic_factor: 0.01, + // equivalent to 4% reflectance see https://google.github.io/filament/Material%20Properties.pdf + reflectance: 0.5, unlit: false, } } diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 25a3c5a226ff7..64ebb7d700d33 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -82,6 +82,10 @@ layout(set = 3, binding = 4) uniform StandardMaterial_metallic_factor { float metallic; }; +layout(set = 3, binding = 5) uniform StandardMaterial_reflectance { + float reflectance; +}; + # define saturate(x) clamp(x, 0.0, 1.0) const float PI = 3.141592653589793; @@ -206,9 +210,6 @@ void main() { vec3 N = normalize(v_Normal); vec3 V = normalize(CameraPos.xyz - w_Position.xyz); - // TODO reflectance material property - float reflectance = 0.02; - // Remapping [0,1] reflectance to F0 // See https://google.github.io/filament/Filament.html#materialsystem/parameterization/remapping vec3 F0 = 0.16 * reflectance * reflectance * (1.0 - metallic) + output_color.rgb * metallic; From 08afa11a2775dcc7941082584f0da96a4a947234 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sun, 7 Mar 2021 00:32:03 +0100 Subject: [PATCH 19/58] Add .clang-format for GLSL --- .clang-format | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000000..88a592eb698c3 --- /dev/null +++ b/.clang-format @@ -0,0 +1,76 @@ +# From https://gist.github.com/Astro36/ef933be73050b4d5a6e0522536723a18 +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +# AlignConsecutiveMacros: false +AlignEscapedNewlines: DontAlign +AlignOperands: true +AlignTrailingComments: false +# AllowAllArgumentsOnNextLine: false +# AllowAllConstructorInitializersOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +# AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +# AllowShortIfStatementsOnASingleLine: Always +# AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +# AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +# BreakInheritanceList: BeforeColon +BreakStringLiterals: false +ColumnLimit: 0 +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 0 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +IncludeBlocks: Merge +IncludeCategories: + - Regex: '^<.*\.h>' + Priority: 1 + - Regex: "^<.*" + Priority: 2 + - Regex: ".*" + Priority: 3 +IndentCaseLabels: false +# IndentGotoLabels: false +IndentPPDirectives: AfterHash +IndentWidth: 4 +IndentWrappedFunctionNames: true +KeepEmptyLinesAtTheStartOfBlocks: false +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +PointerAlignment: Left +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +# SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +# SpaceBeforeCpp11BracedList: true +# SpaceBeforeCtorInitializerColon: false +# SpaceBeforeInheritanceColon: false +SpaceBeforeParens: ControlStatements +# SpaceBeforeRangeBasedForLoopColon: true +# SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +# Standard: Latest +UseTab: Never From 81523f8b650b985bb01cee93e1e12dd63b4047d1 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sun, 7 Mar 2021 08:11:58 +0100 Subject: [PATCH 20/58] Document standard PBR properties --- crates/bevy_pbr/src/material.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 47e37a925bbc0..a5acd7523140a 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -3,14 +3,20 @@ 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 base_color_factor: Color, #[shader_def] pub base_color_texture: Option>, + /// Linear perceptual roughness, clamped to [0.089,1] in the shader + /// Defaults to minimum of 0.089 pub roughness_factor: f32, + /// Range [0,1] from dielectric to pure metallic pub metallic_factor: f32, + /// Specular intensity for non-metals, defaults to 0.5 on a linear scale + /// which is mapped to 4% reflectance in the shader pub reflectance: f32, #[render_resources(ignore)] #[shader_def] @@ -22,10 +28,13 @@ impl Default for StandardMaterial { StandardMaterial { base_color_factor: Color::rgb(1.0, 1.0, 1.0), base_color_texture: None, - // TODO document defaults + // This is the minimum the roughness is clamped to in shader code roughness_factor: 0.089, + // Few materials are purely dielectric or metallic + // This is just a default for mostly-dielectric metallic_factor: 0.01, - // equivalent to 4% reflectance see https://google.github.io/filament/Material%20Properties.pdf + // 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, } From 177ece9baa927fde970dbcf0d1de7019a9b19d12 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sun, 7 Mar 2021 08:14:50 +0100 Subject: [PATCH 21/58] Add comment to base_color_factor mentioning albedo --- crates/bevy_pbr/src/material.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index a5acd7523140a..e283f0970c4fa 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -7,6 +7,7 @@ use bevy_render::{color::Color, renderer::RenderResources, shader::ShaderDefs, t #[derive(Debug, RenderResources, ShaderDefs, TypeUuid)] #[uuid = "dace545e-4bc6-4595-a79d-c224fc694975"] pub struct StandardMaterial { + /// Doubles as diffuse albedo for non-metallic, specular for metallic and a mix for everything in between pub base_color_factor: Color, #[shader_def] pub base_color_texture: Option>, From d1c2e416c1150b4ba47bffc5928c7684f00716d7 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sun, 7 Mar 2021 09:27:45 +0100 Subject: [PATCH 22/58] Swizzle using .rgb for colors --- .../src/render_graph/forward_pipeline/forward.frag | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 64ebb7d700d33..2f17941d11e7e 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -242,14 +242,14 @@ void main() { // f = (f_d + f_r) * light_color * light_intensity * attenuation * ⟨n⋅l⟩ light_accum += - ((diffuse + specular) * light.color.xyz) * (light.intensity * rangeAttenuation * NoL); + ((diffuse + specular) * light.color.rgb) * (light.intensity * rangeAttenuation * NoL); } - output_color.xyz = light_accum; + output_color.rgb = light_accum; // Gamma correction. - output_color.xyz = output_color.xyz / (output_color.xyz + vec3(1.0)); - output_color.xyz = pow(output_color.xyz, vec3(1.0 / 2.2)); + output_color.rgb = output_color.rgb / (output_color.rgb + vec3(1.0)); + output_color.rgb = pow(output_color.rgb, vec3(1.0 / 2.2)); #endif // multiply the light by material color From f0a8cbf514b3260657a152c4f4b822225e4f1a5d Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sun, 7 Mar 2021 09:53:57 +0100 Subject: [PATCH 23/58] Document attenuation and light accumulation Add physically correct 1/4PI --- .../render_graph/forward_pipeline/forward.frag | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 2f17941d11e7e..4e6674f6b0447 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -94,6 +94,11 @@ float pow5(float x) { return x2 * x2 * x; } +// distanceAttenuation is simply the square falloff of light intensity +// combined with a smooth attenuation at the edge of the light radius +// +// light radius is a non-physical construct for efficiency purposes, +// because otherwise every light affects every fragment in the scene float getDistanceAttenuation(const vec3 posToLight, float inverseRadiusSquared) { float distanceSquare = dot(posToLight, posToLight); float factor = distanceSquare * inverseRadiusSquared; @@ -240,9 +245,17 @@ void main() { vec3 specular = specular(F0, roughness, H, NdotV, NoL, NoH, LoH); vec3 diffuse = diffuseColor * Fd_Burley(roughness, NdotV, NoL, LoH); - // f = (f_d + f_r) * light_color * light_intensity * attenuation * ⟨n⋅l⟩ + // Lout = f(v,l) Φ / { 4 π d^2 }⟨n⋅l⟩ + // where + // f(v,l) = (f_d(v,l) + f_r(v,l)) * light_color + // Φ is light intensity + + // our rangeAttentuation = 1 / d^2 multiplied with an attenuation factor for smoothing at the edge of the non-physical maximum light radius + + // See https://google.github.io/filament/Filament.html#mjx-eqn-pointLightLuminanceEquation + // TODO compensate for energy loss https://google.github.io/filament/Filament.html#materialsystem/improvingthebrdfs/energylossinspecularreflectance light_accum += - ((diffuse + specular) * light.color.rgb) * (light.intensity * rangeAttenuation * NoL); + ((diffuse + specular) * light.color.rgb) * (light.intensity * 1 / (4 * PI) * rangeAttenuation * NoL); } output_color.rgb = light_accum; From f6f15f82203fc4e0d78d1760fbce2414ea1e44b3 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sun, 7 Mar 2021 10:31:40 +0100 Subject: [PATCH 24/58] Fix #ifdef STANDARDMATERIAL_BASE_COLOR_TEXTURE --- .../bevy_pbr/src/render_graph/forward_pipeline/forward.frag | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 4e6674f6b0447..2c6ac05d78a40 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -66,7 +66,7 @@ layout(set = 3, binding = 0) uniform StandardMaterial_base_color_factor { vec4 base_color_factor; }; -#ifdef STANDARDMATERIAL_ALBEDO_TEXTURE +#ifdef STANDARDMATERIAL_BASE_COLOR_TEXTURE layout(set = 3, binding = 1) uniform texture2D StandardMaterial_base_color_texture; layout(set = 3, binding = 2) uniform sampler StandardMaterial_base_color_texture_sampler; @@ -202,7 +202,7 @@ float perceptualRoughnessToRoughness(float perceptualRoughness) { void main() { vec4 output_color = base_color_factor; -#ifdef STANDARDMATERIAL_ALBEDO_TEXTURE +#ifdef STANDARDMATERIAL_BASE_COLOR_TEXTURE output_color *= texture(sampler2D(StandardMaterial_base_color_texture, StandardMaterial_base_color_texture_sampler), v_Uv); From 0944cd81e8fc57712e54f77437f747f081a69da2 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sun, 7 Mar 2021 11:11:19 +0100 Subject: [PATCH 25/58] Add reinhard_luminance tonemapping --- .../forward_pipeline/forward.frag | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 2c6ac05d78a40..381f77f77dc9d 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -198,6 +198,41 @@ float perceptualRoughnessToRoughness(float perceptualRoughness) { return clampedPerceptualRoughness * clampedPerceptualRoughness; } +// from https://64.github.io/tonemapping/ +// reinhard on RGB oversaturates colors +vec3 reinhard(vec3 color) { + return color / (1.0 + color); +} + +vec3 reinhard_extended(vec3 color, float max_white) { + vec3 numerator = color * (1.0f + (color / vec3(max_white * max_white))); + return numerator / (1.0 + color); +} + +// luminance coefficients from Rec. 709. +// https://en.wikipedia.org/wiki/Rec._709 +float luminance(vec3 v) { + return dot(v, vec3(0.2126, 0.7152, 0.0722)); +} + +vec3 change_luminance(vec3 c_in, float l_out) { + float l_in = luminance(c_in); + return c_in * (l_out / l_in); +} + +vec3 reinhard_luminance(vec3 color) { + float l_old = luminance(color); + float l_new = l_old / (1.0f + l_old); + return change_luminance(color, l_new); +} + +vec3 reinhard_extended_luminance(vec3 color, float max_white_l) { + float l_old = luminance(color); + float numerator = l_old * (1.0f + (l_old / (max_white_l * max_white_l))); + float l_new = numerator / (1.0f + l_old); + return change_luminance(color, l_new); +} + #endif void main() { @@ -260,11 +295,11 @@ void main() { output_color.rgb = light_accum; + // tone_mapping + output_color.rgb = reinhard_luminance(output_color.rgb); // Gamma correction. - output_color.rgb = output_color.rgb / (output_color.rgb + vec3(1.0)); output_color.rgb = pow(output_color.rgb, vec3(1.0 / 2.2)); #endif - // multiply the light by material color o_Target = output_color; } From 2c3e5e574010f7724dcdcdb8e80bb56494580eee Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sun, 7 Mar 2021 11:23:18 +0100 Subject: [PATCH 26/58] Fix examples by adding light radius of 20.0 --- examples/3d/3d_scene.rs | 4 ++++ examples/3d/msaa.rs | 4 ++++ examples/3d/orthographic.rs | 4 ++++ examples/3d/texture.rs | 2 ++ examples/game/alien_cake_addict.rs | 4 ++++ 5 files changed, 18 insertions(+) diff --git a/examples/3d/3d_scene.rs b/examples/3d/3d_scene.rs index 0e113775ae821..2a089540e2c7d 100644 --- a/examples/3d/3d_scene.rs +++ b/examples/3d/3d_scene.rs @@ -32,6 +32,10 @@ fn setup( // light .spawn(LightBundle { transform: Transform::from_xyz(4.0, 8.0, 4.0), + light: Light { + radius: 20.0, + ..Default::default() + }, ..Default::default() }) // camera diff --git a/examples/3d/msaa.rs b/examples/3d/msaa.rs index d4c5c5ea92c0c..307cdf88f3631 100644 --- a/examples/3d/msaa.rs +++ b/examples/3d/msaa.rs @@ -29,6 +29,10 @@ fn setup( // light .spawn(LightBundle { transform: Transform::from_xyz(4.0, 8.0, 4.0), + light: Light { + radius: 20.0, + ..Default::default() + }, ..Default::default() }) // camera diff --git a/examples/3d/orthographic.rs b/examples/3d/orthographic.rs index caaaf42a16bf4..89a96685df942 100644 --- a/examples/3d/orthographic.rs +++ b/examples/3d/orthographic.rs @@ -55,6 +55,10 @@ fn setup( // light .spawn(LightBundle { transform: Transform::from_xyz(3.0, 8.0, 5.0), + light: Light { + radius: 20.0, + ..Default::default() + }, ..Default::default() }) // camera diff --git a/examples/3d/texture.rs b/examples/3d/texture.rs index 3ac50b7ce8d4b..39900a660cf97 100644 --- a/examples/3d/texture.rs +++ b/examples/3d/texture.rs @@ -38,6 +38,7 @@ fn setup( base_color_factor: Color::rgba(1.0, 0.0, 0.0, 0.5), base_color_texture: Some(texture_handle.clone()), unlit: true, + ..Default::default() }); // and lets make this one blue! (and also slightly transparent) @@ -45,6 +46,7 @@ fn setup( base_color_factor: Color::rgba(0.0, 0.0, 1.0, 0.5), base_color_texture: Some(texture_handle), unlit: true, + ..Default::default() }); // add entities to the world diff --git a/examples/game/alien_cake_addict.rs b/examples/game/alien_cake_addict.rs index dc7213bbdce42..384321838c5fe 100644 --- a/examples/game/alien_cake_addict.rs +++ b/examples/game/alien_cake_addict.rs @@ -107,6 +107,10 @@ fn setup(mut commands: Commands, asset_server: Res, mut game: ResMu commands.spawn(LightBundle { transform: Transform::from_xyz(4.0, 5.0, 4.0), + light: Light { + radius: 20.0, + ..Default::default() + }, ..Default::default() }); From b989da5fd4dec83cfed4d66a8535d7fd1fc89dd3 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sun, 7 Mar 2021 11:51:20 +0100 Subject: [PATCH 27/58] Fix wireframe example --- crates/bevy_render/src/wireframe/wireframe.vert | 1 + examples/3d/wireframe.rs | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/crates/bevy_render/src/wireframe/wireframe.vert b/crates/bevy_render/src/wireframe/wireframe.vert index 87b32a667a1cc..f1cc11d1f7fd2 100644 --- a/crates/bevy_render/src/wireframe/wireframe.vert +++ b/crates/bevy_render/src/wireframe/wireframe.vert @@ -4,6 +4,7 @@ layout(location = 0) in vec3 Vertex_Position; layout(set = 0, binding = 0) uniform CameraViewProj { mat4 ViewProj; + vec4 CameraPos; }; layout(set = 1, binding = 0) uniform Transform { diff --git a/examples/3d/wireframe.rs b/examples/3d/wireframe.rs index 47998572a0358..2a8cb922502d2 100644 --- a/examples/3d/wireframe.rs +++ b/examples/3d/wireframe.rs @@ -48,6 +48,10 @@ fn setup( // light .spawn(LightBundle { transform: Transform::from_xyz(4.0, 8.0, 4.0), + light: Light { + radius: 20.0, + ..Default::default() + }, ..Default::default() }) // camera From c2c965c1bb9b39a7185afa0add25817fc027234e Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sun, 7 Mar 2021 15:58:20 +0100 Subject: [PATCH 28/58] Rename light.radius to light.range --- crates/bevy_pbr/src/light.rs | 6 +++--- examples/3d/3d_scene.rs | 2 +- examples/3d/msaa.rs | 2 +- examples/3d/orthographic.rs | 2 +- examples/3d/pbr.rs | 2 +- examples/3d/wireframe.rs | 2 +- examples/game/alien_cake_addict.rs | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index ec519bf3abdb4..545af3ac4667e 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -16,7 +16,7 @@ pub struct Light { pub fov: f32, pub depth: Range, pub intensity: f32, - pub radius: f32, + pub range: f32, } impl Default for Light { @@ -26,7 +26,7 @@ impl Default for Light { depth: 0.1..50.0, fov: f32::to_radians(60.0), intensity: 100.0, - radius: 10.0, + range: 10.0, } } } @@ -57,7 +57,7 @@ impl LightRaw { color[3] = light.intensity; LightRaw { proj: proj.to_cols_array_2d(), - pos: [x, y, z, 1.0 / (light.radius * light.radius)], // pos.w is the attenuation. + pos: [x, y, z, 1.0 / (light.range * light.range)], // pos.w is the attenuation. color, } } diff --git a/examples/3d/3d_scene.rs b/examples/3d/3d_scene.rs index 2a089540e2c7d..d49c22cd065dd 100644 --- a/examples/3d/3d_scene.rs +++ b/examples/3d/3d_scene.rs @@ -33,7 +33,7 @@ fn setup( .spawn(LightBundle { transform: Transform::from_xyz(4.0, 8.0, 4.0), light: Light { - radius: 20.0, + range: 20.0, ..Default::default() }, ..Default::default() diff --git a/examples/3d/msaa.rs b/examples/3d/msaa.rs index 307cdf88f3631..47cb09a93539b 100644 --- a/examples/3d/msaa.rs +++ b/examples/3d/msaa.rs @@ -30,7 +30,7 @@ fn setup( .spawn(LightBundle { transform: Transform::from_xyz(4.0, 8.0, 4.0), light: Light { - radius: 20.0, + range: 20.0, ..Default::default() }, ..Default::default() diff --git a/examples/3d/orthographic.rs b/examples/3d/orthographic.rs index 89a96685df942..56d1e7784f7ac 100644 --- a/examples/3d/orthographic.rs +++ b/examples/3d/orthographic.rs @@ -56,7 +56,7 @@ fn setup( .spawn(LightBundle { transform: Transform::from_xyz(3.0, 8.0, 5.0), light: Light { - radius: 20.0, + range: 20.0, ..Default::default() }, ..Default::default() diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index fb7df9652b2bb..31988fca6bbd4 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -49,7 +49,7 @@ fn setup( // light .spawn(LightBundle { light: Light { - radius: 20.0, + range: 20.0, intensity: 100.0, ..Default::default() }, diff --git a/examples/3d/wireframe.rs b/examples/3d/wireframe.rs index 2a8cb922502d2..57bb7f219a33f 100644 --- a/examples/3d/wireframe.rs +++ b/examples/3d/wireframe.rs @@ -49,7 +49,7 @@ fn setup( .spawn(LightBundle { transform: Transform::from_xyz(4.0, 8.0, 4.0), light: Light { - radius: 20.0, + range: 20.0, ..Default::default() }, ..Default::default() diff --git a/examples/game/alien_cake_addict.rs b/examples/game/alien_cake_addict.rs index 384321838c5fe..e9875a85ca63d 100644 --- a/examples/game/alien_cake_addict.rs +++ b/examples/game/alien_cake_addict.rs @@ -108,7 +108,7 @@ fn setup(mut commands: Commands, asset_server: Res, mut game: ResMu commands.spawn(LightBundle { transform: Transform::from_xyz(4.0, 5.0, 4.0), light: Light { - radius: 20.0, + range: 20.0, ..Default::default() }, ..Default::default() From ac7a88e7d8aa287bc90cf4dcbe1e4676055b8338 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sun, 7 Mar 2021 16:02:03 +0100 Subject: [PATCH 29/58] Adjust comments --- crates/bevy_pbr/src/material.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index e283f0970c4fa..29a06f6df3fcc 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -11,13 +11,13 @@ pub struct StandardMaterial { pub base_color_factor: Color, #[shader_def] pub base_color_texture: Option>, - /// Linear perceptual roughness, clamped to [0.089,1] in the shader + /// Linear perceptual roughness, clamped to [0.089, 1.0] in the shader /// Defaults to minimum of 0.089 - pub roughness_factor: f32, - /// Range [0,1] from dielectric to pure metallic + pub roughness_factor: PerceptualRoughness, + /// From [0.0, 1.0], dielectric to pure metallic pub metallic_factor: f32, - /// Specular intensity for non-metals, defaults to 0.5 on a linear scale - /// which is mapped to 4% reflectance in the shader + /// 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] From da36141d11027a63279b1cf16ae242a13bf92398 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sun, 7 Mar 2021 20:16:50 +0100 Subject: [PATCH 30/58] Remove 1/4PI term --- crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 381f77f77dc9d..6e72baecc2f89 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -286,11 +286,12 @@ void main() { // Φ is light intensity // our rangeAttentuation = 1 / d^2 multiplied with an attenuation factor for smoothing at the edge of the non-physical maximum light radius + // It's not 100% clear where the 1/4π goes in the derivation, but we follow the filament shader and leave it out // See https://google.github.io/filament/Filament.html#mjx-eqn-pointLightLuminanceEquation // TODO compensate for energy loss https://google.github.io/filament/Filament.html#materialsystem/improvingthebrdfs/energylossinspecularreflectance light_accum += - ((diffuse + specular) * light.color.rgb) * (light.intensity * 1 / (4 * PI) * rangeAttenuation * NoL); + ((diffuse + specular) * light.color.rgb) * (light.intensity * rangeAttenuation * NoL); } output_color.rgb = light_accum; From 2f6cccef6cc3e179574b4cc38fbc571eee5f5621 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Mon, 8 Mar 2021 10:13:51 +0100 Subject: [PATCH 31/58] Add most basic ambient term --- crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 6e72baecc2f89..1cf91f17dad65 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -294,7 +294,7 @@ void main() { ((diffuse + specular) * light.color.rgb) * (light.intensity * rangeAttenuation * NoL); } - output_color.rgb = light_accum; + output_color.rgb = light_accum + output_color.rgb * AmbientColor; // tone_mapping output_color.rgb = reinhard_luminance(output_color.rgb); From 917d1cf5d4bb8c4e8fcaaa3b6c9ec0b961b0dbc5 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Mon, 8 Mar 2021 10:14:08 +0100 Subject: [PATCH 32/58] Disable gamma correction --- crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 1cf91f17dad65..d99bf9a16b573 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -299,7 +299,8 @@ void main() { // tone_mapping output_color.rgb = reinhard_luminance(output_color.rgb); // Gamma correction. - output_color.rgb = pow(output_color.rgb, vec3(1.0 / 2.2)); + // Not needed with sRGB buffer + // output_color.rgb = pow(output_color.rgb, vec3(1.0 / 2.2)); #endif o_Target = output_color; From a3fb8602017962c00ef738359ae731fac28c05d8 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Mon, 8 Mar 2021 17:43:23 +0100 Subject: [PATCH 33/58] Add PBR parameter newtypes/enums for CPU remapping --- crates/bevy_gltf/src/loader.rs | 4 +- crates/bevy_pbr/Cargo.toml | 1 + crates/bevy_pbr/src/lib.rs | 4 +- crates/bevy_pbr/src/material.rs | 12 +- crates/bevy_pbr/src/parameters.rs | 130 ++++++++++++++++++ .../forward_pipeline/forward.frag | 19 +-- examples/3d/pbr.rs | 6 +- 7 files changed, 151 insertions(+), 25 deletions(-) create mode 100644 crates/bevy_pbr/src/parameters.rs diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 8760daa8c2b03..bee5b2aabfae2 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -279,8 +279,8 @@ fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle< LoadedAsset::new(StandardMaterial { base_color_factor: Color::rgba(color[0], color[1], color[2], color[3]), base_color_texture: texture_handle, - roughness_factor: pbr.roughness_factor(), - metallic_factor: pbr.metallic_factor(), + roughness_factor: pbr.roughness_factor().into(), + metallic_factor: pbr.metallic_factor().into(), unlit: material.unlit(), ..Default::default() }) diff --git a/crates/bevy_pbr/Cargo.toml b/crates/bevy_pbr/Cargo.toml index 8a09959024cb7..c13cb283055dd 100644 --- a/crates/bevy_pbr/Cargo.toml +++ b/crates/bevy_pbr/Cargo.toml @@ -18,6 +18,7 @@ bevy_asset = { path = "../bevy_asset", version = "0.4.0" } bevy_core = { path = "../bevy_core", version = "0.4.0" } bevy_derive = { path = "../bevy_derive", version = "0.4.0" } bevy_ecs = { path = "../bevy_ecs", version = "0.4.0" } +bevy_log = { path = "../bevy_log", version = "0.4.0" } bevy_math = { path = "../bevy_math", version = "0.4.0" } bevy_reflect = { path = "../bevy_reflect", version = "0.4.0", features = ["bevy"] } bevy_render = { path = "../bevy_render", version = "0.4.0" } diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index ad01adeb0426d..5bcab6cbced41 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -3,13 +3,15 @@ pub mod render_graph; mod entity; mod light; mod material; +mod parameters; pub use entity::*; pub use light::*; pub use material::*; +pub use parameters::*; pub mod prelude { - pub use crate::{entity::*, light::Light, material::StandardMaterial}; + pub use crate::{entity::*, light::Light, material::StandardMaterial, parameters::*}; } use bevy_app::prelude::*; diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 29a06f6df3fcc..eb9ce77e28236 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -2,6 +2,8 @@ use bevy_asset::{self, Handle}; use bevy_reflect::TypeUuid; use bevy_render::{color::Color, renderer::RenderResources, shader::ShaderDefs, texture::Texture}; +use crate::parameters::*; + /// 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)] @@ -13,9 +15,9 @@ pub struct StandardMaterial { pub base_color_texture: Option>, /// Linear perceptual roughness, clamped to [0.089, 1.0] in the shader /// Defaults to minimum of 0.089 - pub roughness_factor: PerceptualRoughness, + pub roughness_factor: Roughness, /// From [0.0, 1.0], dielectric to pure metallic - pub metallic_factor: f32, + pub metallic_factor: Metallic, /// 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, @@ -30,13 +32,13 @@ impl Default for StandardMaterial { base_color_factor: Color::rgb(1.0, 1.0, 1.0), base_color_texture: None, // This is the minimum the roughness is clamped to in shader code - roughness_factor: 0.089, + roughness_factor: 0.089.into(), // Few materials are purely dielectric or metallic // This is just a default for mostly-dielectric - metallic_factor: 0.01, + metallic_factor: 0.01.into(), // 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, + reflectance: 0.5.into(), unlit: false, } } diff --git a/crates/bevy_pbr/src/parameters.rs b/crates/bevy_pbr/src/parameters.rs new file mode 100644 index 0000000000000..45c447e41c135 --- /dev/null +++ b/crates/bevy_pbr/src/parameters.rs @@ -0,0 +1,130 @@ +use bevy_asset::{self, Handle}; +use bevy_core::Bytes; +use bevy_log::warn; +use bevy_render::{ + impl_render_resource_bytes, + renderer::{RenderResource, RenderResourceType}, + texture::Texture, +}; + +const MIN_ROUGHNESS: f32 = 0.089; +const MAX_ROUGHNESS: f32 = 1.0; + +#[derive(Clone, Copy, Debug)] +pub enum Roughness { + PerceptualRoughness(f32), + Roughness(f32), +} + +impl Roughness { + pub fn perceptual_roughness(roughness: f32) -> Self { + if roughness < MIN_ROUGHNESS || roughness > MAX_ROUGHNESS { + warn!( + "Roughness value {} is not within range [{}, {}]", + roughness, MIN_ROUGHNESS, MAX_ROUGHNESS + ); + } + let perceptual_roughness = roughness.max(MIN_ROUGHNESS).min(MAX_ROUGHNESS); + + Self::PerceptualRoughness(perceptual_roughness) + } + + pub fn roughness(roughness: f32) -> Self { + if roughness < MIN_ROUGHNESS || roughness > MAX_ROUGHNESS { + warn!( + "Roughness value {} is not within range [{}, {}]", + roughness, MIN_ROUGHNESS, MAX_ROUGHNESS + ); + } + let roughness = roughness.max(MIN_ROUGHNESS).min(MAX_ROUGHNESS); + Self::Roughness(roughness) + } + + pub fn to_perceptual_roughness(self) -> f32 { + // See https://google.github.io/filament/Filament.html#materialsystem/parameterization/remapping + match self { + Roughness::PerceptualRoughness(roughness) => roughness, + Roughness::Roughness(roughness) => roughness.sqrt(), + } + } + + pub fn to_roughness(self) -> f32 { + // See https://google.github.io/filament/Filament.html#materialsystem/parameterization/remapping + match self { + Roughness::PerceptualRoughness(roughness) => roughness * roughness, + Roughness::Roughness(roughness) => roughness, + } + } +} + +impl From for Roughness { + fn from(roughness: f32) -> Self { + Self::perceptual_roughness(roughness) + } +} + +impl Bytes for Roughness { + fn write_bytes(&self, buffer: &mut [u8]) { + self.to_roughness().write_bytes(buffer); + } + + fn byte_len(&self) -> usize { + 0.byte_len() + } +} +impl_render_resource_bytes!(Roughness); + +#[derive(Copy, Clone, Debug)] +pub struct Metallic(f32); + +impl From for Metallic { + fn from(metallic: f32) -> Self { + if metallic < 0.0 || metallic > 1.0 { + warn!("Metallic value {} is not within range [0.0, 1.0]", metallic); + } + Self(metallic) + } +} + +impl Bytes for Metallic { + fn write_bytes(&self, buffer: &mut [u8]) { + self.0.write_bytes(buffer); + } + + fn byte_len(&self) -> usize { + self.0.byte_len() + } +} +impl_render_resource_bytes!(Metallic); + +pub struct Reflectance(f32); + +impl Reflectance { + fn remap(&self) -> f32 { + // See https://google.github.io/filament/Filament.html#materialsystem/parameterization/remapping + 0.16 * self.0 * self.0 + } +} + +impl From for Reflectance { + fn from(reflectance: f32) -> Self { + if reflectance < 0.0 || reflectance > 1.0 { + warn!( + "Reflectance value {} is not within range [0.0, 1.0]", + reflectance + ); + } + Self(reflectance) + } +} + +impl Bytes for Reflectance { + fn write_bytes(&self, buffer: &mut [u8]) { + self.remap().write_bytes(buffer); + } + + fn byte_len(&self) -> usize { + self.0.byte_len() + } +} +impl_render_resource_bytes!(Reflectance); diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index d99bf9a16b573..5e995314b573a 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -75,7 +75,8 @@ layout(set = 3, #ifndef STANDARDMATERIAL_UNLIT layout(set = 3, binding = 3) uniform StandardMaterial_roughness_factor { - float perceptual_roughness; + // perceptual roughness is remapped to roughness on the CPU + float roughness; }; layout(set = 3, binding = 4) uniform StandardMaterial_metallic_factor { @@ -83,6 +84,7 @@ layout(set = 3, binding = 4) uniform StandardMaterial_metallic_factor { }; layout(set = 3, binding = 5) uniform StandardMaterial_reflectance { + // reflectance is remapped on the CPU float reflectance; }; @@ -190,14 +192,6 @@ float Fd_Burley(float roughness, float NoV, float NoL, float LoH) { return lightScatter * viewScatter * (1.0 / PI); } -float perceptualRoughnessToRoughness(float perceptualRoughness) { - // clamp perceptual roughness to prevent precision problems - // According to Filament design 0.089 is recommended for mobile - // Filament uses 0.045 for non-mobile - float clampedPerceptualRoughness = clamp(perceptualRoughness, 0.089, 1.0); - return clampedPerceptualRoughness * clampedPerceptualRoughness; -} - // from https://64.github.io/tonemapping/ // reinhard on RGB oversaturates colors vec3 reinhard(vec3 color) { @@ -244,15 +238,12 @@ void main() { #endif #ifndef STANDARDMATERIAL_UNLIT - // calculate non-linear roughness from linear perceptualRoughness - float roughness = perceptualRoughnessToRoughness(perceptual_roughness); - vec3 N = normalize(v_Normal); vec3 V = normalize(CameraPos.xyz - w_Position.xyz); - // Remapping [0,1] reflectance to F0 + // Reflectance is remapped before being passed to the GPU // See https://google.github.io/filament/Filament.html#materialsystem/parameterization/remapping - vec3 F0 = 0.16 * reflectance * reflectance * (1.0 - metallic) + output_color.rgb * metallic; + vec3 F0 = reflectance * (1.0 - metallic) + output_color.rgb * metallic; // Diffuse strength inversely related to metallicity vec3 diffuseColor = output_color.rgb * (1.0 - metallic); diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index 31988fca6bbd4..e520fbb869bf2 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -36,8 +36,8 @@ fn setup( material: materials.add(StandardMaterial { base_color_factor: Color::rgb(0.2, 0.2, 1.0), // vary key PBR parameters on a grid of spheres to show the effect - metallic_factor: y01, - roughness_factor: x01, + metallic_factor: y01.into(), + roughness_factor: x01.into(), ..Default::default() }), transform: Transform::from_xyz(x as f32, y as f32, 0.0), @@ -53,7 +53,7 @@ fn setup( intensity: 100.0, ..Default::default() }, - transform: Transform::from_translation(Vec3::new(0.0, 10.0, 10.0)), + transform: Transform::from_translation(Vec3::new(0.0, 5.0, 5.0)), ..Default::default() }) // camera From 07f2f9f8ce3140dec80cb39ee8c2e8c9357c2302 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Mon, 8 Mar 2021 19:25:49 +0100 Subject: [PATCH 34/58] Use gold in pbr example --- examples/3d/pbr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index e520fbb869bf2..a5fcea68053a5 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -34,7 +34,7 @@ fn setup( subdivisions: 32, })), material: materials.add(StandardMaterial { - base_color_factor: Color::rgb(0.2, 0.2, 1.0), + base_color_factor: Color::hex("ffd891").unwrap(), // vary key PBR parameters on a grid of spheres to show the effect metallic_factor: y01.into(), roughness_factor: x01.into(), From f720ffc2eb79bc2a9e12dad3f4440130db3f5ae4 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Tue, 9 Mar 2021 11:17:47 +0100 Subject: [PATCH 35/58] Revert "Add PBR parameter newtypes/enums for CPU remapping" This reverts commit eaaa1723322190b963e61b8592541a4b60a92afd. --- crates/bevy_gltf/src/loader.rs | 4 +- crates/bevy_pbr/Cargo.toml | 1 - crates/bevy_pbr/src/lib.rs | 4 +- crates/bevy_pbr/src/material.rs | 12 +- crates/bevy_pbr/src/parameters.rs | 130 ------------------ .../forward_pipeline/forward.frag | 19 ++- examples/3d/pbr.rs | 6 +- 7 files changed, 25 insertions(+), 151 deletions(-) delete mode 100644 crates/bevy_pbr/src/parameters.rs diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index bee5b2aabfae2..8760daa8c2b03 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -279,8 +279,8 @@ fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle< LoadedAsset::new(StandardMaterial { base_color_factor: Color::rgba(color[0], color[1], color[2], color[3]), base_color_texture: texture_handle, - roughness_factor: pbr.roughness_factor().into(), - metallic_factor: pbr.metallic_factor().into(), + roughness_factor: pbr.roughness_factor(), + metallic_factor: pbr.metallic_factor(), unlit: material.unlit(), ..Default::default() }) diff --git a/crates/bevy_pbr/Cargo.toml b/crates/bevy_pbr/Cargo.toml index c13cb283055dd..8a09959024cb7 100644 --- a/crates/bevy_pbr/Cargo.toml +++ b/crates/bevy_pbr/Cargo.toml @@ -18,7 +18,6 @@ bevy_asset = { path = "../bevy_asset", version = "0.4.0" } bevy_core = { path = "../bevy_core", version = "0.4.0" } bevy_derive = { path = "../bevy_derive", version = "0.4.0" } bevy_ecs = { path = "../bevy_ecs", version = "0.4.0" } -bevy_log = { path = "../bevy_log", version = "0.4.0" } bevy_math = { path = "../bevy_math", version = "0.4.0" } bevy_reflect = { path = "../bevy_reflect", version = "0.4.0", features = ["bevy"] } bevy_render = { path = "../bevy_render", version = "0.4.0" } diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index 5bcab6cbced41..ad01adeb0426d 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -3,15 +3,13 @@ pub mod render_graph; mod entity; mod light; mod material; -mod parameters; pub use entity::*; pub use light::*; pub use material::*; -pub use parameters::*; pub mod prelude { - pub use crate::{entity::*, light::Light, material::StandardMaterial, parameters::*}; + pub use crate::{entity::*, light::Light, material::StandardMaterial}; } use bevy_app::prelude::*; diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index eb9ce77e28236..29a06f6df3fcc 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -2,8 +2,6 @@ use bevy_asset::{self, Handle}; use bevy_reflect::TypeUuid; use bevy_render::{color::Color, renderer::RenderResources, shader::ShaderDefs, texture::Texture}; -use crate::parameters::*; - /// 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)] @@ -15,9 +13,9 @@ pub struct StandardMaterial { pub base_color_texture: Option>, /// Linear perceptual roughness, clamped to [0.089, 1.0] in the shader /// Defaults to minimum of 0.089 - pub roughness_factor: Roughness, + pub roughness_factor: PerceptualRoughness, /// From [0.0, 1.0], dielectric to pure metallic - pub metallic_factor: Metallic, + pub metallic_factor: 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, @@ -32,13 +30,13 @@ impl Default for StandardMaterial { base_color_factor: Color::rgb(1.0, 1.0, 1.0), base_color_texture: None, // This is the minimum the roughness is clamped to in shader code - roughness_factor: 0.089.into(), + roughness_factor: 0.089, // Few materials are purely dielectric or metallic // This is just a default for mostly-dielectric - metallic_factor: 0.01.into(), + metallic_factor: 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.into(), + reflectance: 0.5, unlit: false, } } diff --git a/crates/bevy_pbr/src/parameters.rs b/crates/bevy_pbr/src/parameters.rs deleted file mode 100644 index 45c447e41c135..0000000000000 --- a/crates/bevy_pbr/src/parameters.rs +++ /dev/null @@ -1,130 +0,0 @@ -use bevy_asset::{self, Handle}; -use bevy_core::Bytes; -use bevy_log::warn; -use bevy_render::{ - impl_render_resource_bytes, - renderer::{RenderResource, RenderResourceType}, - texture::Texture, -}; - -const MIN_ROUGHNESS: f32 = 0.089; -const MAX_ROUGHNESS: f32 = 1.0; - -#[derive(Clone, Copy, Debug)] -pub enum Roughness { - PerceptualRoughness(f32), - Roughness(f32), -} - -impl Roughness { - pub fn perceptual_roughness(roughness: f32) -> Self { - if roughness < MIN_ROUGHNESS || roughness > MAX_ROUGHNESS { - warn!( - "Roughness value {} is not within range [{}, {}]", - roughness, MIN_ROUGHNESS, MAX_ROUGHNESS - ); - } - let perceptual_roughness = roughness.max(MIN_ROUGHNESS).min(MAX_ROUGHNESS); - - Self::PerceptualRoughness(perceptual_roughness) - } - - pub fn roughness(roughness: f32) -> Self { - if roughness < MIN_ROUGHNESS || roughness > MAX_ROUGHNESS { - warn!( - "Roughness value {} is not within range [{}, {}]", - roughness, MIN_ROUGHNESS, MAX_ROUGHNESS - ); - } - let roughness = roughness.max(MIN_ROUGHNESS).min(MAX_ROUGHNESS); - Self::Roughness(roughness) - } - - pub fn to_perceptual_roughness(self) -> f32 { - // See https://google.github.io/filament/Filament.html#materialsystem/parameterization/remapping - match self { - Roughness::PerceptualRoughness(roughness) => roughness, - Roughness::Roughness(roughness) => roughness.sqrt(), - } - } - - pub fn to_roughness(self) -> f32 { - // See https://google.github.io/filament/Filament.html#materialsystem/parameterization/remapping - match self { - Roughness::PerceptualRoughness(roughness) => roughness * roughness, - Roughness::Roughness(roughness) => roughness, - } - } -} - -impl From for Roughness { - fn from(roughness: f32) -> Self { - Self::perceptual_roughness(roughness) - } -} - -impl Bytes for Roughness { - fn write_bytes(&self, buffer: &mut [u8]) { - self.to_roughness().write_bytes(buffer); - } - - fn byte_len(&self) -> usize { - 0.byte_len() - } -} -impl_render_resource_bytes!(Roughness); - -#[derive(Copy, Clone, Debug)] -pub struct Metallic(f32); - -impl From for Metallic { - fn from(metallic: f32) -> Self { - if metallic < 0.0 || metallic > 1.0 { - warn!("Metallic value {} is not within range [0.0, 1.0]", metallic); - } - Self(metallic) - } -} - -impl Bytes for Metallic { - fn write_bytes(&self, buffer: &mut [u8]) { - self.0.write_bytes(buffer); - } - - fn byte_len(&self) -> usize { - self.0.byte_len() - } -} -impl_render_resource_bytes!(Metallic); - -pub struct Reflectance(f32); - -impl Reflectance { - fn remap(&self) -> f32 { - // See https://google.github.io/filament/Filament.html#materialsystem/parameterization/remapping - 0.16 * self.0 * self.0 - } -} - -impl From for Reflectance { - fn from(reflectance: f32) -> Self { - if reflectance < 0.0 || reflectance > 1.0 { - warn!( - "Reflectance value {} is not within range [0.0, 1.0]", - reflectance - ); - } - Self(reflectance) - } -} - -impl Bytes for Reflectance { - fn write_bytes(&self, buffer: &mut [u8]) { - self.remap().write_bytes(buffer); - } - - fn byte_len(&self) -> usize { - self.0.byte_len() - } -} -impl_render_resource_bytes!(Reflectance); diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 5e995314b573a..d99bf9a16b573 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -75,8 +75,7 @@ layout(set = 3, #ifndef STANDARDMATERIAL_UNLIT layout(set = 3, binding = 3) uniform StandardMaterial_roughness_factor { - // perceptual roughness is remapped to roughness on the CPU - float roughness; + float perceptual_roughness; }; layout(set = 3, binding = 4) uniform StandardMaterial_metallic_factor { @@ -84,7 +83,6 @@ layout(set = 3, binding = 4) uniform StandardMaterial_metallic_factor { }; layout(set = 3, binding = 5) uniform StandardMaterial_reflectance { - // reflectance is remapped on the CPU float reflectance; }; @@ -192,6 +190,14 @@ float Fd_Burley(float roughness, float NoV, float NoL, float LoH) { return lightScatter * viewScatter * (1.0 / PI); } +float perceptualRoughnessToRoughness(float perceptualRoughness) { + // clamp perceptual roughness to prevent precision problems + // According to Filament design 0.089 is recommended for mobile + // Filament uses 0.045 for non-mobile + float clampedPerceptualRoughness = clamp(perceptualRoughness, 0.089, 1.0); + return clampedPerceptualRoughness * clampedPerceptualRoughness; +} + // from https://64.github.io/tonemapping/ // reinhard on RGB oversaturates colors vec3 reinhard(vec3 color) { @@ -238,12 +244,15 @@ void main() { #endif #ifndef STANDARDMATERIAL_UNLIT + // calculate non-linear roughness from linear perceptualRoughness + float roughness = perceptualRoughnessToRoughness(perceptual_roughness); + vec3 N = normalize(v_Normal); vec3 V = normalize(CameraPos.xyz - w_Position.xyz); - // Reflectance is remapped before being passed to the GPU + // Remapping [0,1] reflectance to F0 // See https://google.github.io/filament/Filament.html#materialsystem/parameterization/remapping - vec3 F0 = reflectance * (1.0 - metallic) + output_color.rgb * metallic; + vec3 F0 = 0.16 * reflectance * reflectance * (1.0 - metallic) + output_color.rgb * metallic; // Diffuse strength inversely related to metallicity vec3 diffuseColor = output_color.rgb * (1.0 - metallic); diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index a5fcea68053a5..08925d2dce5d6 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -36,8 +36,8 @@ fn setup( material: materials.add(StandardMaterial { base_color_factor: Color::hex("ffd891").unwrap(), // vary key PBR parameters on a grid of spheres to show the effect - metallic_factor: y01.into(), - roughness_factor: x01.into(), + metallic_factor: y01, + roughness_factor: x01, ..Default::default() }), transform: Transform::from_xyz(x as f32, y as f32, 0.0), @@ -53,7 +53,7 @@ fn setup( intensity: 100.0, ..Default::default() }, - transform: Transform::from_translation(Vec3::new(0.0, 5.0, 5.0)), + transform: Transform::from_translation(Vec3::new(0.0, 10.0, 10.0)), ..Default::default() }) // camera From 85a695e4928ac1f8361fbbefcd4b3f1569982625 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Tue, 9 Mar 2021 11:25:20 +0100 Subject: [PATCH 36/58] Add comment about not using mix --- crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index d99bf9a16b573..11c481050574e 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -141,10 +141,12 @@ float V_SmithGGXCorrelated(float roughness, float NoV, float NoL) { // see https://google.github.io/filament/Filament.html#citation-schlick94 // F_Schlick(v,h,f_0,f_90) = f_0 + (f_90 − f_0) (1 − v⋅h)^5 vec3 F_Schlick(const vec3 f0, float f90, float VoH) { + // not using mix to keep the vec3 and float versions identical return f0 + (f90 - f0) * pow5(1.0 - VoH); } float F_Schlick(float f0, float f90, float VoH) { + // not using mix to keep the vec3 and float versions identical return f0 + (f90 - f0) * pow5(1.0 - VoH); } From 79a4d0aa8b781824d6dbfc7f91488b78b800141b Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Tue, 9 Mar 2021 13:45:29 +0100 Subject: [PATCH 37/58] Fix bad commit --- crates/bevy_pbr/src/material.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 29a06f6df3fcc..675179e5e7c0c 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -13,7 +13,7 @@ pub struct StandardMaterial { pub base_color_texture: Option>, /// Linear perceptual roughness, clamped to [0.089, 1.0] in the shader /// Defaults to minimum of 0.089 - pub roughness_factor: PerceptualRoughness, + pub roughness_factor: f32, /// From [0.0, 1.0], dielectric to pure metallic pub metallic_factor: f32, /// Specular intensity for non-metals on a linear scale of [0.0, 1.0] From c57e56d58a07fa4af9296294735f70a28d6b9131 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Tue, 9 Mar 2021 13:46:03 +0100 Subject: [PATCH 38/58] Hoist NdotV out of light loop --- .../bevy_pbr/src/render_graph/forward_pipeline/forward.frag | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 11c481050574e..4fca5e7bf4d9c 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -251,6 +251,8 @@ void main() { vec3 N = normalize(v_Normal); vec3 V = normalize(CameraPos.xyz - w_Position.xyz); + // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886" + float NdotV = max(dot(N, V), 1e-4); // Remapping [0,1] reflectance to F0 // See https://google.github.io/filament/Filament.html#materialsystem/parameterization/remapping @@ -271,10 +273,6 @@ void main() { getDistanceAttenuation(lightDir, light.inverseRadiusSquared); vec3 H = normalize(L + V); - - // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886" - float NdotV = max(dot(N, V), 1e-4); - float NoL = saturate(dot(N, L)); float NoH = saturate(dot(N, H)); float LoH = saturate(dot(L, H)); From 4b358bacc5dd4340505900920bf87012404842b6 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Tue, 9 Mar 2021 13:46:39 +0100 Subject: [PATCH 39/58] Move light closer in pbr example --- examples/3d/pbr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index 08925d2dce5d6..8fdad522926df 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -53,7 +53,7 @@ fn setup( intensity: 100.0, ..Default::default() }, - transform: Transform::from_translation(Vec3::new(0.0, 10.0, 10.0)), + transform: Transform::from_translation(Vec3::new(0.0, 5.0, 5.0)), ..Default::default() }) // camera From fdc07ab0a7f82634ddf7bdd2d806c2b2d78ad792 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Tue, 9 Mar 2021 20:09:50 +0100 Subject: [PATCH 40/58] Better ambient term --- .../render_graph/forward_pipeline/forward.frag | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 4fca5e7bf4d9c..83c1b1565b292 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -192,6 +192,16 @@ float Fd_Burley(float roughness, float NoV, float NoL, float LoH) { return lightScatter * viewScatter * (1.0 / PI); } +// From https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile +vec3 EnvBRDFApprox(vec3 f0, float perceptual_roughness, float NoV) { + const vec4 c0 = { -1, -0.0275, -0.572, 0.022 }; + const vec4 c1 = { 1, 0.0425, 1.04, -0.04 }; + vec4 r = perceptual_roughness * c0 + c1; + float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y; + vec2 AB = vec2(-1.04, 1.04) * a004 + r.zw; + return f0 * AB.x + AB.y; +} + float perceptualRoughnessToRoughness(float perceptualRoughness) { // clamp perceptual roughness to prevent precision problems // According to Filament design 0.089 is recommended for mobile @@ -294,7 +304,10 @@ void main() { ((diffuse + specular) * light.color.rgb) * (light.intensity * rangeAttenuation * NoL); } - output_color.rgb = light_accum + output_color.rgb * AmbientColor; + vec3 diffuse_ambient = EnvBRDFApprox(diffuseColor, 1.0, NdotV); + vec3 specular_ambient = EnvBRDFApprox(F0, perceptual_roughness, NdotV); + + output_color.rgb = light_accum + (diffuse_ambient + specular_ambient) * AmbientColor; // tone_mapping output_color.rgb = reinhard_luminance(output_color.rgb); From aaafa67a1af51d679a1aa31670c0e2987012ca46 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Tue, 9 Mar 2021 20:14:06 +0100 Subject: [PATCH 41/58] Remove unused imports --- examples/3d/pbr.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index 8fdad522926df..adad654ea27d9 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -1,10 +1,4 @@ -use bevy::{ - prelude::*, - render::{ - pipeline::{PipelineDescriptor, RenderPipeline, RenderPipelines}, - shader::ShaderStages, - }, -}; +use bevy::prelude::*; /// This example shows how to configure Physically Based Rendering (PBR) parameters. fn main() { From 39c6b28e281e684457c88890d91245151b00e571 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Tue, 9 Mar 2021 20:27:33 +0100 Subject: [PATCH 42/58] Remove unused import --- crates/bevy_render/src/render_graph/nodes/camera_node.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/render_graph/nodes/camera_node.rs b/crates/bevy_render/src/render_graph/nodes/camera_node.rs index 82dfa3f2d5ad4..fdf2c021e6c20 100644 --- a/crates/bevy_render/src/render_graph/nodes/camera_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/camera_node.rs @@ -6,7 +6,7 @@ use crate::{ RenderResourceContext, }, }; -use bevy_core::{AsBytes, Bytes}; +use bevy_core::AsBytes; use bevy_ecs::{ system::{BoxedSystem, IntoSystem, Local, Query, Res, ResMut}, world::World, From c3d10857f3aaca40c02591428c13fca489f6586b Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Wed, 10 Mar 2021 07:59:54 +0100 Subject: [PATCH 43/58] Fix failing test --- crates/bevy_render/src/shader/shader_reflect.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index 8ee086a779b2e..e35d339ee20a1 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -379,7 +379,10 @@ mod tests { name: "CameraViewProj".into(), bind_type: BindType::Uniform { has_dynamic_offset: false, - property: UniformProperty::Struct(vec![UniformProperty::Mat4]), + property: UniformProperty::Struct(vec![ + UniformProperty::Mat4, + UniformProperty::Vec4 + ]), }, shader_stage: BindingShaderStage::VERTEX, }] From 0eb6a1b59ba81f1d40107d8b2c8508110bf4629d Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Wed, 10 Mar 2021 08:03:15 +0100 Subject: [PATCH 44/58] Premultiply light color by intensity --- crates/bevy_pbr/src/light.rs | 5 +++-- .../bevy_pbr/src/render_graph/forward_pipeline/forward.frag | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index 545af3ac4667e..dbc910b9c4c2e 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -53,8 +53,9 @@ impl LightRaw { let proj = perspective.get_projection_matrix() * global_transform.compute_matrix(); let (x, y, z) = global_transform.translation.into(); - let mut color: [f32; 4] = light.color.into(); - color[3] = light.intensity; + // 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 / (light.range * light.range)], // pos.w is the attenuation. diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 83c1b1565b292..30b5bc6bf943b 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -41,7 +41,7 @@ struct Light { vec3 pos; float inverseRadiusSquared; vec3 color; - float intensity; + // float unused; // unused 4th element of vec4; }; layout(location = 0) in vec3 v_Position; @@ -300,8 +300,9 @@ void main() { // See https://google.github.io/filament/Filament.html#mjx-eqn-pointLightLuminanceEquation // TODO compensate for energy loss https://google.github.io/filament/Filament.html#materialsystem/improvingthebrdfs/energylossinspecularreflectance + // light.color.rgb is premultiplied with light.intensity on the CPU light_accum += - ((diffuse + specular) * light.color.rgb) * (light.intensity * rangeAttenuation * NoL); + ((diffuse + specular) * light.color.rgb) * (rangeAttenuation * NoL); } vec3 diffuse_ambient = EnvBRDFApprox(diffuseColor, 1.0, NdotV); From 2dad217a310d3d20f8952eeebb4a3804057b2b88 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Wed, 10 Mar 2021 08:44:02 +0100 Subject: [PATCH 45/58] Calculate buffer_size once --- .../src/render_graph/nodes/camera_node.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/crates/bevy_render/src/render_graph/nodes/camera_node.rs b/crates/bevy_render/src/render_graph/nodes/camera_node.rs index fdf2c021e6c20..bacbe2a599b57 100644 --- a/crates/bevy_render/src/render_graph/nodes/camera_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/camera_node.rs @@ -6,7 +6,7 @@ use crate::{ RenderResourceContext, }, }; -use bevy_core::AsBytes; +use bevy_core::{AsBytes, Bytes}; use bevy_ecs::{ system::{BoxedSystem, IntoSystem, Local, Query, Res, ResMut}, world::World, @@ -88,6 +88,16 @@ pub fn camera_node_system( return; }; + let camera_pos = &[ + global_transform.translation.x, + global_transform.translation.y, + global_transform.translation.z, + 1.0, + ]; + let camera_matrix_array = + (camera.projection_matrix * global_transform.compute_matrix().inverse()).to_cols_array(); + let buffer_size = camera_pos.byte_len() + camera_matrix_array.byte_len(); + let staging_buffer = if let Some(staging_buffer) = state.staging_buffer { render_resource_context.map_buffer(staging_buffer, BufferMapMode::Write); staging_buffer From ca2b45a133f686081f8d03ddcf3633fee98ed035 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Wed, 10 Mar 2021 16:48:37 +0100 Subject: [PATCH 46/58] Extend default light range, simplifying examples --- crates/bevy_pbr/src/light.rs | 2 +- examples/3d/3d_scene.rs | 4 ---- examples/3d/msaa.rs | 4 ---- examples/3d/orthographic.rs | 4 ---- examples/3d/pbr.rs | 5 ----- examples/3d/wireframe.rs | 4 ---- examples/game/alien_cake_addict.rs | 4 ---- 7 files changed, 1 insertion(+), 26 deletions(-) diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index dbc910b9c4c2e..7f1e7219545d9 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -26,7 +26,7 @@ impl Default for Light { depth: 0.1..50.0, fov: f32::to_radians(60.0), intensity: 100.0, - range: 10.0, + range: 20.0, } } } diff --git a/examples/3d/3d_scene.rs b/examples/3d/3d_scene.rs index d49c22cd065dd..0e113775ae821 100644 --- a/examples/3d/3d_scene.rs +++ b/examples/3d/3d_scene.rs @@ -32,10 +32,6 @@ fn setup( // light .spawn(LightBundle { transform: Transform::from_xyz(4.0, 8.0, 4.0), - light: Light { - range: 20.0, - ..Default::default() - }, ..Default::default() }) // camera diff --git a/examples/3d/msaa.rs b/examples/3d/msaa.rs index 47cb09a93539b..d4c5c5ea92c0c 100644 --- a/examples/3d/msaa.rs +++ b/examples/3d/msaa.rs @@ -29,10 +29,6 @@ fn setup( // light .spawn(LightBundle { transform: Transform::from_xyz(4.0, 8.0, 4.0), - light: Light { - range: 20.0, - ..Default::default() - }, ..Default::default() }) // camera diff --git a/examples/3d/orthographic.rs b/examples/3d/orthographic.rs index 56d1e7784f7ac..caaaf42a16bf4 100644 --- a/examples/3d/orthographic.rs +++ b/examples/3d/orthographic.rs @@ -55,10 +55,6 @@ fn setup( // light .spawn(LightBundle { transform: Transform::from_xyz(3.0, 8.0, 5.0), - light: Light { - range: 20.0, - ..Default::default() - }, ..Default::default() }) // camera diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index adad654ea27d9..96cb6d7b8b1af 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -42,11 +42,6 @@ fn setup( commands // light .spawn(LightBundle { - light: Light { - range: 20.0, - intensity: 100.0, - ..Default::default() - }, transform: Transform::from_translation(Vec3::new(0.0, 5.0, 5.0)), ..Default::default() }) diff --git a/examples/3d/wireframe.rs b/examples/3d/wireframe.rs index 57bb7f219a33f..47998572a0358 100644 --- a/examples/3d/wireframe.rs +++ b/examples/3d/wireframe.rs @@ -48,10 +48,6 @@ fn setup( // light .spawn(LightBundle { transform: Transform::from_xyz(4.0, 8.0, 4.0), - light: Light { - range: 20.0, - ..Default::default() - }, ..Default::default() }) // camera diff --git a/examples/game/alien_cake_addict.rs b/examples/game/alien_cake_addict.rs index e9875a85ca63d..dc7213bbdce42 100644 --- a/examples/game/alien_cake_addict.rs +++ b/examples/game/alien_cake_addict.rs @@ -107,10 +107,6 @@ fn setup(mut commands: Commands, asset_server: Res, mut game: ResMu commands.spawn(LightBundle { transform: Transform::from_xyz(4.0, 5.0, 4.0), - light: Light { - range: 20.0, - ..Default::default() - }, ..Default::default() }); From 98263712e357c52387cd4fc2f805ee759e7576b6 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Thu, 11 Mar 2021 10:01:52 +0100 Subject: [PATCH 47/58] Added additional comment to roughness default --- crates/bevy_pbr/src/material.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 675179e5e7c0c..03d728f17ceee 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -30,6 +30,9 @@ impl Default for StandardMaterial { base_color_factor: 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_factor: 0.089, // Few materials are purely dielectric or metallic // This is just a default for mostly-dielectric From 25b14dcf375ebac0670599dea0646d91e1974ca7 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Fri, 12 Mar 2021 09:22:01 +0100 Subject: [PATCH 48/58] Remove `_factor` from StandardMaterial properties --- crates/bevy_gltf/src/loader.rs | 6 +++--- crates/bevy_pbr/src/lib.rs | 2 +- crates/bevy_pbr/src/material.rs | 20 ++++++++++++------- .../forward_pipeline/forward.frag | 10 +++++----- examples/3d/parenting.rs | 2 +- examples/3d/pbr.rs | 6 +++--- examples/3d/spawner.rs | 4 ++-- examples/3d/texture.rs | 4 ++-- examples/3d/z_sort_debug.rs | 2 +- examples/asset/asset_loading.rs | 2 +- 10 files changed, 32 insertions(+), 26 deletions(-) diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 8760daa8c2b03..7f7b6a71a08d7 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -277,10 +277,10 @@ fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle< load_context.set_labeled_asset( &material_label, LoadedAsset::new(StandardMaterial { - base_color_factor: Color::rgba(color[0], color[1], color[2], color[3]), + base_color: Color::rgba(color[0], color[1], color[2], color[3]), base_color_texture: texture_handle, - roughness_factor: pbr.roughness_factor(), - metallic_factor: pbr.metallic_factor(), + roughness: pbr.roughness_factor(), + metallic: pbr.metallic_factor(), unlit: material.unlit(), ..Default::default() }) diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index ad01adeb0426d..cb130ab9d9a8f 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -42,7 +42,7 @@ impl Plugin for PbrPlugin { materials.set_untracked( Handle::::default(), StandardMaterial { - base_color_factor: Color::PINK, + base_color: Color::PINK, unlit: true, ..Default::default() }, diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 03d728f17ceee..7ccf32b8f6783 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -8,14 +8,20 @@ use bevy_render::{color::Color, renderer::RenderResources, shader::ShaderDefs, t #[uuid = "dace545e-4bc6-4595-a79d-c224fc694975"] pub struct StandardMaterial { /// Doubles as diffuse albedo for non-metallic, specular for metallic and a mix for everything in between - pub base_color_factor: Color, + /// 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 base_color_texture: Option>, /// Linear perceptual roughness, clamped to [0.089, 1.0] in the shader /// Defaults to minimum of 0.089 - pub roughness_factor: f32, + /// 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 - pub metallic_factor: f32, + /// 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, @@ -27,16 +33,16 @@ pub struct StandardMaterial { impl Default for StandardMaterial { fn default() -> Self { StandardMaterial { - base_color_factor: Color::rgb(1.0, 1.0, 1.0), + 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_factor: 0.089, + roughness: 0.089, // Few materials are purely dielectric or metallic // This is just a default for mostly-dielectric - metallic_factor: 0.01, + 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, @@ -48,7 +54,7 @@ impl Default for StandardMaterial { impl From for StandardMaterial { fn from(color: Color) -> Self { StandardMaterial { - base_color_factor: color, + base_color: color, ..Default::default() } } diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 30b5bc6bf943b..050a791e01be8 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -62,8 +62,8 @@ layout(set = 1, binding = 0) uniform Lights { Light SceneLights[MAX_LIGHTS]; }; -layout(set = 3, binding = 0) uniform StandardMaterial_base_color_factor { - vec4 base_color_factor; +layout(set = 3, binding = 0) uniform StandardMaterial_base_color { + vec4 base_color; }; #ifdef STANDARDMATERIAL_BASE_COLOR_TEXTURE @@ -74,11 +74,11 @@ layout(set = 3, #ifndef STANDARDMATERIAL_UNLIT -layout(set = 3, binding = 3) uniform StandardMaterial_roughness_factor { +layout(set = 3, binding = 3) uniform StandardMaterial_roughness { float perceptual_roughness; }; -layout(set = 3, binding = 4) uniform StandardMaterial_metallic_factor { +layout(set = 3, binding = 4) uniform StandardMaterial_metallic { float metallic; }; @@ -248,7 +248,7 @@ vec3 reinhard_extended_luminance(vec3 color, float max_white_l) { #endif void main() { - vec4 output_color = base_color_factor; + vec4 output_color = base_color; #ifdef STANDARDMATERIAL_BASE_COLOR_TEXTURE output_color *= texture(sampler2D(StandardMaterial_base_color_texture, StandardMaterial_base_color_texture_sampler), diff --git a/examples/3d/parenting.rs b/examples/3d/parenting.rs index 589d38c841fde..42f6c7b224ab5 100644 --- a/examples/3d/parenting.rs +++ b/examples/3d/parenting.rs @@ -29,7 +29,7 @@ fn setup( ) { let cube_handle = meshes.add(Mesh::from(shape::Cube { size: 2.0 })); let cube_material_handle = materials.add(StandardMaterial { - base_color_factor: Color::rgb(0.8, 0.7, 0.6), + base_color: Color::rgb(0.8, 0.7, 0.6), ..Default::default() }); diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index 96cb6d7b8b1af..7154c0b4893ed 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -28,10 +28,10 @@ fn setup( subdivisions: 32, })), material: materials.add(StandardMaterial { - base_color_factor: Color::hex("ffd891").unwrap(), + base_color: Color::hex("ffd891").unwrap(), // vary key PBR parameters on a grid of spheres to show the effect - metallic_factor: y01, - roughness_factor: x01, + metallic: y01, + roughness: x01, ..Default::default() }), transform: Transform::from_xyz(x as f32, y as f32, 0.0), diff --git a/examples/3d/spawner.rs b/examples/3d/spawner.rs index d300b7ce802f7..6423207847818 100644 --- a/examples/3d/spawner.rs +++ b/examples/3d/spawner.rs @@ -30,7 +30,7 @@ fn move_cubes( for (mut transform, material_handle) in query.iter_mut() { let material = materials.get_mut(material_handle).unwrap(); transform.translation += Vec3::new(1.0, 0.0, 0.0) * time.delta_seconds(); - material.base_color_factor = + material.base_color = Color::BLUE * Vec3::splat((3.0 * time.seconds_since_startup() as f32).sin()); } } @@ -58,7 +58,7 @@ fn setup( commands.spawn(PbrBundle { mesh: cube_handle.clone(), material: materials.add(StandardMaterial { - base_color_factor: Color::rgb( + base_color: Color::rgb( rng.gen_range(0.0..1.0), rng.gen_range(0.0..1.0), rng.gen_range(0.0..1.0), diff --git a/examples/3d/texture.rs b/examples/3d/texture.rs index 39900a660cf97..b59b3aa3240d7 100644 --- a/examples/3d/texture.rs +++ b/examples/3d/texture.rs @@ -35,7 +35,7 @@ fn setup( // this material modulates the texture to make it red (and slightly transparent) let red_material_handle = materials.add(StandardMaterial { - base_color_factor: Color::rgba(1.0, 0.0, 0.0, 0.5), + base_color: Color::rgba(1.0, 0.0, 0.0, 0.5), base_color_texture: Some(texture_handle.clone()), unlit: true, ..Default::default() @@ -43,7 +43,7 @@ fn setup( // and lets make this one blue! (and also slightly transparent) let blue_material_handle = materials.add(StandardMaterial { - base_color_factor: Color::rgba(0.0, 0.0, 1.0, 0.5), + base_color: Color::rgba(0.0, 0.0, 1.0, 0.5), base_color_texture: Some(texture_handle), unlit: true, ..Default::default() diff --git a/examples/3d/z_sort_debug.rs b/examples/3d/z_sort_debug.rs index a83e3db683a31..5d972504e3232 100644 --- a/examples/3d/z_sort_debug.rs +++ b/examples/3d/z_sort_debug.rs @@ -36,7 +36,7 @@ fn camera_order_color_system( if let Ok(material_handle) = material_query.get(visible_entity.entity) { let material = materials.get_mut(&*material_handle).unwrap(); let value = 1.0 - (visible_entity.order.0.sqrt() - 10.0) / 7.0; - material.base_color_factor = Color::rgb(value, value, value); + material.base_color = Color::rgb(value, value, value); } } } diff --git a/examples/asset/asset_loading.rs b/examples/asset/asset_loading.rs index 0d48b1c199894..2eac853d69c3e 100644 --- a/examples/asset/asset_loading.rs +++ b/examples/asset/asset_loading.rs @@ -39,7 +39,7 @@ fn setup( // You can also add assets directly to their Assets storage: let material_handle = materials.add(StandardMaterial { - base_color_factor: Color::rgb(0.8, 0.7, 0.6), + base_color: Color::rgb(0.8, 0.7, 0.6), ..Default::default() }); From 23bd4b345f96cd78cfd799d51abe60fa4e4d0bc5 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Fri, 12 Mar 2021 09:23:51 +0100 Subject: [PATCH 49/58] Remove .clang-format --- .clang-format | 76 --------------------------------------------------- 1 file changed, 76 deletions(-) delete mode 100644 .clang-format diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 88a592eb698c3..0000000000000 --- a/.clang-format +++ /dev/null @@ -1,76 +0,0 @@ -# From https://gist.github.com/Astro36/ef933be73050b4d5a6e0522536723a18 -AccessModifierOffset: -4 -AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false -# AlignConsecutiveMacros: false -AlignEscapedNewlines: DontAlign -AlignOperands: true -AlignTrailingComments: false -# AllowAllArgumentsOnNextLine: false -# AllowAllConstructorInitializersOnNextLine: false -AllowAllParametersOfDeclarationOnNextLine: false -# AllowShortBlocksOnASingleLine: Empty -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: Empty -# AllowShortIfStatementsOnASingleLine: Always -# AllowShortLambdasOnASingleLine: All -AllowShortLoopsOnASingleLine: true -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -# AlwaysBreakTemplateDeclarations: Yes -BinPackArguments: true -BinPackParameters: true -BreakBeforeBinaryOperators: NonAssignment -BreakBeforeBraces: Attach -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: BeforeColon -# BreakInheritanceList: BeforeColon -BreakStringLiterals: false -ColumnLimit: 0 -CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 0 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: false -DerivePointerAlignment: false -ExperimentalAutoDetectBinPacking: false -FixNamespaceComments: true -IncludeBlocks: Merge -IncludeCategories: - - Regex: '^<.*\.h>' - Priority: 1 - - Regex: "^<.*" - Priority: 2 - - Regex: ".*" - Priority: 3 -IndentCaseLabels: false -# IndentGotoLabels: false -IndentPPDirectives: AfterHash -IndentWidth: 4 -IndentWrappedFunctionNames: true -KeepEmptyLinesAtTheStartOfBlocks: false -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: All -PointerAlignment: Left -SortIncludes: true -SortUsingDeclarations: true -SpaceAfterCStyleCast: true -# SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: false -SpaceBeforeAssignmentOperators: true -# SpaceBeforeCpp11BracedList: true -# SpaceBeforeCtorInitializerColon: false -# SpaceBeforeInheritanceColon: false -SpaceBeforeParens: ControlStatements -# SpaceBeforeRangeBasedForLoopColon: true -# SpaceInEmptyBlock: false -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInCStyleCastParentheses: false -SpacesInContainerLiterals: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -# Standard: Latest -UseTab: Never From 1666f45b51cf10144d1a074e0168ba90dd589955 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Fri, 12 Mar 2021 09:31:47 +0100 Subject: [PATCH 50/58] Remove `forward` in pipeline naming --- crates/bevy_pbr/src/entity.rs | 4 ++-- crates/bevy_pbr/src/render_graph/mod.rs | 9 ++++----- .../render_graph/{forward_pipeline => pipeline}/mod.rs | 8 ++++---- .../{forward_pipeline/forward.frag => pipeline/pbr.frag} | 0 .../{forward_pipeline/forward.vert => pipeline/pbr.vert} | 0 5 files changed, 10 insertions(+), 11 deletions(-) rename crates/bevy_pbr/src/render_graph/{forward_pipeline => pipeline}/mod.rs (89%) rename crates/bevy_pbr/src/render_graph/{forward_pipeline/forward.frag => pipeline/pbr.frag} (100%) rename crates/bevy_pbr/src/render_graph/{forward_pipeline/forward.vert => pipeline/pbr.vert} (100%) diff --git a/crates/bevy_pbr/src/entity.rs b/crates/bevy_pbr/src/entity.rs index d03b0d89cf988..89c0a830c2eb3 100644 --- a/crates/bevy_pbr/src/entity.rs +++ b/crates/bevy_pbr/src/entity.rs @@ -1,4 +1,4 @@ -use crate::{light::Light, material::StandardMaterial, render_graph::FORWARD_PIPELINE_HANDLE}; +use crate::{light::Light, material::StandardMaterial, render_graph::PIPELINE_HANDLE}; use bevy_asset::Handle; use bevy_ecs::bundle::Bundle; use bevy_render::{ @@ -27,7 +27,7 @@ impl Default for PbrBundle { fn default() -> Self { Self { render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new( - FORWARD_PIPELINE_HANDLE.typed(), + PIPELINE_HANDLE.typed(), )]), mesh: Default::default(), visible: Default::default(), diff --git a/crates/bevy_pbr/src/render_graph/mod.rs b/crates/bevy_pbr/src/render_graph/mod.rs index 5eccb6799fc2e..7871555ce8c3d 100644 --- a/crates/bevy_pbr/src/render_graph/mod.rs +++ b/crates/bevy_pbr/src/render_graph/mod.rs @@ -1,9 +1,9 @@ -mod forward_pipeline; mod lights_node; +mod pipeline; use bevy_ecs::world::World; -pub use forward_pipeline::*; pub use lights_node::*; +pub use pipeline::*; /// the names of pbr graph nodes pub mod node { @@ -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::>().unwrap()); + let pipeline = build_pipeline(&mut world.get_resource_mut::>().unwrap()); let mut pipelines = world .get_resource_mut::>() .unwrap(); - pipelines.set_untracked(FORWARD_PIPELINE_HANDLE, forward_pipeline); + pipelines.set_untracked(PIPELINE_HANDLE, pipeline); } diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/mod.rs b/crates/bevy_pbr/src/render_graph/pipeline/mod.rs similarity index 89% rename from crates/bevy_pbr/src/render_graph/forward_pipeline/mod.rs rename to crates/bevy_pbr/src/render_graph/pipeline/mod.rs index f8f606ae0dcdf..19aaaec9a2fc5 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/mod.rs +++ b/crates/bevy_pbr/src/render_graph/pipeline/mod.rs @@ -9,10 +9,10 @@ use bevy_render::{ texture::TextureFormat, }; -pub const FORWARD_PIPELINE_HANDLE: HandleUntyped = +pub const PIPELINE_HANDLE: HandleUntyped = HandleUntyped::weak_from_u64(PipelineDescriptor::TYPE_UUID, 13148362314012771389); -pub(crate) fn build_forward_pipeline(shaders: &mut Assets) -> PipelineDescriptor { +pub(crate) fn build_pipeline(shaders: &mut Assets) -> PipelineDescriptor { PipelineDescriptor { depth_stencil: Some(DepthStencilState { format: TextureFormat::Depth32Float, @@ -48,11 +48,11 @@ pub(crate) fn build_forward_pipeline(shaders: &mut Assets) -> 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"), ))), }) } diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag similarity index 100% rename from crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag rename to crates/bevy_pbr/src/render_graph/pipeline/pbr.frag diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert b/crates/bevy_pbr/src/render_graph/pipeline/pbr.vert similarity index 100% rename from crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert rename to crates/bevy_pbr/src/render_graph/pipeline/pbr.vert From 97d034a9659eaadb3541bd9e1bdf56f69d34f82c Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Fri, 12 Mar 2021 09:55:41 +0100 Subject: [PATCH 51/58] Clear and consistent input/output naming --- crates/bevy_pbr/src/render_graph/pipeline/pbr.frag | 11 ++++++----- crates/bevy_pbr/src/render_graph/pipeline/pbr.vert | 8 ++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag b/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag index 050a791e01be8..56aaaf8c2cf6f 100644 --- a/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag +++ b/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag @@ -45,9 +45,9 @@ struct Light { }; layout(location = 0) in vec3 v_Position; -layout(location = 1) in vec3 v_Normal; +layout(location = 1) in vec3 v_WorldNormal; layout(location = 2) in vec2 v_Uv; -layout(location = 3) in vec3 w_Position; +layout(location = 3) in vec3 v_WorldPosition; layout(location = 0) out vec4 o_Target; @@ -259,8 +259,9 @@ void main() { // calculate non-linear roughness from linear perceptualRoughness float roughness = perceptualRoughnessToRoughness(perceptual_roughness); - vec3 N = normalize(v_Normal); - vec3 V = normalize(CameraPos.xyz - w_Position.xyz); + vec3 N = normalize(v_WorldNormal); + + vec3 V = normalize(CameraPos.xyz - v_WorldPosition.xyz); // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886" float NdotV = max(dot(N, V), 1e-4); @@ -276,7 +277,7 @@ void main() { for (int i = 0; i < int(NumLights.x) && i < MAX_LIGHTS; ++i) { Light light = SceneLights[i]; - vec3 lightDir = light.pos.xyz - w_Position.xyz; + vec3 lightDir = light.pos.xyz - v_WorldPosition.xyz; vec3 L = normalize(lightDir); float rangeAttenuation = diff --git a/crates/bevy_pbr/src/render_graph/pipeline/pbr.vert b/crates/bevy_pbr/src/render_graph/pipeline/pbr.vert index b3e344b801109..b2bb3882d49b3 100644 --- a/crates/bevy_pbr/src/render_graph/pipeline/pbr.vert +++ b/crates/bevy_pbr/src/render_graph/pipeline/pbr.vert @@ -5,9 +5,9 @@ layout(location = 1) in vec3 Vertex_Normal; layout(location = 2) in vec2 Vertex_Uv; layout(location = 0) out vec3 v_Position; -layout(location = 1) out vec3 v_Normal; +layout(location = 1) out vec3 v_WorldNormal; layout(location = 2) out vec2 v_Uv; -layout(location = 3) out vec3 w_Position; +layout(location = 3) out vec3 v_WorldPosition; layout(set = 0, binding = 0) uniform CameraViewProj { mat4 ViewProj; @@ -19,9 +19,9 @@ layout(set = 2, binding = 0) uniform Transform { }; void main() { - v_Normal = mat3(Model) * Vertex_Normal; v_Position = Vertex_Position; - w_Position = (Model * vec4(Vertex_Position, 1.0)).xyz; + v_WorldNormal = mat3(Model) * Vertex_Normal; v_Uv = Vertex_Uv; + v_WorldPosition = (Model * vec4(Vertex_Position, 1.0)).xyz; gl_Position = ViewProj * Model * vec4(v_Position, 1.0); } From f623307eee371e86f31e7b2ad63f2214f79a8f9a Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sat, 13 Mar 2021 08:42:17 +0100 Subject: [PATCH 52/58] Add PBR example to example README.md --- examples/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/README.md b/examples/README.md index 0fe69bfa5d5c0..f1df0b3d2f4a2 100644 --- a/examples/README.md +++ b/examples/README.md @@ -87,6 +87,7 @@ Example | File | Description `msaa` | [`3d/msaa.rs`](./3d/msaa.rs) | Configures MSAA (Multi-Sample Anti-Aliasing) for smoother edges `orthographic` | [`3d/orthographic.rs`](./3d/orthographic.rs) | Shows how to create a 3D orthographic view (for isometric-look games or CAD applications) `parenting` | [`3d/parenting.rs`](./3d/parenting.rs) | Demonstrates parent->child relationships and relative transformations +`pbr` | [`3d/pbr.rs`](./3d/[pbr].rs) | Demonstrates PBR properties Roughness/Metallic `spawner` | [`3d/spawner.rs`](./3d/spawner.rs) | Renders a large number of cubes with changing position and material `texture` | [`3d/texture.rs`](./3d/texture.rs) | Shows configuration of texture materials `update_gltf_scene` | [`3d/update_gltf_scene.rs`](./3d/update_gltf_scene.rs) | Update a scene from a gltf file, either by spawning the scene as a child of another entity, or by accessing the entities of the scene From 20984af99fe9cdfd95df50f4181bdf04dc9061e1 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Sat, 13 Mar 2021 08:51:35 +0100 Subject: [PATCH 53/58] Remove unused v_Position and clean up --- crates/bevy_pbr/src/render_graph/pipeline/pbr.frag | 3 +-- crates/bevy_pbr/src/render_graph/pipeline/pbr.vert | 9 ++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag b/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag index 56aaaf8c2cf6f..7fed3a0ccd641 100644 --- a/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag +++ b/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag @@ -44,10 +44,9 @@ struct Light { // float unused; // unused 4th element of vec4; }; -layout(location = 0) in vec3 v_Position; +layout(location = 0) in vec3 v_WorldPosition; layout(location = 1) in vec3 v_WorldNormal; layout(location = 2) in vec2 v_Uv; -layout(location = 3) in vec3 v_WorldPosition; layout(location = 0) out vec4 o_Target; diff --git a/crates/bevy_pbr/src/render_graph/pipeline/pbr.vert b/crates/bevy_pbr/src/render_graph/pipeline/pbr.vert index b2bb3882d49b3..d7e75d3438196 100644 --- a/crates/bevy_pbr/src/render_graph/pipeline/pbr.vert +++ b/crates/bevy_pbr/src/render_graph/pipeline/pbr.vert @@ -4,10 +4,9 @@ layout(location = 0) in vec3 Vertex_Position; layout(location = 1) in vec3 Vertex_Normal; layout(location = 2) in vec2 Vertex_Uv; -layout(location = 0) out vec3 v_Position; +layout(location = 0) out vec3 v_WorldPosition; layout(location = 1) out vec3 v_WorldNormal; layout(location = 2) out vec2 v_Uv; -layout(location = 3) out vec3 v_WorldPosition; layout(set = 0, binding = 0) uniform CameraViewProj { mat4 ViewProj; @@ -19,9 +18,9 @@ layout(set = 2, binding = 0) uniform Transform { }; void main() { - v_Position = Vertex_Position; + vec4 world_position = Model * vec4(Vertex_Position, 1.0); + v_WorldPosition = world_position.xyz; v_WorldNormal = mat3(Model) * Vertex_Normal; v_Uv = Vertex_Uv; - v_WorldPosition = (Model * vec4(Vertex_Position, 1.0)).xyz; - gl_Position = ViewProj * Model * vec4(v_Position, 1.0); + gl_Position = ViewProj * world_position; } From 9cbb8113a5603e3d489999773925ba90699fef09 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Tue, 16 Mar 2021 08:53:41 +0100 Subject: [PATCH 54/58] Remove comment about 'aspirational' name pbr --- crates/bevy_internal/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_internal/src/lib.rs b/crates/bevy_internal/src/lib.rs index 331a5e90ab256..62fb7cf270b56 100644 --- a/crates/bevy_internal/src/lib.rs +++ b/crates/bevy_internal/src/lib.rs @@ -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::*; } From 36d560817733368ada63b9506af3702bb2ebcbf5 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Tue, 16 Mar 2021 08:55:20 +0100 Subject: [PATCH 55/58] Uncomment `//unused float` in pbr.frag --- crates/bevy_pbr/src/render_graph/pipeline/pbr.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag b/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag index 7fed3a0ccd641..84a483f58a45c 100644 --- a/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag +++ b/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag @@ -41,7 +41,7 @@ struct Light { vec3 pos; float inverseRadiusSquared; vec3 color; - // float unused; // unused 4th element of vec4; + float unused; // unused 4th element of vec4; }; layout(location = 0) in vec3 v_WorldPosition; From 1d4d606432aa283d6cfab333596fc90067780699 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Fri, 19 Mar 2021 14:41:27 -0700 Subject: [PATCH 56/58] Add camera position and update shaders --- .../src/render_graph/pipeline/pbr.frag | 4 +- .../src/render_graph/pipeline/pbr.vert | 1 - .../src/render_graph/nodes/camera_node.rs | 61 +++++++++++++++---- .../src/render_graph/nodes/pass_node.rs | 27 +------- 4 files changed, 52 insertions(+), 41 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag b/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag index 84a483f58a45c..f34b2b222f351 100644 --- a/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag +++ b/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag @@ -52,7 +52,9 @@ layout(location = 0) out vec4 o_Target; layout(set = 0, binding = 0) uniform CameraViewProj { mat4 ViewProj; - vec4 CameraPos; +}; +layout(set = 0, binding = 1) uniform CameraPosition { + vec3 CameraPos; }; layout(set = 1, binding = 0) uniform Lights { diff --git a/crates/bevy_pbr/src/render_graph/pipeline/pbr.vert b/crates/bevy_pbr/src/render_graph/pipeline/pbr.vert index d7e75d3438196..78c1312e1ea76 100644 --- a/crates/bevy_pbr/src/render_graph/pipeline/pbr.vert +++ b/crates/bevy_pbr/src/render_graph/pipeline/pbr.vert @@ -10,7 +10,6 @@ layout(location = 2) out vec2 v_Uv; layout(set = 0, binding = 0) uniform CameraViewProj { mat4 ViewProj; - vec4 CameraPos; }; layout(set = 2, binding = 0) uniform Transform { diff --git a/crates/bevy_render/src/render_graph/nodes/camera_node.rs b/crates/bevy_render/src/render_graph/nodes/camera_node.rs index bacbe2a599b57..9bec01c63c86b 100644 --- a/crates/bevy_render/src/render_graph/nodes/camera_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/camera_node.rs @@ -59,6 +59,7 @@ impl SystemNode for CameraNode { const CAMERA_VIEW_PROJ: &str = "CameraViewProj"; const CAMERA_VIEW: &str = "CameraView"; +const CAMERA_POSITION: &str = "CameraPosition"; #[derive(Debug, Default)] pub struct CameraNodeState { @@ -68,6 +69,7 @@ pub struct CameraNodeState { } const MATRIX_SIZE: usize = std::mem::size_of::<[[f32; 4]; 4]>(); +const VEC3_SIZE: usize = std::mem::size_of::<[f32; 3]>(); pub fn camera_node_system( mut state: Local, @@ -88,22 +90,18 @@ pub fn camera_node_system( return; }; - let camera_pos = &[ - global_transform.translation.x, - global_transform.translation.y, - global_transform.translation.z, - 1.0, - ]; - let camera_matrix_array = - (camera.projection_matrix * global_transform.compute_matrix().inverse()).to_cols_array(); - let buffer_size = camera_pos.byte_len() + camera_matrix_array.byte_len(); - let staging_buffer = if let Some(staging_buffer) = state.staging_buffer { render_resource_context.map_buffer(staging_buffer, BufferMapMode::Write); staging_buffer } else { let staging_buffer = render_resource_context.create_buffer(BufferInfo { - size: MATRIX_SIZE * 2, + size: + // ViewProj + MATRIX_SIZE + + // View + MATRIX_SIZE + + // Position + VEC3_SIZE, buffer_usage: BufferUsage::COPY_SRC | BufferUsage::MAP_WRITE, mapped_at_creation: true, }); @@ -143,8 +141,25 @@ pub fn camera_node_system( }, ); } + + if bindings.get(CAMERA_POSITION).is_none() { + let buffer = render_resource_context.create_buffer(BufferInfo { + size: VEC3_SIZE, + buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, + ..Default::default() + }); + bindings.set( + CAMERA_POSITION, + RenderResourceBinding::Buffer { + buffer, + range: 0..VEC3_SIZE as u64, + dynamic_index: None, + }, + ); + } let view = global_transform.compute_matrix(); + let mut offset = 0; if let Some(RenderResourceBinding::Buffer { buffer, .. }) = bindings.get(CAMERA_VIEW) { render_resource_context.write_mapped_buffer( @@ -161,24 +176,44 @@ pub fn camera_node_system( 0, MATRIX_SIZE as u64, ); + offset += MATRIX_SIZE as u64; } if let Some(RenderResourceBinding::Buffer { buffer, .. }) = bindings.get(CAMERA_VIEW_PROJ) { let view_proj = camera.projection_matrix * view.inverse(); render_resource_context.write_mapped_buffer( staging_buffer, - MATRIX_SIZE as u64..(2 * MATRIX_SIZE) as u64, + offset..(offset + MATRIX_SIZE as u64), &mut |data, _renderer| { data[0..MATRIX_SIZE].copy_from_slice(view_proj.to_cols_array_2d().as_bytes()); }, ); state.command_queue.copy_buffer_to_buffer( staging_buffer, - MATRIX_SIZE as u64, + offset, *buffer, 0, MATRIX_SIZE as u64, ); + offset += MATRIX_SIZE as u64; + } + + if let Some(RenderResourceBinding::Buffer { buffer, .. }) = bindings.get(CAMERA_POSITION) { + let position: [f32; 3] = global_transform.translation.into(); + render_resource_context.write_mapped_buffer( + staging_buffer, + offset..(offset + VEC3_SIZE as u64), + &mut |data, _renderer| { + data[0..VEC3_SIZE].copy_from_slice(position.as_bytes()); + }, + ); + state.command_queue.copy_buffer_to_buffer( + staging_buffer, + offset, + *buffer, + 0, + VEC3_SIZE as u64, + ); } render_resource_context.unmap_buffer(staging_buffer); diff --git a/crates/bevy_render/src/render_graph/nodes/pass_node.rs b/crates/bevy_render/src/render_graph/nodes/pass_node.rs index 3258efa934b73..16cf5fef314dc 100644 --- a/crates/bevy_render/src/render_graph/nodes/pass_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/pass_node.rs @@ -2,10 +2,7 @@ use crate::{ camera::{ActiveCameras, VisibleEntities}, draw::{Draw, RenderCommand}, pass::{ClearColor, LoadOp, PassDescriptor, TextureAttachment}, - pipeline::{ - BindGroupDescriptor, BindType, BindingDescriptor, BindingShaderStage, IndexFormat, - PipelineDescriptor, UniformProperty, - }, + pipeline::{IndexFormat, PipelineDescriptor}, prelude::Visible, render_graph::{Node, ResourceSlotInfo, ResourceSlots}, renderer::{ @@ -29,7 +26,6 @@ pub struct PassNode { color_resolve_target_indices: Vec>, depth_stencil_attachment_input_index: Option, default_clear_color_inputs: Vec, - camera_bind_group_descriptor: BindGroupDescriptor, query_state: Option>, commands: Vec, } @@ -56,10 +52,6 @@ impl fmt::Debug for PassNode { "default_clear_color_inputs", &self.default_clear_color_inputs, ) - .field( - "camera_bind_group_descriptor", - &self.camera_bind_group_descriptor, - ) .finish() } } @@ -102,22 +94,6 @@ impl PassNode { } } - let camera_bind_group_descriptor = BindGroupDescriptor::new( - 0, - vec![BindingDescriptor { - name: "Camera".to_string(), - index: 0, - bind_type: BindType::Uniform { - has_dynamic_offset: false, - property: UniformProperty::Struct(vec![ - UniformProperty::Mat4, - UniformProperty::Vec4, - ]), - }, - shader_stage: BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT, - }], - ); - PassNode { descriptor, inputs, @@ -126,7 +102,6 @@ impl PassNode { color_resolve_target_indices, depth_stencil_attachment_input_index, default_clear_color_inputs: Vec::new(), - camera_bind_group_descriptor, query_state: None, commands: Vec::new(), } From 5f47748c465b3049c2a87aff9c975fa8a06b1bc4 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Fri, 19 Mar 2021 14:41:43 -0700 Subject: [PATCH 57/58] increase default intensity --- crates/bevy_pbr/src/light.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index 7f1e7219545d9..149bfd92b2551 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -25,7 +25,7 @@ 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: 100.0, + intensity: 200.0, range: 20.0, } } From 243b7dcbb2cfd78fcc02dc7dc05cb1dfa92def17 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Fri, 19 Mar 2021 14:44:51 -0700 Subject: [PATCH 58/58] rename "pipeline" to "pbr_pipeline" --- crates/bevy_pbr/src/entity.rs | 4 ++-- crates/bevy_pbr/src/render_graph/mod.rs | 8 ++++---- .../src/render_graph/{pipeline => pbr_pipeline}/mod.rs | 4 ++-- .../src/render_graph/{pipeline => pbr_pipeline}/pbr.frag | 0 .../src/render_graph/{pipeline => pbr_pipeline}/pbr.vert | 0 crates/bevy_render/src/render_graph/nodes/camera_node.rs | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) rename crates/bevy_pbr/src/render_graph/{pipeline => pbr_pipeline}/mod.rs (93%) rename crates/bevy_pbr/src/render_graph/{pipeline => pbr_pipeline}/pbr.frag (100%) rename crates/bevy_pbr/src/render_graph/{pipeline => pbr_pipeline}/pbr.vert (100%) diff --git a/crates/bevy_pbr/src/entity.rs b/crates/bevy_pbr/src/entity.rs index 89c0a830c2eb3..fe7ea9d8f7bb6 100644 --- a/crates/bevy_pbr/src/entity.rs +++ b/crates/bevy_pbr/src/entity.rs @@ -1,4 +1,4 @@ -use crate::{light::Light, material::StandardMaterial, render_graph::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::{ @@ -27,7 +27,7 @@ impl Default for PbrBundle { fn default() -> Self { Self { render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new( - PIPELINE_HANDLE.typed(), + PBR_PIPELINE_HANDLE.typed(), )]), mesh: Default::default(), visible: Default::default(), diff --git a/crates/bevy_pbr/src/render_graph/mod.rs b/crates/bevy_pbr/src/render_graph/mod.rs index 7871555ce8c3d..507cd3fdb2347 100644 --- a/crates/bevy_pbr/src/render_graph/mod.rs +++ b/crates/bevy_pbr/src/render_graph/mod.rs @@ -1,9 +1,9 @@ mod lights_node; -mod pipeline; +mod pbr_pipeline; use bevy_ecs::world::World; pub use lights_node::*; -pub use pipeline::*; +pub use pbr_pipeline::*; /// the names of pbr graph nodes pub mod node { @@ -50,9 +50,9 @@ pub(crate) fn add_pbr_graph(world: &mut World) { .add_node_edge(node::LIGHTS, base::node::MAIN_PASS) .unwrap(); } - let pipeline = build_pipeline(&mut world.get_resource_mut::>().unwrap()); + let pipeline = build_pbr_pipeline(&mut world.get_resource_mut::>().unwrap()); let mut pipelines = world .get_resource_mut::>() .unwrap(); - pipelines.set_untracked(PIPELINE_HANDLE, pipeline); + pipelines.set_untracked(PBR_PIPELINE_HANDLE, pipeline); } diff --git a/crates/bevy_pbr/src/render_graph/pipeline/mod.rs b/crates/bevy_pbr/src/render_graph/pbr_pipeline/mod.rs similarity index 93% rename from crates/bevy_pbr/src/render_graph/pipeline/mod.rs rename to crates/bevy_pbr/src/render_graph/pbr_pipeline/mod.rs index 19aaaec9a2fc5..8868f818cea6d 100644 --- a/crates/bevy_pbr/src/render_graph/pipeline/mod.rs +++ b/crates/bevy_pbr/src/render_graph/pbr_pipeline/mod.rs @@ -9,10 +9,10 @@ use bevy_render::{ texture::TextureFormat, }; -pub const PIPELINE_HANDLE: HandleUntyped = +pub const PBR_PIPELINE_HANDLE: HandleUntyped = HandleUntyped::weak_from_u64(PipelineDescriptor::TYPE_UUID, 13148362314012771389); -pub(crate) fn build_pipeline(shaders: &mut Assets) -> PipelineDescriptor { +pub(crate) fn build_pbr_pipeline(shaders: &mut Assets) -> PipelineDescriptor { PipelineDescriptor { depth_stencil: Some(DepthStencilState { format: TextureFormat::Depth32Float, diff --git a/crates/bevy_pbr/src/render_graph/pipeline/pbr.frag b/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag similarity index 100% rename from crates/bevy_pbr/src/render_graph/pipeline/pbr.frag rename to crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag diff --git a/crates/bevy_pbr/src/render_graph/pipeline/pbr.vert b/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.vert similarity index 100% rename from crates/bevy_pbr/src/render_graph/pipeline/pbr.vert rename to crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.vert diff --git a/crates/bevy_render/src/render_graph/nodes/camera_node.rs b/crates/bevy_render/src/render_graph/nodes/camera_node.rs index 9bec01c63c86b..d86b0e4d0abf5 100644 --- a/crates/bevy_render/src/render_graph/nodes/camera_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/camera_node.rs @@ -6,7 +6,7 @@ use crate::{ RenderResourceContext, }, }; -use bevy_core::{AsBytes, Bytes}; +use bevy_core::AsBytes; use bevy_ecs::{ system::{BoxedSystem, IntoSystem, Local, Query, Res, ResMut}, world::World, @@ -141,7 +141,7 @@ pub fn camera_node_system( }, ); } - + if bindings.get(CAMERA_POSITION).is_none() { let buffer = render_resource_context.create_buffer(BufferInfo { size: VEC3_SIZE,