浏览代码

HDRenderLoop: Make cubemap work (without parallax) and add ref mode

- comparison with ref GGX is not too bad, but still require improvement.
- wait for trilinear issue with cubemap to be solve before investigating
/main
Sebastien Lagarde 8 年前
当前提交
bce39f68
共有 5 个文件被更改,包括 173 次插入154 次删除
  1. 26
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs
  2. 161
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit/Lit.hlsl
  3. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/ShaderConfig.cs
  4. 134
      Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl
  5. 4
      Assets/TestScenes/HDTest/HDRenderLoopTest.unity

26
Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs


Material m_FinalPassMaterial;
// TODO: Find a way to automatically create/iterate through these kind of class
Lit.RenderLoop m_litRenderLoop = new Lit.RenderLoop();
Lit.RenderLoop m_litRenderLoop;
GBufferManager gbufferManager = new GBufferManager();
GBufferManager m_gbufferManager = new GBufferManager();
static private int s_CameraColorBuffer;
static private int s_CameraDepthBuffer;

m_cubeReflTexArray.AllocTextureArray(32, (int)m_TextureSettings.reflectionCubemapSize, TextureFormat.BC6H, true);
// Init Lit material buffer - GBuffer and init
gbufferManager.gbufferCount = m_litRenderLoop.GetGBufferCount();
for (int gbufferIndex = 0; gbufferIndex < gbufferManager.gbufferCount; ++gbufferIndex)
m_litRenderLoop = new Lit.RenderLoop(); // Our object can be garbacge collected, so need to be allocate here
m_gbufferManager.gbufferCount = m_litRenderLoop.GetGBufferCount();
for (int gbufferIndex = 0; gbufferIndex < m_gbufferManager.gbufferCount; ++gbufferIndex)
gbufferManager.SetBufferDescription(gbufferIndex, "_CameraGBufferTexture" + gbufferIndex, m_litRenderLoop.RTFormat[gbufferIndex], m_litRenderLoop.RTReadWrite[gbufferIndex]);
m_gbufferManager.SetBufferDescription(gbufferIndex, "_CameraGBufferTexture" + gbufferIndex, m_litRenderLoop.RTFormat[gbufferIndex], m_litRenderLoop.RTReadWrite[gbufferIndex]);
}
m_litRenderLoop.Rebuild();

cmd.GetTemporaryRT(s_CameraColorBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Default);
cmd.GetTemporaryRT(s_CameraDepthBuffer, w, h, 24, FilterMode.Point, RenderTextureFormat.Depth);
gbufferManager.InitGBuffers(w, h, cmd);
m_gbufferManager.InitGBuffers(w, h, cmd);
cmd.SetRenderTarget(new RenderTargetIdentifier(s_CameraColorBuffer), new RenderTargetIdentifier(s_CameraDepthBuffer));
cmd.ClearRenderTarget(true, false, new Color(0, 0, 0, 0));

var cmd = new CommandBuffer();
cmd.name = "Clear GBuffer";
// Write into the Camera Depth buffer
cmd.SetRenderTarget(gbufferManager.GetGBuffers(cmd), new RenderTargetIdentifier(s_CameraDepthBuffer));
cmd.SetRenderTarget(m_gbufferManager.GetGBuffers(cmd), new RenderTargetIdentifier(s_CameraDepthBuffer));
// Clear everything
// TODO: Clear is not required for color as we rewrite everything, will save performance.
cmd.ClearRenderTarget(false, true, new Color(0, 0, 0, 0));

// setup GBuffer for rendering
var cmd = new CommandBuffer();
cmd.name = "GBuffer Pass";
cmd.SetRenderTarget(gbufferManager.GetGBuffers(cmd), new RenderTargetIdentifier(s_CameraDepthBuffer));
cmd.SetRenderTarget(m_gbufferManager.GetGBuffers(cmd), new RenderTargetIdentifier(s_CameraDepthBuffer));
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();

