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.
 
 
 
 

64 lines
2.6 KiB

using System;
using UnityEngine.Rendering;
namespace UnityEngine.Rendering.HighDefinition.LTC
{
/// <summary>
/// Ward implementation of the BRDF interface
// Formulas come from -> Walter, B. 2005 "Notes on the Ward BRDF" (https://pdfs.semanticscholar.org/330e/59117d7da6c794750730a15f9a178391b9fe.pdf)
// The BRDF though, is the one most proeminently used by the AxF materials and is based on the Geisler-Moroder variation of Ward (http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.169.9908&rep=rep1&type=pdf)
/// </summary>
struct BRDF_Ward : 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 = (_tsView + _tsLight).normalized;
double NdotL = Math.Max(1e-8, _tsLight.z);
double NdotH = Math.Max(1e-8, H.z);
double LdotH = Math.Max(1e-8, Vector3.Dot(_tsLight, H));
// D (basically a Beckmann distribution + an additional divider for albedo bounding)
double m2 = _alpha * _alpha;
double cosb2 = NdotH * NdotH;
double D = Math.Exp(-(1 - cosb2) / (m2 * cosb2)) // exp( -tan(a)² / m² )
/ (Math.PI * m2 * cosb2 * cosb2); // / (PI * m² * cos(a)^4)
D /= 4.0 * LdotH * LdotH; // Moroder
// fr = F(H) * D(H)
double res = D;
// Remember we must include the N.L term!
res *= NdotL;
// From Walter, eq. 24 we know that pdf(H) = D(H) * (N.H)
_pdf = Math.Abs(D * NdotH);
return res;
}
public void GetSamplingDirection(ref Vector3 _tsView, float _alpha, float _U1, float _U2, ref Vector3 _direction)
{
// Ward NDF sampling (eqs. 6 & 7 from above paper)
float tanTheta = _alpha * Mathf.Sqrt(-Mathf.Log(Mathf.Max(1e-6f, _U1)));
float phi = _U2 * 2.0f * Mathf.PI;
float cosTheta = 1.0f / Mathf.Sqrt(1 + tanTheta * tanTheta);
float sinTheta = Mathf.Sqrt(1 - cosTheta * cosTheta);
Vector3 H = new Vector3(sinTheta * Mathf.Cos(phi), sinTheta * Mathf.Sin(phi), cosTheta);
_direction = 2.0f * Vector3.Dot(H, _tsView) * H - _tsView; // Mirror view direction
}
public LTCLightingModel GetLightingModel()
{
return LTCLightingModel.Ward;
}
}
}