in unity/Assets/PostProcessingV2/Runtime/Effects/Bloom.cs [92:216]
public override void Render(PostProcessRenderContext context)
{
var cmd = context.command;
cmd.BeginSample("BloomPyramid");
var sheet = context.propertySheets.Get(context.resources.shaders.bloom);
// Apply auto exposure adjustment in the prefiltering pass
sheet.properties.SetTexture(ShaderIDs.AutoExposureTex, context.autoExposureTexture);
// Negative anamorphic ratio values distort vertically - positive is horizontal
float ratio = Mathf.Clamp(settings.anamorphicRatio, -1, 1);
float rw = ratio < 0 ? -ratio : 0f;
float rh = ratio > 0 ? ratio : 0f;
// Do bloom on a half-res buffer, full-res doesn't bring much and kills performances on
// fillrate limited platforms
int tw = Mathf.FloorToInt(context.screenWidth / (2f - rw));
int th = Mathf.FloorToInt(context.screenHeight / (2f - rh));
// Determine the iteration count
int s = Mathf.Max(tw, th);
float logs = Mathf.Log(s, 2f) + Mathf.Min(settings.diffusion.value, 10f) - 10f;
int logs_i = Mathf.FloorToInt(logs);
int iterations = Mathf.Clamp(logs_i, 1, k_MaxPyramidSize);
float sampleScale = 0.5f + logs - logs_i;
sheet.properties.SetFloat(ShaderIDs.SampleScale, sampleScale);
// Prefiltering parameters
float lthresh = Mathf.GammaToLinearSpace(settings.threshold.value);
float knee = lthresh * settings.softKnee.value + 1e-5f;
var threshold = new Vector4(lthresh, lthresh - knee, knee * 2f, 0.25f / knee);
sheet.properties.SetVector(ShaderIDs.Threshold, threshold);
int qualityOffset = settings.fastMode ? 1 : 0;
// Downsample
var lastDown = context.source;
for (int i = 0; i < iterations; i++)
{
int mipDown = m_Pyramid[i].down;
int mipUp = m_Pyramid[i].up;
int pass = i == 0
? (int)Pass.Prefilter13 + qualityOffset
: (int)Pass.Downsample13 + qualityOffset;
context.GetScreenSpaceTemporaryRT(cmd, mipDown, 0, context.sourceFormat, RenderTextureReadWrite.Default, FilterMode.Bilinear, tw, th);
context.GetScreenSpaceTemporaryRT(cmd, mipUp, 0, context.sourceFormat, RenderTextureReadWrite.Default, FilterMode.Bilinear, tw, th);
cmd.BlitFullscreenTriangle(lastDown, mipDown, sheet, pass);
lastDown = mipDown;
tw = Mathf.Max(tw / 2, 1);
th = Mathf.Max(th / 2, 1);
}
// Upsample
int lastUp = m_Pyramid[iterations - 1].down;
for (int i = iterations - 2; i >= 0; i--)
{
int mipDown = m_Pyramid[i].down;
int mipUp = m_Pyramid[i].up;
cmd.SetGlobalTexture(ShaderIDs.BloomTex, mipDown);
cmd.BlitFullscreenTriangle(lastUp, mipUp, sheet, (int)Pass.UpsampleTent + qualityOffset);
lastUp = mipUp;
}
var linearColor = settings.color.value.linear;
float intensity = RuntimeUtilities.Exp2(settings.intensity.value / 10f) - 1f;
var shaderSettings = new Vector4(sampleScale, intensity, settings.dirtIntensity.value, iterations);
// Debug overlays
if (context.IsDebugOverlayEnabled(DebugOverlay.BloomThreshold))
{
context.PushDebugOverlay(cmd, context.source, sheet, (int)Pass.DebugOverlayThreshold);
}
else if (context.IsDebugOverlayEnabled(DebugOverlay.BloomBuffer))
{
sheet.properties.SetVector(ShaderIDs.ColorIntensity, new Vector4(linearColor.r, linearColor.g, linearColor.b, intensity));
context.PushDebugOverlay(cmd, m_Pyramid[0].up, sheet, (int)Pass.DebugOverlayTent + qualityOffset);
}
// Lens dirtiness
// Keep the aspect ratio correct & center the dirt texture, we don't want it to be
// stretched or squashed
var dirtTexture = settings.dirtTexture.value == null
? RuntimeUtilities.blackTexture
: settings.dirtTexture.value;
var dirtRatio = (float)dirtTexture.width / (float)dirtTexture.height;
var screenRatio = (float)context.screenWidth / (float)context.screenHeight;
var dirtTileOffset = new Vector4(1f, 1f, 0f, 0f);
if (dirtRatio > screenRatio)
{
dirtTileOffset.x = screenRatio / dirtRatio;
dirtTileOffset.z = (1f - dirtTileOffset.x) * 0.5f;
}
else if (screenRatio > dirtRatio)
{
dirtTileOffset.y = dirtRatio / screenRatio;
dirtTileOffset.w = (1f - dirtTileOffset.y) * 0.5f;
}
// Shader properties
var uberSheet = context.uberSheet;
uberSheet.EnableKeyword("BLOOM");
uberSheet.properties.SetVector(ShaderIDs.Bloom_DirtTileOffset, dirtTileOffset);
uberSheet.properties.SetVector(ShaderIDs.Bloom_Settings, shaderSettings);
uberSheet.properties.SetColor(ShaderIDs.Bloom_Color, linearColor);
uberSheet.properties.SetTexture(ShaderIDs.Bloom_DirtTex, dirtTexture);
cmd.SetGlobalTexture(ShaderIDs.BloomTex, lastUp);
// Cleanup
for (int i = 0; i < iterations; i++)
{
if (m_Pyramid[i].down != lastUp)
cmd.ReleaseTemporaryRT(m_Pyramid[i].down);
if (m_Pyramid[i].up != lastUp)
cmd.ReleaseTemporaryRT(m_Pyramid[i].up);
}
cmd.EndSample("BloomPyramid");
context.bloomBufferNameID = lastUp;
}