zifa2003293 发表于 2022-6-22 11:34

unity URP bloom 移动端性能优化

本文主要记录在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;
            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 : ShaderConstants._BloomMipUp;
                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);
                }
            }
页: [1]
查看完整版本: unity URP bloom 移动端性能优化