浏览代码

Factor out the GGX filtering code

/main
Evgenii Golubev 8 年前
当前提交
65c98c8d
共有 9 个文件被更改,包括 170 次插入103 次删除
  1. 8
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/Resources/GGXConvolve.shader
  2. 4
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/Resources/ComputeGgxIblSampleData.compute
  3. 93
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/SkyManager.cs
  4. 4
      Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl
  5. 9
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/Resources/ComputeGgxIblSampleData.compute.meta
  6. 134
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/RuntimeFilterIBL.cs
  7. 12
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/RuntimeFilterIBL.cs.meta
  8. 9
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/Resources/PrecomputeIblGgxData.compute.meta
  9. 0
      /Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/Resources/ComputeGgxIblSampleData.compute

8
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/Resources/GGXConvolve.shader


TEXTURECUBE(_MainTex);
SAMPLERCUBE(sampler_MainTex);
TEXTURE2D(_IblGgxSamples);
TEXTURE2D(_GgxIblSamples);
#ifdef USE_MIS
TEXTURE2D(_MarginalRowDensities);

float _Level;
float _MaxLevel;
float _LastLevel;
float _InvOmegaP;
half4 Frag(Varyings input) : SV_Target

false);
#else
float4 val = IntegrateLD(TEXTURECUBE_PARAM(_MainTex, sampler_MainTex),
_IblGgxSamples,
_GgxIblSamples,
_MaxLevel,
_LastLevel,
_InvOmegaP,
sampleCount, // Must be a Fibonacci number
true,

4
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/Resources/ComputeGgxIblSampleData.compute


RWTexture2D<float4> output; // [MAX_SAMPLE_CNT x UNITY_SPECCUBE_LOD_STEPS]
#pragma kernel PrecomputeIblGgxData
#pragma kernel ComputeGgxIblSampleData
void PrecomputeIblGgxData(uint3 groupThreadId : SV_GroupThreadID)
void ComputeGgxIblSampleData(uint3 groupThreadId : SV_GroupThreadID)
{
uint sampleIndex = groupThreadId.x;
uint mipLevel = groupThreadId.y + 1;

93
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/SkyManager.cs


RenderTexture m_SkyboxGGXCubemapRT = null;
RenderTexture m_SkyboxMarginalRowCdfRT = null;
RenderTexture m_SkyboxConditionalCdfRT = null;
RenderTexture m_IblGgxSamples = null;
Material m_GGXConvolveMaterial = null; // Apply GGX convolution to cubemap
ComputeShader m_InitIblGgxSamples = null;
const int k_IblGgxMaxSampleCount = 89;
const int k_IblGgxMipCountMinusOne = 6; // UNITY_SPECCUBE_LOD_STEPS
ComputeShader m_BuildProbabilityTablesCS = null;
int m_ConditionalDensitiesKernel = -1;
int m_MarginalRowDensitiesKernel = -1;
IBLFilterGGX m_iblFilterGgx = null;
Vector4 m_CubemapScreenSize;
Matrix4x4[] m_faceCameraViewProjectionMatrix = new Matrix4x4[6];

if (m_Renderer != null)
m_Renderer.Build();
m_InitIblGgxSamples = Resources.Load<ComputeShader>("PrecomputeIblGgxData");
// Create unititialized. Lazy initialization is performed later.
m_iblFilterGgx = new IBLFilterGGX();
m_GGXConvolveMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/GGXConvolve");
m_BuildProbabilityTablesCS = Resources.Load<ComputeShader>("BuildProbabilityTables");
m_ConditionalDensitiesKernel = m_BuildProbabilityTablesCS.FindKernel("ComputeConditionalDensities");
m_MarginalRowDensitiesKernel = m_BuildProbabilityTablesCS.FindKernel("ComputeMarginalRowDensities");
m_CurrentUpdateTime = 0.0f;
}

Utilities.Destroy(m_IblGgxSamples);
Utilities.Destroy(m_GGXConvolveMaterial);
Utilities.Destroy(m_SkyboxCubemapRT);
Utilities.Destroy(m_SkyboxGGXCubemapRT);
Utilities.Destroy(m_SkyboxMarginalRowCdfRT);

}
}
private void BuildProbabilityTables(ScriptableRenderContext renderContext)
{
// Bind the input cubemap.
m_BuildProbabilityTablesCS.SetTexture(m_ConditionalDensitiesKernel, "envMap", m_SkyboxCubemapRT);
// Bind the outputs.
m_BuildProbabilityTablesCS.SetTexture(m_ConditionalDensitiesKernel, "marginalRowDensities", m_SkyboxMarginalRowCdfRT);
m_BuildProbabilityTablesCS.SetTexture(m_ConditionalDensitiesKernel, "conditionalDensities", m_SkyboxConditionalCdfRT);
m_BuildProbabilityTablesCS.SetTexture(m_MarginalRowDensitiesKernel, "marginalRowDensities", m_SkyboxMarginalRowCdfRT);
var cmd = new CommandBuffer() { name = "" };
cmd.DispatchCompute(m_BuildProbabilityTablesCS, m_ConditionalDensitiesKernel, (int)LightSamplingParameters.TextureHeight, 1, 1);
cmd.DispatchCompute(m_BuildProbabilityTablesCS, m_MarginalRowDensitiesKernel, 1, 1, 1);
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
private void RenderCubemapGGXConvolution(ScriptableRenderContext renderContext, BuiltinSkyParameters builtinParams, SkyParameters skyParams, Texture input, RenderTexture target)
{
using (new Utilities.ProfilingSample("Sky Pass: GGX Convolution", renderContext))

return;
}
if (m_IblGgxSamples == null)
if (!m_iblFilterGgx.IsInitialized())
// Precompute the samples. It is done only once (lazy initialization).
m_IblGgxSamples = new RenderTexture(k_IblGgxMaxSampleCount, k_IblGgxMipCountMinusOne, 1, RenderTextureFormat.ARGBFloat);
m_IblGgxSamples.dimension = TextureDimension.Tex2D;
m_IblGgxSamples.useMipMap = false;
m_IblGgxSamples.autoGenerateMips = false;
m_IblGgxSamples.enableRandomWrite = true;
m_IblGgxSamples.filterMode = FilterMode.Point;
m_IblGgxSamples.Create();
int kernel = m_InitIblGgxSamples.FindKernel("PrecomputeIblGgxData");
m_InitIblGgxSamples.SetTexture(kernel, "output", m_IblGgxSamples);
var cmd = new CommandBuffer();
cmd.name = "Init IBL GGX Samples";
cmd.DispatchCompute(m_InitIblGgxSamples, kernel, 1, 1, 1);
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
if (m_useMIS)
{
BuildProbabilityTables(renderContext);
m_iblFilterGgx.Initialize(renderContext);
}
// Copy the first mip.

if (m_useMIS)
{
m_GGXConvolveMaterial.EnableKeyword("USE_MIS");
m_GGXConvolveMaterial.SetTexture("_MarginalRowDensities", m_SkyboxMarginalRowCdfRT);
m_GGXConvolveMaterial.SetTexture("_ConditionalDensities", m_SkyboxConditionalCdfRT);
m_iblFilterGgx.FilterCubemapGgxMis(renderContext, mipCount, input, target, m_SkyboxConditionalCdfRT, m_SkyboxMarginalRowCdfRT, m_CubemapFaceMesh);
m_GGXConvolveMaterial.DisableKeyword("USE_MIS");
m_iblFilterGgx.FilterCubemapGgx(renderContext, mipCount, input, target, m_CubemapFaceMesh);
// Do the convolution on remaining mipmaps
float invOmegaP = (6.0f * input.width * input.width) / (4.0f * Mathf.PI); // Solid angle associated to a pixel of the cubemap;
m_GGXConvolveMaterial.SetTexture("_MainTex", input);
m_GGXConvolveMaterial.SetTexture("_IblGgxSamples", m_IblGgxSamples);
m_GGXConvolveMaterial.SetFloat("_MaxLevel", mipCount - 1);
m_GGXConvolveMaterial.SetFloat("_InvOmegaP", invOmegaP);
for (int mip = 1; mip < ((int)EnvConstants.SpecCubeLodStep + 1); ++mip)
{
MaterialPropertyBlock propertyBlock = new MaterialPropertyBlock();
propertyBlock.SetFloat("_Level", mip);
for (int face = 0; face < 6; ++face)
{
Utilities.SetRenderTarget(renderContext, target, ClearFlag.ClearNone, mip, (CubemapFace)face);
var cmd = new CommandBuffer { name = "" };
cmd.DrawMesh(m_CubemapFaceMesh[face], Matrix4x4.identity, m_GGXConvolveMaterial, 0, 0, propertyBlock);
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
}
}
}

4
Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl


float3 N,
float roughness,
float index, // Current MIP level minus one
float maxMipLevel,
float lastMipLevel,
float invOmegaP,
uint sampleCount, // Must be a Fibonacci number
bool prefilter,

// Bias the MIP map level to compensate for the importance sampling bias.
// This will blur the reflection.
// TODO: find a more accurate MIP bias function.
mipLevel = lerp(mipLevel, maxMipLevel, bias);
mipLevel = lerp(mipLevel, lastMipLevel, bias);
// TODO: There is a bug currently where autogenerate mipmap for the cubemap seems to
// clamp the mipLevel to 6. correct it! Then remove this clamp

9
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/Resources/ComputeGgxIblSampleData.compute.meta


fileFormatVersion: 2
guid: 764a24bb47ef5ba4781d9ae82ca07445
timeCreated: 1484572881
licenseType: Pro
ComputeShaderImporter:
currentAPIMask: 4
userData:
assetBundleName:
assetBundleVariant:

134
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/RuntimeFilterIBL.cs


using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
using System;
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
public class IBLFilterGGX
{
RenderTexture m_GgxIblSampleData = null;
const int k_GgxIblMaxSampleCount = 89; // Width
const int k_GgxIblMipCountMinusOne = 6; // Height (UNITY_SPECCUBE_LOD_STEPS)
ComputeShader m_ComputeGgxIblSampleDataCS = null;
int m_ComputeIblGgxSampleDataKernel = -1;
ComputeShader m_BuildProbabilityTablesCS = null;
int m_ConditionalDensitiesKernel = -1;
int m_MarginalRowDensitiesKernel = -1;
Material m_GgxConvolveMaterial = null; // Convolves a cubemap with GGX
public bool IsInitialized()
{
return m_GgxIblSampleData != null;
}
public void Initialize(ScriptableRenderContext context)
{
if (!m_ComputeGgxIblSampleDataCS)
{
m_ComputeGgxIblSampleDataCS = Resources.Load<ComputeShader>("ComputeGgxIblSampleData");
m_ComputeIblGgxSampleDataKernel = m_ComputeGgxIblSampleDataCS.FindKernel("ComputeGgxIblSampleData");
}
if (!m_BuildProbabilityTablesCS)
{
m_BuildProbabilityTablesCS = Resources.Load<ComputeShader>("BuildProbabilityTables");
m_ConditionalDensitiesKernel = m_BuildProbabilityTablesCS.FindKernel("ComputeConditionalDensities");
m_MarginalRowDensitiesKernel = m_BuildProbabilityTablesCS.FindKernel("ComputeMarginalRowDensities");
}
if (!m_GgxConvolveMaterial)
{
m_GgxConvolveMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/GGXConvolve");
}
if (!m_GgxIblSampleData)
{
m_GgxIblSampleData = new RenderTexture(k_GgxIblMaxSampleCount, k_GgxIblMipCountMinusOne, 1, RenderTextureFormat.ARGBFloat);
m_GgxIblSampleData.dimension = TextureDimension.Tex2D;
m_GgxIblSampleData.useMipMap = false;
m_GgxIblSampleData.autoGenerateMips = false;
m_GgxIblSampleData.enableRandomWrite = true;
m_GgxIblSampleData.filterMode = FilterMode.Point;
m_GgxIblSampleData.Create();
m_ComputeGgxIblSampleDataCS.SetTexture(m_ComputeIblGgxSampleDataKernel, "output", m_GgxIblSampleData);
var cmd = new CommandBuffer() { name = "Compute GGX IBL Sample Data" };
cmd.DispatchCompute(m_ComputeGgxIblSampleDataCS, m_ComputeIblGgxSampleDataKernel, 1, 1, 1);
context.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
}
void FilterCubemapGgxCommon(ScriptableRenderContext context, int mipCount,
Texture source, RenderTexture target,
Mesh[] cubemapFaceMesh)
{
// Solid angle associated with a texel of the cubemap.
float invOmegaP = (6.0f * source.width * source.width) / (4.0f * Mathf.PI);
m_GgxConvolveMaterial.SetTexture("_MainTex", source);
m_GgxConvolveMaterial.SetTexture("_GgxIblSamples", m_GgxIblSampleData);
m_GgxConvolveMaterial.SetFloat("_LastLevel", mipCount - 1);
m_GgxConvolveMaterial.SetFloat("_InvOmegaP", invOmegaP);
for (int mip = 1; mip < ((int)EnvConstants.SpecCubeLodStep + 1); ++mip)
{
MaterialPropertyBlock props = new MaterialPropertyBlock();
props.SetFloat("_Level", mip);
for (int face = 0; face < 6; ++face)
{
Utilities.SetRenderTarget(context, target, ClearFlag.ClearNone, mip, (CubemapFace)face);
var cmd = new CommandBuffer { name = "" };
cmd.DrawMesh(cubemapFaceMesh[face], Matrix4x4.identity, m_GgxConvolveMaterial, 0, 0, props);
context.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
}
}
// Filters MIP map levels (other than 0) with GGX using BRDF importance sampling.
public void FilterCubemapGgx(ScriptableRenderContext context, int mipCount,
Texture source, RenderTexture target,
Mesh[] cubemapFaceMesh)
{
m_GgxConvolveMaterial.DisableKeyword("USE_MIS");
FilterCubemapGgxCommon(context, mipCount, source, target, cubemapFaceMesh);
}
// Filters MIP map levels (other than 0) with GGX using multiple importance sampling.
public void FilterCubemapGgxMis(ScriptableRenderContext context, int mipCount,
Texture source, RenderTexture target,
RenderTexture conditionalCdf, RenderTexture marginalRowCdf,
Mesh[] cubemapFaceMesh)
{
// Bind the input cubemap.
m_BuildProbabilityTablesCS.SetTexture(m_ConditionalDensitiesKernel, "envMap", source);
// Bind the outputs.
m_BuildProbabilityTablesCS.SetTexture(m_ConditionalDensitiesKernel, "conditionalDensities", conditionalCdf);
m_BuildProbabilityTablesCS.SetTexture(m_ConditionalDensitiesKernel, "marginalRowDensities", marginalRowCdf);
m_BuildProbabilityTablesCS.SetTexture(m_MarginalRowDensitiesKernel, "marginalRowDensities", marginalRowCdf);
int numRows = conditionalCdf.height;
var cmd = new CommandBuffer() { name = "Build Probability Tables" };
cmd.DispatchCompute(m_BuildProbabilityTablesCS, m_ConditionalDensitiesKernel, numRows, 1, 1);
cmd.DispatchCompute(m_BuildProbabilityTablesCS, m_MarginalRowDensitiesKernel, 1, 1, 1);
context.ExecuteCommandBuffer(cmd);
cmd.Dispose();
m_GgxConvolveMaterial.EnableKeyword("USE_MIS");
m_GgxConvolveMaterial.SetTexture("_ConditionalDensities", conditionalCdf);
m_GgxConvolveMaterial.SetTexture("_MarginalRowDensities", marginalRowCdf);
FilterCubemapGgxCommon(context, mipCount, source, target, cubemapFaceMesh);
}
}
}

12
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/RuntimeFilterIBL.cs.meta


fileFormatVersion: 2
guid: 827056f7b26e8a64883735043af76431
timeCreated: 1484572874
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/Resources/PrecomputeIblGgxData.compute.meta


fileFormatVersion: 2
guid: d1d990f8fa3bd5040b4ceb3aaa64fa07
timeCreated: 1484498071
licenseType: Pro
ComputeShaderImporter:
currentAPIMask: 4
userData:
assetBundleName:
assetBundleVariant:

/Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/Resources/PrecomputeIblGgxData.compute → /Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/Resources/ComputeGgxIblSampleData.compute

正在加载...
取消
保存