您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
198 行
6.6 KiB
198 行
6.6 KiB
// ------------------------------------------------------------------
|
|
// Diffuse
|
|
|
|
// From UE4 - Used for Cloth (Deprecated)
|
|
float3 Diffuse_Lambert(float3 DiffuseColor)
|
|
{
|
|
return DiffuseColor * (1 / UNITY_PI);
|
|
}
|
|
|
|
// ------------------------------------------------------------------
|
|
// Fresnel
|
|
|
|
// From UE4 - Used for Cloth
|
|
// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
|
|
float3 F_Schlick(float3 SpecularColor, float VoH)
|
|
{
|
|
float Fc = Pow5(1 - VoH); // 1 sub, 3 mul
|
|
//return Fc + (1 - Fc) * SpecularColor; // 1 add, 3 mad
|
|
// Anything less than 2% is physically impossible and is instead considered to be shadowing
|
|
return saturate(50.0 * SpecularColor.g) * Fc + (1 - Fc) * SpecularColor;
|
|
}
|
|
|
|
// ------------------------------------------------------------------
|
|
// Distribution
|
|
|
|
// From UE4 - USed for Cloth
|
|
// GGX / Trowbridge-Reitz
|
|
// [Walter et al. 2007, "Microfacet models for refraction through rough surfaces"]
|
|
float D_GGX(float roughness, float NdotH)
|
|
{
|
|
float a = roughness * roughness;
|
|
float a2 = a * a;
|
|
float d = (NdotH * a2 - NdotH) * NdotH + 1; // 2 mad
|
|
return a2 / (UNITY_PI*d*d); // 4 mul, 1 rcp
|
|
}
|
|
|
|
// Anisotropic GGX
|
|
// Taken from HDRenderPipeline
|
|
float D_GGXAnisotropic(float TdotH, float BdotH, float NdotH, float roughnessT, float roughnessB)
|
|
{
|
|
float f = TdotH * TdotH / (roughnessT * roughnessT) + BdotH * BdotH / (roughnessB * roughnessB) + NdotH * NdotH;
|
|
return 1.0 / (roughnessT * roughnessB * f * f);
|
|
}
|
|
|
|
// From UE4 - Used for Cloth
|
|
float D_InvGGX(float roughness, float NdotH)
|
|
{
|
|
float a = roughness * roughness;
|
|
float a2 = a * a;
|
|
float A = 4;
|
|
float d = (NdotH - a2 * NdotH) * NdotH + a2;
|
|
return 1/(UNITY_PI * (1 + A*a2)) * (1 + 4 * a2*a2 / (d*d)); //RCP
|
|
}
|
|
|
|
// ------------------------------------------------------------------
|
|
// Visibility
|
|
|
|
// From UE4 - Used for Cloth
|
|
// Appoximation of joint Smith term for GGX
|
|
// [Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs"]
|
|
float Vis_SmithJointApprox(float Roughness, float NoV, float NoL)
|
|
{
|
|
float a = (Roughness*Roughness);
|
|
float Vis_SmithV = NoL * (NoV * (1 - a) + a);
|
|
float Vis_SmithL = NoV * (NoL * (1 - a) + a);
|
|
// Note: will generate NaNs with Roughness = 0. MinRoughness is used to prevent this
|
|
return 0.5 * 1/(Vis_SmithV + Vis_SmithL); //RCP
|
|
}
|
|
|
|
// From UE4 - Used for Cloth
|
|
float Vis_Cloth(float NoV, float NoL)
|
|
{
|
|
return 1/(4 * (NoL + NoV - NoL * NoV)); //RCP
|
|
}
|
|
|
|
// ------------------------------------------------------------------
|
|
// SORT THESE
|
|
|
|
// Smith Joint GGX Anisotropic Visibility
|
|
// Taken from https://cedec.cesa.or.jp/2015/session/ENG/14698.html
|
|
float SmithJointGGXAnisotropic(float TdotV, float BdotV, float NdotV, float TdotL, float BdotL, float NdotL, float roughnessT, float roughnessB)
|
|
{
|
|
float aT = roughnessT;
|
|
float aT2 = aT * aT;
|
|
float aB = roughnessB;
|
|
float aB2 = aB * aB;
|
|
|
|
float lambdaV = NdotL * sqrt(aT2 * TdotV * TdotV + aB2 * BdotV * BdotV + NdotV * NdotV);
|
|
float lambdaL = NdotV * sqrt(aT2 * TdotL * TdotL + aB2 * BdotL * BdotL + NdotL * NdotL);
|
|
|
|
return 0.5 / (lambdaV + lambdaL);
|
|
}
|
|
|
|
// Convert Anistropy to roughness
|
|
void ConvertAnisotropyToRoughness(float roughness, float anisotropy, out float roughnessT, out float roughnessB)
|
|
{
|
|
// (0 <= anisotropy <= 1), therefore (0 <= anisoAspect <= 1)
|
|
// The 0.9 factor limits the aspect ratio to 10:1.
|
|
float anisoAspect = sqrt(1.0 - 0.9 * anisotropy);
|
|
roughnessT = roughness / anisoAspect; // Distort along tangent (rougher)
|
|
roughnessB = roughness * anisoAspect; // Straighten along bitangent (smoother)
|
|
}
|
|
|
|
// Schlick Fresnel
|
|
float FresnelSchlick(float f0, float f90, float u)
|
|
{
|
|
float x = 1.0 - u;
|
|
float x5 = x * x;
|
|
x5 = x5 * x5 * x;
|
|
return (f90 - f0) * x5 + f0; // sub mul mul mul sub mad
|
|
}
|
|
|
|
//Clamp roughness
|
|
float ClampRoughnessForAnalyticalLights(float roughness)
|
|
{
|
|
return max(roughness, 0.000001);
|
|
}
|
|
|
|
//Calculate tangent warp for IBL (Reference Version - not used)
|
|
float3 SpecularGGXIBLRef(float3 viewDir, float3 normalDir, float3 tangentDir, float3 bitangentDir, float roughnessT, float roughnessB)
|
|
{
|
|
return float3(1, 1, 1);
|
|
//Hidden in UnityAnisotropicLighting.cginc
|
|
}
|
|
|
|
// Sample Anisotropic Direction for IBL (Reference Version - not used)
|
|
void SampleAnisoGGXDir(float2 u, float3 viewDir, float3 normalDir, float3 tangent, float3 bitangent, float roughnessT, float roughnessB, out float3 halfDir, out float3 lightDir)
|
|
{
|
|
// AnisoGGX NDF sampling
|
|
halfDir = sqrt(u.x / (1.0 - u.x)) * (roughnessT * cos((UNITY_PI * 2) * u.y) * tangent + roughnessB * sin((UNITY_PI * 2) * u.y) * bitangent) + normalDir;
|
|
halfDir = normalize(halfDir);
|
|
|
|
// Convert sample from half angle to incident angle
|
|
lightDir = 2.0 * saturate(dot(viewDir, halfDir)) * halfDir - viewDir;
|
|
}
|
|
|
|
// Ref: Donald Revie - Implementing Fur Using Deferred Shading (GPU Pro 2)
|
|
// The grain direction (e.g. hair or brush direction) is assumed to be orthogonal to the normal.
|
|
// The returned normal is NOT normalized.
|
|
float3 ComputeGrainNormal(float3 grainDir, float3 V)
|
|
{
|
|
float3 B = cross(-V, grainDir);
|
|
return cross(B, grainDir);
|
|
}
|
|
|
|
//Modify Normal for Anisotropic IBL (Realtime version)
|
|
// Fake anisotropic by distorting the normal.
|
|
// The grain direction (e.g. hair or brush direction) is assumed to be orthogonal to N.
|
|
// Anisotropic ratio (0->no isotropic; 1->full anisotropy in tangent direction)
|
|
float3 GetAnisotropicModifiedNormal(float3 grainDir, float3 N, float3 V, float anisotropy)
|
|
{
|
|
float3 grainNormal = ComputeGrainNormal(grainDir, V);
|
|
// TODO: test whether normalizing 'grainNormal' is worth it.
|
|
return normalize(lerp(N, grainNormal, anisotropy));
|
|
}
|
|
|
|
/// REGION END - ANISOTROPY
|
|
|
|
/// REGION START - SUBSURFACE SCATTERING
|
|
|
|
half Fresnel(half3 H, half3 V, half F0)
|
|
{
|
|
half base = 1.0 - dot(V, H);
|
|
half exponential = pow(base, 5.0);
|
|
return exponential + F0 * (1.0 - exponential);
|
|
}
|
|
/*
|
|
inline half3 KelemenSzirmayKalosSpecular(half3 normal, half3 lightDir, half3 viewDir, float roughness, float rho_s)
|
|
{
|
|
half3 result = half3(0, 0, 0);
|
|
half NdotL = dot(normal, lightDir);
|
|
if (NdotL > 0.0)
|
|
{
|
|
half3 h = lightDir + viewDir;
|
|
half3 H = normalize(h);
|
|
half NdotH = dot(normal, H);
|
|
half PH = pow(2.0 * tex2D(_BeckmannPrecomputedTex, half2(NdotH, roughness)).r, 10.0);
|
|
half F = Fresnel(H, viewDir, 0.028);
|
|
half frSpec = max(PH * F / dot(h, h), 0);
|
|
half term = NdotL * rho_s * frSpec;
|
|
result = half3(term, term, term);
|
|
}
|
|
return result;
|
|
}*/
|
|
/*
|
|
half3 SkinDiffuse(float curv, float3 NdotL)
|
|
{
|
|
float3 lookup = NdotL * 0.5 + 0.5;
|
|
float3 diffuse;
|
|
|
|
diffuse.r = tex2D(_DiffusionProfileTexture, float2(lookup.r, curv)).r;
|
|
diffuse.g = tex2D(_DiffusionProfileTexture, float2(lookup.g, curv)).g;
|
|
diffuse.b = tex2D(_DiffusionProfileTexture, float2(lookup.b, curv)).b;
|
|
|
|
return diffuse;
|
|
}*/
|
|
|
|
/// REGION END - SUBSURFACE SCATTERING
|