|
本文主要记录在urp下对移动端的bloom性能优化,文中的测试数据来自vivo x5 打包实测。
先来看看原生的bloom,真机测试bloom的消耗是有4ms的开销,而目标消耗是1ms。
原始的bloom效果
从framedebug中我们可以看到在处理bloom时消耗掉了23个call。第一个是选取要做bloom区域的,最后一个是跟原图混合的。刨掉这两个还剩21个
进到源码中可以看到在降采样时是对缩小的图片做了高斯模糊。在升采样的时候没有对图片做操作,只是单纯的放大。
先不管那么多,直接把这些升降采样操作给屏蔽了,只剩基础的选去bloom区域的图,最后合成的图操作。打包看消耗,这时的消耗就已经是1ms了。但是bloom效果也没了,显然达不到优化的目的。
接下从升降采样次数下手来,因为高斯模糊每次模糊需要两次采样。我先利用BilinearFilter的特性采样到四个像素的中间像素,这样就相当与有了一个硬件级别的模糊。这里的消耗就基本是免费的。然后call的次数降低到了15次,做下来的效果如下图
BilinearFilter特性采样,15次call
采样的代码
可以看打这个模糊的效果散得太开而且过度也相当的不自然。于是我在升降采样的最后一次保留了原始的采样。(这里升采样用原始的,是因为在upr中有一个Scatter值,可以调节bloom边缘散射的程度,所以需要保留可调节的参数,方便美术使用。)出来的的效果bloom不明显,而且Scatter调节控制不平滑,效果如下图:
最后一次升降用原始的模糊
最后,经过不断的测试,在升降采样最后两次使用原始的高斯模糊和升采样的lerp效果比较理想。考虑到优化小iv的限制,在预处理bloom区域时把原来的TR的分辨率从1/2降低到了1/3。call数从原来的22次降低到了16次。真机测试整个bloom的消耗控制在了1ms内,对移动端来说可以大大提高效率。
最终效果
对比原始的bloom会发现有些锯齿状的小亮点,这是因为RT的分辨率降低导致的。在移动端上面认为时可以接受的。
最后考虑到灵活性做了高中低性能的切换开关,以期达到高自由度。下面是相关的代码块。
int tw;
int th;
if (m_Bloom.bloomQuality.value== BloomQuality.High)
{
tw = m_Descriptor.width >> 1;
th = m_Descriptor.height >> 1;
}
else
{
tw = m_Descriptor.width / 3;
th = m_Descriptor.height / 3;
}
// Determine the iteration count
int maxSize = Mathf.Max(tw, th);
int iterations = Mathf.FloorToInt(Mathf.Log(maxSize, 2f) - 1);
int mipCount = Mathf.Clamp(iterations, 1, k_MaxPyramidSize);
if (m_Bloom.bloomQuality.value != BloomQuality.High)
{
mipCount -= 2;
}
);
-----------------------------------------------------------
// Downsample - gaussian pyramid
int lastDown = ShaderConstants._BloomMipDown[0];
for (int i = 1; i < mipCount; i++)
{
tw = Mathf.Max(1, tw >> 1);
th = Mathf.Max(1, th >> 1);
int mipDown = ShaderConstants._BloomMipDown;
int mipUp = ShaderConstants._BloomMipUp;
desc.width = tw;
desc.height = th;
cmd.GetTemporaryRT(mipDown, desc, FilterMode.Bilinear);
cmd.GetTemporaryRT(mipUp, desc, FilterMode.Bilinear);
if(m_Bloom.bloomQuality.value == BloomQuality.Low)
{
if (mipCount - i > 4) //use fast blur
{
cmd.Blit(lastDown, mipDown, bloomMaterial, 4);
}
else
{
cmd.Blit(lastDown, mipUp, bloomMaterial, 1);
cmd.Blit(mipUp, mipDown, bloomMaterial, 2);
}
}
else
{
cmd.Blit(lastDown, mipUp, bloomMaterial, 1);
cmd.Blit(mipUp, mipDown, bloomMaterial, 2);
}
lastDown = mipDown;
}
// Upsample (bilinear by default, HQ filtering does bicubic instead
for (int i = mipCount - 2; i >= 0; i--)
{
int lowMip = (i == mipCount - 2) ? ShaderConstants._BloomMipDown[i + 1] : ShaderConstants._BloomMipUp[i + 1];
int highMip = ShaderConstants._BloomMipDown;
int dst = ShaderConstants._BloomMipUp;
cmd.SetGlobalTexture(ShaderConstants._MainTexLowMip, lowMip);
if (m_Bloom.bloomQuality.value == BloomQuality.Low)
{
if (i < 2)
{
cmd.Blit(highMip, BlitDstDiscardContent(cmd, dst), bloomMaterial, 3); //last use defulat shader pass
}
else
{
cmd.Blit(highMip, BlitDstDiscardContent(cmd, dst), bloomMaterial, 5);
}
}
else
{
cmd.Blit(highMip, BlitDstDiscardContent(cmd, dst), bloomMaterial, 3);
}
} |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|