Updated Skin shader

This commit is contained in:
antonmic
2021-04-17 12:37:25 -07:00
parent d0760009b0
commit 0d412abe52
5 changed files with 95 additions and 44 deletions
@@ -10,12 +10,24 @@
*
*/
#include <viewsrg.srgi>
#include "Skin_Common.azsli"
// SRGs
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
// Pass Output
#include <Atom/Features/PBR/ForwardPassOutput.azsli>
// Utility
#include <Atom/Features/ColorManagement/TransformColor.azsli>
#include <Atom/Features/PBR/AlphaUtils.azsli> // TODO: Remove this after OpacityMode is removed from LightingModel
// Custom Surface & Lighting
#include <Atom/Features/PBR/Lighting/SkinLighting.azsli>
// Decals
#include <Atom/Features/PBR/Decals.azsli>
// ---------- Material Parameters ----------
@@ -54,6 +66,8 @@ option bool o_blendMask_isBound;
#include "MaterialInputs/TransmissionInput.azsli"
// ---------- Vertex Shader ----------
struct VSInput
{
// Base fields (required by the template azsli file)...
@@ -90,8 +104,6 @@ struct VSOutput
float4 m_blendMask : UV8;
};
#include <Atom/Features/PBR/AlphaUtils.azsli> // TODO: Remove this after OpacityMode is removed from LightingModel
#include <Atom/Features/PBR/LightingModel.azsli>
#include <Atom/Features/Vertex/VertexHelper.azsli>
VSOutput SkinVS(VSInput IN)
@@ -132,6 +144,9 @@ VSOutput SkinVS(VSInput IN)
return OUT;
}
// ---------- Pixel Shader ----------
float3 ApplyBaseColorWrinkleMap(bool shouldApply, float3 baseColor, Texture2D map, sampler mapSampler, float2 uv, float factor)
{
if (shouldApply)
@@ -178,6 +193,9 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, startIndex);
}
Surface surface;
surface.position = IN.m_worldPosition;
// ------- Detail Layer Setup -------
// When the detail maps and the detail blend mask are on the same UV, they both use the transformed detail UVs because they are 'attached' to each other
@@ -213,19 +231,18 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
normalMapSample = ApplyNormalWrinkleMap(o_wrinkleLayers_normal_useTexture4, normalMapSample, MaterialSrg::m_wrinkle_normal_texture4, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, IN.m_blendMask.a);
}
float3 normalWS;
if(o_detail_normal_useTexture)
{
float3 normalTS = GetTangentSpaceNormal(normalMapSample, uvMatrix, MaterialSrg::m_normalFactor);
bool applyOverlay = true;
normalWS = ApplyNormalMapOverlayWS(applyOverlay, IN.m_normal, normalTS, tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex],
surface.normal = ApplyNormalMapOverlayWS(applyOverlay, IN.m_normal, normalTS, tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex],
MaterialSrg::m_detail_normal_texture, MaterialSrg::m_sampler, IN.m_detailUv, MaterialSrg::m_detail_normal_flipX, MaterialSrg::m_detail_normal_flipY,
detailLayerNormalFactor, tangents[MaterialSrg::m_detail_allMapsUvIndex], bitangents[MaterialSrg::m_detail_allMapsUvIndex], MaterialSrg::m_detailUvMatrix);
}
else
{
normalWS = GetWorldSpaceNormal(normalMapSample, IN.m_normal, tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex],
surface.normal = GetWorldSpaceNormal(normalMapSample, IN.m_normal, tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex],
uvMatrix, MaterialSrg::m_normalFactor);
}
@@ -266,17 +283,29 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
baseColor = ApplyTextureOverlay(o_detail_baseColor_useTexture, baseColor, MaterialSrg::m_detail_baseColor_texture, MaterialSrg::m_sampler, IN.m_detailUv, detailLayerBaseColorFactor);
// ------- Roughness -------
float2 roughnessUv = IN.m_uv[MaterialSrg::m_roughnessMapUvIndex];
float roughness = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor,
MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture);
if(o_wrinkleLayers_enabled && o_wrinkleLayers_showBlendMaskValues && o_blendMask_isBound)
{
// Overlay debug colors to highlight the different blend weights coming from the vertex color stream.
if(o_wrinkleLayers_count > 0) { baseColor = lerp(baseColor, float3(1,0,0), IN.m_blendMask.r); }
if(o_wrinkleLayers_count > 1) { baseColor = lerp(baseColor, float3(0,1,0), IN.m_blendMask.g); }
if(o_wrinkleLayers_count > 2) { baseColor = lerp(baseColor, float3(0,0,1), IN.m_blendMask.b); }
if(o_wrinkleLayers_count > 3) { baseColor = lerp(baseColor, float3(1,1,1), IN.m_blendMask.a); }
}
// ------- Specular -------
float2 specularUv = IN.m_uv[MaterialSrg::m_specularF0MapUvIndex];
float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture);
float specularF0 = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture);
surface.SetAlbedoAndSpecularF0(baseColor, specularF0);
// ------- 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();
// ------- Subsurface -------
@@ -287,30 +316,54 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
float2 transmissionUv = IN.m_uv[MaterialSrg::m_transmissionThicknessMapUvIndex];
float4 transmissionTintThickness = GeTransmissionInput(MaterialSrg::m_transmissionThicknessMap, MaterialSrg::m_sampler, transmissionUv, MaterialSrg::m_transmissionTintThickness);
surface.transmission.tint = transmissionTintThickness.rgb;
surface.transmission.thickness = transmissionTintThickness.w;
surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams;
// ------- Anisotropy -------
if (o_enableAnisotropy)
{
const float anisotropyAngle = 0.0f;
const float anisotropyFactor = 0.0f;
surface.anisotropy.Init(surface.normal, tangents[0], bitangents[0], anisotropyAngle, anisotropyFactor, surface.roughnessA);
}
// ------- Lighting Data -------
LightingData lightingData;
// Light iterator
lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData);
lightingData.Init(surface.position, surface.normal, surface.roughnessLinear);
// Directional light shadow coordinates
lightingData.shadowCoords = IN.m_shadowCoords;
// Diffuse and Specular response (used in IBL calculations)
lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear);
lightingData.diffuseResponse = 1.0 - lightingData.specularResponse;
// ------- Lighting Calculation -------
if(o_wrinkleLayers_enabled && o_wrinkleLayers_showBlendMaskValues && o_blendMask_isBound)
{
// Overlay debug colors to highlight the different blend weights coming from the vertex color stream.
if(o_wrinkleLayers_count > 0) { baseColor = lerp(baseColor, float3(1,0,0), IN.m_blendMask.r); }
if(o_wrinkleLayers_count > 1) { baseColor = lerp(baseColor, float3(0,1,0), IN.m_blendMask.g); }
if(o_wrinkleLayers_count > 2) { baseColor = lerp(baseColor, float3(0,0,1), IN.m_blendMask.b); }
if(o_wrinkleLayers_count > 3) { baseColor = lerp(baseColor, float3(1,1,1), IN.m_blendMask.a); }
}
surface.clearCoat.factor = 0.0;
surface.clearCoat.roughness = 0.0;
surface.clearCoat.normal = float3(0.0, 0.0, 0.0);
float metallic = 0;
float3 emissive = float3(0,0,0);
float occlusion = 1;
float2 anisotropy = float2(0,0);
float clearCoatFactor = 0.0;
float clearCoatRoughness = 0.0;
float3 clearCoatNormal = float3(0.0, 0.0, 0.0);
float alpha = 1;
// Apply Decals
ApplyDecals(lightingData.tileIterator, surface);
PbrLightingOutput lightingOutput = PbrLighting(IN, baseColor, metallic, roughness, specularF0Factor,
normalWS, tangents[0], bitangents[0], anisotropy,
emissive, occlusion, transmissionTintThickness, MaterialSrg::m_transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, o_opacity_mode);
// Apply Direct Lighting
ApplyDirectLighting(surface, lightingData);
// Apply Image Based Lighting (IBL)
ApplyIBL(surface, lightingData);
// Finalize Lighting
lightingData.FinalizeLighting(surface.transmission.tint);
PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData);
// ------- Preparing output -------
@@ -13,6 +13,7 @@
#pragma once
#include <Atom/Features/SrgSemantics.azsli>
#include <viewsrg.srgi>
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
#include "MaterialInputs/BaseColorInput.azsli"
@@ -17,7 +17,7 @@
// Then include custom surface and lighting data types
#include <Atom/Features/PBR/Lighting/LightingData.azsli>
#include <Atom/Features/PBR/Surfaces/StandardSurface.azsli>
#include <Atom/Features/PBR/Surfaces/EnhancedSurface.azsli>
#include <Atom/Features/PBR/LightingUtils.azsli>
#include <Atom/Features/PBR/Microfacet/Brdf.azsli>
@@ -17,7 +17,7 @@
// Then include custom surface and lighting data types
#include <Atom/Features/PBR/Lighting/LightingData.azsli>
#include <Atom/Features/PBR/Surfaces/StandardSurface.azsli>
#include <Atom/Features/PBR/Surfaces/SkinSurface.azsli>
#include <Atom/Features/PBR/LightingUtils.azsli>
#include <Atom/Features/PBR/Microfacet/Brdf.azsli>
@@ -98,12 +98,12 @@ struct PbrLightingOutput
};
PbrLightingOutput GetPbrLightingOutput(Surface surface, LightingData lightingData, float alpha)
PbrLightingOutput GetPbrLightingOutput(Surface surface, LightingData lightingData)
{
PbrLightingOutput lightingOutput;
lightingOutput.m_diffuseColor = float4(lightingData.diffuseLighting, alpha);
lightingOutput.m_specularColor = float4(lightingData.specularLighting, 1.0);
lightingOutput.m_diffuseColor = float4(lightingData.diffuseLighting, 1.0f);
lightingOutput.m_specularColor = float4(lightingData.specularLighting, 1.0f);
// albedo, specularF0, roughness, and normals for later passes (specular IBL, Diffuse GI, SSR, AO, etc)
lightingOutput.m_specularF0 = float4(surface.specularF0, surface.roughnessLinear);
@@ -41,7 +41,7 @@ class Surface //: BasePbrSurfaceData
void CalculateRoughnessA();
//! Sets albedo and specularF0 using metallic workflow
void SetAlbedoAndSpecularF0(float3 baseColor, float inSpecularF0, float metallic);
void SetAlbedoAndSpecularF0(float3 baseColor, float inSpecularF0);
};
@@ -80,12 +80,9 @@ void Surface::CalculateRoughnessA()
}
}
void Surface::SetAlbedoAndSpecularF0(float3 baseColor, float inSpecularF0, float metallic)
void Surface::SetAlbedoAndSpecularF0(float3 baseColor, float inSpecularF0)
{
float3 dielectricSpecularF0 = MaxDielectricSpecularF0 * inSpecularF0;
// Compute albedo and specularF0 based on metalness
albedo = lerp(baseColor, float3(0.0f, 0.0f, 0.0f), metallic);
specularF0 = lerp(dielectricSpecularF0, baseColor, metallic);
albedo = baseColor;
specularF0 = MaxDielectricSpecularF0 * inSpecularF0;
}