2026-04-16 오브젝트 그림자
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7318e34b1fd83b4b9c1d76f71e029ed
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 490fe8da71f8576488b30a4a922fc442
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace BadDog.Rendering.AreaLight.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>
|
||||
public 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 BadDog.Rendering.AreaLight.LTCLightingModel GetLightingModel()
|
||||
{
|
||||
return BadDog.Rendering.AreaLight.LTCLightingModel.Charlie;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3273a65ebf1c474397e1eb12a73cf98
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/BRDF/BRDF_Charlie.cs
|
||||
uploadId: 884030
|
||||
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace BadDog.Rendering.AreaLight.LTC
|
||||
{
|
||||
/// <summary>
|
||||
/// Cook-Torrance implementation of the BRDF interface
|
||||
/// </summary>
|
||||
public struct BRDF_CookTorrance : 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 NdotV = Math.Max(1e-8, _tsView.z);
|
||||
double NdotH = H.z;
|
||||
double LdotH = Math.Max(1e-8, Vector3.Dot(_tsLight, H));
|
||||
|
||||
// D
|
||||
double cosb2 = NdotH * NdotH;
|
||||
double m2 = _alpha * _alpha;
|
||||
double D = Math.Exp((cosb2 - 1.0) / (cosb2 * m2)) // exp( -tan(a)² / m² )
|
||||
/ Math.Max(1e-12, Math.PI * m2 * cosb2 * cosb2); // / (PI * m² * cos(a)^4)
|
||||
|
||||
// masking/shadowing
|
||||
double G = Math.Min(1, 2.0 * NdotH * Math.Min(NdotV, NdotL) / LdotH);
|
||||
|
||||
// fr = F(H) * G(V, L) * D(H) / (4 * (N.L) * (N.V))
|
||||
double res = D * G / (4.0 * NdotV); // Full specular mico-facet model is F * D * G / (4 * NdotL * NdotV) but since we're fitting with the NdotL included, it gets nicely canceled out!
|
||||
|
||||
// pdf = D(H) * (N.H) / (4 * (L.H))
|
||||
_pdf = Math.Abs(D * NdotH / (4.0 * LdotH));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
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 / Mathf.Sqrt(1 - _alpha * _alpha * Mathf.Log(Mathf.Max(1e-6f, _U2)));
|
||||
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 BadDog.Rendering.AreaLight.LTCLightingModel GetLightingModel()
|
||||
{
|
||||
return BadDog.Rendering.AreaLight.LTCLightingModel.CookTorrance;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 432ee4d0aec53c943894a42d0bf30444
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/BRDF/BRDF_CookTorrance.cs
|
||||
uploadId: 884030
|
||||
@@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace BadDog.Rendering.AreaLight.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>
|
||||
public 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 BadDog.Rendering.AreaLight.LTCLightingModel GetLightingModel()
|
||||
{
|
||||
return BadDog.Rendering.AreaLight.LTCLightingModel.DisneyDiffuse;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff4aa0c2af19abb42bade44e76256186
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/BRDF/BRDF_Disney.cs
|
||||
uploadId: 884030
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace BadDog.Rendering.AreaLight.LTC
|
||||
{
|
||||
/// <summary>
|
||||
/// GGX implementation of the BRDF interface
|
||||
/// </summary>
|
||||
public class BRDF_GGX : IBRDF
|
||||
{
|
||||
public double Eval(ref Vector3 _tsView, ref Vector3 _tsLight, float _alpha, out double _pdf)
|
||||
{
|
||||
if (_tsView.z <= 0)
|
||||
{
|
||||
_pdf = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// masking
|
||||
double lambdaV = Lambda(_tsView.z, _alpha);
|
||||
|
||||
// shadowing
|
||||
double G2 = 0;
|
||||
if (_tsLight.z > 0.0f)
|
||||
{
|
||||
double lambdaL = Lambda(_tsLight.z, _alpha);
|
||||
G2 = 1.0 / (1.0 + lambdaV + lambdaL);
|
||||
}
|
||||
|
||||
// D
|
||||
Vector3 H = _tsView + _tsLight;
|
||||
float lengthH = H.magnitude;
|
||||
if (lengthH > 1e-8f)
|
||||
H = H / lengthH;
|
||||
else
|
||||
H = new Vector3(0, 0, 1);
|
||||
|
||||
double slopex = H.x / H.z;
|
||||
double slopey = H.y / H.z;
|
||||
double D = 1.0 / (1.0 + (slopex * slopex + slopey * slopey) / _alpha / _alpha);
|
||||
D = D * D;
|
||||
D = D / (Math.PI * _alpha * _alpha * H.z * H.z * H.z * H.z);
|
||||
|
||||
// Full specular mico-facet model is F * D * G / (4 * NdotL * NdotV) but since we're fitting with the NdotL included, it gets nicely canceled out!
|
||||
double res = D * G2 / 4.0 / _tsView.z;
|
||||
|
||||
// pdf = D(H) * (N.H) / (4 * (L.H))
|
||||
_pdf = Math.Abs(D * H.z / 4.0 / Vector3.Dot(_tsView, H));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public void GetSamplingDirection(ref Vector3 _tsView, float _alpha, float _U1, float _U2, ref Vector3 _direction)
|
||||
{
|
||||
float phi = 2.0f * Mathf.PI * _U1;
|
||||
float r = _alpha * Mathf.Sqrt(_U2 / (1.0f - _U2));
|
||||
Vector3 H = new Vector3(r * Mathf.Cos(phi), r * Mathf.Sin(phi), 1.0f).normalized;
|
||||
_direction = -_tsView + 2.0f * H * Vector3.Dot(H, _tsView);
|
||||
}
|
||||
|
||||
double Lambda(float _cosTheta, float _alpha)
|
||||
{
|
||||
double a = 1.0f / _alpha / Math.Tan(Math.Acos(_cosTheta));
|
||||
double lambda = _cosTheta < 1.0 ? 0.5 * (-1.0 + Math.Sqrt(1.0 + 1.0 / (a * a))) : 0.0;
|
||||
return lambda;
|
||||
}
|
||||
|
||||
public BadDog.Rendering.AreaLight.LTCLightingModel GetLightingModel()
|
||||
{
|
||||
return BadDog.Rendering.AreaLight.LTCLightingModel.GGX;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e67e2cd414ae81a4f8f5a76bce9f6b35
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/BRDF/BRDF_GGX.cs
|
||||
uploadId: 884030
|
||||
@@ -0,0 +1,38 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// BRDF Interface
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace BadDog.Rendering.AreaLight.LTC
|
||||
{
|
||||
/// <summary>
|
||||
/// BRDF Interface that you must implement in order to generate a new table
|
||||
/// </summary>
|
||||
public interface IBRDF
|
||||
{
|
||||
/// <summary>
|
||||
/// Evaluation of the ***cosine-weighted*** BRDF
|
||||
/// </summary>
|
||||
/// <param name="_tsView">The vector pointing toward the camera</param>
|
||||
/// <param name="_tsLight">The vector pointing toward the light</param>
|
||||
/// <param name="_alpha">Surface roughness</param>
|
||||
/// <param name="_pdf">The Probability Density Function of sampling the light in that direction</param>
|
||||
/// <returns></returns>
|
||||
double Eval(ref Vector3 _tsView, ref Vector3 _tsLight, float _alpha, out double _pdf);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an importance-sampled light direction given a view vector and the surface roughness
|
||||
/// </summary>
|
||||
/// <param name="_tsView">The vector pointing toward the camera</param>
|
||||
/// <param name="_alpha">>Surface roughness</param>
|
||||
/// <param name="_U1">A random value in [0,1]</param>
|
||||
/// <param name="_U2">A 2nd random value in [0,1]</param>
|
||||
/// <param name="_direction">The generated direction</param>
|
||||
void GetSamplingDirection(ref Vector3 _tsView, float _alpha, float _U1, float _U2, ref Vector3 _direction);
|
||||
|
||||
BadDog.Rendering.AreaLight.LTCLightingModel GetLightingModel();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e6541bb3b842494ab1ec4bf036a37e9
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/BRDF/BRDF_Interface.cs
|
||||
uploadId: 884030
|
||||
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace BadDog.Rendering.AreaLight.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>
|
||||
public struct BRDF_KajiyaKaySpecular : 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 perceptualRoughness = Math.Sqrt(_alpha);
|
||||
|
||||
Vector3 T = Vector3.right;
|
||||
Vector3 N = Vector3.forward;
|
||||
|
||||
double NdotV = Math.Max(0, _tsView.z);
|
||||
double NdotL = Math.Max(0, _tsLight.z);
|
||||
|
||||
double LdotV = Math.Max(0, Vector3.Dot(_tsLight, _tsView));
|
||||
Vector3 H = Vector3.Normalize(_tsLight + _tsView);
|
||||
double LdotH = Math.Max(0, Vector3.Dot(_tsLight, H));
|
||||
|
||||
Vector3 t1 = ShiftTangent(T, N, 0.0f);
|
||||
Vector3 t2 = ShiftTangent(T, N, 0.0f);
|
||||
|
||||
double specularExponent = RoughnessToBlinnPhongSpecularExponent(_alpha);
|
||||
|
||||
// Balancing energy between lobes, as well as between diffuse and specular is left to artists.
|
||||
double hairSpec1 = D_KajiyaKay(t1, H, specularExponent);
|
||||
double hairSpec2 = D_KajiyaKay(t2, H, specularExponent);
|
||||
|
||||
double fd90 = 0.5 + (perceptualRoughness + perceptualRoughness * LdotV);
|
||||
double F = F_Schlick(1.0, fd90, LdotH);
|
||||
|
||||
// G = NdotL * NdotV.
|
||||
double res = 0.25 * F * (hairSpec1 + hairSpec2) * NdotL * Math.Min(Math.Max(NdotV * double.MaxValue, 0.0), 1.0);
|
||||
|
||||
// Uniform Sampling
|
||||
_pdf = 0.5 / Math.PI;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// Uniform Sampling
|
||||
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 RoughnessToBlinnPhongSpecularExponent(double roughness)
|
||||
{
|
||||
// 1e-4 and 3e3 are the lowest/highest values that do not cause numerical instabilities with the fitting tool
|
||||
return Math.Min(Math.Max(2.0 / (roughness * roughness) - 2.0, 1e-4), 3e3);
|
||||
}
|
||||
|
||||
double F_Schlick(double _F0, double _F90, double _cosTheta)
|
||||
{
|
||||
double x = 1.0f - _cosTheta;
|
||||
double x2 = x * x;
|
||||
double x5 = x * x2 * x2;
|
||||
return (_F90 - _F0) * x5 + _F0; // sub mul mul mul sub mad
|
||||
}
|
||||
|
||||
//http://web.engr.oregonstate.edu/~mjb/cs519/Projects/Papers/HairRendering.pdf
|
||||
Vector3 ShiftTangent(Vector3 T, Vector3 N, float shift)
|
||||
{
|
||||
return Vector3.Normalize(T + N * shift);
|
||||
}
|
||||
|
||||
double PositivePow(double value, double power)
|
||||
{
|
||||
return Math.Pow(Math.Max(Math.Abs(value), 1.192092896e-07), power);
|
||||
}
|
||||
|
||||
double D_KajiyaKay(Vector3 T, Vector3 H, double specularExponent)
|
||||
{
|
||||
float TdotH = Vector3.Dot(T, H);
|
||||
float sinTHSq = Mathf.Clamp(1.0f - TdotH * TdotH, 0.0f, 1.0f);
|
||||
|
||||
float dirAttn = Mathf.Clamp(TdotH + 1.0f, 0.0f, 1.0f); // Evgenii: this seems like a hack? Do we really need this?
|
||||
|
||||
// Note: Kajiya-Kay is not energy conserving.
|
||||
// We attempt at least some energy conservation by approximately normalizing Blinn-Phong NDF.
|
||||
// We use the formulation with the NdotL.
|
||||
// See http://www.thetenthplanet.de/archives/255.
|
||||
double n = specularExponent;
|
||||
double norm = (n + 2) / (2.0 * Math.PI);
|
||||
|
||||
return dirAttn * norm * PositivePow(sinTHSq, 0.5 * n);
|
||||
}
|
||||
|
||||
public BadDog.Rendering.AreaLight.LTCLightingModel GetLightingModel()
|
||||
{
|
||||
return BadDog.Rendering.AreaLight.LTCLightingModel.KajiyaKaySpecular;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4288b6ce37f7e2f40b421a4053ff7b73
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/BRDF/BRDF_KajiyaKaySpecular.cs
|
||||
uploadId: 884030
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace BadDog.Rendering.AreaLight.LTC
|
||||
{
|
||||
public struct BRDF_Marschner : IBRDF
|
||||
{
|
||||
public double Eval(ref Vector3 _tsView, ref Vector3 _tsLight, float _alpha, out double _pdf)
|
||||
{
|
||||
// Uniform sampled over a sphere.
|
||||
_pdf = 1f / (4f * Math.PI);
|
||||
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public void GetSamplingDirection(ref Vector3 _tsView, float _alpha, float _U1, float _U2, ref Vector3 _direction)
|
||||
{
|
||||
_direction = Vector3.up;
|
||||
}
|
||||
|
||||
public BadDog.Rendering.AreaLight.LTCLightingModel GetLightingModel()
|
||||
{
|
||||
return BadDog.Rendering.AreaLight.LTCLightingModel.Marschner;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4986784e6e6a4a048aa882f5bcd44d55
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/BRDF/BRDF_Marschner.cs
|
||||
uploadId: 884030
|
||||
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace BadDog.Rendering.AreaLight.LTC
|
||||
{
|
||||
/// <summary>
|
||||
/// Oren-Nayar Implementation
|
||||
/// Source from 1994 Oren, M. Nayar, S. K. "Generalization of Lambert's Reflectance Model"
|
||||
/// </summary>
|
||||
public struct BRDF_OrenNayar : IBRDF
|
||||
{
|
||||
public double Eval(ref Vector3 _tsView, ref Vector3 _tsLight, float _alpha, out double _pdf)
|
||||
{
|
||||
if (_tsView.z <= 0)
|
||||
{
|
||||
_pdf = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
float sigma = Mathf.Max(0.002f, 0.5f * Mathf.PI * _alpha); // Standard deviation is a [0,PI/2] angle
|
||||
|
||||
double NdotL = Math.Max(0, _tsLight.z);
|
||||
double NdotV = Math.Max(0, _tsView.z);
|
||||
|
||||
double gamma = (_tsView.x * _tsLight.x + _tsView.y * _tsLight.y)
|
||||
/ Math.Max(1e-20, Math.Sqrt(1.0 - NdotV * NdotV) * Math.Sqrt(1.0 - NdotL * NdotL));
|
||||
|
||||
double rough_sq = sigma * sigma;
|
||||
double A = 1.0 - 0.5 * (rough_sq / (rough_sq + 0.57)); // You can replace 0.33 by 0.57 to simulate the missing inter-reflection term, as specified in footnote of page 22 of the 1992 paper
|
||||
double B = 0.45 * (rough_sq / (rough_sq + 0.09));
|
||||
|
||||
// Original formulation
|
||||
// float angle_vn = acos( NdotV );
|
||||
// float angle_ln = acos( NdotL );
|
||||
// float alpha = max( angle_vn, angle_ln );
|
||||
// float beta = min( angle_vn, angle_ln );
|
||||
// float C = sin(alpha) * tan(beta);
|
||||
|
||||
// Optimized formulation (without tangents, arccos or sines)
|
||||
double cos_alpha = NdotV < NdotL ? NdotV : NdotL;
|
||||
double cos_beta = NdotV < NdotL ? NdotL : NdotV;
|
||||
double sin_alpha = Math.Sqrt(1.0 - cos_alpha * cos_alpha);
|
||||
double sin_beta = Math.Sqrt(1.0 - cos_beta * cos_beta);
|
||||
double C = sin_alpha * sin_beta / Math.Max(1e-20, cos_beta);
|
||||
|
||||
double res = A + B * Math.Max(0.0, gamma) * C;
|
||||
res /= Math.PI;
|
||||
|
||||
// Remember we must include the N.L term!
|
||||
res *= NdotL;
|
||||
|
||||
// Cosine-weighted hemisphere sampling
|
||||
_pdf = NdotL / Math.PI;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// Here we use a simple cosine-weighted hemisphere sampling
|
||||
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.
|
||||
}
|
||||
|
||||
public BadDog.Rendering.AreaLight.LTCLightingModel GetLightingModel()
|
||||
{
|
||||
return BadDog.Rendering.AreaLight.LTCLightingModel.OrenNayar;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cdf80bc060c4e8d4a8665c2b4a01044b
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/BRDF/BRDF_OrenNayar.cs
|
||||
uploadId: 884030
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace BadDog.Rendering.AreaLight.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>
|
||||
public 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 BadDog.Rendering.AreaLight.LTCLightingModel GetLightingModel()
|
||||
{
|
||||
return BadDog.Rendering.AreaLight.LTCLightingModel.Ward;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70fe8e92f23e84f49aabe7648f8e96f3
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/BRDF/BRDF_Ward.cs
|
||||
uploadId: 884030
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af77b71311e87fa4cab06868233eb576
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96d291f160288ea468dde951087fa54e
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/Generated/LtcData.BRDF_Charlie.cs
|
||||
uploadId: 884030
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c435ba0443ef98a4e9e433deafc998ee
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/Generated/LtcData.BRDF_CookTorrance.cs
|
||||
uploadId: 884030
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb7356e92da7a6f45945e956f9059704
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/Generated/LtcData.BRDF_Disney.cs
|
||||
uploadId: 884030
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c69fea42cc6cc8408effc5faaa54d9a
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/Generated/LtcData.BRDF_GGX.cs
|
||||
uploadId: 884030
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88b3449d431767348a2539b2d5060742
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/Generated/LtcData.BRDF_KajiyaKaySpecular.cs
|
||||
uploadId: 884030
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b69d82badd3dc24bb73acfdf1aa56a1
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/Generated/LtcData.BRDF_Marschner.cs
|
||||
uploadId: 884030
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0119dd4c2903cc34f9ed4e249d71c6f7
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/Generated/LtcData.BRDF_OrenNayar.cs
|
||||
uploadId: 884030
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 217af18bde2ac0645bd0f017a4e3cfe7
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/Generated/LtcData.BRDF_Ward.cs
|
||||
uploadId: 884030
|
||||
@@ -0,0 +1,135 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Experimental.Rendering;
|
||||
using UnityEngine.Rendering;
|
||||
using BadDog.Rendering.AreaLight.LTC;
|
||||
|
||||
namespace BadDog.Rendering.AreaLight
|
||||
{
|
||||
[GenerateHLSL]
|
||||
public enum LTCLightingModel
|
||||
{
|
||||
// Lit, Stack-Lit and Fabric/Silk
|
||||
GGX,
|
||||
DisneyDiffuse,
|
||||
|
||||
// Fabric/CottonWool shader
|
||||
Charlie,
|
||||
// FabricLambert, (Isotropic)
|
||||
|
||||
// Hair
|
||||
KajiyaKaySpecular,
|
||||
// KajiyaKayDiffuse, (Isotropic)
|
||||
Marschner, // TODO
|
||||
|
||||
// Other
|
||||
CookTorrance,
|
||||
Ward,
|
||||
OrenNayar,
|
||||
Count
|
||||
}
|
||||
|
||||
public partial class LTCAreaLight
|
||||
{
|
||||
public static IBRDF GetBRDFInterface(LTCLightingModel model)
|
||||
{
|
||||
switch (model)
|
||||
{
|
||||
case LTCLightingModel.GGX:
|
||||
return new BRDF_GGX();
|
||||
case LTCLightingModel.DisneyDiffuse:
|
||||
return new BRDF_Disney();
|
||||
|
||||
case LTCLightingModel.Charlie:
|
||||
return new BRDF_Charlie();
|
||||
|
||||
case LTCLightingModel.KajiyaKaySpecular:
|
||||
return new BRDF_KajiyaKaySpecular();
|
||||
case LTCLightingModel.Marschner:
|
||||
return new BRDF_Marschner();
|
||||
|
||||
case LTCLightingModel.CookTorrance:
|
||||
return new BRDF_CookTorrance();
|
||||
case LTCLightingModel.Ward:
|
||||
return new BRDF_Ward();
|
||||
case LTCLightingModel.OrenNayar:
|
||||
return new BRDF_OrenNayar();
|
||||
}
|
||||
return new BRDF_GGX();
|
||||
}
|
||||
|
||||
static LTCAreaLight s_Instance;
|
||||
|
||||
public static LTCAreaLight instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_Instance == null)
|
||||
s_Instance = new LTCAreaLight();
|
||||
|
||||
return s_Instance;
|
||||
}
|
||||
}
|
||||
|
||||
int m_refCounting;
|
||||
|
||||
// For area lighting - We pack all texture inside a texture array to reduce the number of resource required
|
||||
Texture2DArray m_LtcData; // 0: m_LtcGGXMatrix - RGBA, 1: m_LtcDisneyDiffuseMatrix - RGBA
|
||||
|
||||
public const int k_LtcLUTResolution = 64;
|
||||
|
||||
LTCAreaLight()
|
||||
{
|
||||
m_refCounting = 0;
|
||||
}
|
||||
|
||||
public void Build()
|
||||
{
|
||||
Debug.Assert(m_refCounting >= 0);
|
||||
|
||||
if (m_refCounting == 0)
|
||||
{
|
||||
m_LtcData = new Texture2DArray(k_LtcLUTResolution, k_LtcLUTResolution, (int)LTCLightingModel.Count, GraphicsFormat.R16G16B16A16_SFloat, TextureCreationFlags.None)
|
||||
{
|
||||
hideFlags = HideFlags.HideAndDontSave,
|
||||
wrapMode = TextureWrapMode.Clamp,
|
||||
filterMode = FilterMode.Bilinear,
|
||||
name = CoreUtils.GetTextureAutoName(k_LtcLUTResolution, k_LtcLUTResolution, GraphicsFormat.R16G16B16A16_SFloat, depth: (int)LTCLightingModel.Count, dim: TextureDimension.Tex2DArray, name: "LTC_LUT")
|
||||
};
|
||||
|
||||
m_LtcData.SetPixelData(s_LtcMatrixData_BRDF_GGX, 0, (int)LTCLightingModel.GGX);
|
||||
m_LtcData.SetPixelData(s_LtcMatrixData_BRDF_Disney, 0, (int)LTCLightingModel.DisneyDiffuse);
|
||||
|
||||
m_LtcData.SetPixelData(s_LtcMatrixData_BRDF_Charlie, 0, (int)LTCLightingModel.Charlie);
|
||||
|
||||
m_LtcData.SetPixelData(s_LtcMatrixData_BRDF_KajiyaKaySpecular, 0, (int)LTCLightingModel.KajiyaKaySpecular);
|
||||
// TODO: Generate the Marschner LCT Table
|
||||
|
||||
m_LtcData.SetPixelData(s_LtcMatrixData_BRDF_CookTorrance, 0, (int)LTCLightingModel.CookTorrance);
|
||||
m_LtcData.SetPixelData(s_LtcMatrixData_BRDF_Ward, 0, (int)LTCLightingModel.Ward);
|
||||
m_LtcData.SetPixelData(s_LtcMatrixData_BRDF_OrenNayar, 0, (int)LTCLightingModel.OrenNayar);
|
||||
|
||||
m_LtcData.Apply();
|
||||
}
|
||||
|
||||
m_refCounting++;
|
||||
}
|
||||
|
||||
public void Cleanup()
|
||||
{
|
||||
m_refCounting--;
|
||||
|
||||
if (m_refCounting == 0)
|
||||
{
|
||||
CoreUtils.Destroy(m_LtcData);
|
||||
}
|
||||
|
||||
Debug.Assert(m_refCounting >= 0);
|
||||
}
|
||||
|
||||
public void Bind(CommandBuffer cmd)
|
||||
{
|
||||
cmd.SetGlobalTexture("_LtcData", m_LtcData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aea83b49b088a6047859da87f9277680
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/LTCAreaLight/LTCAreaLight.cs
|
||||
uploadId: 884030
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a19f6e467644af244b2d0559127ea6cf
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,168 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Experimental.Rendering;
|
||||
|
||||
namespace BadDog.Rendering.AreaLight
|
||||
{
|
||||
public class PreIntegratedFGD
|
||||
{
|
||||
[GenerateHLSL]
|
||||
public enum FGDTexture
|
||||
{
|
||||
Resolution = 64
|
||||
}
|
||||
|
||||
static PreIntegratedFGD s_Instance;
|
||||
|
||||
public static PreIntegratedFGD instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_Instance == null)
|
||||
{
|
||||
s_Instance = new PreIntegratedFGD();
|
||||
}
|
||||
|
||||
return s_Instance;
|
||||
}
|
||||
}
|
||||
|
||||
public enum FGDIndex
|
||||
{
|
||||
FGD_GGXAndDisneyDiffuse = 0,
|
||||
FGD_CharlieAndFabricLambert = 1,
|
||||
FGD_Marschner = 2,
|
||||
Count = 3
|
||||
}
|
||||
|
||||
bool[] m_isInit = new bool[(int)FGDIndex.Count];
|
||||
int[] m_refCounting = new int[(int)FGDIndex.Count];
|
||||
|
||||
Material[] m_PreIntegratedFGDMaterial = new Material[(int)FGDIndex.Count];
|
||||
RenderTexture[] m_PreIntegratedFGD = new RenderTexture[(int)FGDIndex.Count];
|
||||
Shader[] m_CustomShaders = new Shader[(int)FGDIndex.Count];
|
||||
|
||||
PreIntegratedFGD()
|
||||
{
|
||||
for (int i = 0; i < (int)FGDIndex.Count; ++i)
|
||||
{
|
||||
m_isInit[i] = false;
|
||||
m_refCounting[i] = 0;
|
||||
m_CustomShaders[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set custom shader for a specific FGD index. If null, will fallback to Shader.Find()
|
||||
/// </summary>
|
||||
public void SetShader(FGDIndex index, Shader shader)
|
||||
{
|
||||
if (index >= FGDIndex.Count)
|
||||
{
|
||||
Debug.LogError($"Invalid FGD index: {index}");
|
||||
return;
|
||||
}
|
||||
m_CustomShaders[(int)index] = shader;
|
||||
}
|
||||
|
||||
private Shader GetShaderForIndex(FGDIndex index)
|
||||
{
|
||||
// Use custom shader if set, otherwise fallback to Shader.Find()
|
||||
Shader customShader = m_CustomShaders[(int)index];
|
||||
if (customShader != null)
|
||||
{
|
||||
return customShader;
|
||||
}
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case FGDIndex.FGD_GGXAndDisneyDiffuse: return Shader.Find("Hidden/BadDog/URP/PreIntegratedFGD_GGXDisneyDiffuse");
|
||||
case FGDIndex.FGD_CharlieAndFabricLambert: return Shader.Find("Hidden/BadDog/URP/PreIntegratedFGD_CharlieFabricLambert");
|
||||
case FGDIndex.FGD_Marschner: return Shader.Find("Hidden/BadDog/URP/PreIntegratedFGD_Marschner");
|
||||
default: Debug.LogError($"Unable to get shader for index: {index}."); break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Build(FGDIndex index)
|
||||
{
|
||||
Debug.Assert(index != FGDIndex.Count);
|
||||
Debug.Assert(m_refCounting[(int)index] >= 0);
|
||||
|
||||
if (m_refCounting[(int)index] == 0)
|
||||
{
|
||||
Shader pixelShader = GetShaderForIndex(index);
|
||||
int res = (int)FGDTexture.Resolution;
|
||||
m_PreIntegratedFGDMaterial[(int)index] = CoreUtils.CreateEngineMaterial(pixelShader);
|
||||
m_PreIntegratedFGD[(int)index] = new RenderTexture(res, res, 0, GraphicsFormat.A2B10G10R10_UNormPack32)
|
||||
{
|
||||
hideFlags = HideFlags.HideAndDontSave,
|
||||
filterMode = FilterMode.Bilinear,
|
||||
wrapMode = TextureWrapMode.Clamp,
|
||||
name = CoreUtils.GetRenderTargetAutoName(res, res, 1, GraphicsFormat.A2B10G10R10_UNormPack32, $"preIntegrated{index}")
|
||||
};
|
||||
m_PreIntegratedFGD[(int)index].Create();
|
||||
m_isInit[(int)index] = false;
|
||||
}
|
||||
|
||||
m_refCounting[(int)index]++;
|
||||
}
|
||||
|
||||
public void RenderInit(FGDIndex index, CommandBuffer cmd)
|
||||
{
|
||||
if (m_isInit[(int)index] && m_PreIntegratedFGD[(int)index].IsCreated())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If we are in wireframe mode, the drawfullscreen will not work as expected, but we don't need the LUT anyway
|
||||
// So create the texture to avoid errors, it will be initialized by the first render without wireframe
|
||||
if (GL.wireframe)
|
||||
{
|
||||
m_PreIntegratedFGD[(int)index].Create();
|
||||
return;
|
||||
}
|
||||
|
||||
CoreUtils.DrawFullScreen(cmd, m_PreIntegratedFGDMaterial[(int)index], new RenderTargetIdentifier(m_PreIntegratedFGD[(int)index]));
|
||||
m_isInit[(int)index] = true;
|
||||
}
|
||||
|
||||
public void Cleanup(FGDIndex index)
|
||||
{
|
||||
m_refCounting[(int)index]--;
|
||||
|
||||
if (m_refCounting[(int)index] == 0)
|
||||
{
|
||||
CoreUtils.Destroy(m_PreIntegratedFGDMaterial[(int)index]);
|
||||
CoreUtils.Destroy(m_PreIntegratedFGD[(int)index]);
|
||||
|
||||
m_isInit[(int)index] = false;
|
||||
}
|
||||
|
||||
Debug.Assert(m_refCounting[(int)index] >= 0);
|
||||
}
|
||||
|
||||
public void Bind(CommandBuffer cmd, FGDIndex index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case FGDIndex.FGD_GGXAndDisneyDiffuse:
|
||||
cmd.SetGlobalTexture(PreIntegratedFGDShaderIDs._PreIntegratedFGD_GGXDisneyDiffuse, m_PreIntegratedFGD[(int)index]);
|
||||
break;
|
||||
|
||||
case FGDIndex.FGD_CharlieAndFabricLambert:
|
||||
cmd.SetGlobalTexture(PreIntegratedFGDShaderIDs._PreIntegratedFGD_CharlieAndFabric, m_PreIntegratedFGD[(int)index]);
|
||||
break;
|
||||
|
||||
case FGDIndex.FGD_Marschner:
|
||||
cmd.SetGlobalTexture(PreIntegratedFGDShaderIDs._PreIntegratedFGD_Marschner, m_PreIntegratedFGD[(int)index]);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 595ce7af30b78214f9930f6a78f1b917
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/PreIntegratedFGD/PreIntegratedFGD.cs
|
||||
uploadId: 884030
|
||||
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace BadDog.Rendering.AreaLight
|
||||
{
|
||||
/// <summary>
|
||||
/// Shader property IDs for Pre-Integrated FGD (Fresnel, Geometric, Diffuse)
|
||||
/// </summary>
|
||||
public static class PreIntegratedFGDShaderIDs
|
||||
{
|
||||
// Pre-integrated FGD texture IDs
|
||||
public static readonly int _PreIntegratedFGD_GGXDisneyDiffuse = Shader.PropertyToID("_PreIntegratedFGD_GGXDisneyDiffuse");
|
||||
public static readonly int _PreIntegratedFGD_CharlieAndFabric = Shader.PropertyToID("_PreIntegratedFGD_CharlieAndFabric");
|
||||
public static readonly int _PreIntegratedFGD_Marschner = Shader.PropertyToID("_PreIntegratedFGD_Marschner");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71b06b7ce73f870438526fc0d026ba8c
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 346790
|
||||
packageName: Realtime Area Light for URP
|
||||
packageVersion: 1.3.0
|
||||
assetPath: Packages/com.baddog.rendering.arealight/Runtime/Material/PreIntegratedFGD/PreIntegratedFGDShaderIDs.cs
|
||||
uploadId: 884030
|
||||
Reference in New Issue
Block a user