浏览代码

Replace tangent frames with 'localToWorld'

/main
Evgenii Golubev 8 年前
当前提交
efd3ad16
共有 3 个文件被更改,包括 113 次插入127 次删除
  1. 37
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.hlsl
  2. 19
      Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl
  3. 184
      Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl

37
Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.hlsl


EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 2048)
{
float3 N = bsdfData.normalWS;
float3 tangentX = bsdfData.tangentWS;
float3 tangentY = bsdfData.bitangentWS;
float3 acc = float3(0.0, 0.0, 0.0);
float3 N = bsdfData.normalWS;
float3 tangentX = bsdfData.tangentWS;
float3x3 localToWorld = GetLocalFrame(N, tangentX);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(N.xy * 0.5 + 0.5);

float3 L;
float NdotL;
float weightOverPdf;
ImportanceSampleLambert(u, N, tangentX, tangentY, L, NdotL, weightOverPdf);
ImportanceSampleLambert(u, localToWorld, L, NdotL, weightOverPdf);
if (NdotL > 0.0)
{

float3 V, EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 2048)
{
float3 N = bsdfData.normalWS;
float3 tangentX = bsdfData.tangentWS;
float3 tangentY = bsdfData.bitangentWS;
float NdotV = GetShiftedNdotV(N, V, false);
float3 acc = float3(0.0, 0.0, 0.0);
float3 N = bsdfData.normalWS;
float3 tangentX = bsdfData.tangentWS;
float3x3 localToWorld = GetLocalFrame(N, tangentX);
float NdotV = GetShiftedNdotV(N, V, false);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(N.xy * 0.5 + 0.5);

float NdotL;
float weightOverPdf;
// for Disney we still use a Cosine importance sampling, true Disney importance sampling imply a look up table
ImportanceSampleLambert(u, N, tangentX, tangentY, L, NdotL, weightOverPdf);
ImportanceSampleLambert(u, localToWorld, L, NdotL, weightOverPdf);
{
{
float3 H = normalize(L + V);
float LdotH = dot(L, H);
// Note: we call DisneyDiffuse that require to multiply by Albedo / PI. Divide by PI is already taken into account

float3 V, EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 2048)
{
float3 N = bsdfData.normalWS;
float3 tangentX = bsdfData.tangentWS;
float3 tangentY = bsdfData.bitangentWS;
float NdotV = GetShiftedNdotV(N, V, false);
float3 acc = float3(0.0, 0.0, 0.0);
float3 N = bsdfData.normalWS;
float3 tangentX = bsdfData.tangentWS;
float3 tangentY = bsdfData.bitangentWS;
float3x3 localToWorld = GetLocalFrame(N, tangentX);
float NdotV = GetShiftedNdotV(N, V, false);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);

}
else
{
ImportanceSampleGGX(u, V, N, tangentX, tangentY, bsdfData.roughness, NdotV, L, VdotH, NdotL, weightOverPdf);
ImportanceSampleGGX(u, V, localToWorld, bsdfData.roughness, NdotV, L, VdotH, NdotL, weightOverPdf);
}

19
Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl


// Get local frame
//-----------------------------------------------------------------------------
// generate an orthonormalBasis from 3d unit vector.
void GetLocalFrame(float3 N, out float3 tangentX, out float3 tangentY)
// Generates an orthonormal basis from two orthogonal unit vectors.
float3x3 GetLocalFrame(float3 localZ, float3 localX)
{
float3 localY = cross(localZ, localX);
return float3x3(localX, localY, localZ);
}
// Generates an orthonormal basis from a unit vector.
float3x3 GetLocalFrame(float3 localZ)
float3 upVector = abs(N.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0);
tangentX = normalize(cross(upVector, N));
tangentY = cross(N, tangentX);
float3 upVector = abs(localZ.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0);
float3 localX = normalize(cross(upVector, localZ));
return GetLocalFrame(localZ, localX);
}
// TODO: test

184
Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl


// Coordinate system conversion
//-----------------------------------------------------------------------------
// Transforms the unit vector from the spherical to the Cartesian (right-handed, Z up) coordinate.
float3 SphericalToCartesian(float phi, float sinTheta, float cosTheta)
{
float sinPhi, cosPhi;
sincos(phi, sinPhi, cosPhi);
return float3(sinTheta * cosPhi, sinTheta * sinPhi, cosTheta);
}
// Converts Cartesian coordinates given in the right-handed coordinate system
// with Z pointing upwards (OpenGL style) to the coordinates in the left-handed
// coordinate system with Y pointing up and Z facing forward (DirectX style).

// Performs conversion from equiareal map coordinates to Cartesian (DirectX cubemap) ones.
float3 ConvertEquiarealToCubemap(float u, float v)
{
// We have to convert the direction vector from the spherical to the Cartesian coordinates:
// x = sin(theta) * cos(phi)
// y = sin(theta) * sin(phi)
// z = cos(theta)
// phi = TWO_PI * (1.0 - u)
// cos(theta) = 1.0 - 2.0 * v
// sin(theta) = sqrt(1.0 - cos^2(theta)) = 2.0 * sqrt(v - v * v)
// phi = TWO_PI * (1.0 - u)
// cos(theta) = 1.0 - 2.0 * v
// sin(theta) = sqrt(1.0 - cos^2(theta)) = 2.0 * sqrt(v - v * v)
float sinPhi, cosPhi;
sincos(TWO_PI - TWO_PI * u, sinPhi, cosPhi);
float phi = TWO_PI - TWO_PI * u;
return TransformGLtoDX(sinTheta * cosPhi, sinTheta * sinPhi, cosTheta);
return TransformGLtoDX(SphericalToCartesian(phi, sinTheta, cosTheta));
}
// Ref: See "Moving Frostbite to PBR" Listing 22

// Importance sampling BSDF functions
// ----------------------------------------------------------------------------
void ImportanceSampleCosDir(float2 u,
float3 N,
float3 tangentX,
float3 tangentY,
out float3 L)
void ImportanceSampleCosDir(float2 u,
float3x3 localToWorld,
out float3 L)
float phi = TWO_PI * u.y;
float phi = TWO_PI * u.y;
// Transform from spherical into cartesian
L = float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
// Local to world
L = tangentX * L.x + tangentY * L.y + N * L.z;
L = SphericalToCartesian(phi, sinTheta, cosTheta);
L = mul(L, localToWorld);
void ImportanceSampleGGXDir(float2 u,
float3 V,
float3 N,
float3 tangentX,
float3 tangentY,
float roughness,
out float3 H,
out float3 L)
void ImportanceSampleGGXDir(float2 u,
float3 V,
float3x3 localToWorld,
float roughness,
out float3 L,
out float NdotH,
out float VdotH,
bool VeqN = false)
float cosThetaH = sqrt((1.0 - u.x) / (1.0 + (roughness * roughness - 1.0) * u.x));
float sinThetaH = sqrt(saturate(1.0 - cosThetaH * cosThetaH));
float phiH = TWO_PI * u.y;
float cosTheta = sqrt((1.0 - u.x) / (1.0 + (roughness * roughness - 1.0) * u.x));
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
float phi = TWO_PI * u.y;
// Transform from spherical into cartesian
H = float3(sinThetaH * cos(phiH), sinThetaH * sin(phiH), cosThetaH);
// Local to world
H = tangentX * H.x + tangentY * H.y + N * H.z;
// Convert sample from half angle to incident angle
L = 2.0 * dot(V, H) * H - V;
}
float3 localH = SphericalToCartesian(phi, sinTheta, cosTheta);
// Special case of ImportanceSampleGGXDir() where V == N.
void ImportanceSampleGGXDirVeqN(float2 u,
float3 N,
float3 tangentX,
float3 tangentY,
float roughness,
out float3 L,
out float NdotH)
{
// GGX NDF sampling
float cosThetaH = sqrt((1.0 - u.x) / (1.0 + (roughness * roughness - 1.0) * u.x));
float sinThetaH = sqrt(saturate(1.0 - cosThetaH * cosThetaH));
float phiH = TWO_PI * u.y;
NdotH = cosTheta;
// Transform from spherical to Cartesian
float3 localH = float3(sinThetaH * cos(phiH), sinThetaH * sin(phiH), cosThetaH);
float3 localV;
// localN == localV == float3(0.0, 0.0, 1.0)
NdotH = localH.z;
if (VeqN)
{
// localV == localN
localV = float3(0.0, 0.0, 1.0);
VdotH = NdotH;
}
else
{
localV = mul(V, transpose(localToWorld));
VdotH = saturate(dot(localV, localH));
}
float VdotH = NdotH;
L = float3(0.0, 0.0, -1.0) + 2.0 * VdotH * localH;
L = -localV + 2.0 * VdotH * localH;
// Local to world
L = tangentX * L.x + tangentY * L.y + N * L.z;
L = mul(L, localToWorld);
}
// ref: http://blog.selfshadow.com/publications/s2012-shading-course/burley/s2012_pbs_disney_brdf_notes_v3.pdf p26

