UE4移动端的Checkerboard Rendering
https://zhuanlan.zhihu.com/p/124898057
前言
棋盘渲染(Checkerboard Rendering,后续简称CBR)是一种降低着色消耗还原全分辨率的一种技术。本文主要介绍在UE的Mobile管线中的各个Graph API实现,参考大多来源于Intel的paper[1].
技术简介
在介绍详细的实现细节前,我们先看看相关的原理。设原分辨率为 ,对于四分之一分辨率(长宽均为原来的一半)开启2x的MSAA[2]后采样点分布如下:
我们保存这张TextureMS的RT,接着在奇数帧抖动原始分辨率一个像素:
继续保存这张TextureMS到另一个buffer中,接着在CS中采样两张多重采样贴图的子采样点还原:
注意最左边的像素因为抖动而永远丢失了,而在实现的时候也可以让整个相机向左抖动,这样丢失的像素信息就会变成最右边的一列。
但实际上,MSAA采样点的位置不会总是在原分辨率的中心,分布点也可能并不均匀
Qualcomm Adreno
4x位置
所以当DownSample渲染的结果如果处于几何的边缘上,可能结果差别会比较大。
另外场景不是一成不变的,所以还需要记录Motion vector来还原因为相机移动和物体移动造成的pixel变化。而这种处理因游戏而异,一种通用的处理是对于相机使用深度来计算motion vector,对于动态物体单体写入velocity buffer然后在重建的CS中匹配对应的ID时采样velocity buffer。
管线改造
UE的MobileRenderer还是使用的Forward模式,所以修改起来相对容易。大体流程如下:
算法流程如下:
- 创建两个color和Depth buffer(第N-1帧和第N帧),大小均为四分之一分辨率
- 不带jittere渲染偶数帧(起始帧为第0帧)
- 修改Projection Matrix带上jittere渲染奇数帧
- 运行CS重建整个分辨率
FMobileSceneRenderer的Render流程十分简单,将BassPass和TranslucencyPass的RenderPassInfo的RT修改为自己创建的RT即可,然后在Post前执行自己的CS。
这里提一些重要的注意点:
- Pipline MSAA的shading方式要使用sample shading,而不是fragment shading
- 使用四分之一分辨率渲染到RT上时,mipmap的level要减去0.5来使得与原分辨率使用的texture level相同.(可以直接修改GlobalMipmapLODBias,而且引擎自身带有对其值的callback,当改变时自动更新所有的Material的SamplerState)
- 由于UE代码中到处都是直接引用SceneColor和SceneDepthZ的代码,所以最好的方式不是修改BassPass的RT,而是将SceneColor替换为自定义的RT,这样不用手动控制中间Pass对于原始SceneColor或Depth的访问(比如RenderOcclusion),在BassPass执行完Opque和Translucency时设置会原始的SceneColor和Depth.
Vulkan:
Vulkan的修改十分简单,可以对每一个具体的PiplineInfo来设置,在VkPipelineMultisampleStateCreateInfo中开启sampleShadingEnable并且设置minSampleShading为1.f:
OpenGL ES:
OpenGL的修改相对就复杂了很多,首先确保你的手机支持GL_OES_sample_shading拓展,然后手动开启GL_SAMPLE_SHADING_OES并设置minSampleShading,详细可以参考OpenGL ES3.2文档[3]。
另外UE原生并不支持在使用OpenGL ES的情况下输出MultisampleTexture,所以我们需要在OpenGLTexture下手动创建MultisampleTexture,并且在OpenGLRenderTarget中绑定到Framebuffer上。
性能结果:
以下为官方demo太阳神庙在Snapdragon 660上CBR表现(720p):
1.开启CBR
Vulkan开启CBR
2.关闭CBR
总结
这套方案对于几何边缘处理上无法做到完美还原,但在手机上分辨率较高屏幕较小效果比较可观。而且对于那些性能瓶颈在BassPass的情况能有较大的性能提升,反之如果材质不那么复杂即PS消耗不大,耗费在CS上的性能可能超过节省出的着色性能而出现负优化。所以开发人员需要针对不同情况自行斟酌。另外当前实现是没有对PostProcess进行处理的,对于某些后效也可以用一半着色的RT降低消耗。
参考
- ^Intel CBR https://software.intel.com/en-us/articles/checkerboard-rendering-for-real-time-upscaling-on-intel-integrated-graphics
- ^MSAA https://zhuanlan.zhihu.com/p/32823370
- ^GLES 3.2 https://www.khronos.org/registry/OpenGL/specs/es/3.2/es_spec_3.2.pdf
编辑于 04-04
文章被以下专栏收录
推荐阅读
UE4 Separate translucency 在IOS上的一些坑
【UE4】实时渲染(RTR——Real Time Rendering)基础入门 笔记
虚幻4渲染编程(Shader篇)【第二十二卷:Translucency With Depth】
UE4 Hair Strands浅析
8 条评论
写下你的评论...
- JDYYX04-07
顶一个
- xsky04-13
吃瓜学习了
- 天麒05-29
请问一下“Pipline MSAA的shading方式要使用sample shading,而不是fragment shading”MSAA默认是fragment shading,怎么开启sample shading?
leesanghoy (作者) 回复天麒05-29
我文章后面有说,不同api的方式
- 蘑菇头队长06-21
请问ios(metal)有对应的sample shading的api么?就是逐采样点渲染
leesanghoy (作者) 回复蘑菇头队长06-21
与DX类似,使用Sampling and Interpolation Attributes。在文档5.4章节,https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
- profhua09-02
采样的操作似乎在PS中也能实现啊,用cs是有什么优化嘛
leesanghoy (作者) 回复profhua09-03
可以的,用cs是为了方便。。