You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
97 lines
3.8 KiB
97 lines
3.8 KiB
using System;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace UnityEngine.Rendering.HighDefinition.LTC
|
|
{
|
|
/// <summary>
|
|
/// "Charlie" Sheen Implementation
|
|
/// Source from Sony Pictures Imageworks by Estevez and Kulla, "Production Friendly Microfacet Sheen BRDF" (http://blog.selfshadow.com/publications/s2017-shading-course/imageworks/s2017_pbs_imageworks_sheen.pdf)
|
|
/// Details: https://knarkowicz.wordpress.com/2018/01/04/cloth-shading/
|
|
/// </summary>
|
|
struct BRDF_Charlie : IBRDF
|
|
{
|
|
public double Eval(ref Vector3 _tsView, ref Vector3 _tsLight, float _alpha, out double _pdf)
|
|
{
|
|
if (_tsView.z <= 0)
|
|
{
|
|
_pdf = 0;
|
|
return 0;
|
|
}
|
|
|
|
_alpha = Mathf.Max(0.002f, _alpha);
|
|
|
|
Vector3 H = Vector3.Normalize(_tsView + _tsLight);
|
|
double NdotL = _tsLight.z;
|
|
double NdotV = _tsView.z;
|
|
double NdotH = H.z;
|
|
|
|
// D
|
|
double D = CharlieD(_alpha, NdotH);
|
|
|
|
// Ashikmin masking/shadowing
|
|
// double G = V_Ashikhmin( NdotV, NdotL );
|
|
double G = V_Charlie(NdotV, NdotL, _alpha);
|
|
|
|
// fr = F(H) * G(V, L) * D(H)
|
|
// Note that the usual 1 / (4 * (N.L) * (N.V)) part of the Cook-Torrance micro-facet model is actually contained in the G visibility term in our case (as reported by Ashkmin in "Distribution-based BRDFs" eq. 2)
|
|
double res = D * G * NdotL; // We also include the (N.L) term here
|
|
|
|
// We're using uniform distribution
|
|
_pdf = 0.5 / Math.PI;
|
|
|
|
return res;
|
|
}
|
|
|
|
// Paper recommend plain uniform sampling of upper hemisphere instead of importance sampling for Charlie
|
|
public void GetSamplingDirection(ref Vector3 _tsView, float _alpha, float _U1, float _U2, ref Vector3 _direction)
|
|
{
|
|
float phi = 2.0f * Mathf.PI * _U1;
|
|
float cosTheta = 1.0f - _U2;
|
|
float sinTheta = Mathf.Sqrt(1 - cosTheta * cosTheta);
|
|
_direction = new Vector3(sinTheta * Mathf.Cos(phi), sinTheta * Mathf.Sin(phi), cosTheta);
|
|
}
|
|
|
|
double CharlieD(float _roughness, double _NdotH)
|
|
{
|
|
double invR = 1.0 / _roughness;
|
|
double cos2h = _NdotH * _NdotH;
|
|
double sin2h = 1.0f - cos2h;
|
|
double res = (2.0 + invR) * Math.Pow(sin2h, invR * 0.5) / (2.0 * Math.PI);
|
|
return res;
|
|
}
|
|
|
|
double V_Ashikhmin(double _NdotV, double _NdotL)
|
|
{
|
|
return 1.0 / (4.0 * (_NdotL + _NdotV - _NdotL * _NdotV));
|
|
}
|
|
|
|
// Note: This version doesn't include the softening of the paper: Production Friendly Microfacet Sheen BRDF
|
|
double V_Charlie(double _NdotV, double _NdotL, double _roughness)
|
|
{
|
|
double lambdaV = _NdotV < 0.5 ? Math.Exp(CharlieL(_NdotV, _roughness)) : Math.Exp(2.0 * CharlieL(0.5, _roughness) - CharlieL(1.0 - _NdotV, _roughness));
|
|
double lambdaL = _NdotL < 0.5 ? Math.Exp(CharlieL(_NdotL, _roughness)) : Math.Exp(2.0 * CharlieL(0.5, _roughness) - CharlieL(1.0 - _NdotL, _roughness));
|
|
|
|
return 1.0 / ((1.0 + lambdaV + lambdaL) * (4.0 * _NdotV * _NdotL));
|
|
}
|
|
|
|
double CharlieL(double x, double _roughness)
|
|
{
|
|
float r = Mathf.Clamp01((float)_roughness);
|
|
r = 1.0f - r * r;
|
|
|
|
float a = Mathf.Lerp(25.3245f, 21.5473f, r);
|
|
float b = Mathf.Lerp(3.32435f, 3.82987f, r);
|
|
float c = Mathf.Lerp(0.16801f, 0.19823f, r);
|
|
float d = Mathf.Lerp(-1.27393f, -1.97760f, r);
|
|
float e = Mathf.Lerp(-4.85967f, -4.32054f, r);
|
|
|
|
double res = a / (1.0 + b * Math.Pow(Math.Max(0, x), c)) + d * x + e;
|
|
return res;
|
|
}
|
|
|
|
public LTCLightingModel GetLightingModel()
|
|
{
|
|
return LTCLightingModel.Charlie;
|
|
}
|
|
}
|
|
}
|