From 8511f61fd3d6fdea6b1bc5e587313d022eb48ee8 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Mon, 13 Dec 2021 12:08:00 -0800 Subject: [PATCH] duplicating standardPBR files for BasePBR Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Materials/Types/BasePBR.materialtype | 1202 +++++++++++++++++ .../Materials/Types/BasePBR_Common.azsli | 95 ++ .../Materials/Types/BasePBR_ForwardPass.azsl | 362 +++++ .../Types/BasePBR_ForwardPass.shader | 54 + .../BasePBR_ForwardPass.shadervariantlist | 29 + .../Types/BasePBR_LowEndForward.azsl | 13 + .../Types/BasePBR_LowEndForward.shader | 59 + .../Materials/Types/BasePBR_ShaderEnable.lua | 82 ++ .../atom_feature_common_asset_files.cmake | 10 + 9 files changed, 1906 insertions(+) create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR.materialtype create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_Common.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.shader create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.shadervariantlist create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_LowEndForward.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_LowEndForward.shader create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ShaderEnable.lua 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..f324394309 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR.materialtype @@ -0,0 +1,1202 @@ +{ + "description": "Material Type with properties used to define Standard PBR, a metallic-roughness Physically-Based Rendering (PBR) material shading model.", + "version": 4, + "versionUpdates": [ + { + "toVersion": 4, + "actions": [ + {"op": "rename", "from": "opacity.doubleSided", "to": "general.doubleSided"} + ] + } + ], + "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": "occlusion", + "displayName": "Occlusion", + "description": "Properties for baked textures that represent geometric occlusion of light." + }, + { + "name": "emissive", + "displayName": "Emissive", + "description": "Properties to add light emission, independent of other lights in the scene." + }, + { + "name": "clearCoat", + "displayName": "Clear Coat", + "description": "Properties for configuring gloss clear coat" + }, + { + "name": "parallax", + "displayName": "Displacement", + "description": "Properties for parallax effect produced by a height map." + }, + { + "name": "opacity", + "displayName": "Opacity", + "description": "Properties for configuring the materials transparency." + }, + { + "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 StandardPBR 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" + } + } + ], + "clearCoat": [ + { + "name": "enable", + "displayName": "Enable", + "description": "Enable clear coat", + "type": "Bool", + "defaultValue": false + }, + { + "name": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the percentage of effect applied", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatFactor" + } + }, + { + "name": "influenceMap", + "displayName": " Influence Map", + "description": "Strength factor texture", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatInfluenceMap" + } + }, + { + "name": "useInfluenceMap", + "displayName": " Use Texture", + "description": "Whether to use the texture, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "influenceMapUv", + "displayName": " UV", + "description": "Strength factor map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatInfluenceMapUvIndex" + } + }, + { + "name": "roughness", + "displayName": "Roughness", + "description": "Clear coat layer roughness", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatRoughness" + } + }, + { + "name": "roughnessMap", + "displayName": " Roughness Map", + "description": "Texture for defining surface roughness", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatRoughnessMap" + } + }, + { + "name": "useRoughnessMap", + "displayName": " Use Texture", + "description": "Whether to use the texture, or just default to the roughness value.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "roughnessMapUv", + "displayName": " UV", + "description": "Roughness map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatRoughnessMapUvIndex" + } + }, + { + "name": "normalStrength", + "displayName": "Normal Strength", + "description": "Scales the impact of the clear coat normal map", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 2.0, + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatNormalStrength" + } + }, + { + "name": "normalMap", + "displayName": "Normal Map", + "description": "Normal map for clear coat layer, as top layer material clear coat doesn't affect by base layer normal map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatNormalMap" + } + }, + { + "name": "useNormalMap", + "displayName": " Use Texture", + "description": "Whether to use the normal map", + "type": "Bool", + "defaultValue": true + }, + { + "name": "normalMapUv", + "displayName": " UV", + "description": "Normal map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatNormalMapUvIndex" + } + } + ], + "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" + } + } + ], + "opacity": [ + { + "name": "mode", + "displayName": "Opacity Mode", + "description": "Indicates the general approach how transparency is to be applied.", + "type": "Enum", + "enumValues": [ "Opaque", "Cutout", "Blended", "TintedTransparent" ], + "defaultValue": "Opaque", + "connection": { + "type": "ShaderOption", + "name": "o_opacity_mode" + } + }, + { + "name": "alphaSource", + "displayName": "Alpha Source", + "description": "Indicates whether to get the opacity texture from the Base Color map (Packed) or from a separate greyscale texture (Split).", + "type": "Enum", + "enumValues": [ "Packed", "Split", "None" ], + "defaultValue": "Packed", + "connection": { + "type": "ShaderOption", + "name": "o_opacity_source" + } + }, + { + "name": "textureMap", + "displayName": "Texture", + "description": "Texture for defining surface opacity.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_opacityMap" + } + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Opacity map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_opacityMapUvIndex" + } + }, + { + "name": "factor", + "displayName": "Factor", + "description": "Factor for cutout threshold and blending", + "type": "Float", + "min": 0.0, + "max": 1.0, + "defaultValue": 0.5, + "connection": { + "type": "ShaderInput", + "name": "m_opacityFactor" + } + }, + { + "name": "alphaAffectsSpecular", + "displayName": "Alpha affects specular", + "description": "How much the alpha value should also affect specular reflection. This should be 0.0 for materials where light can transmit through their physical surface (like glass), but 1.0 when alpha determines the very presence of a surface (like hair or grass)", + "type": "float", + "min": 0.0, + "max": 1.0, + "defaultValue": 0.0, + "connection": { + "type": "ShaderInput", + "name": "m_opacityAffectsSpecularFactor" + } + } + ], + "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 + } + ], + "occlusion": [ + { + "name": "diffuseTextureMap", + "displayName": "Diffuse AO", + "description": "Texture for defining occlusion area for diffuse ambient lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_diffuseOcclusionMap" + } + }, + { + "name": "diffuseUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Diffuse AO map.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "diffuseTextureMapUv", + "displayName": " UV", + "description": "Diffuse AO map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_diffuseOcclusionMapUvIndex" + } + }, + { + "name": "diffuseFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Diffuse AO", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "name": "m_diffuseOcclusionFactor" + } + }, + { + "name": "specularTextureMap", + "displayName": "Specular Cavity", + "description": "Texture for defining occlusion area for specular lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_specularOcclusionMap" + } + }, + { + "name": "specularUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Specular Cavity map.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "specularTextureMapUv", + "displayName": " UV", + "description": "Specular Cavity map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_specularOcclusionMapUvIndex" + } + }, + { + "name": "specularFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Specular Cavity", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "name": "m_specularOcclusionFactor" + } + } + ], + "emissive": [ + { + "name": "enable", + "displayName": "Enable", + "description": "Enable the emissive group", + "type": "Bool", + "defaultValue": false + }, + { + "name": "unit", + "displayName": "Units", + "description": "The photometric units of the Intensity property.", + "type": "Enum", + "enumValues": ["Ev100"], + "defaultValue": "Ev100" + }, + { + "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_emissiveColor" + } + }, + { + "name": "intensity", + "displayName": "Intensity", + "description": "The amount of energy emitted.", + "type": "Float", + "defaultValue": 4, + "min": -10, + "max": 20, + "softMin": -6, + "softMax": 16 + }, + { + "name": "textureMap", + "displayName": "Texture", + "description": "Texture for defining emissive area.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_emissiveMap" + } + }, + { + "name": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Emissive map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_emissiveMapUvIndex" + } + } + ], + "parallax": [ + { + "name": "textureMap", + "displayName": "Height Map", + "description": "Displacement height map to create parallax effect.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_heightmap" + } + }, + { + "name": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the height map.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Height map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_parallaxUvIndex" + } + }, + { + "name": "factor", + "displayName": "Height Map Scale", + "description": "The total height of the height map in local model units.", + "type": "Float", + "defaultValue": 0.05, + "min": 0.0, + "softMax": 0.1, + "connection": { + "type": "ShaderInput", + "name": "m_heightmapScale" + } + }, + { + "name": "offset", + "displayName": "Offset", + "description": "Adjusts the overall displacement amount in local model units.", + "type": "Float", + "defaultValue": 0.0, + "softMin": -0.1, + "softMax": 0.1, + "connection": { + "type": "ShaderInput", + "name": "m_heightmapOffset" + } + }, + { + "name": "algorithm", + "displayName": "Algorithm", + "description": "Select the algorithm to use for parallax mapping.", + "type": "Enum", + "enumValues": [ "Basic", "Steep", "POM", "Relief", "ContactRefinement" ], + "defaultValue": "POM", + "connection": { + "type": "ShaderOption", + "name": "o_parallax_algorithm" + } + }, + { + "name": "quality", + "displayName": "Quality", + "description": "Quality of parallax mapping.", + "type": "Enum", + "enumValues": [ "Low", "Medium", "High", "Ultra" ], + "defaultValue": "Low", + "connection": { + "type": "ShaderOption", + "name": "o_parallax_quality" + } + }, + { + "name": "pdo", + "displayName": "Pixel Depth Offset", + "description": "Enable PDO to offset the original pixel depths. This will affect any shaders using depth, for example, when receiving shadows.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "name": "o_parallax_enablePixelDepthOffset" + } + }, + { + "name": "showClipping", + "displayName": "Show Clipping", + "description": "Highlight areas where the height map is clipped by the mesh surface.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "name": "o_parallax_highlightClipping" + } + } + ], + "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": "./StandardPBR_ForwardPass.shader", + "tag": "ForwardPass" + }, + { + "file": "./StandardPBR_ForwardPass_EDS.shader", + "tag": "ForwardPass_EDS" + }, + { + "file": "./StandardPBR_LowEndForward.shader", + "tag": "LowEndForward" + }, + { + "file": "./StandardPBR_LowEndForward_EDS.shader", + "tag": "LowEndForward_EDS" + }, + { + "file": "Shaders/Shadow/Shadowmap.shader", + "tag": "Shadowmap" + }, + { + "file": "./StandardPBR_Shadowmap_WithPS.shader", + "tag": "Shadowmap_WithPS" + }, + { + "file": "Shaders/Depth/DepthPass.shader", + "tag": "DepthPass" + }, + { + "file": "./StandardPBR_DepthPass_WithPS.shader", + "tag": "DepthPass_WithPS" + }, + { + "file": "Shaders/MotionVector/MeshMotionVector.shader", + "tag": "MeshMotionVector" + }, + // Used by the light culling system to produce accurate depth bounds for this object when it uses blended transparency + { + "file": "Shaders/Depth/DepthPassTransparentMin.shader", + "tag": "DepthPassTransparentMin" + }, + { + "file": "Shaders/Depth/DepthPassTransparentMax.shader", + "tag": "DepthPassTransparentMax" + } + ], + "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" + } + }, + { + // Convert emissive unit. + "type": "ConvertEmissiveUnit", + "args": { + "intensityProperty": "emissive.intensity", + "lightUnitProperty": "emissive.unit", + "shaderInput": "m_emissiveIntensity", + "ev100Index": 0, + "nitIndex" : 1, + "ev100MinMax": [-10, 20], + "nitMinMax": [0.001, 100000.0] + } + }, + { + "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": "UseTexture", + "args": { + "textureProperty": "occlusion.diffuseTextureMap", + "useTextureProperty": "occlusion.diffuseUseTexture", + "dependentProperties": ["occlusion.diffuseTextureMapUv", "occlusion.diffuseFactor"], + "shaderOption": "o_diffuseOcclusion_useTexture" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "occlusion.specularTextureMap", + "useTextureProperty": "occlusion.specularUseTexture", + "dependentProperties": ["occlusion.specularTextureMapUv", "occlusion.specularFactor"], + "shaderOption": "o_specularOcclusion_useTexture" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_ClearCoatState.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_ClearCoatEnableFeature.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_EmissiveState.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_ParallaxState.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_Roughness.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_Metallic.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_HandleOpacityDoubleSided.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_HandleOpacityMode.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_ShaderEnable.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..0aebc11f1d --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_Common.azsli @@ -0,0 +1,95 @@ +/* + * 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/ClearCoatInput.azsli" +#include "MaterialInputs/OcclusionInput.azsli" +#include "MaterialInputs/EmissiveInput.azsli" +#include "MaterialInputs/ParallaxInput.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() + COMMON_SRG_INPUTS_CLEAR_COAT() + COMMON_SRG_INPUTS_OCCLUSION() + COMMON_SRG_INPUTS_EMISSIVE() + COMMON_SRG_INPUTS_PARALLAX() + + uint m_parallaxUvIndex; + + 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. + + float m_opacityFactor; + float m_opacityAffectsSpecularFactor; + Texture2D m_opacityMap; + uint m_opacityMapUvIndex; + + 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; + }; +} + +// Callback function for ParallaxMapping.azsli +DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) +{ + return SampleDepthFromHeightmap(MaterialSrg::m_heightmap, MaterialSrg::m_sampler, uv, uv_ddx, uv_ddy); +} + + +COMMON_OPTIONS_PARALLAX() + +bool ShouldHandleParallax() +{ + // Parallax mapping's non uniform uv transformations break screen space subsurface scattering, disable it when subsurface scattering is enabled. + return !o_enableSubsurfaceScattering && o_parallax_feature_enabled && o_useHeightmap; +} + +bool ShouldHandleParallaxInDepthShaders() +{ + // The depth pass shaders need to calculate parallax when the result could affect the depth buffer, or when + // parallax could affect texel clipping. + return ShouldHandleParallax() && (o_parallax_enablePixelDepthOffset || o_opacity_mode == OpacityMode::Cutout); +} 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..1d5e4ad9e3 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.azsl @@ -0,0 +1,362 @@ +/* + * 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 "StandardPBR_Common.azsli" + +// SRGs +#include +#include + +// Pass Output +#include + +// Utility +#include +#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() +COMMON_OPTIONS_CLEAR_COAT() +COMMON_OPTIONS_OCCLUSION() +COMMON_OPTIONS_EMISSIVE() +// Note COMMON_OPTIONS_PARALLAX is in StandardPBR_Common.azsli because it's needed by all StandardPBR shaders. + +// Alpha +#include "MaterialInputs/AlphaInput.azsli" + +// ---------- 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 StandardPbr_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; + + // Shadow coords will be calculated in the pixel shader in this case + bool skipShadowCoords = ShouldHandleParallax() && o_parallax_enablePixelDepthOffset; + + VertexHelper(IN, OUT, worldPosition, skipShadowCoords); + + return OUT; +} + + +// ---------- Pixel Shader ---------- + +PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depthNDC) +{ + 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 (ShouldHandleParallax() || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture)) + { + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); + } + + // ------- Depth & Parallax ------- + + depthNDC = IN.m_position.z; + + bool displacementIsClipped = false; + + if(ShouldHandleParallax()) + { + + 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_heightmapScale, MaterialSrg::m_heightmapOffset, + ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, + IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depthNDC, IN.m_position.w, displacementIsClipped); + + // Adjust directional light shadow coordinates for parallax correction + if(o_parallax_enablePixelDepthOffset) + { + const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; + if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) + { + DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, vertexNormal, IN.m_shadowCoords); + } + } + } + + Surface surface; + surface.position = IN.m_worldPosition.xyz; + + // ------- Alpha & Clip ------- + + float2 baseColorUv = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; + float2 opacityUv = IN.m_uv[MaterialSrg::m_opacityMapUvIndex]; + float alpha = GetAlphaInputAndClip(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUv, opacityUv, MaterialSrg::m_sampler, MaterialSrg::m_opacityFactor, o_opacity_source); + + // ------- 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 ------- + + 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); + + if(o_parallax_highlightClipping && displacementIsClipped) + { + ApplyParallaxClippingHighlight(baseColor); + } + + // ------- 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; + + // ------- 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 ------- + + lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); + lightingData.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); + + // ------- Clearcoat ------- + + // [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags + if(o_clearCoat_feature_enabled) + { + 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 ------- + + // Apply Decals + ApplyDecals(lightingData.tileIterator, surface); + + // Apply Direct Lighting + ApplyDirectLighting(surface, lightingData); + + // Apply Image Based Lighting (IBL) + ApplyIBL(surface, lightingData); + + // Finalize Lighting + lightingData.FinalizeLighting(); + + PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha); + + // ------- Opacity ------- + + if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent) + { + // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. + // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface + // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor + // values close to 1.0, that indicates the absence of a surface entirely, so this effect should + // not apply. + float fresnelAlpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; + alpha = lerp(fresnelAlpha, alpha, MaterialSrg::m_opacityAffectsSpecularFactor); + } + + if (o_opacity_mode == OpacityMode::Blended) + { + // [GFX_TODO ATOM-13187] PbrLighting shouldn't be writing directly to render targets. It's confusing when + // specular is being added to diffuse just because we're calling render target 0 "diffuse". + + // For blended mode, we do (dest * alpha) + (source * 1.0). This allows the specular + // to be added on top of the diffuse, but then the diffuse must be pre-multiplied. + // It's done this way because surface transparency doesn't really change specular response (eg, glass). + + lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse + + // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. + float3 specular = lightingOutput.m_specularColor.rgb; + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, MaterialSrg::m_opacityAffectsSpecularFactor); + lightingOutput.m_diffuseColor.rgb += specular; + + lightingOutput.m_diffuseColor.w = alpha; + } + else if (o_opacity_mode == OpacityMode::TintedTransparent) + { + // See OpacityMode::Blended above for the basic method. TintedTransparent adds onto the above concept by supporting + // colored alpha. This is currently a very basic calculation that uses the baseColor as a multiplier with strength + // determined by the alpha. We'll modify this later to be more physically accurate and allow surface depth, + // absorption, and interior color to be specified. + // + // The technique uses dual source blending to allow two separate sources to be part of the blending equation + // even though ultimately only a single render target is being written to. m_diffuseColor is render target 0 and + // m_specularColor render target 1, and the blend mode is (dest * source1color) + (source * 1.0). + // + // This means that m_specularColor.rgb (source 1) is multiplied against the destination, then + // m_diffuseColor.rgb (source) is added to that, and the final result is stored in render target 0. + + lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse + + // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. + float3 specular = lightingOutput.m_specularColor.rgb; + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, MaterialSrg::m_opacityAffectsSpecularFactor); + lightingOutput.m_diffuseColor.rgb += specular; + + lightingOutput.m_specularColor.rgb = baseColor * (1.0 - alpha); + } + else + { + lightingOutput.m_diffuseColor.w = -1; // Disable subsurface scattering + } + + return lightingOutput; +} + +ForwardPassOutputWithDepth StandardPbr_ForwardPassPS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + ForwardPassOutputWithDepth OUT; + float depth; + + PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); + +#ifdef UNIFIED_FORWARD_OUTPUT + OUT.m_color.rgb = lightingOutput.m_diffuseColor.rgb + lightingOutput.m_specularColor.rgb; + OUT.m_color.a = lightingOutput.m_diffuseColor.a; + OUT.m_depth = depth; +#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; + OUT.m_depth = depth; +#endif + return OUT; +} + +[earlydepthstencil] +ForwardPassOutput StandardPbr_ForwardPassPS_EDS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + ForwardPassOutput OUT; + float depth; + + PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); + +#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..d8df49f4b0 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.shader @@ -0,0 +1,54 @@ +{ + "Source" : "./StandardPBR_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": "StandardPbr_ForwardPassVS", + "type": "Vertex" + }, + { + "name": "StandardPbr_ForwardPassPS", + "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..39f101aca9 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.shadervariantlist @@ -0,0 +1,29 @@ +{ + "Shader" : "StandardPBR_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..02e9e93ba2 --- /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 "StandardPBR_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..44139608ca --- /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" : "./StandardPBR_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": "StandardPbr_ForwardPassVS", + "type": "Vertex" + }, + { + "name": "StandardPbr_ForwardPassPS", + "type": "Fragment" + } + ] + }, + + "DrawList" : "lowEndForward" +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ShaderEnable.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ShaderEnable.lua new file mode 100644 index 0000000000..7e19641c6b --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ShaderEnable.lua @@ -0,0 +1,82 @@ +-------------------------------------------------------------------------------------- +-- +-- 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 +-- +-- +-- +---------------------------------------------------------------------------------------------------- + +function GetMaterialPropertyDependencies() + return {"opacity.mode", "parallax.textureMap", "parallax.useTexture", "parallax.pdo"} +end + +OpacityMode_Opaque = 0 +OpacityMode_Cutout = 1 +OpacityMode_Blended = 2 +OpacityMode_TintedTransparent = 3 + +function TryGetShaderByTag(context, shaderTag) + if context:HasShaderWithTag(shaderTag) then + return context:GetShaderByTag(shaderTag) + else + return nil + end +end + +function TrySetShaderEnabled(shader, enabled) + if shader then + shader:SetEnabled(enabled) + end +end + +function Process(context) + local opacityMode = context:GetMaterialPropertyValue_enum("opacity.mode") + local displacementMap = context:GetMaterialPropertyValue_Image("parallax.textureMap") + local useDisplacementMap = context:GetMaterialPropertyValue_bool("parallax.useTexture") + local parallaxEnabled = displacementMap ~= nil and useDisplacementMap + local parallaxPdoEnabled = context:GetMaterialPropertyValue_bool("parallax.pdo") + + local depthPass = context:GetShaderByTag("DepthPass") + local shadowMap = context:GetShaderByTag("Shadowmap") + local forwardPassEDS = context:GetShaderByTag("ForwardPass_EDS") + + local depthPassWithPS = context:GetShaderByTag("DepthPass_WithPS") + local shadowMapWithPS = context:GetShaderByTag("Shadowmap_WithPS") + local forwardPass = context:GetShaderByTag("ForwardPass") + + -- Use TryGetShaderByTag because these shaders only exist in StandardPBR but this script is also used for EnhancedPBR + local lowEndForwardEDS = TryGetShaderByTag(context, "LowEndForward_EDS") + local lowEndForward = TryGetShaderByTag(context, "LowEndForward") + + if parallaxEnabled and parallaxPdoEnabled then + depthPass:SetEnabled(false) + shadowMap:SetEnabled(false) + forwardPassEDS:SetEnabled(false) + + depthPassWithPS:SetEnabled(true) + shadowMapWithPS:SetEnabled(true) + forwardPass:SetEnabled(true) + + TrySetShaderEnabled(lowEndForwardEDS, false) + TrySetShaderEnabled(lowEndForward, true) + else + depthPass:SetEnabled(opacityMode == OpacityMode_Opaque) + shadowMap:SetEnabled(opacityMode == OpacityMode_Opaque) + forwardPassEDS:SetEnabled((opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent)) + + depthPassWithPS:SetEnabled(opacityMode == OpacityMode_Cutout) + shadowMapWithPS:SetEnabled(opacityMode == OpacityMode_Cutout) + forwardPass:SetEnabled(opacityMode == OpacityMode_Cutout) + + -- Only enable lowEndForwardEDS in Opaque mode, Transparent mode will be handled by forwardPassEDS. The transparent pass uses the "transparent" draw tag + -- for both standard and low end pipelines, so this keeps both shaders from rendering to the transparent draw list. + TrySetShaderEnabled(lowEndForwardEDS, opacityMode == OpacityMode_Opaque) + TrySetShaderEnabled(lowEndForward, opacityMode == OpacityMode_Cutout) + end + + context:GetShaderByTag("DepthPassTransparentMin"):SetEnabled((opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent)) + context:GetShaderByTag("DepthPassTransparentMax"):SetEnabled((opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent)) +end 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 c4d198fef9..f595202218 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,13 @@ 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/BasePBR_ShaderEnable.lua Materials/Types/EnhancedPBR.materialtype Materials/Types/EnhancedPBR_Common.azsli Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl @@ -53,6 +60,7 @@ set(FILES Materials/Types/StandardPBR_LowEndForward.azsl Materials/Types/StandardPBR_LowEndForward.shader Materials/Types/StandardPBR_LowEndForward_EDS.shader + Materials/Types/StandardPBR_Metallic.lua Materials/Types/StandardPBR_ParallaxState.lua Materials/Types/StandardPBR_Roughness.lua Materials/Types/StandardPBR_ShaderEnable.lua @@ -129,6 +137,7 @@ set(FILES Passes/DownsampleMipChain.pass Passes/EnvironmentCubeMapDepthMSAA.pass Passes/EnvironmentCubeMapForwardMSAA.pass + Passes/EnvironmentCubeMapForwardSubsurfaceMSAA.pass Passes/EnvironmentCubeMapPipeline.pass Passes/EnvironmentCubeMapSkyBox.pass Passes/EsmShadowmaps.pass @@ -303,6 +312,7 @@ set(FILES ShaderLib/Atom/Features/ScreenSpace/ScreenSpaceUtil.azsli ShaderLib/Atom/Features/Shadow/BicubicPcfFilters.azsli ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli + ShaderLib/Atom/Features/Shadow/ESM.azsli ShaderLib/Atom/Features/Shadow/NormalOffsetShadows.azsli ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli ShaderLib/Atom/Features/Shadow/ReceiverPlaneDepthBias.azsli