浏览代码

Refactor sampling methods

/main
Evgenii Golubev 8 年前
当前提交
e492618c
共有 4 个文件被更改,包括 75 次插入99 次删除
  1. 17
      Assets/ScriptableRenderLoop/HDRenderPipeline/SceneSettings/SubsurfaceScatteringParameters.cs
  2. 2
      Assets/ScriptableRenderLoop/ShaderLibrary/Hammersley.hlsl
  3. 72
      Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl
  4. 83
      Assets/ScriptableRenderLoop/ShaderLibrary/Sampling.hlsl

17
Assets/ScriptableRenderLoop/HDRenderPipeline/SceneSettings/SubsurfaceScatteringParameters.cs


[Serializable]
public class SubsurfaceScatteringProfile
{
public const int numSamples = 7;
public const int numSamples = 7; // Must be an odd number
Color m_StdDev1;
Color m_StdDev2;

return Mathf.Lerp(NormalCdfInverse(p, stdDev1), NormalCdfInverse(p, stdDev2), lerpWeight);
}
// Ref: http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
static float VanDerCorputBase2(uint i)
{
i = i + 1;
i = (i << 16) | (i >> 16);
i = ((i & 0x00ff00ff) << 8) | ((i & 0xff00ff00) >> 8);
i = ((i & 0x0f0f0f0f) << 4) | ((i & 0xf0f0f0f0) >> 4);
i = ((i & 0x33333333) << 2) | ((i & 0xcccccccc) >> 2);
i = ((i & 0x55555555) << 1) | ((i & 0xaaaaaaaa) >> 1);
return i * (1.0f / 4294967296);
}
void ComputeKernel()
{
if (m_FilterKernel == null)

// Importance sample the linear combination of two Gaussians.
for (uint i = 0; i < numSamples; i++)
{
float u = VanDerCorputBase2(i);
float u = (i + 0.5f) / numSamples;
float pos = GaussianCombinationCdfInverse(u, maxStdDev1, maxStdDev2, m_LerpWeight);
float pdf = GaussianCombination(pos, maxStdDev1, maxStdDev2, m_LerpWeight);

2
Assets/ScriptableRenderLoop/ShaderLibrary/Hammersley.hlsl


float VanDerCorputBase2(uint i)
{
return float(ReverseBits32(i + 1)) * 2.3283064365386963e-10; // 0x100000000
return ReverseBits32(i) * rcp(4294967296.0); // 0x100000000
}
float2 Hammersley2dSeq(uint i, uint sequenceLength)

72
Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl


return roughness * lerp(saturate(NdotV * 2.0), 1.0, perceptualRoughness);
}
//-----------------------------------------------------------------------------
// Coordinate system conversion
//-----------------------------------------------------------------------------
// Transforms the unit vector from the spherical to the Cartesian (right-handed, Z up) coordinate.
float3 SphericalToCartesian(float phi, float cosTheta)
{
float sinPhi, cosPhi;
sincos(phi, sinPhi, cosPhi);
float sinTheta = sqrt(saturate(1.0 - cosTheta * cosTheta));
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).
float3 TransformGLtoDX(float3 v)
{
return v.xzy;
}
// Performs conversion from equiareal map coordinates to Cartesian (DirectX cubemap) ones.
float3 ConvertEquiarealToCubemap(float u, float v)
{
float phi = TWO_PI - TWO_PI * u;
float cosTheta = 1.0 - 2.0 * v;
return TransformGLtoDX(SphericalToCartesian(phi, cosTheta));
}
// Performs uniform sampling of the unit disk.
// Ref: PBRT v3, p. 777.
float2 SampleDiskUniform(float2 u)
{
float r = sqrt(u.x);
float phi = TWO_PI * u.y;
float sinPhi, cosPhi;
sincos(phi, sinPhi, cosPhi);
return r * float2(cosPhi, sinPhi);
}
// Performs cosine-weighted sampling of the hemisphere.
// Ref: PBRT v3, p. 780.
void SampleHemisphereCosine(float2 u,
float3x3 localToWorld,
out float3 L,
out float NdotL)
{
float3 localL;
// Since we don't really care about the area distortion,
// we substitute uniform disk sampling for the concentric one.
localL.xy = SampleDiskUniform(u);
// Project the point from the disk onto the hemisphere.
localL.z = sqrt(1.0 - u.x);
NdotL = localL.z;
L = mul(localL, localToWorld);
}
void SampleGGXDir(float2 u,
float3 V,
float3x3 localToWorld,

out float NdotL,
out float weightOverPdf)
{
SampleHemisphereCosine(u, localToWorld, L, NdotL);
float3 localL = SampleHemisphereCosine(u.x, u.y);
NdotL = localL.z;
L = mul(localL, localToWorld);
// Importance sampling weight for each sample
// pdf = N.L / PI

83
Assets/ScriptableRenderLoop/ShaderLibrary/Sampling.hlsl


}
//-----------------------------------------------------------------------------
// Coordinate system conversion
//-----------------------------------------------------------------------------
// Transforms the unit vector from the spherical to the Cartesian (right-handed, Z up) coordinate.
float3 SphericalToCartesian(float phi, float cosTheta)
{
float sinPhi, cosPhi;
sincos(phi, sinPhi, cosPhi);
float sinTheta = sqrt(saturate(1.0 - cosTheta * cosTheta));
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).
float3 TransformGLtoDX(float3 v)
{
return v.xzy;
}
// Performs conversion from equiareal map coordinates to Cartesian (DirectX cubemap) ones.
float3 ConvertEquiarealToCubemap(float u, float v)
{
float phi = TWO_PI - TWO_PI * u;
float cosTheta = 1.0 - 2.0 * v;
return TransformGLtoDX(SphericalToCartesian(phi, cosTheta));
}
//-----------------------------------------------------------------------------
float3 UniformSampleSphere(float u1, float u2)
// Performs uniform sampling of the unit disk.
// Ref: PBRT v3, p. 777.
float2 SampleDiskUniform(float u1, float u2)
float r = sqrt(u1);
float cosTheta = 1.0 - 2.0 * u1;
float sinTheta = sqrt(max(0.0, 1.0 - cosTheta * cosTheta));
float sinPhi, cosPhi;
sincos(phi, sinPhi, cosPhi);
return r * float2(cosPhi, sinPhi);
}
return float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); // Light point backward (-Z)
// Performs cosine-weighted sampling of the hemisphere.
// Ref: PBRT v3, p. 780.
float3 SampleHemisphereCosine(float u1, float u2)
{
float3 localL;
// Since we don't really care about the area distortion,
// we substitute uniform disk sampling for the concentric one.
localL.xy = SampleDiskUniform(u1, u2);
// Project the point from the disk onto the hemisphere.
localL.z = sqrt(1.0 - u1);
return localL;
float3 UniformSampleHemisphere(float u1, float u2)
float3 SampleHemisphereUniform(float u1, float u2)
float phi = TWO_PI * u2;
float cosTheta = u1;
float sinTheta = sqrt(max(0.0, 1.0 - cosTheta * cosTheta));
float phi = TWO_PI * u2;
float cosTheta = 1.0 - u1;
return float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); // Light point backward (-Z)
return SphericalToCartesian(phi, cosTheta);
float3 UniformSampleDisk(float u1, float u2)
float3 SampleSphereUniform(float u1, float u2)
float r = sqrt(u1);
float phi = TWO_PI * u2;
float phi = TWO_PI * u2;
float cosTheta = 1.0 - 2.0 * u1;
return float3(r * cos(phi), r * sin(phi), 0); // Generate in XY plane as light point backward (-Z)
return SphericalToCartesian(phi, cosTheta);
}
void SampleSphere( float2 u,

float u1 = u.x;
float u2 = u.y;
Ns = UniformSampleSphere(u1, u2);
Ns = SampleSphereUniform(u1, u2);
// Transform from unit sphere to world space
P = radius * Ns + localToWorld[3].xyz;

float u2 = u.y;
// Random point at hemisphere surface
Ns = -UniformSampleHemisphere(u1, u2); // We want the y down hemisphere
Ns = -SampleHemisphereUniform(u1, u2); // We want the y down hemisphere
P = radius * Ns;
// Transform to world space

out float3 Ns)
{
// Random point at disk surface
P = UniformSampleDisk(u.x, u.y) * radius;
P = float3(radius * SampleDiskUniform(u.x, u.y), 0);
Ns = float3(0.0, 0.0, -1.0); // Light point backward (-Z)
// Transform to world space

正在加载...
取消
保存