m_DebugViewMaterialGBuffer.SetVector("_ScreenSize", screenSize);
m_DebugViewMaterialGBuffer.SetFloat("_DebugViewMaterial", (float)debugParameters.debugViewMaterial);
// gbufferManager.BindBuffers(m_DeferredMaterial);
// m_gbufferManager.BindBuffers(m_DeferredMaterial);
// TODO: Bind depth textures
var cmd = new CommandBuffer();
cmd.name = "GBuffer Debug Pass";

m_DeferredMaterial.SetMatrix("_InvViewProjMatrix", invViewProj);
Vector4 screenSize = ComputeScreenSize(camera);
m_DeferredMaterial.SetVector("_ScreenSize", screenSize);
m_DeferredMaterial.SetVector("_ScreenSize", screenSize);
// gbufferManager.BindBuffers(m_DeferredMaterial);
// m_gbufferManager.BindBuffers(m_DeferredMaterial);
// TODO: Bind depth textures
var cmd = new CommandBuffer();
cmd.name = "Deferred Ligthing Pass";

Shader.SetGlobalBuffer("_PunctualLightList", s_punctualLightList);
Shader.SetGlobalInt("_PunctualLightCount", lights.Count);
Shader.SetGlobalTexture("_EnvTextures", m_cubeReflTexArray.GetTexCache());
}
void UpdateReflectionProbes(VisibleReflectionProbe[] activeReflectionProbes)

Shader.SetGlobalBuffer("_EnvLightList", s_envLightList);
Shader.SetGlobalInt("_EnvLightCount", lights.Count);
Shader.SetGlobalTexture("_EnvTextures", m_cubeReflTexArray.GetTexCache());
}
public override void Render(Camera[] cameras, RenderLoop renderLoop)

161
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit/Lit.hlsl


}
// TODO: How can I declare a sampler for this one that is bilinear filtering
// TODO: This one should be set into a constant Buffer at pass frequency (with _Screensize)
UNITY_DECLARE_TEX2D(_PreIntegratedFGD);
// For image based lighting, a part of the BSDF is pre-integrated.