// H = tangentX * H.x + tangentY * H.y + N * H.z;
// Convert sample from half angle to incident angle
L = 2.0 * dot(V, H) * H - V;
L = 2.0 * saturate(dot(V, H)) * H - V;
void ImportanceSampleLambert(
float2 u,
float3 N,
float3 tangentX,
float3 tangentY,
out float3 L,
out float NdotL,
out float weightOverPdf)
void ImportanceSampleLambert(float2 u,
float3x3 localToWorld,
out float3 L,
out float NdotL,
out float weightOverPdf)
ImportanceSampleCosDir(u, N, tangentX, tangentY, L);
ImportanceSampleCosDir(u, localToWorld, L);
NdotL = saturate(dot(N, L));
NdotL = saturate(dot(localToWorld[2], L));
// Importance sampling weight for each sample
// pdf = N.L / PI

}
// weightOverPdf return the weight (without the Fresnel term) over pdf. Fresnel term must be apply by the caller.
void ImportanceSampleGGX(
float2 u,
float3 V,
float3 N,
float3 tangentX,
float3 tangentY,
float roughness,
float NdotV,
out float3 L,
out float VdotH,
out float NdotL,
out float weightOverPdf)
void ImportanceSampleGGX(float2 u,
float3 V,
float3x3 localToWorld,
float roughness,
float NdotV,
out float3 L,
out float VdotH,
out float NdotL,
out float weightOverPdf)
ImportanceSampleGGXDir(u, V, N, tangentX, tangentY, roughness, H, L);
float NdotH;
ImportanceSampleGGXDir(u, V, localToWorld, roughness, L, NdotH, VdotH);
float NdotH = saturate(dot(N, H));
// Note: since L and V are symmetric around H, LdotH == VdotH
VdotH = saturate(dot(V, H));
NdotL = saturate(dot(N, L));
NdotL = saturate(dot(localToWorld[2], L));
// Importance sampling weight for each sample
// pdf = D(H) * (N.H) / (4 * (L.H))

// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
float3x3 localToWorld = GetLocalFrame(N);
for (uint i = 0; i < sampleCount; ++i)
{

float weightOverPdf;
float3 L; // Unused
ImportanceSampleGGX(u, V, N, tangentX, tangentY, roughness, NdotV,
ImportanceSampleGGX(u, V, localToWorld, roughness, NdotV,
L, VdotH, NdotL, weightOverPdf);
if (NdotL > 0.0)

}
// for Disney we still use a Cosine importance sampling, true Disney importance sampling imply a look up table
ImportanceSampleLambert(u, N, tangentX, tangentY, L, NdotL, weightOverPdf);
ImportanceSampleLambert(u, localToWorld, L, NdotL, weightOverPdf);
if (NdotL > 0.0)
{

float3 N,
float roughness,
float invOmegaP,
uint sampleCount, // static uint (must be a Fibonacci number)
bool prefilter) // static bool
uint sampleCount, // Must be a Fibonacci number
bool prefilter)
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
float3x3 localToWorld = GetLocalFrame(N);
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);

float2 u = frac(randNum + Fibonacci2d(i, sampleCount));
float3 L;
float NdotH;
ImportanceSampleGGXDirVeqN(u, N, tangentX, tangentY, roughness, L, NdotH);
float NdotH, VdotH;
ImportanceSampleGGXDir(u, V, localToWorld, roughness, L, NdotH, VdotH, true);
float NdotL = saturate(dot(N, L));

float3 N,
float roughness,
float invOmegaP,
uint width, // static uint
uint height, // static uint
uint sampleCount, // static uint
bool prefilter) // static bool
uint width,
uint height,
uint sampleCount,
bool prefilter)
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
float3x3 localToWorld = GetLocalFrame(N);
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);

正在加载...
取消
保存