浏览代码

Implement multi-bounce GGX for direct lighting (no Fresnel yet)

/Yibing-Project-2
Evgenii Golubev 7 年前
当前提交
d610a7cf
共有 6 个文件被更改,包括 137 次插入6 次删除
  1. 12
      ScriptableRenderPipeline/Core/ShaderLibrary/Fibonacci.hlsl
  2. 26
      ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl
  3. 17
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs
  4. 9
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  5. 69
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/ComputeGgxEnergyCompensationFactors.shader
  6. 10
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/ComputeGgxEnergyCompensationFactors.shader.meta

12
ScriptableRenderPipeline/Core/ShaderLibrary/Fibonacci.hlsl


// Computes a point using the Fibonacci sequence of length N.
// Input: Fib[N - 1], Fib[N - 2], and the index 'i' of the point.
// Ref: Efficient Quadrature Rules for Illumination Integrals
float2 Fibonacci2dSeq(float fibN1, float fibN2, int i)
float2 Fibonacci2dSeq(float fibN1, float fibN2, uint i)
{
// 3 cycles on GCN if 'fibN1' and 'fibN2' are known at compile time.
// N.b.: According to Swinbank and Pusser [SP06], the uniformity of the distribution

#define GOLDEN_RATIO 1.6180339887498948482
// Replaces the Fibonacci sequence in Fibonacci2dSeq() with the Golden ratio.
float2 Golden2dSeq(int i, float n)
float2 Golden2dSeq(uint i, float n)
static const int k_FibonacciSeq[] = {
static const uint k_FibonacciSeq[] = {
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181
};

case 89: return k_Fibonacci2dSeq89[i];
default:
{
int fibN1 = sampleCount;
int fibN2 = sampleCount;
uint fibN1 = sampleCount;
uint fibN2 = sampleCount;
for (int j = 1; j < 20; j++)
for (uint j = 1; j < 20; j++)
{
if (k_FibonacciSeq[j] == fibN1)
{

26
ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl


return acc / sampleCount;
}
float ComputeGgxEnergyCompensationFactor(float3 V, float3 N, float roughness, uint sampleCount = 4096)
{
float NdotV = saturate(dot(N, V));
float total = 0;
float3x3 localToWorld = GetLocalFrame(N);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Golden2dSeq(i, sampleCount);
float3 L;
float VdotH, NdotL, weight;
// Compute Weight = BSDF * NdotL / PDF.
ImportanceSampleGGX(u, V, localToWorld, roughness, NdotV, L, VdotH, NdotL, weight);
if (NdotL > 0.0)
{
total += weight * rcp(sampleCount);
}
}
return saturate(total);
}
uint GetIBLRuntimeFilterSampleCount(uint mipLevel)
{
uint sampleCount = 0;

17
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs


// For image based lighting
Material m_InitPreFGD;
Material m_ComputeGgxEnergyCompensationFactors;
RenderTexture m_GgxEnergyCompensationFactors;
// 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, 2: m_LtcDisneyDiffuseMatrix - RGBA, 3: m_LtcMultiGGXFresnelDisneyDiffuse - RGB, A unused

public override void Build(RenderPipelineResources renderPipelineResources)
{
m_InitPreFGD = CoreUtils.CreateEngineMaterial("Hidden/HDRenderPipeline/PreIntegratedFGD");
m_ComputeGgxEnergyCompensationFactors = CoreUtils.CreateEngineMaterial("Hidden/HDRenderPipeline/ComputeGgxEnergyCompensationFactors");
// For DisneyDiffuse integration values goes from (0.5 to 1.53125). GGX need 0 to 1. Use float format.
m_PreIntegratedFGD = new RenderTexture(128, 128, 0, RenderTextureFormat.RGB111110Float, RenderTextureReadWrite.Linear);

m_PreIntegratedFGD.Create();
m_GgxEnergyCompensationFactors = new RenderTexture(128, 128, 0, RenderTextureFormat.RFloat, RenderTextureReadWrite.Linear);
m_GgxEnergyCompensationFactors.filterMode = FilterMode.Bilinear;
m_GgxEnergyCompensationFactors.wrapMode = TextureWrapMode.Clamp;
m_GgxEnergyCompensationFactors.hideFlags = HideFlags.DontSave;
m_GgxEnergyCompensationFactors.Create();
m_LtcData = new Texture2DArray(k_LtcLUTResolution, k_LtcLUTResolution, 3, TextureFormat.RGBAHalf, false /*mipmap*/, true /* linear */)
{

public override void Cleanup()
{
CoreUtils.Destroy(m_InitPreFGD);
CoreUtils.Destroy(m_ComputeGgxEnergyCompensationFactors);
// TODO: how to delete RenderTexture ? or do we need to do it ?
m_isInit = false;

{
CoreUtils.DrawFullScreen(cmd, m_InitPreFGD, new RenderTargetIdentifier(m_PreIntegratedFGD));
}
using (new ProfilingSample(cmd, "Compute GGX Energy Compensation Factors"))
{
CoreUtils.DrawFullScreen(cmd, m_ComputeGgxEnergyCompensationFactors, new RenderTargetIdentifier(m_GgxEnergyCompensationFactors));
}
m_isInit = true;
}

Shader.SetGlobalTexture("_GgxEnergyCompensationFactors", m_GgxEnergyCompensationFactors);
Shader.SetGlobalTexture("_LtcData", m_LtcData);
}
}

9
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


// Area light textures
// TODO: This one should be set into a constant Buffer at pass frequency (with _Screensize)
TEXTURE2D(_PreIntegratedFGD);
TEXTURE2D(_GgxEnergyCompensationFactors);
TEXTURE2D_ARRAY(_LtcData); // We pack the 3 Ltc data inside a texture array
#define LTC_GGX_MATRIX_INDEX 0 // RGBA
#define LTC_DISNEY_DIFFUSE_MATRIX_INDEX 1 // RGBA

#endif
}
specularLighting += F * DV;
#define MS_GGX 1
#if MS_GGX
float ecV = SAMPLE_TEXTURE2D_LOD(_GgxEnergyCompensationFactors, s_linear_clamp_sampler, float2(NdotV, bsdfData.perceptualRoughness), 0).r;
float ecL = SAMPLE_TEXTURE2D_LOD(_GgxEnergyCompensationFactors, s_linear_clamp_sampler, float2(NdotL, bsdfData.perceptualRoughness), 0).r;
specularLighting += F * ecV * ecL;
#endif
#ifdef LIT_DIFFUSE_LAMBERT_BRDF
float diffuseTerm = Lambert();

69
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/ComputeGgxEnergyCompensationFactors.shader


Shader "Hidden/HDRenderPipeline/ComputeGgxEnergyCompensationFactors"
{
SubShader {
Pass {
ZTest Always Cull Off ZWrite Off
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
#include "../../../../Core/ShaderLibrary/Common.hlsl"
#include "../../../../Core/ShaderLibrary/ImageBasedLighting.hlsl"
#include "../../../ShaderVariables.hlsl"
struct Attributes
{
uint vertexID : SV_VertexID;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 texCoord : TEXCOORD0;
};
Varyings Vert(Attributes input)
{
Varyings output;
output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID);
output.texCoord = GetFullScreenTriangleTexCoord(input.vertexID);
return output;
}
float4 Frag(Varyings input) : SV_Target
{
// These coordinate sampling must match the decoding in GetPreIntegratedDFG in lit.hlsl, i.e here we use perceptualRoughness, must be the same in shader
float NdotV = input.texCoord.x;
float roughness = PerceptualRoughnessToRoughness(input.texCoord.y);
float3 N = float3(0, 0, 1);
float3 V = float3(sqrt(1 - NdotV * NdotV), 0, NdotV);
float fDir = ComputeGgxEnergyCompensationFactor(V, N, roughness);
float fAvg = 0;
const uint numSamples = 128;
for (uint i = 0; i < numSamples; i++)
{
NdotV = (i + 0.5) * rcp(numSamples);
V = float3(sqrt(1 - NdotV * NdotV), 0, NdotV);
fAvg += ComputeGgxEnergyCompensationFactor(V, N, roughness) * NdotV * (2 * rcp(numSamples));
}
float f = (1 - fDir) * rsqrt(PI * (1 - fAvg));
// f_ms = f[NdotV, perceptualRoughness] * f[NdotL, perceptualRoughness].
return f.xxxx;
}
ENDHLSL
}
}
Fallback Off
}

10
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/ComputeGgxEnergyCompensationFactors.shader.meta


fileFormatVersion: 2
guid: c7c7d11c211eb5746b7fe3d016ae62e8
timeCreated: 1508422200
licenseType: Pro
ShaderImporter:
externalObjects: {}
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存