diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Presets/PBR/metal_gold.material b/Gems/Atom/Feature/Common/Assets/Materials/Presets/PBR/metal_gold.material index 6ee7eed53f..d7b99e748a 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Presets/PBR/metal_gold.material +++ b/Gems/Atom/Feature/Common/Assets/Materials/Presets/PBR/metal_gold.material @@ -1,6 +1,6 @@ { "description": "", - "materialType": "Materials\\Types\\StandardPBR.materialtype", + "materialType": "Materials\\Types\\BasePBR.materialtype", "parentMaterial": "", "materialTypeVersion": 3, "properties": { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Presets/PBR/metal_gold_matte.material b/Gems/Atom/Feature/Common/Assets/Materials/Presets/PBR/metal_gold_matte.material index 6fa842b6f7..aab80cb271 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Presets/PBR/metal_gold_matte.material +++ b/Gems/Atom/Feature/Common/Assets/Materials/Presets/PBR/metal_gold_matte.material @@ -1,6 +1,6 @@ { "description": "", - "materialType": "Materials\\Types\\StandardPBR.materialtype", + "materialType": "Materials\\Types\\BasePBR.materialtype", "parentMaterial": "", "materialTypeVersion": 3, "properties": { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Presets/PBR/metal_gold_polished.material b/Gems/Atom/Feature/Common/Assets/Materials/Presets/PBR/metal_gold_polished.material index 55a5412af1..104865ead5 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Presets/PBR/metal_gold_polished.material +++ b/Gems/Atom/Feature/Common/Assets/Materials/Presets/PBR/metal_gold_polished.material @@ -1,6 +1,6 @@ { "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", + "materialType": "Materials/Types/BasePBR.materialtype", "parentMaterial": "", "materialTypeVersion": 3, "properties": { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR.materialtype new file mode 100644 index 0000000000..5765537120 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR.materialtype @@ -0,0 +1,605 @@ +{ + "description": "Material Type with properties used to define Base PBR, a metallic-roughness Physically-Based Rendering (PBR) material shading model.", + "version": 0, + "propertyLayout": { + "groups": [ + { + "name": "baseColor", + "displayName": "Base Color", + "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." + }, + { + "name": "metallic", + "displayName": "Metallic", + "description": "Properties for configuring whether the surface is metallic or not." + }, + { + "name": "roughness", + "displayName": "Roughness", + "description": "Properties for configuring how rough the surface appears." + }, + { + "name": "specularF0", + "displayName": "Specular Reflectance f0", + "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces." + }, + { + "name": "normal", + "displayName": "Normal", + "description": "Properties related to configuring surface normal." + }, + { + "name": "uv", + "displayName": "UVs", + "description": "Properties for configuring UV transforms." + }, + { + // Note: this property group is used in the DiffuseGlobalIllumination pass, it is not read by the BasePBR shader + "name": "irradiance", + "displayName": "Irradiance", + "description": "Properties for configuring the irradiance used in global illumination." + }, + { + "name": "general", + "displayName": "General Settings", + "description": "General settings." + } + ], + "properties": { + "general": [ + { + "name": "doubleSided", + "displayName": "Double-sided", + "description": "Whether to render back-faces or just front-faces.", + "type": "Bool" + }, + { + "name": "applySpecularAA", + "displayName": "Apply Specular AA", + "description": "Whether to apply specular anti-aliasing in the shader.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "name": "o_applySpecularAA" + } + }, + { + "name": "enableShadows", + "displayName": "Enable Shadows", + "description": "Whether to use the shadow maps.", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "name": "o_enableShadows" + } + }, + { + "name": "enableDirectionalLights", + "displayName": "Enable Directional Lights", + "description": "Whether to use directional lights.", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "name": "o_enableDirectionalLights" + } + }, + { + "name": "enablePunctualLights", + "displayName": "Enable Punctual Lights", + "description": "Whether to use punctual lights.", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "name": "o_enablePunctualLights" + } + }, + { + "name": "enableAreaLights", + "displayName": "Enable Area Lights", + "description": "Whether to use area lights.", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "name": "o_enableAreaLights" + } + }, + { + "name": "enableIBL", + "displayName": "Enable IBL", + "description": "Whether to use Image Based Lighting (IBL).", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "name": "o_enableIBL" + } + }, + { + "name": "forwardPassIBLSpecular", + "displayName": "Forward Pass IBL Specular", + "description": "Whether to apply IBL specular in the forward pass.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "name": "o_materialUseForwardPassIBLSpecular" + } + } + ], + "baseColor": [ + { + "name": "color", + "displayName": "Color", + "description": "Color is displayed as sRGB but the values are stored as linear color.", + "type": "Color", + "defaultValue": [ 1.0, 1.0, 1.0 ], + "connection": { + "type": "ShaderInput", + "name": "m_baseColor" + } + }, + { + "name": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_baseColorFactor" + } + }, + { + "name": "textureMap", + "displayName": "Texture", + "description": "Base color texture map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_baseColorMap" + } + }, + { + "name": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Base color map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_baseColorMapUvIndex" + } + }, + { + "name": "textureBlendMode", + "displayName": "Texture Blend Mode", + "description": "Selects the equation to use when combining Color, Factor, and Texture.", + "type": "Enum", + "enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ], + "defaultValue": "Multiply", + "connection": { + "type": "ShaderOption", + "name": "o_baseColorTextureBlendMode" + } + } + ], + "metallic": [ + { + "name": "factor", + "displayName": "Factor", + "description": "This value is linear, black is non-metal and white means raw metal.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_metallicFactor" + } + }, + { + "name": "textureMap", + "displayName": "Texture", + "description": "", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_metallicMap" + } + }, + { + "name": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Metallic map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_metallicMapUvIndex" + } + } + ], + "roughness": [ + { + "name": "textureMap", + "displayName": "Texture", + "description": "Texture for defining surface roughness.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_roughnessMap" + } + }, + { + "name": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Roughness map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_roughnessMapUvIndex" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "name": "lowerBound", + "displayName": "Lower Bound", + "description": "The roughness value that corresponds to black in the texture.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_roughnessLowerBound" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "name": "upperBound", + "displayName": "Upper Bound", + "description": "The roughness value that corresponds to white in the texture.", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_roughnessUpperBound" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "name": "factor", + "displayName": "Factor", + "description": "Controls the roughness value", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_roughnessFactor" + } + } + ], + "specularF0": [ + { + "name": "factor", + "displayName": "Factor", + "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", + "type": "Float", + "defaultValue": 0.5, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_specularF0Factor" + } + }, + { + "name": "textureMap", + "displayName": "Texture", + "description": "Texture for defining surface reflectance.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_specularF0Map" + } + }, + { + "name": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Specular reflection map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_specularF0MapUvIndex" + } + }, + // Consider moving this to the "general" group to be consistent with StandardMultilayerPBR + { + "name": "enableMultiScatterCompensation", + "displayName": "Multiscattering Compensation", + "description": "Whether to enable multiple scattering compensation.", + "type": "Bool", + "connection": { + "type": "ShaderOption", + "name": "o_specularF0_enableMultiScatterCompensation" + } + } + ], + "normal": [ + { + "name": "textureMap", + "displayName": "Texture", + "description": "Texture for defining surface normal direction.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_normalMap" + } + }, + { + "name": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture, or just rely on vertex normals.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Normal map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_normalMapUvIndex" + } + }, + { + "name": "flipX", + "displayName": "Flip X Channel", + "description": "Flip tangent direction for this normal map.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderInput", + "name": "m_flipNormalX" + } + }, + { + "name": "flipY", + "displayName": "Flip Y Channel", + "description": "Flip bitangent direction for this normal map.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderInput", + "name": "m_flipNormalY" + } + }, + { + "name": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the values", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "name": "m_normalFactor" + } + } + ], + "uv": [ + { + "name": "center", + "displayName": "Center", + "description": "Center point for scaling and rotation transformations.", + "type": "vector2", + "vectorLabels": [ "U", "V" ], + "defaultValue": [ 0.5, 0.5 ] + }, + { + "name": "tileU", + "displayName": "Tile U", + "description": "Scales texture coordinates in U.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + }, + { + "name": "tileV", + "displayName": "Tile V", + "description": "Scales texture coordinates in V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + }, + { + "name": "offsetU", + "displayName": "Offset U", + "description": "Offsets texture coordinates in the U direction.", + "type": "float", + "defaultValue": 0.0, + "min": -1.0, + "max": 1.0 + }, + { + "name": "offsetV", + "displayName": "Offset V", + "description": "Offsets texture coordinates in the V direction.", + "type": "float", + "defaultValue": 0.0, + "min": -1.0, + "max": 1.0 + }, + { + "name": "rotateDegrees", + "displayName": "Rotate", + "description": "Rotates the texture coordinates (degrees).", + "type": "float", + "defaultValue": 0.0, + "min": -180.0, + "max": 180.0, + "step": 1.0 + }, + { + "name": "scale", + "displayName": "Scale", + "description": "Scales texture coordinates in both U and V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + } + ], + "irradiance": [ + // Note: this property group is used in the DiffuseGlobalIllumination pass and not by the main forward shader + { + "name": "color", + "displayName": "Color", + "description": "Color is displayed as sRGB but the values are stored as linear color.", + "type": "Color", + "defaultValue": [ 1.0, 1.0, 1.0 ] + }, + { + "name": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the irradiance color values. Zero (0.0) is black, white (1.0) is full color.", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0 + } + ] + } + }, + "shaders": [ + { + "file": "./BasePBR_ForwardPass.shader", + "tag": "ForwardPass_EDS" + }, + { + "file": "./BasePBR_LowEndForward.shader", + "tag": "LowEndForward_EDS" + }, + { + "file": "Shaders/Shadow/Shadowmap.shader", + "tag": "Shadowmap" + }, + { + "file": "Shaders/Depth/DepthPass.shader", + "tag": "DepthPass" + }, + { + "file": "Shaders/MotionVector/MeshMotionVector.shader", + "tag": "MeshMotionVector" + } + ], + "functors": [ + { + // Maps 2D scale, offset, and rotate properties into a float3x3 transform matrix. + "type": "Transform2D", + "args": { + "transformOrder": [ "Rotate", "Translate", "Scale" ], + "centerProperty": "uv.center", + "scaleProperty": "uv.scale", + "scaleXProperty": "uv.tileU", + "scaleYProperty": "uv.tileV", + "translateXProperty": "uv.offsetU", + "translateYProperty": "uv.offsetV", + "rotateDegreesProperty": "uv.rotateDegrees", + "float3x3ShaderInput": "m_uvMatrix", + "float3x3InverseShaderInput": "m_uvMatrixInverse" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "baseColor.textureMap", + "useTextureProperty": "baseColor.useTexture", + "dependentProperties": ["baseColor.textureMapUv", "baseColor.textureBlendMode"], + "shaderOption": "o_baseColor_useTexture" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "specularF0.textureMap", + "useTextureProperty": "specularF0.useTexture", + "dependentProperties": ["specularF0.textureMapUv"], + "shaderOption": "o_specularF0_useTexture" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "normal.textureMap", + "useTextureProperty": "normal.useTexture", + "dependentProperties": ["normal.textureMapUv", "normal.factor", "normal.flipX", "normal.flipY"], + "shaderOption": "o_normal_useTexture" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_Roughness.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_Metallic.lua" + } + } + ], + "uvNameMap": { + "UV0": "Tiled", + "UV1": "Unwrapped" + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_Common.azsli new file mode 100644 index 0000000000..dbec7458fc --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_Common.azsli @@ -0,0 +1,59 @@ +/* + * 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 + +#include +#include +#include +#include +#include + +#include "MaterialInputs/BaseColorInput.azsli" +#include "MaterialInputs/RoughnessInput.azsli" +#include "MaterialInputs/MetallicInput.azsli" +#include "MaterialInputs/SpecularInput.azsli" +#include "MaterialInputs/NormalInput.azsli" +#include "MaterialInputs/UvSetCount.azsli" + +ShaderResourceGroup MaterialSrg : SRG_PerMaterial +{ + // Auto-generate material SRG fields for common inputs + COMMON_SRG_INPUTS_BASE_COLOR() + COMMON_SRG_INPUTS_ROUGHNESS() + COMMON_SRG_INPUTS_METALLIC() + COMMON_SRG_INPUTS_SPECULAR_F0() + COMMON_SRG_INPUTS_NORMAL() + + + float3x3 m_uvMatrix; + float4 m_pad1; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. + float3x3 m_uvMatrixInverse; + float4 m_pad2; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. + + Sampler m_sampler + { + AddressU = Wrap; + AddressV = Wrap; + MinFilter = Linear; + MagFilter = Linear; + MipFilter = Linear; + MaxAnisotropy = 16; + }; + + Texture2D m_brdfMap; + + Sampler m_samplerBrdf + { + AddressU = Clamp; + AddressV = Clamp; + MinFilter = Linear; + MagFilter = Linear; + MipFilter = Linear; + }; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.azsl new file mode 100644 index 0000000000..96318f2284 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.azsl @@ -0,0 +1,199 @@ +/* + * 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 + * + */ + +#include "Atom/Features/ShaderQualityOptions.azsli" + +#include "BasePBR_Common.azsli" + +// SRGs +#include +#include + +// Pass Output +#include + +// Utility +#include + +// Custom Surface & Lighting +#include + +// Decals +#include + + +// ---------- Material Parameters ---------- + +COMMON_OPTIONS_BASE_COLOR() +COMMON_OPTIONS_ROUGHNESS() +COMMON_OPTIONS_METALLIC() +COMMON_OPTIONS_SPECULAR_F0() +COMMON_OPTIONS_NORMAL() + +// ---------- Vertex Shader ---------- + +struct VSInput +{ + // Base fields (required by the template azsli file)... + float3 m_position : POSITION; + float3 m_normal : NORMAL; + float4 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + + // Extended fields (only referenced in this azsl file)... + float2 m_uv0 : UV0; + float2 m_uv1 : UV1; +}; + +struct VSOutput +{ + // Base fields (required by the template azsli file)... + // "centroid" is needed for SV_Depth to compile + linear centroid float4 m_position : SV_Position; + float3 m_normal: NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float3 m_worldPosition : UV0; + float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV3; + + // Extended fields (only referenced in this azsl file)... + float2 m_uv[UvSetCount] : UV1; +}; + +#include + +VSOutput BasePbr_ForwardPassVS(VSInput IN) +{ + VSOutput OUT; + + float3 worldPosition = mul(ObjectSrg::GetWorldMatrix(), float4(IN.m_position, 1.0)).xyz; + + // By design, only UV0 is allowed to apply transforms. + OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; + OUT.m_uv[1] = IN.m_uv1; + + // No parallax in BaseBPR, so do shadow coordinate calculations in vertex shader + bool skipShadowCoords = false; + + VertexHelper(IN, OUT, worldPosition, skipShadowCoords); + + return OUT; +} + + +// ---------- Pixel Shader ---------- + +PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace) +{ + const float3 vertexNormal = normalize(IN.m_normal); + + // ------- Tangents & Bitangets ------- + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; + + if (o_normal_useTexture) + { + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); + } + + Surface surface; + surface.position = IN.m_worldPosition.xyz; + + // ------- Normal ------- + + float2 normalUv = IN.m_uv[MaterialSrg::m_normalMapUvIndex]; + float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms. + surface.vertexNormal = vertexNormal; + surface.normal = GetNormalInputWS(MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, isFrontFace, IN.m_normal, + tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], uvMatrix, o_normal_useTexture, MaterialSrg::m_normalFactor); + + // ------- Base Color ------- + + float2 baseColorUv = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; + float3 sampledColor = GetBaseColorInput(MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, MaterialSrg::m_baseColor.rgb, o_baseColor_useTexture); + float3 baseColor = BlendBaseColor(sampledColor, MaterialSrg::m_baseColor.rgb, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, o_baseColor_useTexture); + + // ------- Metallic ------- + + float2 metallicUv = IN.m_uv[MaterialSrg::m_metallicMapUvIndex]; + float metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_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); + + surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); + + // ------- Roughness ------- + + 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); + surface.CalculateRoughnessA(); + + // ------- 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; + + // Diffuse and Specular response (used in IBL calculations) + lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear); + lightingData.diffuseResponse = float3(1.0, 1.0, 1.0) - lightingData.specularResponse; + + // ------- Multiscatter ------- + + lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation); + + // ------- Lighting Calculation ------- + + // Apply Decals + ApplyDecals(lightingData.tileIterator, surface); + + // Apply Direct Lighting + ApplyDirectLighting(surface, lightingData); + + // Apply Image Based Lighting (IBL) + ApplyIBL(surface, lightingData); + + // Finalize Lighting + lightingData.FinalizeLighting(); + + float alpha = 1.0f; + PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha); + + // Disable subsurface scattering + lightingOutput.m_diffuseColor.w = -1; + + return lightingOutput; +} + + +ForwardPassOutput BasePbr_ForwardPassPS_EDS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + ForwardPassOutput OUT; + PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace); + +#ifdef UNIFIED_FORWARD_OUTPUT + OUT.m_color.rgb = lightingOutput.m_diffuseColor.rgb + lightingOutput.m_specularColor.rgb; + OUT.m_color.a = lightingOutput.m_diffuseColor.a; +#else + OUT.m_diffuseColor = lightingOutput.m_diffuseColor; + OUT.m_specularColor = lightingOutput.m_specularColor; + OUT.m_specularF0 = lightingOutput.m_specularF0; + OUT.m_albedo = lightingOutput.m_albedo; + OUT.m_normal = lightingOutput.m_normal; +#endif + return OUT; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.shader b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.shader new file mode 100644 index 0000000000..377c0eae95 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.shader @@ -0,0 +1,53 @@ +{ + "Source" : "./BasePBR_ForwardPass.azsl", + + "DepthStencilState" : + { + "Depth" : + { + "Enable" : true, + "CompareFunc" : "GreaterEqual" + }, + "Stencil" : + { + "Enable" : true, + "ReadMask" : "0x00", + "WriteMask" : "0xFF", + "FrontFace" : + { + "Func" : "Always", + "DepthFailOp" : "Keep", + "FailOp" : "Keep", + "PassOp" : "Replace" + }, + "BackFace" : + { + "Func" : "Always", + "DepthFailOp" : "Keep", + "FailOp" : "Keep", + "PassOp" : "Replace" + } + } + }, + + "CompilerHints" : { + "DisableOptimizations" : false + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "BasePbr_ForwardPassVS", + "type": "Vertex" + }, + { + "name": "BasePbr_ForwardPassPS_EDS", + "type": "Fragment" + } + ] + }, + + "DrawList" : "forward" +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.shadervariantlist b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.shadervariantlist new file mode 100644 index 0000000000..c817c793bd --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.shadervariantlist @@ -0,0 +1,29 @@ +{ + "Shader" : "BasePBR_ForwardPass.shader", + "Variants": [ + { + "StableId": 1, + "Options": { + "o_directional_shadow_filtering_method": "ShadowFilterMethod::None" + } + }, + { + "StableId": 2, + "Options": { + "o_directional_shadow_filtering_method": "ShadowFilterMethod::Pcf" + } + }, + { + "StableId": 3, + "Options": { + "o_directional_shadow_filtering_method": "ShadowFilterMethod::Esm" + } + }, + { + "StableId": 4, + "Options": { + "o_directional_shadow_filtering_method": "ShadowFilterMethod::EsmPcf" + } + } + ] +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_LowEndForward.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_LowEndForward.azsl new file mode 100644 index 0000000000..d380045d88 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_LowEndForward.azsl @@ -0,0 +1,13 @@ +/* + * 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 + * + */ + +// NOTE: This file is a temporary workaround until .shader files can #define macros for their .azsl files + +#define QUALITY_LOW_END 1 + +#include "BasePBR_ForwardPass.azsl" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_LowEndForward.shader b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_LowEndForward.shader new file mode 100644 index 0000000000..005b001063 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_LowEndForward.shader @@ -0,0 +1,59 @@ +{ + // Note: "LowEnd" shaders are for supporting the low end pipeline + // These shaders can be safely added to materials without incurring additional runtime draw + // items as draw items for shaders are only created if the scene has a pass with a matching + // DrawListTag. If your pipeline doesn't have a "lowEndForward" DrawListTag, no draw items + // for this shader will be created. + + "Source" : "./BasePBR_LowEndForward.azsl", + + "DepthStencilState" : + { + "Depth" : + { + "Enable" : true, + "CompareFunc" : "GreaterEqual" + }, + "Stencil" : + { + "Enable" : true, + "ReadMask" : "0x00", + "WriteMask" : "0xFF", + "FrontFace" : + { + "Func" : "Always", + "DepthFailOp" : "Keep", + "FailOp" : "Keep", + "PassOp" : "Replace" + }, + "BackFace" : + { + "Func" : "Always", + "DepthFailOp" : "Keep", + "FailOp" : "Keep", + "PassOp" : "Replace" + } + } + }, + + "CompilerHints" : { + "DisableOptimizations" : false + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "BasePbr_ForwardPassVS", + "type": "Vertex" + }, + { + "name": "BasePbr_ForwardPassPS_EDS", + "type": "Fragment" + } + ] + }, + + "DrawList" : "lowEndForward" +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl index 5b05e48d3b..3617b7fb04 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl @@ -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; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.shader b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.shader index d8df49f4b0..7c7a19efc9 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.shader +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.shader @@ -30,7 +30,6 @@ } }, - "CompilerHints" : { "DisableOptimizations" : false }, diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli index dfd5522f5c..d33780641d 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli @@ -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; } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/BaseLighting.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/BaseLighting.azsli new file mode 100644 index 0000000000..8bd645498c --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/BaseLighting.azsli @@ -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 + +// Then include custom surface and lighting data types +#include +#include + +#include +#include + +// 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 +#include + + +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; +} diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli index 878bed02d4..721c9e13cc 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli @@ -56,10 +56,10 @@ class LightingData void LightingData::Init(float3 positionWS, float3 normal, float roughnessLinear) { - diffuseLighting = 0; - specularLighting = 0; - translucentBackLighting = 0; - multiScatterCompensation = 1.0f; + diffuseLighting = float3(0.0, 0.0, 0.0); + specularLighting = float3(0.0, 0.0, 0.0); + translucentBackLighting = float3(0.0, 0.0, 0.0); + multiScatterCompensation = float3(1.0f, 1.0f, 1.0f); emissiveLighting = float3(0.0f, 0.0f, 0.0f); diffuseAmbientOcclusion = 1.0f; specularOcclusion = 1.0f; @@ -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 } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/StandardLighting.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/StandardLighting.azsli index 773c86ff0f..ad3c9715d4 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/StandardLighting.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/StandardLighting.azsli @@ -8,6 +8,8 @@ #pragma once +#define ENABLE_TRANSMISSION 0 + // Include options first #include diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingOptions.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingOptions.azsli index f807acc374..9febc6a9f7 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingOptions.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingOptions.azsli @@ -8,6 +8,58 @@ #pragma once +// --- Note: About this file --- +// This file uses #defines to completely strip out certain lighting features from shaders +// This enables us to avoid code duplication and write an uber-esque shader code and then +// be able to adjust the code for different use cases (for example basic materials can strip +// away transimission related code used for foliage). These are different from shader options +// in that shader options allow more user flexibility to adjust materials at runtime, whereas +// these #define options are for customizing and optimizing material types (like BasePBR) + +// --- 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 +67,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 diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/CapsuleLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/CapsuleLight.azsli index e6b18df9b5..733ea2dbea 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/CapsuleLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/CapsuleLight.azsli @@ -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 } } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli index 1eee53a24f..7cf10f13a3 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli @@ -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; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli index 63f671f021..79b377c568 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli @@ -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 } } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli index abc2d3d3bd..e813993794 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli @@ -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); diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/LightTypesCommon.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/LightTypesCommon.azsli index f0169e29b8..16adbba280 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/LightTypesCommon.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/LightTypesCommon.azsli @@ -13,9 +13,6 @@ #include #include -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) { diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ltc.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ltc.azsli index 531eb6e885..0f542870a8 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ltc.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ltc.azsli @@ -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; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli index 92f4065931..883d86af48 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli @@ -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 } } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PolygonLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PolygonLight.azsli index 07fe6d4f00..e4e25e351b 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PolygonLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PolygonLight.azsli @@ -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 } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/QuadLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/QuadLight.azsli index 63515339d8..a705e663c2 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/QuadLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/QuadLight.azsli @@ -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 } } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/ClearCoatSurfaceData.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/ClearCoatSurfaceData.azsli index ff8d4c0a25..6e30f55af4 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/ClearCoatSurfaceData.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/ClearCoatSurfaceData.azsli @@ -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 diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli index e1b3ff8206..cf4edba923 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli @@ -15,8 +15,10 @@ class Surface { + +#if ENABLE_CLEAR_COAT ClearCoatSurfaceData clearCoat; - TransmissionSurfaceData transmission; // This is not actually used for Standard PBR, but must be present for common lighting code to compile +#endif // ------- BasePbrSurfaceData ------- @@ -37,7 +39,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: diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/TransmissionSurfaceData.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/TransmissionSurfaceData.azsli index 9b575de3ec..dda62d85e5 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/TransmissionSurfaceData.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/TransmissionSurfaceData.azsli @@ -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 diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ShaderQualityOptions.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ShaderQualityOptions.azsli index 32cd30b97e..430e095bf4 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ShaderQualityOptions.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ShaderQualityOptions.azsli @@ -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 -#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 diff --git a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake index 1844d26e10..e6ad71bde3 100644 --- a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake +++ b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake @@ -10,6 +10,12 @@ set(FILES Materials/Special/ShadowCatcher.azsl Materials/Special/ShadowCatcher.materialtype Materials/Special/ShadowCatcher.shader + Materials/Types/BasePBR.materialtype + Materials/Types/BasePBR_Common.azsli + Materials/Types/BasePBR_ForwardPass.azsl + Materials/Types/BasePBR_ForwardPass.shader + Materials/Types/BasePBR_LowEndForward.azsl + Materials/Types/BasePBR_LowEndForward.shader Materials/Types/EnhancedPBR.materialtype Materials/Types/EnhancedPBR_Common.azsli Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl @@ -258,6 +264,7 @@ set(FILES ShaderLib/Atom/Features/PBR/Hammersley.azsli ShaderLib/Atom/Features/PBR/LightingOptions.azsli ShaderLib/Atom/Features/PBR/LightingUtils.azsli + ShaderLib/Atom/Features/PBR/Lighting/BaseLighting.azsli ShaderLib/Atom/Features/PBR/Lighting/DualSpecularLighting.azsli ShaderLib/Atom/Features/PBR/Lighting/EnhancedLighting.azsli ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli diff --git a/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl b/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl index 05ce5f4774..13f1e33ef7 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl +++ b/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl @@ -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); diff --git a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl index fe9e4099d0..140fc57961 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl +++ b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl @@ -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); diff --git a/Gems/Terrain/Assets/Shaders/Terrain/TerrainPBR_ForwardPass.azsl b/Gems/Terrain/Assets/Shaders/Terrain/TerrainPBR_ForwardPass.azsl index c9c3e0ab00..119a81e49c 100644 --- a/Gems/Terrain/Assets/Shaders/Terrain/TerrainPBR_ForwardPass.azsl +++ b/Gems/Terrain/Assets/Shaders/Terrain/TerrainPBR_ForwardPass.azsl @@ -177,9 +177,8 @@ ForwardPassOutput TerrainPBR_MainPassPS(VSOutput IN) surface.CalculateRoughnessA(); } - // Clear Coat, Transmission (Not used for terrain) + // Clear Coat surface.clearCoat.InitializeToZero(); - surface.transmission.InitializeToZero(); // ------- LightingData ------- @@ -211,7 +210,7 @@ ForwardPassOutput TerrainPBR_MainPassPS(VSOutput IN) ApplyIBL(surface, lightingData); // Finalize Lighting - lightingData.FinalizeLighting(surface.transmission.tint); + lightingData.FinalizeLighting(); PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha);