您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
151 行
6.8 KiB
151 行
6.8 KiB
using UnityEngine.Rendering;
|
|
using UnityEngine.Experimental.Rendering.HDPipeline;
|
|
using System;
|
|
|
|
namespace UnityEngine.Experimental.Rendering.HDPipeline
|
|
{
|
|
public class IBLFilterGGX
|
|
{
|
|
RenderTexture m_GgxIblSampleData = null;
|
|
int k_GgxIblMaxSampleCount = TextureCache.isMobileBuildTarget ? 34 : 89; // Width
|
|
const int k_GgxIblMipCountMinusOne = 6; // Height (UNITY_SPECCUBE_LOD_STEPS)
|
|
|
|
ComputeShader m_ComputeGgxIblSampleDataCS = null;
|
|
int m_ComputeGgxIblSampleDataKernel = -1;
|
|
|
|
ComputeShader m_BuildProbabilityTablesCS = null;
|
|
int m_ConditionalDensitiesKernel = -1;
|
|
int m_MarginalRowDensitiesKernel = -1;
|
|
|
|
Material m_GgxConvolveMaterial = null; // Convolves a cubemap with GGX
|
|
|
|
bool m_SupportMIS = !TextureCache.isMobileBuildTarget;
|
|
|
|
RenderPipelineResources m_RenderPipelinesResources;
|
|
|
|
public IBLFilterGGX(RenderPipelineResources renderPipelinesResources)
|
|
{
|
|
m_RenderPipelinesResources = renderPipelinesResources;
|
|
}
|
|
|
|
public bool IsInitialized()
|
|
{
|
|
return m_GgxIblSampleData != null;
|
|
}
|
|
|
|
public bool SupportMIS
|
|
{
|
|
get { return m_SupportMIS; }
|
|
}
|
|
|
|
public void Initialize(CommandBuffer cmd)
|
|
{
|
|
if (!m_ComputeGgxIblSampleDataCS)
|
|
{
|
|
m_ComputeGgxIblSampleDataCS = m_RenderPipelinesResources.computeGgxIblSampleData;
|
|
m_ComputeGgxIblSampleDataKernel = m_ComputeGgxIblSampleDataCS.FindKernel("ComputeGgxIblSampleData");
|
|
}
|
|
|
|
if (!m_BuildProbabilityTablesCS && SupportMIS)
|
|
{
|
|
m_BuildProbabilityTablesCS = m_RenderPipelinesResources.buildProbabilityTables;
|
|
m_ConditionalDensitiesKernel = m_BuildProbabilityTablesCS.FindKernel("ComputeConditionalDensities");
|
|
m_MarginalRowDensitiesKernel = m_BuildProbabilityTablesCS.FindKernel("ComputeMarginalRowDensities");
|
|
}
|
|
|
|
if (!m_GgxConvolveMaterial)
|
|
{
|
|
m_GgxConvolveMaterial = Utilities.CreateEngineMaterial(m_RenderPipelinesResources.GGXConvolve);
|
|
}
|
|
|
|
if (!m_GgxIblSampleData)
|
|
{
|
|
m_GgxIblSampleData = new RenderTexture(k_GgxIblMaxSampleCount, k_GgxIblMipCountMinusOne, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
|
|
m_GgxIblSampleData.useMipMap = false;
|
|
m_GgxIblSampleData.autoGenerateMips = false;
|
|
m_GgxIblSampleData.enableRandomWrite = true;
|
|
m_GgxIblSampleData.filterMode = FilterMode.Point;
|
|
m_GgxIblSampleData.Create();
|
|
|
|
m_ComputeGgxIblSampleDataCS.SetTexture(m_ComputeGgxIblSampleDataKernel, "output", m_GgxIblSampleData);
|
|
|
|
using (new Utilities.ProfilingSample("Compute GGX IBL Sample Data", cmd))
|
|
{
|
|
cmd.DispatchCompute(m_ComputeGgxIblSampleDataCS, m_ComputeGgxIblSampleDataKernel, 1, 1, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FilterCubemapCommon(CommandBuffer cmd,
|
|
Texture source, RenderTexture target, int mipCount,
|
|
Matrix4x4[] worldToViewMatrices)
|
|
{
|
|
// 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)
|
|
{
|
|
string sampleName = String.Format("Filter Cubemap Mip {0}", mip);
|
|
cmd.BeginSample(sampleName);
|
|
|
|
for (int face = 0; face < 6; ++face)
|
|
{
|
|
Vector4 faceSize = new Vector4(source.width >> mip, source.height >> mip, 1.0f / (source.width >> mip), 1.0f / (source.height >> mip));
|
|
Matrix4x4 transform = SkyManager.ComputePixelCoordToWorldSpaceViewDirectionMatrix(0.5f * Mathf.PI, faceSize, worldToViewMatrices[face], true);
|
|
|
|
MaterialPropertyBlock props = new MaterialPropertyBlock();
|
|
props.SetFloat("_Level", mip);
|
|
props.SetMatrix(HDShaderIDs._PixelCoordToViewDirWS, transform);
|
|
|
|
Utilities.SetRenderTarget(cmd, target, ClearFlag.ClearNone, mip, (CubemapFace)face);
|
|
Utilities.DrawFullScreen(cmd, m_GgxConvolveMaterial, props);
|
|
}
|
|
cmd.EndSample(sampleName);
|
|
}
|
|
}
|
|
|
|
// Filters MIP map levels (other than 0) with GGX using BRDF importance sampling.
|
|
public void FilterCubemap(CommandBuffer cmd,
|
|
Texture source, RenderTexture target, int mipCount,
|
|
Matrix4x4[] worldToViewMatrices)
|
|
{
|
|
m_GgxConvolveMaterial.DisableKeyword("USE_MIS");
|
|
|
|
FilterCubemapCommon(cmd, source, target, mipCount, worldToViewMatrices);
|
|
}
|
|
|
|
// Filters MIP map levels (other than 0) with GGX using multiple importance sampling.
|
|
public void FilterCubemapMIS(CommandBuffer cmd,
|
|
Texture source, RenderTexture target, int mipCount,
|
|
RenderTexture conditionalCdf, RenderTexture marginalRowCdf,
|
|
Matrix4x4[] worldToViewMatrices)
|
|
{
|
|
// 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;
|
|
|
|
using (new Utilities.ProfilingSample("Build Probability Tables", cmd))
|
|
{
|
|
cmd.DispatchCompute(m_BuildProbabilityTablesCS, m_ConditionalDensitiesKernel, numRows, 1, 1);
|
|
cmd.DispatchCompute(m_BuildProbabilityTablesCS, m_MarginalRowDensitiesKernel, 1, 1, 1);
|
|
}
|
|
|
|
m_GgxConvolveMaterial.EnableKeyword("USE_MIS");
|
|
m_GgxConvolveMaterial.SetTexture("_ConditionalDensities", conditionalCdf);
|
|
m_GgxConvolveMaterial.SetTexture("_MarginalRowDensities", marginalRowCdf);
|
|
|
|
FilterCubemapCommon(cmd, source, target, mipCount, worldToViewMatrices);
|
|
}
|
|
}
|
|
}
|