Skip to content

MSAA_Implement

zilch edited this page Aug 10, 2021 · 4 revisions

SRP抗锯齿实现 - MSAA

在之前的文章里,已经对业界的一些抗锯齿算法做了简单的总结 - 抗锯齿算法总结。 因此本篇主要聚焦在如何在SRP里实现这些算法。此篇为MSAA的实现。

现代的GPU大多提供了MSAA支持。因此,在Unity里我们只需要申请一个支持MultiSample的RenderTexture(后面简写为RT),然后向里面绘制就行了。流程大致如下:

  • 申请支持MultiSample的RT(以下简写为MSRT)
  • 将MSRT设置为管线的RenderTarget
  • 渲染场景到MSRT上(这里硬件自动完成MSAA抗锯齿)
  • 将MSRRT Blit到设备屏幕(这里会自动对MSRT进行ResolveAA)

下面依次说明。

在SRP中,我们可以通过CommandBuffer.GetTemporaryRT这个接口来申请一个临时的RT

public void GetTemporaryRT(int nameID, int width, int height, int depthBuffer, FilterMode filter, RenderTextureFormat format, RenderTextureReadWrite readWrite, int antiAliasing, bool enableRandomWrite);

antiAliasing这个参数的官方说明如下:

Anti-aliasing value indicates the number of samples per pixel. If unsupported by the hardware or rendering API, the greatest supported number of samples less than the indicated number is used. When a RenderTexture is using anti-aliasing, then any rendering into it will happen into the multi-sampled texture, which will be "resolved" into a regular texture when switching to another render target. To the rest of the system only this "resolved" surface is visible.

意思就是antiAliasing这个值表示了我们希望在一个像素内部生成多少个采样点。如果设为1,那就相当于没有抗锯齿效果。ResolveAA是指MultiSample-RT重新降采样为一张普通RT的过程,这个操作会自动发生在RenderTarget发生变化的时候。

于是为了能使用MSAA,我们首先要申请一个和屏幕相同尺寸的支持AntiAliasing的RT,并将其设置为管线的RenderTarget。

//申请Multi-Sample RT
_currentColorTarget = RenderTextureManager.AcquireColorTexture(_command,ref cameraRenderDescription);
_currentDepthTarget = _currentColorTarget;
//设置为管线的RenderTarget
_command.SetRenderTarget(_currentColorTarget,_currentDepthTarget);
//Clear一下
_command.ClearRenderTarget(true,true,cameraRenderDescription.camera.backgroundColor);
context.ExecuteCommandBuffer(_command);

特别需要注意的是,申请MSRT的时候,我们需要将memoryless配置为RenderTextureMemoryless.MSAA,这个配置意味着在Mobile这种TBR架构上,MSAA->ResolveAA->Display-FrameBuffer整个过程可以在On-Chip Memory上完成,而无需与System Memory进行交互。可以大大优化Mobile上的GPU 带宽。

在完成所有的场景渲染之后,我们需要一个Pass将这张RT重新Blit输出到设备屏幕上。

_blitPass.Config(_currentColorTarget,BuiltinRenderTextureType.CameraTarget);
_blitPass.Execute(context);

BlitPass里使用了CommandBuffer.Blit这个API配置一个自定义的BlitShader来完成操作。

这样一个完整的MSAA就实现了,还是非常简单的。效果对比如下:

上图为无抗锯齿效果,下图为MSAAx2效果。

Clone this wiki locally