in unity/Assets/PostProcessingV2/Runtime/Effects/ScreenSpaceReflections.cs [115:232]
public override void Render(PostProcessRenderContext context)
{
var cmd = context.command;
cmd.BeginSample("Screen-space Reflections");
// Get quality settings
if (settings.preset.value != ScreenSpaceReflectionPreset.Custom)
{
int id = (int)settings.preset.value;
settings.maximumIterationCount.value = m_Presets[id].maximumIterationCount;
settings.thickness.value = m_Presets[id].thickness;
settings.resolution.value = m_Presets[id].downsampling;
}
settings.maximumMarchDistance.value = Mathf.Max(0f, settings.maximumMarchDistance.value);
// Square POT target
int size = Mathf.ClosestPowerOfTwo(Mathf.Min(context.width, context.height));
if (settings.resolution.value == ScreenSpaceReflectionResolution.Downsampled)
size >>= 1;
else if (settings.resolution.value == ScreenSpaceReflectionResolution.Supersampled)
size <<= 1;
// The gaussian pyramid compute works in blocks of 8x8 so make sure the last lod has a
// minimum size of 8x8
const int kMaxLods = 12;
int lodCount = Mathf.FloorToInt(Mathf.Log(size, 2f) - 3f);
lodCount = Mathf.Min(lodCount, kMaxLods);
CheckRT(ref m_Resolve, size, size, context.sourceFormat, FilterMode.Trilinear, true);
var noiseTex = context.resources.blueNoise256[0];
var sheet = context.propertySheets.Get(context.resources.shaders.screenSpaceReflections);
sheet.properties.SetTexture(ShaderIDs.Noise, noiseTex);
var screenSpaceProjectionMatrix = new Matrix4x4();
screenSpaceProjectionMatrix.SetRow(0, new Vector4(size * 0.5f, 0f, 0f, size * 0.5f));
screenSpaceProjectionMatrix.SetRow(1, new Vector4(0f, size * 0.5f, 0f, size * 0.5f));
screenSpaceProjectionMatrix.SetRow(2, new Vector4(0f, 0f, 1f, 0f));
screenSpaceProjectionMatrix.SetRow(3, new Vector4(0f, 0f, 0f, 1f));
var projectionMatrix = GL.GetGPUProjectionMatrix(context.camera.projectionMatrix, false);
screenSpaceProjectionMatrix *= projectionMatrix;
sheet.properties.SetMatrix(ShaderIDs.ViewMatrix, context.camera.worldToCameraMatrix);
sheet.properties.SetMatrix(ShaderIDs.InverseViewMatrix, context.camera.worldToCameraMatrix.inverse);
sheet.properties.SetMatrix(ShaderIDs.InverseProjectionMatrix, projectionMatrix.inverse);
sheet.properties.SetMatrix(ShaderIDs.ScreenSpaceProjectionMatrix, screenSpaceProjectionMatrix);
sheet.properties.SetVector(ShaderIDs.Params, new Vector4((float)settings.vignette.value, settings.distanceFade.value, settings.maximumMarchDistance.value, lodCount));
sheet.properties.SetVector(ShaderIDs.Params2, new Vector4((float)context.width / (float)context.height, (float)size / (float)noiseTex.width, settings.thickness.value, settings.maximumIterationCount.value));
cmd.GetTemporaryRT(ShaderIDs.Test, size, size, 0, FilterMode.Point, context.sourceFormat);
cmd.BlitFullscreenTriangle(context.source, ShaderIDs.Test, sheet, (int)Pass.Test);
if (context.isSceneView)
{
cmd.BlitFullscreenTriangle(context.source, m_Resolve, sheet, (int)Pass.Resolve);
}
else
{
CheckRT(ref m_History, size, size, context.sourceFormat, FilterMode.Bilinear, false);
if (m_ResetHistory)
{
context.command.BlitFullscreenTriangle(context.source, m_History);
m_ResetHistory = false;
}
cmd.GetTemporaryRT(ShaderIDs.SSRResolveTemp, size, size, 0, FilterMode.Bilinear, context.sourceFormat);
cmd.BlitFullscreenTriangle(context.source, ShaderIDs.SSRResolveTemp, sheet, (int)Pass.Resolve);
sheet.properties.SetTexture(ShaderIDs.History, m_History);
cmd.BlitFullscreenTriangle(ShaderIDs.SSRResolveTemp, m_Resolve, sheet, (int)Pass.Reproject);
cmd.CopyTexture(m_Resolve, 0, 0, m_History, 0, 0);
cmd.ReleaseTemporaryRT(ShaderIDs.SSRResolveTemp);
}
cmd.ReleaseTemporaryRT(ShaderIDs.Test);
// Pre-cache mipmaps ids
if (m_MipIDs == null || m_MipIDs.Length == 0)
{
m_MipIDs = new int[kMaxLods];
for (int i = 0; i < kMaxLods; i++)
m_MipIDs[i] = Shader.PropertyToID("_SSRGaussianMip" + i);
}
var compute = context.resources.computeShaders.gaussianDownsample;
int kernel = compute.FindKernel("KMain");
var last = new RenderTargetIdentifier(m_Resolve);
for (int i = 0; i < lodCount; i++)
{
size >>= 1;
Assert.IsTrue(size > 0);
cmd.GetTemporaryRT(m_MipIDs[i], size, size, 0, FilterMode.Bilinear, context.sourceFormat, RenderTextureReadWrite.Default, 1, true);
cmd.SetComputeTextureParam(compute, kernel, "_Source", last);
cmd.SetComputeTextureParam(compute, kernel, "_Result", m_MipIDs[i]);
cmd.SetComputeVectorParam(compute, "_Size", new Vector4(size, size, 1f / size, 1f / size));
cmd.DispatchCompute(compute, kernel, size / 8, size / 8, 1);
cmd.CopyTexture(m_MipIDs[i], 0, 0, m_Resolve, 0, i + 1);
last = m_MipIDs[i];
}
for (int i = 0; i < lodCount; i++)
cmd.ReleaseTemporaryRT(m_MipIDs[i]);
sheet.properties.SetTexture(ShaderIDs.Resolve, m_Resolve);
cmd.BlitFullscreenTriangle(context.source, context.destination, sheet, (int)Pass.Composite);
cmd.EndSample("Screen-space Reflections");
}