99 lines
4.0 KiB
HLSL
99 lines
4.0 KiB
HLSL
//-----------------------------------------------------------------------------
|
|
// Helper functions
|
|
//-----------------------------------------------------------------------------
|
|
|
|
float RoughnessToPerceptualRoughness(float roughness)
|
|
{
|
|
return sqrt(roughness);
|
|
}
|
|
|
|
float RoughnessToPerceptualSmoothness(float roughness)
|
|
{
|
|
return 1.0 - sqrt(roughness);
|
|
}
|
|
|
|
float PerceptualSmoothnessToRoughness(float perceptualSmoothness)
|
|
{
|
|
return (1.0 - perceptualSmoothness) * (1.0 - perceptualSmoothness);
|
|
}
|
|
|
|
float PerceptualSmoothnessToPerceptualRoughness(float perceptualSmoothness)
|
|
{
|
|
return (1.0 - perceptualSmoothness);
|
|
}
|
|
|
|
float PerceptualRoughnessToPerceptualSmoothness(float perceptualRoughness)
|
|
{
|
|
return (1.0 - perceptualRoughness);
|
|
}
|
|
|
|
// Return modified perceptualSmoothness based on provided variance (get from GeometricNormalVariance + TextureNormalVariance)
|
|
float NormalFiltering(float perceptualSmoothness, float variance, float threshold)
|
|
{
|
|
float roughness = PerceptualSmoothnessToRoughness(perceptualSmoothness);
|
|
// Ref: Geometry into Shading - http://graphics.pixar.com/library/BumpRoughness/paper.pdf - equation (3)
|
|
float squaredRoughness = saturate(roughness * roughness + min(2.0 * variance, threshold * threshold)); // threshold can be really low, square the value for easier control
|
|
|
|
return RoughnessToPerceptualSmoothness(sqrt(squaredRoughness));
|
|
}
|
|
|
|
// Reference: Error Reduction and Simplification for Shading Anti-Aliasing
|
|
// Specular antialiasing for geometry-induced normal (and NDF) variations: Tokuyoshi / Kaplanyan et al.'s method.
|
|
// This is the deferred approximation, which works reasonably well so we keep it for forward too for now.
|
|
// screenSpaceVariance should be at most 0.5^2 = 0.25, as that corresponds to considering
|
|
// a gaussian pixel reconstruction kernel with a standard deviation of 0.5 of a pixel, thus 2 sigma covering the whole pixel.
|
|
float GeometricNormalVariance(float3 geometricNormalWS, float screenSpaceVariance)
|
|
{
|
|
float3 deltaU = ddx(geometricNormalWS);
|
|
float3 deltaV = ddy(geometricNormalWS);
|
|
|
|
return screenSpaceVariance * (dot(deltaU, deltaU) + dot(deltaV, deltaV));
|
|
}
|
|
|
|
// Return modified perceptualSmoothness
|
|
float GeometricNormalFiltering(float perceptualSmoothness, float3 geometricNormalWS, float screenSpaceVariance, float threshold)
|
|
{
|
|
float variance = GeometricNormalVariance(geometricNormalWS, screenSpaceVariance);
|
|
return NormalFiltering(perceptualSmoothness, variance, threshold);
|
|
}
|
|
|
|
//SSS method from GDC 2011 conference by Colin Barre-Bresebois & Marc Bouchard and modified by Xiexe
|
|
float3 getSubsurfaceScatteringLight (float3 lightColor, float3 lightDirection, float3 normalDirection, float3 viewDirection,
|
|
float attenuation, float3 thickness, float3 indirectLight, float3 subsurfaceColour)
|
|
{
|
|
float3 vLTLight = lightDirection + normalDirection * _SSSDist; // Distortion
|
|
float3 fLTDot = pow(saturate(dot(viewDirection, -vLTLight)), _SSSPow)
|
|
* _SSSIntensity;
|
|
|
|
return lerp(1, attenuation, float(any(_WorldSpaceLightPos0.xyz)))
|
|
* (fLTDot + _SSSAmbient) * abs(_ThicknessMapInvert-thickness)
|
|
* (lightColor + indirectLight) * subsurfaceColour;
|
|
|
|
}
|
|
|
|
inline float3 BlendNormalsPD(float3 n1, float3 n2) {
|
|
return normalize(float3(n1.xy*n2.z + n2.xy*n1.z, n1.z*n2.z));
|
|
}
|
|
|
|
// Based on NormalInTangentSpace from UnityStandardInput
|
|
inline float3 NormalInTangentSpace(float2 texcoords, float2 texcoords2, half mask)
|
|
{
|
|
//float3 normalTangent = UnpackNormal(tex2D(_BumpMap,TRANSFORM_TEX(texcoords.xy, _MainTex)));
|
|
//float3 normalTangent = UnpackNormal(tex2D(_BumpMap,texcoords.xy));
|
|
half3 normalTangent = UnpackScaleNormal(tex2D (_BumpMap, texcoords.xy), _BumpScale);
|
|
|
|
half3 detailNormalTangent = UnpackScaleNormal(tex2D (_DetailBumpMap, TRANSFORM_TEX(texcoords2.xy, _DetailBumpMap)), _DetailBumpMapScale);
|
|
#if _DETAIL_LERP
|
|
normalTangent = lerp(
|
|
normalTangent,
|
|
detailNormalTangent,
|
|
mask);
|
|
#else
|
|
normalTangent = lerp(
|
|
normalTangent,
|
|
BlendNormalsPD(normalTangent, detailNormalTangent),
|
|
mask);
|
|
#endif
|
|
|
|
return normalTangent;
|
|
} |