added defines in the shaders to turn off clear coat, transmission and area light types. Allows for thiner surface data and more control over features when authoring bespoke material shaders

Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com>
This commit is contained in:
antonmic
2021-12-16 01:13:12 -08:00
parent a436ea7f9b
commit a839a8f761
22 changed files with 222 additions and 20 deletions
@@ -21,7 +21,7 @@
#include <Atom/Features/ColorManagement/TransformColor.azsli>
// Custom Surface & Lighting
#include <Atom/Features/PBR/Lighting/StandardLighting.azsli>
#include <Atom/Features/PBR/Lighting/BaseLighting.azsli>
// Decals
#include <Atom/Features/PBR/Decals.azsli>
@@ -102,7 +102,6 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace)
}
Surface surface;
surface.clearCoat.InitializeToZero();
surface.position = IN.m_worldPosition.xyz;
// ------- Normal -------
@@ -428,7 +428,6 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
Surface surface;
surface.position = IN.m_worldPosition;
surface.transmission.InitializeToZero();
// ------- Combine Normals ---------
@@ -523,7 +522,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
ApplyIBL(surface, lightingData);
// Finalize Lighting
lightingData.FinalizeLighting(0);
lightingData.FinalizeLighting();
const float alpha = 1.0;
@@ -36,6 +36,9 @@ float ThinObjectFalloff(const float3 surfaceNormal, const float3 dirToLight)
float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight, float shadowRatio)
{
float3 result = float3(0.0, 0.0, 0.0);
#if ENABLE_TRANSMISSION
float thickness = 0.0;
float4 transmissionParams = surface.transmission.transmissionParams;
@@ -71,7 +74,9 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI
break;
}
#endif
return result;
}
@@ -0,0 +1,83 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#define ENABLE_CLEAR_COAT 0
#define ENABLE_TRANSMISSION 0
#define ENABLE_AREA_LIGHT_VALIDATION 0
// 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 = DiffuseLambertian(surface.albedo, surface.normal, dirToLight, lightingData.diffuseResponse);
diffuse *= lightIntensity;
return diffuse;
}
float3 GetSpecularLighting(Surface surface, LightingData lightingData, const float3 lightIntensity, const float3 dirToLight)
{
float3 specular = SpecularGGX(lightingData.dirToCamera, dirToLight, surface.normal, surface.specularF0, lightingData.NdotV, surface.roughnessA2, lightingData.multiScatterCompensation);
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;
};
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 * lightingData.diffuseAmbientOcclusion;
lightingOutput.m_albedo.a = lightingData.specularOcclusion;
lightingOutput.m_normal.rgb = EncodeNormalSignedOctahedron(surface.normal);
lightingOutput.m_normal.a = o_specularF0_enableMultiScatterCompensation ? 1.0f : 0.0f;
return lightingOutput;
}
PbrLightingOutput DebugOutput(float3 color)
{
PbrLightingOutput output = (PbrLightingOutput)0;
float3 defaultNormal = float3(0.0f, 0.0f, 1.0f);
output.m_diffuseColor = float4(color.rgb, 1.0f);
output.m_normal.rgb = EncodeNormalSignedOctahedron(defaultNormal);
return output;
}
@@ -88,8 +88,10 @@ void LightingData::FinalizeLighting(float3 transmissionTint)
FinalizeLighting();
// Transmitted light
#if ENABLE_TRANSMISSION
if(o_transmission_mode != TransmissionMode::None)
{
diffuseLighting += translucentBackLighting * transmissionTint;
}
#endif
}
@@ -8,6 +8,8 @@
#pragma once
#define ENABLE_TRANSMISSION 0
// Include options first
#include <Atom/Features/PBR/LightingOptions.azsli>
@@ -8,6 +8,50 @@
#pragma once
// --- Light Defines ---
#ifndef ENABLE_AREA_LIGHT_VALIDATION
#define ENABLE_AREA_LIGHT_VALIDATION 1
#endif
#ifndef ENABLE_AREA_LIGHTS
#define ENABLE_AREA_LIGHTS 1
#endif
#ifndef ENABLE_SPHERE_LIGHTS
#define ENABLE_SPHERE_LIGHTS ENABLE_AREA_LIGHTS
#endif
#ifndef ENABLE_DISK_LIGHTS
#define ENABLE_DISK_LIGHTS ENABLE_AREA_LIGHTS
#endif
#ifndef ENABLE_CAPSULE_LIGHTS
#define ENABLE_CAPSULE_LIGHTS ENABLE_AREA_LIGHTS
#endif
#ifndef ENABLE_QUAD_LIGHTS
#define ENABLE_QUAD_LIGHTS ENABLE_AREA_LIGHTS
#endif
#ifndef ENABLE_POLYGON_LTC_LIGHTS
#define ENABLE_POLYGON_LTC_LIGHTS ENABLE_AREA_LIGHTS
#endif
// --- Material defines ---
#ifndef ENABLE_CLEAR_COAT
#define ENABLE_CLEAR_COAT 1
#endif
#ifndef ENABLE_TRANSMISSION
#define ENABLE_TRANSMISSION 1
#endif
// --- Shader Options ---
option bool o_specularF0_enableMultiScatterCompensation = true;
option bool o_enableShadows = true;
option bool o_enableDirectionalLights = true;
@@ -15,8 +59,14 @@ option bool o_enablePunctualLights = true;
option bool o_enableAreaLights = true;
option bool o_enableIBL = true;
option bool o_enableSubsurfaceScattering = false;
option bool o_clearCoat_feature_enabled = false;
option enum class TransmissionMode {None, ThickObject, ThinObject} o_transmission_mode;
option bool o_meshUseForwardPassIBLSpecular = false;
option bool o_materialUseForwardPassIBLSpecular = false;
option bool o_area_light_validation = false;
#if ENABLE_CLEAR_COAT
option bool o_clearCoat_feature_enabled = false;
#endif
#if ENABLE_TRANSMISSION
option enum class TransmissionMode {None, ThickObject, ThinObject} o_transmission_mode;
#endif
@@ -224,14 +224,21 @@ void ApplyCapsuleLights(Surface surface, inout LightingData lightingData)
uint currLightIndex = lightingData.tileIterator.GetValue();
lightingData.tileIterator.LoadAdvance();
#if ENABLE_CAPSULE_LIGHTS
ViewSrg::CapsuleLight light = ViewSrg::m_capsuleLights[currLightIndex];
#if ENABLE_AREA_LIGHT_VALIDATION
if (o_area_light_validation)
{
ValidateCapsuleLight(light, surface, lightingData);
}
else
#endif
{
ApplyCapsuleLight(light, surface, lightingData);
}
#endif
}
}
@@ -27,10 +27,12 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData)
surface.vertexNormal,
debugInfo);
#if ENABLE_TRANSMISSION
if (o_transmission_mode == TransmissionMode::ThickObject)
{
backShadowRatio = DirectionalLightShadow::GetThickness(shadowIndex, lightingData.shadowCoords);
}
#endif
}
// Add the lighting contribution for each directional light
@@ -56,10 +58,12 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData)
currentLitRatio = (index == shadowIndex) ? litRatio : 1.;
currentBackShadowRatio = 1.0 - currentLitRatio;
#if ENABLE_TRANSMISSION
if (o_transmission_mode == TransmissionMode::ThickObject)
{
currentBackShadowRatio = (index == shadowIndex) ? backShadowRatio : 0.;
}
#endif
}
lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio;
@@ -90,12 +90,14 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat
// Use backShadowRatio to carry thickness from shadow map for thick mode
backShadowRatio = 1.0 - litRatio;
#if ENABLE_TRANSMISSION
if (o_transmission_mode == TransmissionMode::ThickObject)
{
backShadowRatio = ProjectedShadow::GetThickness(
light.m_shadowIndex,
surface.position);
}
#endif
}
if (useConeAngle && dotWithDirection < light.m_cosInnerConeAngle) // in penumbra
@@ -209,15 +211,21 @@ void ApplyDiskLights(Surface surface, inout LightingData lightingData)
uint currLightIndex = lightingData.tileIterator.GetValue();
lightingData.tileIterator.LoadAdvance();
#if ENABLE_DISK_LIGHTS
ViewSrg::DiskLight light = ViewSrg::m_diskLights[currLightIndex];
#if ENABLE_AREA_LIGHT_VALIDATION
if (o_area_light_validation)
{
ValidateDiskLight(light, surface, lightingData);
}
else
#endif
{
ApplyDiskLight(light, surface, lightingData);
}
#endif
}
}
@@ -98,6 +98,7 @@ void ApplyIBL(Surface surface, inout LightingData lightingData)
float3 iblSpecular = GetIblSpecular(surface.position, surface.normal, surface.specularF0, surface.roughnessLinear, lightingData.dirToCamera, lightingData.brdf);
iblSpecular *= lightingData.multiScatterCompensation;
#if ENABLE_CLEAR_COAT
if (o_clearCoat_feature_enabled && surface.clearCoat.factor > 0.0f)
{
float clearCoatNdotV = saturate(dot(surface.clearCoat.normal, lightingData.dirToCamera));
@@ -115,6 +116,7 @@ void ApplyIBL(Surface surface, inout LightingData lightingData)
float3 clearCoatResponse = FresnelSchlickWithRoughness(clearCoatNdotV, clearCoatSpecularF0, surface.clearCoat.roughness) * surface.clearCoat.factor;
iblSpecular = iblSpecular * (1.0 - clearCoatResponse) * (1.0 - clearCoatResponse) + clearCoatIblSpecular;
}
#endif
float exposure = ObjectSrg::m_reflectionProbeData.m_useReflectionProbe ? pow(2.0, ObjectSrg::m_reflectionProbeData.m_exposure) : globalIblExposure;
lightingData.specularLighting += (iblSpecular * exposure);
@@ -13,9 +13,6 @@
#include <Atom/Features/PBR/BackLighting.azsli>
#include <Atom/Features/PBR/Hammersley.azsli>
option bool o_area_light_validation = false;
//! 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)
{
@@ -403,6 +403,7 @@ void LtcQuadEvaluate(
float2 schlick = ltcAmpMatrix.Sample(PassSrg::LinearSampler, ltcCoords).xy;
float3 specularRgb = specular * (schlick.x * surface.specularF0 + (1.0 - surface.specularF0) * schlick.y);
#if ENABLE_CLEAR_COAT
if(o_clearCoat_feature_enabled)
{
int vertexCountCc = LtcQuadTransformAndClip(surface.clearCoat.normal, lightingData.dirToCamera, p, polygon);
@@ -422,6 +423,7 @@ void LtcQuadEvaluate(
specularRgb = (specularRgb * (1.0 - F)) + (clearCoatSpecular * F);
}
}
#endif
diffuseOut = diffuse;
specularOut = specularRgb;
@@ -620,6 +622,7 @@ void LtcPolygonEvaluate(
float2 schlick = ltcAmpMatrix.Sample(PassSrg::LinearSampler, ltcCoords).xy;
float3 specularRgb = specular * ((schlick.x * surface.specularF0) + (1.0 - surface.specularF0) * schlick.y);
#if ENABLE_CLEAR_COAT
if(o_clearCoat_feature_enabled)
{
// Rotate ltc matrix
@@ -660,6 +663,7 @@ void LtcPolygonEvaluate(
specularRgb = (specularRgb * (1.0 - F)) + (specularCc * F);
}
}
#endif
diffuseOut = diffuse;
specularRgbOut = specularRgb;
@@ -99,12 +99,14 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD
// Use backShadowRatio to carry thickness from shadow map for thick mode
backShadowRatio = 1.0 - litRatio;
#if ENABLE_TRANSMISSION
if (o_transmission_mode == TransmissionMode::ThickObject)
{
backShadowRatio = ProjectedShadow::GetThickness(
shadowIndex,
surface.position);
}
#endif
}
// Diffuse contribution
@@ -177,15 +179,21 @@ void ApplyPointLights(Surface surface, inout LightingData lightingData)
uint currLightIndex = lightingData.tileIterator.GetValue();
lightingData.tileIterator.LoadAdvance();
#if ENABLE_SPHERE_LIGHTS
ViewSrg::PointLight light = ViewSrg::m_pointLights[currLightIndex];
#if ENABLE_AREA_LIGHT_VALIDATION
if (o_area_light_validation)
{
ValidatePointLight(light, surface, lightingData);
}
else
#endif
{
ApplyPointLight(light, surface, lightingData);
}
#endif
}
}
@@ -68,10 +68,12 @@ void ApplyPoylgonLight(ViewSrg::PolygonLight light, Surface surface, inout Light
void ApplyPolygonLights(Surface surface, inout LightingData lightingData)
{
#if ENABLE_POLYGON_LTC_LIGHTS
for (uint currLightIndex = 0; currLightIndex < ViewSrg::m_polygonLightCount; ++currLightIndex)
{
ViewSrg::PolygonLight light = ViewSrg::m_polygonLights[currLightIndex];
ApplyPoylgonLight(light, surface, lightingData);
}
#endif
}
@@ -245,16 +245,22 @@ void ApplyQuadLights(Surface surface, inout LightingData lightingData)
{
uint currLightIndex = lightingData.tileIterator.GetValue();
lightingData.tileIterator.LoadAdvance();
#if ENABLE_QUAD_LIGHTS
ViewSrg::QuadLight light = ViewSrg::m_quadLights[currLightIndex];
#if ENABLE_AREA_LIGHT_VALIDATION
if (o_area_light_validation)
{
ValidateQuadLight(light, surface, lightingData);
}
else
#endif
{
ApplyQuadLight(light, surface, lightingData);
}
#endif
}
}
@@ -8,6 +8,8 @@
#pragma once
#if ENABLE_CLEAR_COAT
class ClearCoatSurfaceData
{
float factor; //!< clear coat strength factor
@@ -23,3 +25,5 @@ void ClearCoatSurfaceData::InitializeToZero()
roughness = 0.0f;
normal = float3(0.0f, 0.0f, 0.0f);
}
#endif
@@ -15,8 +15,14 @@
class Surface
{
#if ENABLE_CLEAR_COAT
ClearCoatSurfaceData clearCoat;
#endif
#if ENABLE_TRANSMISSION
TransmissionSurfaceData transmission; // This is not actually used for Standard PBR, but must be present for common lighting code to compile
#endif
// ------- BasePbrSurfaceData -------
@@ -37,7 +43,6 @@ class Surface
//! Sets albedo and specularF0 using metallic workflow
void SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic);
};
// Specular Anti-Aliasing technique from this paper:
@@ -8,6 +8,8 @@
#pragma once
#if ENABLE_TRANSMISSION
class TransmissionSurfaceData
{
float3 tint;
@@ -23,3 +25,5 @@ void TransmissionSurfaceData::InitializeToZero()
thickness = 0.0f;
transmissionParams = float4(0.0f, 0.0f, 0.0f, 0.0f);
}
#endif
@@ -13,10 +13,23 @@
#ifdef QUALITY_LOW_END
// Unifies the forward output into a single lighting buffer instead of splitting it into a GBuffer
#ifndef UNIFIED_FORWARD_OUTPUT
#define UNIFIED_FORWARD_OUTPUT 1
#endif
// Forces IBL lighting to be executed in the forward pass instead of subsequent refleciton passes
#ifndef FORCE_IBL_IN_FORWARD_PASS
#define FORCE_IBL_IN_FORWARD_PASS 1
#endif
// Forces removal of area light validation code
#ifndef ENABLE_AREA_LIGHT_VALIDATION
#define ENABLE_AREA_LIGHT_VALIDATION 0
#endif
// Uncomment to disable all area light calcuation
// #ifndef ENABLE_AREA_LIGHTS
// #define ENABLE_AREA_LIGHTS 0
// #endif
#endif
@@ -179,9 +179,8 @@ ForwardPassOutput AutoBrick_ForwardPassPS(VSOutput IN)
const float specularF0Factor = 0.5f;
surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic);
// Clear Coat, Transmission
// Clear Coat
surface.clearCoat.InitializeToZero();
surface.transmission.InitializeToZero();
// ------- LightingData -------
@@ -213,7 +212,7 @@ ForwardPassOutput AutoBrick_ForwardPassPS(VSOutput IN)
ApplyIBL(surface, lightingData);
// Finalize Lighting
lightingData.FinalizeLighting(surface.transmission.tint);
lightingData.FinalizeLighting();
PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha);
@@ -71,9 +71,8 @@ ForwardPassOutput MinimalPBR_MainPassPS(VSOutput IN)
const float specularF0Factor = 0.5f;
surface.SetAlbedoAndSpecularF0(MinimalPBRSrg::m_baseColor, specularF0Factor, MinimalPBRSrg::m_metallic);
// Clear Coat, Transmission
// Clear Coat
surface.clearCoat.InitializeToZero();
surface.transmission.InitializeToZero();
// ------- LightingData -------
@@ -104,7 +103,7 @@ ForwardPassOutput MinimalPBR_MainPassPS(VSOutput IN)
ApplyIBL(surface, lightingData);
// Finalize Lighting
lightingData.FinalizeLighting(surface.transmission.tint);
lightingData.FinalizeLighting();
PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha);