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.
 
 
 
 

82 lines
3.0 KiB

using System;
using UnityEngine.Rendering;
namespace UnityEngine.Rendering.HighDefinition.LTC
{
/// <summary>
/// Disney Diffuse Implementation
/// Source from 2012 Burley, B. "Physically-Based Shading at Disney" Section 5.3
/// (https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf)
/// </summary>
struct BRDF_Disney : 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);
double NdotL = Math.Max(0, _tsLight.z);
double NdotV = Math.Max(0, _tsView.z);
double LdotV = Math.Max(0, Vector3.Dot(_tsLight, _tsView));
double perceptualRoughness = Math.Sqrt(_alpha);
// (2 * LdotH * LdotH) = 1 + LdotV
// real fd90 = 0.5 + 2 * LdotH * LdotH * perceptualRoughness;
double fd90 = 0.5 + (perceptualRoughness + perceptualRoughness * LdotV);
// Two schlick fresnel term
double lightScatter = F_Schlick(1.0, fd90, NdotL);
double viewScatter = F_Schlick(1.0, fd90, NdotV);
// Normalize the BRDF for polar view angles of up to (Pi/4).
// We use the worst case of (roughness = albedo = 1), and, for each view angle,
// integrate (brdf * cos(theta_light)) over all light directions.
// The resulting value is for (theta_view = 0), which is actually a little bit larger
// than the value of the integral for (theta_view = Pi/4).
// Hopefully, the compiler folds the constant together with (1/Pi).
double res = lightScatter * viewScatter / Math.PI;
res /= 1.03571;
// Remember we must include the N.L term!
res *= NdotL;
// Cosine-weighted hemisphere sampling
_pdf = NdotL / Math.PI;
return res;
}
public void GetSamplingDirection(ref Vector3 _tsView, float _alpha, float _U1, float _U2, ref Vector3 _direction)
{
// Performs uniform sampling of the unit disk.
// Ref: PBRT v3, p. 777.
float r = Mathf.Sqrt(_U1);
float phi = 2.0f * Mathf.PI * _U2;
// Performs cosine-weighted sampling of the hemisphere.
// Ref: PBRT v3, p. 780.
_direction.x = r * Mathf.Cos(phi);
_direction.y = r * Mathf.Sin(phi);
_direction.z = Mathf.Sqrt(1 - _U1); // Project the point from the disk onto the hemisphere.
}
double F_Schlick(double _F0, double _F90, double _cosTheta)
{
double x = 1.0 - _cosTheta;
double x2 = x * x;
double x5 = x * x2 * x2;
return (_F90 - _F0) * x5 + _F0; // sub mul mul mul sub mad
}
public LTCLightingModel GetLightingModel()
{
return LTCLightingModel.DisneyDiffuse;
}
}
}