// _PreIntegratedFGD.y = Gv * Fc
// Pre integrate DisneyDiffuse FGD:
// _PreIntegratedFGD.z = DisneyDiffuse
// TEMP: CAUTION: use 1.0 - perceptualRoughness instead of perceptualRoughness because rendering is inversed due to dumb "openGL convention"...
float3 preFGD = UNITY_SAMPLE_TEX2D_LOD(_PreIntegratedFGD, float2(NdotV, 1.0 - perceptualRoughness), 0).xyz;
float3 preFGD = UNITY_SAMPLE_TEX2D_LOD(_PreIntegratedFGD, float2(NdotV, perceptualRoughness), 0).xyz;
// f0 * Gv * (1 - Fc) + Gv * Fc
specularFGD = fresnel0 * preFGD.x + preFGD.y;

}
//-----------------------------------------------------------------------------
// EvaluateBSDF functions for each light type
// EvaluateBSDF_Punctual
//-----------------------------------------------------------------------------
void EvaluateBSDF_Punctual( float3 V, float3 positionWS, PreLightData prelightData, PunctualLightData lightData, BSDFData bsdfData,

}
}
//-----------------------------------------------------------------------------
// Reference code for image based lighting
// ----------------------------------------------------------------------------
// Ref: Moving Frostbite to PBR (Appendix A)
float3 IntegrateLambertIBLRef( EnvLightData lightData, BSDFData bsdfData,
UNITY_ARGS_ENV(_EnvTextures),
uint sampleCount = 2048)
{
float3 N = bsdfData.normalWS;
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(N.xy * 0.5 + 0.5);
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float3 L;
float NdotL;
float weightOverPdf;
ImportanceSampleLambert(u, N, tangentX, tangentY, L, NdotL, weightOverPdf);
if (NdotL > 0.0)
{
float4 val = UNITY_SAMPLE_ENV_LOD(_EnvTextures, L, lightData, 0);
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
acc += bsdfData.diffuseColor * Lambert() * weightOverPdf * val.rgb;
}
}
return acc / sampleCount;
}
float3 IntegrateDisneyDiffuseIBLRef(float3 V, EnvLightData lightData, BSDFData bsdfData,
UNITY_ARGS_ENV(_EnvTextures),
uint sampleCount = 2048)
{
float3 N = bsdfData.normalWS;
float NdotV = dot(N, V);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(N.xy * 0.5 + 0.5);
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float3 L;
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);
if (NdotL > 0.0)
{
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
// in weightOverPdf of ImportanceSampleLambert call.
float disneyDiffuse = DisneyDiffuse(NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
float4 val = UNITY_SAMPLE_ENV_LOD(_EnvTextures, L, lightData, 0);
acc += bsdfData.diffuseColor * disneyDiffuse * weightOverPdf * val.rgb;
}
}
return acc / sampleCount;
}
// Ref: Moving Frostbite to PBR (Appendix A)
float3 IntegrateSpecularGGXIBLRef( float3 V, EnvLightData lightData, BSDFData bsdfData,
UNITY_ARGS_ENV(_EnvTextures),
uint sampleCount = 2048)
{
float3 N = bsdfData.normalWS;
float NdotV = saturate(dot(N, V));
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float VdotH;
float NdotL;
float3 L;
float weightOverPdf;
// GGX BRDF
ImportanceSampleGGX(u, V, N, tangentX, tangentY, bsdfData.roughness, NdotV,
L, VdotH, NdotL, weightOverPdf);
if (NdotL > 0.0)
{
// Fresnel component is apply here as describe in ImportanceSampleGGX function
float3 FweightOverPdf = F_Schlick(bsdfData.fresnel0, VdotH) * weightOverPdf;
float4 val = UNITY_SAMPLE_ENV_LOD(_EnvTextures, L, lightData, 0);
acc += FweightOverPdf * val.rgb;
}
}
return acc / sampleCount;
}
//-----------------------------------------------------------------------------
// EvaluateBSDF_Env
// ----------------------------------------------------------------------------
// _preIntegratedFGD and _CubemapLD are unique for each BRDF
void EvaluateBSDF_Env( float3 V, float3 positionWS, PreLightData prelightData, EnvLightData lightData, BSDFData bsdfData,
UNITY_ARGS_ENV(_EnvTextures),

// Reference Lambert diffuse / GGX Specular
//#define LIT_DISPLAY_REFERENCE
#ifdef LIT_DISPLAY_REFERENCE
specularLighting.rgb = IntegrateSpecularGGXIBLRef(V, lightData, bsdfData, UNITY_PASS_ENV(_EnvTextures));
specularLighting.a = 1.0;
/*
#ifdef DIFFUSE_LAMBERT_BRDF
diffuseLighting.rgb = IntegrateLambertIBLRef(lightData, bsdfData, UNITY_PASS_ENV(_EnvTextures));
#else
diffuseLighting.rgb = IntegrateDisneyDiffuseIBLRef(V, lightData, bsdfData, UNITY_PASS_ENV(_EnvTextures));
#endif
diffuseLighting.a = 1.0;
*/
diffuseLighting = float4(0.0, 0.0, 0.0, 0.0);
#else
// TODO: factor this code in common, so other material authoring don't require to rewrite everything,
// also think about how such a loop can handle 2 cubemap at the same time as old unity. Macro can allow to do that
// but we need to have UNITY_SAMPLE_ENV_LOD replace by a true function instead that is define by the lighting arcitecture.

// float shrinkedRoughness = AnisotropicStrechAtGrazingAngle(bsdfData.roughness, bsdfData.perceptualRoughness, NdotV);
// Note: As explain in GetPreLightData we use normalWS and not iblNormalWS here (in case of anisotropy)
float3 rayWS = GetSpecularDominantDir(bsdfData.normalWS, prelightData.iblR, bsdfData.roughness);
//float3 rayWS = GetSpecularDominantDir(bsdfData.normalWS, prelightData.iblR, bsdfData.roughness);
float3 rayWS = prelightData.iblR;
/*
if (lightData.shapeType == ENVSHAPETYPE_BOX)
{
// worldToLocal assume no scaling

// Smooth weighting
weight = smoothstep01(weight);
}
*/
float mip = perceptualRoughnessToMipmapLevel(bsdfData.perceptualRoughness);
float4 preLD = UNITY_SAMPLE_ENV_LOD(_EnvTextures, R, lightData, mip);

specularLighting.a = weight;
diffuseLighting = float4(0.0, 0.0, 0.0, 0.0);
#endif
}
#endif // UNITY_MATERIAL_LIT_INCLUDED

