Updated EnhancedPBR and touched up some includes

This commit is contained in:
antonmic
2021-04-17 09:52:04 -07:00
parent 9c01e993db
commit aa06908024
23 changed files with 687 additions and 235 deletions
@@ -13,6 +13,7 @@
#pragma once
#include <Atom/Features/SrgSemantics.azsli>
#include <viewsrg.srgi>
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
#include "MaterialInputs/BaseColorInput.azsli"
@@ -10,7 +10,6 @@
*
*/
#include <viewsrg.srgi>
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include "./EnhancedPBR_Common.azsli"
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
@@ -10,11 +10,25 @@
*
*/
#include <viewsrg.srgi>
#include "EnhancedPBR_Common.azsli"
// SRGs
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
// Pass Output
#include <Atom/Features/PBR/ForwardPassOutput.azsli>
// Utility
#include <Atom/Features/ColorManagement/TransformColor.azsli>
#include <Atom/Features/PBR/AlphaUtils.azsli>
// Custom Surface & Lighting
#include <Atom/Features/PBR/Lighting/EnhancedLighting.azsli>
// Decals
#include <Atom/Features/PBR/Decals.azsli>
// ---------- Material Parameters ----------
@@ -39,6 +53,8 @@ COMMON_OPTIONS_DETAIL_MAPS()
#include "MaterialInputs/TransmissionInput.azsli"
// ---------- Vertex Shader ----------
struct VSInput
{
// Base fields (required by the template azsli file)...
@@ -67,8 +83,6 @@ struct VSOutput
float2 m_detailUv[UvSetCount] : UV3;
};
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include <Atom/Features/PBR/LightingModel.azsli>
#include <Atom/Features/Vertex/VertexHelper.azsli>
VSOutput EnhancedPbr_ForwardPassVS(VSInput IN)
@@ -94,6 +108,9 @@ VSOutput EnhancedPbr_ForwardPassVS(VSInput IN)
return OUT;
}
// ---------- Pixel Shader ----------
PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth)
{
// ------- Tangents & Bitangets -------
@@ -144,6 +161,9 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
}
}
Surface surface;
surface.position = IN.m_worldPosition;
// ------- Alpha & Clip -------
float2 baseColorUv = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex];
@@ -172,7 +192,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms.
float detailLayerNormalFactor = MaterialSrg::m_detail_normal_factor * detailLayerBlendFactor;
float3 normal = GetDetailedNormalInputWS(
surface.normal = GetDetailedNormalInputWS(
isFrontFace, IN.m_normal,
tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_normalFactor, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, uvMatrix, o_normal_useTexture,
tangents[MaterialSrg::m_detail_allMapsUvIndex], bitangents[MaterialSrg::m_detail_allMapsUvIndex], MaterialSrg::m_detail_normal_texture, MaterialSrg::m_sampler, detailUv, detailLayerNormalFactor, MaterialSrg::m_detail_normal_flipX, MaterialSrg::m_detail_normal_flipY, MaterialSrg::m_detailUvMatrix, o_detail_normal_useTexture);
@@ -196,26 +216,20 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture);
}
// ------- Roughness -------
float2 roughnessUv = IN.m_uv[MaterialSrg::m_roughnessMapUvIndex];
float roughness = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor,
MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture);
// ------- Specular -------
float2 specularUv = IN.m_uv[MaterialSrg::m_specularF0MapUvIndex];
float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture);
float specularF0 = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture);
// ------- Emissive -------
surface.SetAlbedoAndSpecularF0(baseColor, specularF0, metallic);
float2 emissiveUv = IN.m_uv[MaterialSrg::m_emissiveMapUvIndex];
float3 emissive = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture);
// ------- Roughness -------
// ------- Occlusion -------
float2 roughnessUv = IN.m_uv[MaterialSrg::m_roughnessMapUvIndex];
surface.roughnessLinear = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor,
MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture);
float2 occlusionUv = IN.m_uv[MaterialSrg::m_ambientOcclusionMapUvIndex];
float occlusion = GetOcclusionInput(MaterialSrg::m_ambientOcclusionMap, MaterialSrg::m_sampler, occlusionUv, MaterialSrg::m_ambientOcclusionFactor, o_ambientOcclusion_useTexture);
surface.CalculateRoughnessA();
// ------- Subsurface -------
@@ -226,33 +240,100 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float2 transmissionUv = IN.m_uv[MaterialSrg::m_transmissionThicknessMapUvIndex];
float4 transmissionTintThickness = GeTransmissionInput(MaterialSrg::m_transmissionThicknessMap, MaterialSrg::m_sampler, transmissionUv, MaterialSrg::m_transmissionTintThickness);
surface.transmission.tint = transmissionTintThickness.rgb;
surface.transmission.thickness = transmissionTintThickness.w;
surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams;
// ------- Anisotropy -------
if (o_enableAnisotropy)
{
// Convert the angle from [0..1] = [0 .. 180 degrees] to radians [0 .. PI]
const float anisotropyAngle = MaterialSrg::m_anisotropicAngle * PI;
const float anisotropyFactor = MaterialSrg::m_anisotropicFactor;
surface.anisotropy.Init(surface.normal, tangents[0], bitangents[0], anisotropyAngle, anisotropyFactor, surface.roughnessA);
}
// ------- Lighting Data -------
LightingData lightingData;
// Light iterator
lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData);
lightingData.Init(surface.position, surface.normal, surface.roughnessLinear);
// Directional light shadow coordinates
lightingData.shadowCoords = IN.m_shadowCoords;
// ------- Emissive -------
float2 emissiveUv = IN.m_uv[MaterialSrg::m_emissiveMapUvIndex];
lightingData.emissiveLighting = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture);
// ------- Occlusion -------
float2 occlusionUv = IN.m_uv[MaterialSrg::m_ambientOcclusionMapUvIndex];
lightingData.occlusion = GetOcclusionInput(MaterialSrg::m_ambientOcclusionMap, MaterialSrg::m_sampler, occlusionUv, MaterialSrg::m_ambientOcclusionFactor, o_ambientOcclusion_useTexture);
// ------- Clearcoat -------
float clearCoatFactor = 0.0;
float clearCoatRoughness = 0.0;
float3 clearCoatNormal = float3(0.0, 0.0, 0.0);
// TODO: Clean up the double uses of these clear coat flags
if(o_clearCoat_enabled && o_clearCoat_feature_enabled)
// [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags
if(o_clearCoat_feature_enabled)
{
float3x3 uvMatrix = MaterialSrg::m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
GetClearCoatInputs(MaterialSrg::m_clearCoatInfluenceMap, IN.m_uv[MaterialSrg::m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_clearCoatFactor, o_clearCoat_factor_useTexture,
MaterialSrg::m_clearCoatRoughnessMap, IN.m_uv[MaterialSrg::m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_clearCoatRoughness, o_clearCoat_roughness_useTexture,
MaterialSrg::m_clearCoatNormalMap, IN.m_uv[MaterialSrg::m_clearCoatNormalMapUvIndex], IN.m_normal, o_clearCoat_normal_useTexture, MaterialSrg::m_clearCoatNormalStrength,
uvMatrix, tangents[MaterialSrg::m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_clearCoatNormalMapUvIndex],
MaterialSrg::m_sampler, isFrontFace,
clearCoatFactor, clearCoatRoughness, clearCoatNormal);
if(o_clearCoat_enabled)
{
float3x3 uvMatrix = MaterialSrg::m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
GetClearCoatInputs(MaterialSrg::m_clearCoatInfluenceMap, IN.m_uv[MaterialSrg::m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_clearCoatFactor, o_clearCoat_factor_useTexture,
MaterialSrg::m_clearCoatRoughnessMap, IN.m_uv[MaterialSrg::m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_clearCoatRoughness, o_clearCoat_roughness_useTexture,
MaterialSrg::m_clearCoatNormalMap, IN.m_uv[MaterialSrg::m_clearCoatNormalMapUvIndex], IN.m_normal, o_clearCoat_normal_useTexture, MaterialSrg::m_clearCoatNormalStrength,
uvMatrix, tangents[MaterialSrg::m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_clearCoatNormalMapUvIndex],
MaterialSrg::m_sampler, isFrontFace,
surface.clearCoat.factor, surface.clearCoat.roughness, surface.clearCoat.normal);
}
// manipulate base layer f0 if clear coat is enabled
// modify base layer's normal incidence reflectance
// for the derivation of the following equation please refer to:
// https://google.github.io/filament/Filament.md.html#materialsystem/clearcoatmodel/baselayermodification
float3 f0 = (1.0 - 5.0 * sqrt(surface.specularF0)) / (5.0 - sqrt(surface.specularF0));
surface.specularF0 = lerp(surface.specularF0, f0 * f0, surface.clearCoat.factor);
}
// Diffuse and Specular response (used in IBL calculations)
lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear);
lightingData.diffuseResponse = 1.0 - lightingData.specularResponse;
if(o_clearCoat_feature_enabled)
{
// Clear coat layer has fixed IOR = 1.5 and transparent => F0 = (1.5 - 1)^2 / (1.5 + 1)^2 = 0.04
lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor);
}
// ------- Multiscatter -------
lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation);
// ------- Lighting Calculation -------
// Convert the angle from [0..1] = [0 .. 180 degrees] to radians [0 .. PI]
const float2 anisotropy = float2(MaterialSrg::m_anisotropicAngle * PI, MaterialSrg::m_anisotropicFactor);
// Apply Decals
ApplyDecals(lightingData.tileIterator, surface);
PbrLightingOutput lightingOutput = PbrLighting(IN,
baseColor, metallic, roughness, specularF0Factor,
normal, IN.m_tangent, IN.m_bitangent, anisotropy,
emissive, occlusion, transmissionTintThickness, MaterialSrg::m_transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, o_opacity_mode);
// Apply Direct Lighting
ApplyDirectLighting(surface, lightingData);
// Apply Image Based Lighting (IBL)
ApplyIBL(surface, lightingData);
// Finalize Lighting
lightingData.FinalizeLighting(surface.transmission.tint);
if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent)
{
alpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; // Increase opacity at grazing angles.
}
PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha);
// ------- Opacity -------
@@ -11,7 +11,6 @@
*/
#include <scenesrg.srgi>
#include <viewsrg.srgi>
#include "EnhancedPBR_Common.azsli"
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
@@ -13,6 +13,7 @@
#include <viewsrg.srgi>
#include "Skin_Common.azsli"
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
#include <Atom/Features/PBR/ForwardPassOutput.azsli>
#include <Atom/Features/ColorManagement/TransformColor.azsli>
@@ -10,10 +10,23 @@
*
*/
// SRGs
#include <viewsrg.srgi>
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
// Pass Output
#include <Atom/Features/PBR/ForwardPassOutput.azsli>
// Utility
#include <Atom/Features/ColorManagement/TransformColor.azsli>
#include <Atom/Features/PBR/AlphaUtils.azsli>
// Custom Surface & Lighting
#include <Atom/Features/PBR/Lighting/StandardLighting.azsli>
// Decals
#include <Atom/Features/PBR/Decals.azsli>
// ---------- Material Parameters ----------
@@ -47,6 +60,9 @@ DEFINE_LAYER_OPTIONS(o_layer3_)
#include "MaterialInputs/TransmissionInput.azsli"
#include "StandardMultilayerPBR_Common.azsli"
// ---------- Vertex Shader ----------
struct VSInput
{
// Base fields (required by the template azsli file)...
@@ -83,7 +99,6 @@ struct VSOutput
float3 m_blendMask : UV7;
};
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include <Atom/Features/PBR/LightingModel.azsli>
#include <Atom/Features/Vertex/VertexHelper.azsli>
@@ -115,6 +130,9 @@ VSOutput ForwardPassVS(VSInput IN)
return OUT;
}
// ---------- Pixel Shader ----------
PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth)
{
depth = IN.m_position.z;
@@ -13,6 +13,7 @@
#pragma once
#include <Atom/Features/SrgSemantics.azsli>
#include <viewsrg.srgi>
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
#include "MaterialInputs/BaseColorInput.azsli"
@@ -10,7 +10,6 @@
*
*/
#include <viewsrg.srgi>
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include "./StandardPBR_Common.azsli"
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
@@ -10,11 +10,25 @@
*
*/
#include <viewsrg.srgi>
#include "StandardPBR_Common.azsli"
// SRGs
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
// Pass Output
#include <Atom/Features/PBR/ForwardPassOutput.azsli>
// Utility
#include <Atom/Features/ColorManagement/TransformColor.azsli>
#include <Atom/Features/PBR/AlphaUtils.azsli>
// Custom Surface & Lighting
#include <Atom/Features/PBR/Lighting/StandardLighting.azsli>
// Decals
#include <Atom/Features/PBR/Decals.azsli>
// ---------- Material Parameters ----------
@@ -38,6 +52,8 @@ COMMON_OPTIONS_PARALLAX()
#include "MaterialInputs/TransmissionInput.azsli"
// ---------- Vertex Shader ----------
struct VSInput
{
// Base fields (required by the template azsli file)...
@@ -66,8 +82,6 @@ struct VSOutput
float2 m_uv[UvSetCount] : UV1;
};
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include <Atom/Features/PBR/LightingModel.azsli>
#include <Atom/Features/Vertex/VertexHelper.azsli>
VSOutput StandardPbr_ForwardPassVS(VSInput IN)
@@ -85,6 +99,9 @@ VSOutput StandardPbr_ForwardPassVS(VSInput IN)
return OUT;
}
// ---------- Pixel Shader ----------
PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth)
{
// ------- Tangents & Bitangets -------
@@ -112,7 +129,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
{
float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_depthFactor,
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_depthFactor,
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depth);
@@ -130,7 +147,6 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
Surface surface;
surface.position = IN.m_worldPosition.xyz;
// ------- Alpha & Clip -------
float2 baseColorUv = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex];
@@ -250,9 +266,9 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor);
}
// Multiscatter compensation factor
lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation);
// ------- Multiscatter -------
lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation);
// ------- Lighting Calculation -------
@@ -11,7 +11,6 @@
*/
#include <scenesrg.srgi>
#include <viewsrg.srgi>
#include "StandardPBR_Common.azsli"
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
@@ -1,7 +1,23 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
// ------------------------------------------------------------------------------
// NOTE: The following must be included or defined before including this file:
// - Surface - LightingData
// ---------------------------------------------------------------------------------
#include <Atom/Features/PBR/LightingOptions.azsli>
#include <Atom/Features/PBR/Surface.azsli>
// Analytical integation (approximation) of diffusion profile over radius, could be replaced by other pre integrated kernels
// such as sum of Gaussian
@@ -12,23 +12,27 @@
#pragma once
// ------------------------------------------------------------------------------
// NOTE: The following must be included or defined before including this file:
// - Surface
// ---------------------------------------------------------------------------------
#include <Atom/Features/MatrixUtility.azsli>
#include <Atom/Features/Decals/DecalTextureUtil.azsli>
#include <Atom/Features/LightCulling/LightCullingTileIterator.azsli>
#include <Atom/Features/PBR/Surface.azsli>
void ApplyDecal(uint currDecalIndex, inout Surface surface);
void ApplyDecals(inout LightCullingTileIterator tileIterator, inout Surface surface)
{
tileIterator.LoadAdvance();
while( !tileIterator.IsDone() )
{
uint currDecalIndex = tileIterator.GetValue();
while( !tileIterator.IsDone() )
{
uint currDecalIndex = tileIterator.GetValue();
tileIterator.LoadAdvance();
ApplyDecal(currDecalIndex, surface);
ApplyDecal(currDecalIndex, surface);
}
}
@@ -44,13 +48,13 @@ float GetDecalAttenuation(float3 surfNormal, float3 decalUp, float decalAngleAtt
void ApplyDecal(uint currDecalIndex, inout Surface surface)
{
ViewSrg::Decal decal = ViewSrg::m_decals[currDecalIndex];
ViewSrg::Decal decal = ViewSrg::m_decals[currDecalIndex];
float3x3 decalRot = MatrixFromQuaternion(decal.m_quaternion);
float3 localPos = surface.position - decal.m_position;
float3 localPos = surface.position - decal.m_position;
localPos = mul(localPos, decalRot);
float3 decalUVW = localPos * rcp(decal.m_halfSize);
if(decalUVW.x >= -1.0f && decalUVW.x <= 1.0f &&
decalUVW.y >= -1.0f && decalUVW.y <= 1.0f &&
@@ -70,25 +74,23 @@ void ApplyDecal(uint currDecalIndex, inout Surface surface)
switch(textureArrayIndex)
{
case 0:
baseMap = ViewSrg::m_decalTextureArray0.Sample(PassSrg::LinearSampler, decalUV);
baseMap = ViewSrg::m_decalTextureArray0.Sample(PassSrg::LinearSampler, decalUV);
break;
case 1:
baseMap = ViewSrg::m_decalTextureArray1.Sample(PassSrg::LinearSampler, decalUV);
baseMap = ViewSrg::m_decalTextureArray1.Sample(PassSrg::LinearSampler, decalUV);
break;
case 2:
baseMap = ViewSrg::m_decalTextureArray2.Sample(PassSrg::LinearSampler, decalUV);
baseMap = ViewSrg::m_decalTextureArray2.Sample(PassSrg::LinearSampler, decalUV);
break;
case 3:
baseMap = ViewSrg::m_decalTextureArray3.Sample(PassSrg::LinearSampler, decalUV);
baseMap = ViewSrg::m_decalTextureArray3.Sample(PassSrg::LinearSampler, decalUV);
break;
case 4:
baseMap = ViewSrg::m_decalTextureArray4.Sample(PassSrg::LinearSampler, decalUV);
baseMap = ViewSrg::m_decalTextureArray4.Sample(PassSrg::LinearSampler, decalUV);
break;
}
float opacity = baseMap.a * decal.m_opacity * GetDecalAttenuation(surface.normal, decalRot[2], decal.m_angleAttenuation);
surface.albedo = lerp(surface.albedo, baseMap.rgb, opacity);
}
float opacity = baseMap.a * decal.m_opacity * GetDecalAttenuation(surface.normal, decalRot[2], decal.m_angleAttenuation);
surface.albedo = lerp(surface.albedo, baseMap.rgb, opacity);
}
}
@@ -0,0 +1,119 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
// Include options first
#include <Atom/Features/PBR/LightingOptions.azsli>
// Then include custom surface and lighting data types
#include <Atom/Features/PBR/Lighting/LightingData.azsli>
#include <Atom/Features/PBR/Surfaces/StandardSurface.azsli>
#include <Atom/Features/PBR/LightingUtils.azsli>
#include <Atom/Features/PBR/Microfacet/Brdf.azsli>
// Then define the Diffuse and Specular lighting functions
float3 GetDiffuseLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight)
{
float3 diffuse;
if(o_enableSubsurfaceScattering)
{
// Use diffuse brdf contains double Fresnel (enter/exit surface) terms if subsurface scattering is enabled
diffuse = NormalizedDisneyDiffuse(surface.albedo, surface.normal, lightingData.dirToCamera, dirToLight, surface.roughnessLinear);
}
else
{
diffuse = DiffuseLambertian(surface.albedo, surface.normal, dirToLight);
}
if(o_clearCoat_feature_enabled)
{
// Attenuate diffuse term by clear coat's fresnel term to account for energy loss
float HdotV = saturate(dot(normalize(dirToLight + lightingData.dirToCamera), lightingData.dirToCamera));
diffuse *= 1.0 - (FresnelSchlick(HdotV, 0.04) * surface.clearCoat.factor);
}
diffuse *= lightIntensity;
return diffuse;
}
float3 GetSpecularLighting(Surface surface, LightingData lightingData, const float3 lightIntensity, const float3 dirToLight)
{
float3 specular;
if (o_enableAnisotropy)
{
specular = AnisotropicGGX( lightingData.dirToCamera, dirToLight, surface.normal, surface.anisotropy.tangent, surface.anisotropy.bitangent, surface.anisotropy.anisotropyFactors,
surface.specularF0, lightingData.NdotV, lightingData.multiScatterCompensation );
}
else
{
specular = SpecularGGX(lightingData.dirToCamera, dirToLight, surface.normal, surface.specularF0, lightingData.NdotV, surface.roughnessA2, lightingData.multiScatterCompensation);
}
if(o_clearCoat_feature_enabled)
{
float3 halfVector = normalize(dirToLight + lightingData.dirToCamera);
float NdotH = saturate(dot(surface.clearCoat.normal, halfVector));
float NdotL = saturate(dot(surface.clearCoat.normal, dirToLight));
float HdotL = saturate(dot(halfVector, dirToLight));
// HdotV = HdotL due to the definition of half vector
float3 clearCoatF = FresnelSchlick(HdotL, 0.04) * surface.clearCoat.factor;
float clearCoatRoughness = max(surface.clearCoat.roughness * surface.clearCoat.roughness, 0.0005f);
float3 clearCoatSpecular = ClearCoatGGX(NdotH, HdotL, NdotL, surface.clearCoat.normal, clearCoatRoughness, clearCoatF );
specular = specular * (1.0 - clearCoatF) * (1.0 - clearCoatF) + clearCoatSpecular;
}
specular *= lightIntensity;
return specular;
}
// Then include everything else
#include <Atom/Features/PBR/Lights/Lights.azsli>
#include <Atom/Features/PBR/Lights/Ibl.azsli>
struct PbrLightingOutput
{
float4 m_diffuseColor;
float4 m_specularColor;
float4 m_albedo;
float4 m_specularF0;
float4 m_normal;
float4 m_clearCoatNormal;
float3 m_scatterDistance;
};
PbrLightingOutput GetPbrLightingOutput(Surface surface, LightingData lightingData, float alpha)
{
PbrLightingOutput lightingOutput;
lightingOutput.m_diffuseColor = float4(lightingData.diffuseLighting, alpha);
lightingOutput.m_specularColor = float4(lightingData.specularLighting, 1.0);
// albedo, specularF0, roughness, and normals for later passes (specular IBL, Diffuse GI, SSR, AO, etc)
lightingOutput.m_specularF0 = float4(surface.specularF0, surface.roughnessLinear);
lightingOutput.m_albedo.rgb = surface.albedo * lightingData.diffuseResponse;
lightingOutput.m_albedo.a = lightingData.occlusion;
lightingOutput.m_normal.rgb = EncodeNormalSignedOctahedron(surface.normal);
lightingOutput.m_normal.a = o_specularF0_enableMultiScatterCompensation ? 1.0f : 0.0f;
// layout: (packedNormal.x, packedNormal.y, strength factor, clear coat roughness (not base material's roughness))
lightingOutput.m_clearCoatNormal = float4(EncodeNormalSphereMap(surface.clearCoat.normal), o_clearCoat_feature_enabled ? surface.clearCoat.factor : 0.0, surface.clearCoat.roughness);
return lightingOutput;
}
@@ -0,0 +1,119 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
// Include options first
#include <Atom/Features/PBR/LightingOptions.azsli>
// Then include custom surface and lighting data types
#include <Atom/Features/PBR/Lighting/LightingData.azsli>
#include <Atom/Features/PBR/Surfaces/StandardSurface.azsli>
#include <Atom/Features/PBR/LightingUtils.azsli>
#include <Atom/Features/PBR/Microfacet/Brdf.azsli>
// Then define the Diffuse and Specular lighting functions
float3 GetDiffuseLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight)
{
float3 diffuse;
if(o_enableSubsurfaceScattering)
{
// Use diffuse brdf contains double Fresnel (enter/exit surface) terms if subsurface scattering is enabled
diffuse = NormalizedDisneyDiffuse(surface.albedo, surface.normal, lightingData.dirToCamera, dirToLight, surface.roughnessLinear);
}
else
{
diffuse = DiffuseLambertian(surface.albedo, surface.normal, dirToLight);
}
if(o_clearCoat_feature_enabled)
{
// Attenuate diffuse term by clear coat's fresnel term to account for energy loss
float HdotV = saturate(dot(normalize(dirToLight + lightingData.dirToCamera), lightingData.dirToCamera));
diffuse *= 1.0 - (FresnelSchlick(HdotV, 0.04) * surface.clearCoat.factor);
}
diffuse *= lightIntensity;
return diffuse;
}
float3 GetSpecularLighting(Surface surface, LightingData lightingData, const float3 lightIntensity, const float3 dirToLight)
{
float3 specular;
if (o_enableAnisotropy)
{
specular = AnisotropicGGX( lightingData.dirToCamera, dirToLight, surface.normal, surface.anisotropy.tangent, surface.anisotropy.bitangent, surface.anisotropy.anisotropyFactors,
surface.specularF0, lightingData.NdotV, lightingData.multiScatterCompensation );
}
else
{
specular = SpecularGGX(lightingData.dirToCamera, dirToLight, surface.normal, surface.specularF0, lightingData.NdotV, surface.roughnessA2, lightingData.multiScatterCompensation);
}
if(o_clearCoat_feature_enabled)
{
float3 halfVector = normalize(dirToLight + lightingData.dirToCamera);
float NdotH = saturate(dot(surface.clearCoat.normal, halfVector));
float NdotL = saturate(dot(surface.clearCoat.normal, dirToLight));
float HdotL = saturate(dot(halfVector, dirToLight));
// HdotV = HdotL due to the definition of half vector
float3 clearCoatF = FresnelSchlick(HdotL, 0.04) * surface.clearCoat.factor;
float clearCoatRoughness = max(surface.clearCoat.roughness * surface.clearCoat.roughness, 0.0005f);
float3 clearCoatSpecular = ClearCoatGGX(NdotH, HdotL, NdotL, surface.clearCoat.normal, clearCoatRoughness, clearCoatF );
specular = specular * (1.0 - clearCoatF) * (1.0 - clearCoatF) + clearCoatSpecular;
}
specular *= lightIntensity;
return specular;
}
// Then include everything else
#include <Atom/Features/PBR/Lights/Lights.azsli>
#include <Atom/Features/PBR/Lights/Ibl.azsli>
struct PbrLightingOutput
{
float4 m_diffuseColor;
float4 m_specularColor;
float4 m_albedo;
float4 m_specularF0;
float4 m_normal;
float4 m_clearCoatNormal;
float3 m_scatterDistance;
};
PbrLightingOutput GetPbrLightingOutput(Surface surface, LightingData lightingData, float alpha)
{
PbrLightingOutput lightingOutput;
lightingOutput.m_diffuseColor = float4(lightingData.diffuseLighting, alpha);
lightingOutput.m_specularColor = float4(lightingData.specularLighting, 1.0);
// albedo, specularF0, roughness, and normals for later passes (specular IBL, Diffuse GI, SSR, AO, etc)
lightingOutput.m_specularF0 = float4(surface.specularF0, surface.roughnessLinear);
lightingOutput.m_albedo.rgb = surface.albedo * lightingData.diffuseResponse;
lightingOutput.m_albedo.a = lightingData.occlusion;
lightingOutput.m_normal.rgb = EncodeNormalSignedOctahedron(surface.normal);
lightingOutput.m_normal.a = o_specularF0_enableMultiScatterCompensation ? 1.0f : 0.0f;
// layout: (packedNormal.x, packedNormal.y, strength factor, clear coat roughness (not base material's roughness))
lightingOutput.m_clearCoatNormal = float4(EncodeNormalSphereMap(surface.clearCoat.normal), o_clearCoat_feature_enabled ? surface.clearCoat.factor : 0.0, surface.clearCoat.roughness);
return lightingOutput;
}
@@ -19,6 +19,68 @@
#include <Atom/Features/PBR/Lighting/LightingData.azsli>
#include <Atom/Features/PBR/Surfaces/StandardSurface.azsli>
#include <Atom/Features/PBR/LightingUtils.azsli>
#include <Atom/Features/PBR/Microfacet/Brdf.azsli>
// Then define the Diffuse and Specular lighting functions
float3 GetDiffuseLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight)
{
float3 diffuse;
if(o_enableSubsurfaceScattering)
{
// Use diffuse brdf contains double Fresnel (enter/exit surface) terms if subsurface scattering is enabled
diffuse = NormalizedDisneyDiffuse(surface.albedo, surface.normal, lightingData.dirToCamera, dirToLight, surface.roughnessLinear);
}
else
{
diffuse = DiffuseLambertian(surface.albedo, surface.normal, dirToLight);
}
if(o_clearCoat_feature_enabled)
{
// Attenuate diffuse term by clear coat's fresnel term to account for energy loss
float HdotV = saturate(dot(normalize(dirToLight + lightingData.dirToCamera), lightingData.dirToCamera));
diffuse *= 1.0 - (FresnelSchlick(HdotV, 0.04) * surface.clearCoat.factor);
}
diffuse *= lightIntensity;
return diffuse;
}
float3 GetSpecularLighting(Surface surface, LightingData lightingData, const float3 lightIntensity, const float3 dirToLight)
{
float3 specular;
if (o_enableAnisotropy)
{
specular = AnisotropicGGX( lightingData.dirToCamera, dirToLight, surface.normal, surface.anisotropy.tangent, surface.anisotropy.bitangent, surface.anisotropy.anisotropyFactors,
surface.specularF0, lightingData.NdotV, lightingData.multiScatterCompensation );
}
else
{
specular = SpecularGGX(lightingData.dirToCamera, dirToLight, surface.normal, surface.specularF0, lightingData.NdotV, surface.roughnessA2, lightingData.multiScatterCompensation);
}
if(o_clearCoat_feature_enabled)
{
float3 halfVector = normalize(dirToLight + lightingData.dirToCamera);
float NdotH = saturate(dot(surface.clearCoat.normal, halfVector));
float NdotL = saturate(dot(surface.clearCoat.normal, dirToLight));
float HdotL = saturate(dot(halfVector, dirToLight));
// HdotV = HdotL due to the definition of half vector
float3 clearCoatF = FresnelSchlick(HdotL, 0.04) * surface.clearCoat.factor;
float clearCoatRoughness = max(surface.clearCoat.roughness * surface.clearCoat.roughness, 0.0005f);
float3 clearCoatSpecular = ClearCoatGGX(NdotH, HdotL, NdotL, surface.clearCoat.normal, clearCoatRoughness, clearCoatF );
specular = specular * (1.0 - clearCoatF) * (1.0 - clearCoatF) + clearCoatSpecular;
}
specular *= lightIntensity;
return specular;
}
// Then include everything else
#include <Atom/Features/PBR/Lights/Lights.azsli>
#include <Atom/Features/PBR/Lights/Ibl.azsli>
@@ -55,9 +117,3 @@ PbrLightingOutput GetPbrLightingOutput(Surface surface, LightingData lightingDat
return lightingOutput;
}
@@ -28,30 +28,6 @@
#include <Atom/Features/PBR/Lighting/StandardLighting.azsli>
#include <Atom/Features/PBR/Decals.azsli>
// VSInput, VSOutput, ObjectSrg must be defined before including this file.
// DEPRECATED: Please use the VertexHelper(...) function in VertexHelper.azsli instead.
//! @param skipShadowCoords can be useful for example when PixelDepthOffset is enable, because the pixel shader will have to run before the final world position is known
void PbrVsHelper(in VSInput IN, inout VSOutput OUT, float3 worldPosition, bool skipShadowCoords = false)
{
OUT.m_worldPosition = worldPosition;
OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(OUT.m_worldPosition, 1.0));
float4x4 objectToWorld = ObjectSrg::GetWorldMatrix();
float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose();
ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent);
// directional light shadow
const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight;
if (o_enableShadows && !skipShadowCoords && shadowIndex < SceneSrg::m_directionalLightCount)
{
DirectionalLightShadow::GetShadowCoords(
shadowIndex,
worldPosition,
OUT.m_shadowCoords);
}
}
// DEPRECATED: Please use the functions in StandardLighting.azsli instead.
@@ -16,71 +16,9 @@
#include <Atom/Features/PBR/BackLighting.azsli>
#include <Atom/Features/PBR/Hammersley.azsli>
#include <Atom/Features/PBR/LightingUtils.azsli>
#include <Atom/Features/PBR/Surface.azsli>
#include <Atom/Features/PBR/Microfacet/Brdf.azsli>
option bool o_area_light_validation = false;
float3 GetDiffuseLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight)
{
float3 diffuse;
if(o_enableSubsurfaceScattering)
{
// Use diffuse brdf contains double Fresnel (enter/exit surface) terms if subsurface scattering is enabled
diffuse = NormalizedDisneyDiffuse(surface.albedo, surface.normal, lightingData.dirToCamera, dirToLight, surface.roughnessLinear);
}
else
{
diffuse = DiffuseLambertian(surface.albedo, surface.normal, dirToLight);
}
if(o_clearCoat_feature_enabled)
{
// Attenuate diffuse term by clear coat's fresnel term to account for energy loss
float HdotV = saturate(dot(normalize(dirToLight + lightingData.dirToCamera), lightingData.dirToCamera));
diffuse *= 1.0 - (FresnelSchlick(HdotV, 0.04) * surface.clearCoat.factor);
}
diffuse *= lightIntensity;
return diffuse;
}
float3 GetSpecularLighting(Surface surface, LightingData lightingData, const float3 lightIntensity, const float3 dirToLight)
{
float3 specular;
if (o_enableAnisotropy)
{
//AnisotropicGGX( float3 dirToCamera, float3 dirToLight, float3 normal, float3 tangent, float3 bitangent, float2 anisotropyFactors,
// float3 specularF0, float NdotV, float multiScatterCompensation )
specular = AnisotropicGGX( lightingData.dirToCamera, dirToLight, surface.normal, surface.anisotropy.tangent, surface.anisotropy.bitangent, surface.anisotropy.anisotropyFactors,
surface.specularF0, lightingData.NdotV, lightingData.multiScatterCompensation );
}
else
{
specular = SpecularGGX(lightingData.dirToCamera, dirToLight, surface.normal, surface.specularF0, lightingData.NdotV, surface.roughnessA2, lightingData.multiScatterCompensation);
}
if(o_clearCoat_feature_enabled)
{
float3 halfVector = normalize(dirToLight + lightingData.dirToCamera);
float NdotH = saturate(dot(surface.clearCoat.normal, halfVector));
float NdotL = saturate(dot(surface.clearCoat.normal, dirToLight));
float HdotL = saturate(dot(halfVector, dirToLight));
// HdotV = HdotL due to the definition of half vector
float3 clearCoatF = FresnelSchlick(HdotL, 0.04) * surface.clearCoat.factor;
float clearCoatRoughness = max(surface.clearCoat.roughness * surface.clearCoat.roughness, 0.0005f);
float3 clearCoatSpecular = ClearCoatGGX(NdotH, HdotL, NdotL, surface.clearCoat.normal, clearCoatRoughness, clearCoatF );
specular = specular * (1.0 - clearCoatF) * (1.0 - clearCoatF) + clearCoatSpecular;
}
specular *= lightIntensity;
return specular;
}
//! Adjust the intensity of specular light based on the radius of the light source and roughness of the surface to approximate energy conservation.
float GetIntensityAdjustedByRadiusAndRoughness(float roughnessA, float radius, float distance2)
@@ -18,7 +18,6 @@
* rather than transmit.
**/
#include <Atom/Features/PBR/Surface.azsli>
#include <Atom/RPI/Math.azsli>
#include "Ggx.azsli"
#include "Fresnel.azsli"
@@ -81,9 +80,6 @@ float3 DiffuseTitanfall(float roughnessA, float3 albedo, float3 normal, float3 d
}
// ------- Specular Lighting -------
//! Computes specular response from surfaces with microgeometry. The common form for microfacet
@@ -1,68 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
// //! The surface struct should contain all the info for a pixel that can be
// //! passed onto the rendering logic for shading.
// //! Note that metallic workflow can be supported by first converting to these physical properties first.
// struct Surface
// {
// float3 position;
// float3 normal;
// float3 tangentAniso; //! surface space tangent for anisotropic use
// float3 bitangentAniso; //! surface space bitangent for anisotropic use
// float2 anisotropyFactors; //! anisotory factors along the tangent and the bitangent directions
// float3 albedo;
// float3 specularF0; //!< actual fresnel f0 spectral value of the surface (as opposed to a "factor")
// float3 multiScatterCompensation; //!< the constant scaling term to approximate multiscattering contribution in specular BRDF
// float roughnessLinear; //!< perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use
// float roughnessA; //!< actual roughness value ( a.k.a. "alpha roughness") to be used in microfacet calculations
// float thickness; //!< pre baked local thickness, used for transmission
// float4 transmissionParams; //!< parameters: thick mode->(attenuation coefficient, power, distortion, scale), thin mode: (float3 scatter distance, scale)
// float clearCoatFactor; //!< clear coat strength factor
// float clearCoatRoughness; //!< clear coat linear roughness (not base layer one)
// float3 clearCoatNormal; //!< normal used for top layer clear coat
// };
//
// //! Calculate and fill the data required for fast directional anisotropty surface response.
// //! Assumption: the normal and roughnessA surface properties were filled and are valid
// //! Notice that since the newly created surface tangent and bitangent will be rotated
// //! according to the anisotropy direction and should not be used for other purposes uness
// //! rotated back.
// void CalculateSurfaceDirectionalAnisotropicData(
// inout Surface surface, float2 anisotropyAngleAndFactor,
// float3 vtxTangent, float3 vtxBitangent )
// {
// const float anisotropyAngle = anisotropyAngleAndFactor.x;
// const float anisotropyFactor = anisotropyAngleAndFactor.y;
//
// surface.anisotropyFactors = max( 0.01,
// float2( surface.roughnessA * (1.0 + anisotropyFactor),
// surface.roughnessA * (1.0 - anisotropyFactor) )
// );
//
// if (anisotropyAngle > 0.01)
// {
// // Base rotation according to anisotropic main direction
// float aniSin, aniCos;
// sincos(anisotropyAngle, aniSin, aniCos);
//
// // Rotate the vertex tangent to get new aligned to surface normal tangent
// vtxTangent = aniCos * vtxTangent - aniSin * vtxBitangent;
// }
//
// // Now create the new surface base according to the surface normal
// // If rotation was required it was already applied to the tangent, hence to the bitangent
// surface.bitangentAniso = normalize(cross(surface.normal, vtxTangent));
// surface.tangentAniso = cross(surface.bitangentAniso, surface.normal);
// }
@@ -63,6 +63,9 @@ void BasePbrSurfaceData::ApplySpecularAA()
float kernelRoughnessA2 = min(2.0 * variance , varianceThresh );
float filteredRoughnessA2 = saturate ( roughnessA2 + kernelRoughnessA2 );
roughnessA2 = filteredRoughnessA2;
roughnessA = sqrt(roughnessA2);
roughnessLinear = sqrt(roughnessA);
}
void BasePbrSurfaceData::CalculateRoughnessA()
@@ -0,0 +1,91 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Atom/Features/PBR/Surfaces/AnisotropicSurfaceData.azsli>
#include <Atom/Features/PBR/Surfaces/BasePbrSurfaceData.azsli>
#include <Atom/Features/PBR/Surfaces/ClearCoatSurfaceData.azsli>
#include <Atom/Features/PBR/Surfaces/TransmissionSurfaceData.azsli>
class Surface //: BasePbrSurfaceData
{
//BasePbrSurfaceData pbr;
AnisotropicSurfaceData anisotropy;
ClearCoatSurfaceData clearCoat;
TransmissionSurfaceData transmission;
// ------- BasePbrSurfaceData -------
float3 position; //!< Position in world-space
float3 normal; //!< Normal in world-space
float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value
float3 specularF0; //!< Fresnel f0 spectral value of the surface
float roughnessLinear; //!< Perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use
float roughnessA; //!< Actual roughness value ( a.k.a. "alpha roughness") to be used in microfacet calculations
float roughnessA2; //!< Alpha roughness ^ 2 (i.e. roughnessA * roughnessA), used in GGX, cached here for perfromance
//! Applies specular anti-aliasing to roughnessA2
void ApplySpecularAA();
//! Calculates roughnessA and roughnessA2 after roughness has been set
void CalculateRoughnessA();
//! Sets albedo and specularF0 using metallic workflow
void SetAlbedoAndSpecularF0(float3 baseColor, float inSpecularF0, float metallic);
};
// Specular Anti-Aliasing technique from this paper:
// http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
void Surface::ApplySpecularAA()
{
// Constants for formula below
const float screenVariance = 0.25f;
const float varianceThresh = 0.18f;
// Specular Anti-Aliasing
float3 dndu = ddx_fine( normal );
float3 dndv = ddy_fine( normal );
float variance = screenVariance * (dot( dndu , dndu ) + dot( dndv , dndv ));
float kernelRoughnessA2 = min(2.0 * variance , varianceThresh );
float filteredRoughnessA2 = saturate ( roughnessA2 + kernelRoughnessA2 );
roughnessA2 = filteredRoughnessA2;
}
void Surface::CalculateRoughnessA()
{
// The roughness value in microfacet calculations (called "alpha" in the literature) does not give perceptually
// linear results. Disney found that squaring the roughness value before using it in microfacet equations causes
// the user-provided roughness parameter to be more perceptually linear. We keep both values available as some
// equations need roughnessLinear (i.e. IBL sampling) while others need roughnessA (i.e. GGX equations).
// See Burley's Disney PBR: https://pdfs.semanticscholar.org/eeee/3b125c09044d3e2f58ed0e4b1b66a677886d.pdf
roughnessA = max(roughnessLinear * roughnessLinear, MinRoughnessA);
roughnessA2 = roughnessA * roughnessA;
if(o_applySpecularAA)
{
ApplySpecularAA();
}
}
void Surface::SetAlbedoAndSpecularF0(float3 baseColor, float inSpecularF0, float metallic)
{
float3 dielectricSpecularF0 = MaxDielectricSpecularF0 * inSpecularF0;
// Compute albedo and specularF0 based on metalness
albedo = lerp(baseColor, float3(0.0f, 0.0f, 0.0f), metallic);
specularF0 = lerp(dielectricSpecularF0, baseColor, metallic);
}
@@ -0,0 +1,91 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Atom/Features/PBR/Surfaces/AnisotropicSurfaceData.azsli>
#include <Atom/Features/PBR/Surfaces/BasePbrSurfaceData.azsli>
#include <Atom/Features/PBR/Surfaces/ClearCoatSurfaceData.azsli>
#include <Atom/Features/PBR/Surfaces/TransmissionSurfaceData.azsli>
class Surface //: BasePbrSurfaceData
{
//BasePbrSurfaceData pbr;
AnisotropicSurfaceData anisotropy;
ClearCoatSurfaceData clearCoat;
TransmissionSurfaceData transmission;
// ------- BasePbrSurfaceData -------
float3 position; //!< Position in world-space
float3 normal; //!< Normal in world-space
float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value
float3 specularF0; //!< Fresnel f0 spectral value of the surface
float roughnessLinear; //!< Perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use
float roughnessA; //!< Actual roughness value ( a.k.a. "alpha roughness") to be used in microfacet calculations
float roughnessA2; //!< Alpha roughness ^ 2 (i.e. roughnessA * roughnessA), used in GGX, cached here for perfromance
//! Applies specular anti-aliasing to roughnessA2
void ApplySpecularAA();
//! Calculates roughnessA and roughnessA2 after roughness has been set
void CalculateRoughnessA();
//! Sets albedo and specularF0 using metallic workflow
void SetAlbedoAndSpecularF0(float3 baseColor, float inSpecularF0, float metallic);
};
// Specular Anti-Aliasing technique from this paper:
// http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
void Surface::ApplySpecularAA()
{
// Constants for formula below
const float screenVariance = 0.25f;
const float varianceThresh = 0.18f;
// Specular Anti-Aliasing
float3 dndu = ddx_fine( normal );
float3 dndv = ddy_fine( normal );
float variance = screenVariance * (dot( dndu , dndu ) + dot( dndv , dndv ));
float kernelRoughnessA2 = min(2.0 * variance , varianceThresh );
float filteredRoughnessA2 = saturate ( roughnessA2 + kernelRoughnessA2 );
roughnessA2 = filteredRoughnessA2;
}
void Surface::CalculateRoughnessA()
{
// The roughness value in microfacet calculations (called "alpha" in the literature) does not give perceptually
// linear results. Disney found that squaring the roughness value before using it in microfacet equations causes
// the user-provided roughness parameter to be more perceptually linear. We keep both values available as some
// equations need roughnessLinear (i.e. IBL sampling) while others need roughnessA (i.e. GGX equations).
// See Burley's Disney PBR: https://pdfs.semanticscholar.org/eeee/3b125c09044d3e2f58ed0e4b1b66a677886d.pdf
roughnessA = max(roughnessLinear * roughnessLinear, MinRoughnessA);
roughnessA2 = roughnessA * roughnessA;
if(o_applySpecularAA)
{
ApplySpecularAA();
}
}
void Surface::SetAlbedoAndSpecularF0(float3 baseColor, float inSpecularF0, float metallic)
{
float3 dielectricSpecularF0 = MaxDielectricSpecularF0 * inSpecularF0;
// Compute albedo and specularF0 based on metalness
albedo = lerp(baseColor, float3(0.0f, 0.0f, 0.0f), metallic);
specularF0 = lerp(dielectricSpecularF0, baseColor, metallic);
}
@@ -13,7 +13,9 @@
#pragma once
// ------------------------------------------------------------------------------
// NOTE: VSInput, VSOutput, ObjectSrg must be defined before including this file.
// NOTE: The following must be included or defined before including this file:
// - VSInput - ObjectSrg
// - VSOutput - PassSrg
// ---------------------------------------------------------------------------------
// Options
@@ -23,8 +25,6 @@
#include <viewsrg.srgi>
#include <scenesrg.srgi>
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
// Math
#include <Atom/RPI/Math.azsli>
@@ -33,7 +33,6 @@
// Shadow Coords
#include <Atom/Features/Shadow/DirectionalLightShadow.azsli>
//! @param skipShadowCoords can be useful for example when PixelDepthOffset is enable, because the pixel shader will have to run before the final world position is known
void VertexHelper(in VSInput IN, inout VSOutput OUT, float3 worldPosition, bool skipShadowCoords = false)
{