2
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/ShaderConfig.cs


// #define DIFFUSE_LAMBERT_BRDF
// #define USE_BSDF_PRE_LAMBDAV
// #define VELOCITY_IN_GBUFFER
// #define VELOCITY_IN_GBUFFER

134
Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl


weightOverPdf = 4.0 * Vis * NdotL * VdotH / NdotH;
}
//-----------------------------------------------------------------------------
// Reference
// ----------------------------------------------------------------------------
// Ref: Moving Frostbite to PBR (Appendix A)
void IntegrateLambertDiffuseIBLRef( out float3 diffuseLighting,
UNITY_ARGS_TEXCUBE(tex),
float3 N,
float3 diffuseAlbedo,
uint sampleCount = 2048)
{
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(N.xy * 0.5 + 0.5);
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float3 L;
float NdotL;
float weightOverPdf;
ImportanceSampleLambert(u, N, tangentX, tangentY, L, NdotL, weightOverPdf);
if (NdotL > 0.0)
{
float3 val = UNITY_SAMPLE_TEXCUBE_LOD(tex, L, 0).rgb;
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
acc += diffuseAlbedo * Lambert() * weightOverPdf * val;
}
}
diffuseLighting = acc / sampleCount;
}
// ----------------------------------------------------------------------------
void IntegrateDisneyDiffuseIBLRef( out float3 diffuseLighting,
UNITY_ARGS_TEXCUBE(tex),
float3 N,
float3 V,
float roughness,
float3 diffuseAlbedo,
uint sampleCount = 2048)
{
float NdotV = dot(N, V);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(N.xy * 0.5 + 0.5);
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float3 L;
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);
if (NdotL > 0.0)
{
float3 val = UNITY_SAMPLE_TEXCUBE_LOD(tex, L, 0).rgb;
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
// in weightOverPdf of ImportanceSampleLambert call.
float disneyDiffuse = DisneyDiffuse(NdotV, NdotL, LdotH, RoughnessToPerceptualRoughness(roughness));
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
acc += diffuseAlbedo * disneyDiffuse * weightOverPdf * val;
}
}
diffuseLighting = acc / sampleCount;
}
// ----------------------------------------------------------------------------
// Ref: Moving Frostbite to PBR (Appendix A)
void IntegrateSpecularGGXIBLRef(out float3 specularLighting,
UNITY_ARGS_TEXCUBE(tex),
float3 N,
float3 V,
float roughness,
float3 f0,
float f90,
uint sampleCount = 2048)
{
float NdotV = saturate(dot(N, V));
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float VdotH;
float NdotL;
float3 L;
float weightOverPdf;
// GGX BRDF
ImportanceSampleGGX(u, V, N, tangentX, tangentY, roughness, NdotV,
L, VdotH, NdotL, weightOverPdf);
if (NdotL > 0.0)
{
// Fresnel component is apply here as describe in ImportanceSampleGGX function
float3 FweightOverPdf = F_Schlick(f0, f90, VdotH) * weightOverPdf;
float3 val = UNITY_SAMPLE_TEXCUBE_LOD(tex, L, 0).rgb;
acc += FweightOverPdf * val;
}
}
specularLighting = acc / sampleCount;
}
// ----------------------------------------------------------------------------
// Pre-integration
// ----------------------------------------------------------------------------

4
Assets/TestScenes/HDTest/HDRenderLoopTest.unity


m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1175446862}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -9.72, y: -2.2412233, z: 6.43}
m_LocalPosition: {x: -8.72, y: -2.2412233, z: 6.43}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}

m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1828470159}
m_Enabled: 1
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92bb16b4ee20841929b24d6bd771738d, type: 3}
m_Name:

正在加载...
取消
保存