
最近在看了下unity的urp_shader是怎么写多端的,就看到了类似于这样的宏
// Deferred Rendering Path does not support the OpenGL-based graphics API: // Desktop OpenGL, OpenGL ES 3.0, WebGL 2.0. #pragma exclude_renderers gles3 glcore
从注释就能看出来,这段代码的意思是:
他不支持延迟渲染管线在OpenGL的图形API比如以下的渲染器:
$$
Desktop OpenGL, OpenGL ES 3.0, WebGL 2.0.
$$
所以就想着来盘点一下,常见的渲染器和一般用的支持平台
同时回答下以下的疑问:
Unity不是号称「多平台一次编写」吗? GLES3明明也支持 MRT,为什么还是被排除? 不同渲染器(renderer / graphics API)之间到底差异在哪? 为什么有些平台天然就不适合延迟渲染?
先挂个列表:(markDown的表格支持并不是很好喵,让ai跑了个板式喵)
渲染器 | API 全名 | 主要平台 | 定位关键词
---——- | —————- | —————— | ————
gles | OpenGL ES 2.0 | 老移动端 | 兼容、低特性
gles3 | OpenGL ES 3.x | 移动端 | 主流移动
glcore | Desktop OpenGL | PC / Linux | 传统桌面
d3d11 | DirectX 11 | Windows | 稳定、易用
d3d12 | DirectX 12 | Windows / Xbox | 底层、高性能
vulkan | Vulkan API | 全平台 | 跨平台低层
metal | Apple Metal | iOS / macOS | 苹果专用
下面就按照这个列表,一个一个拆:
gles(OpenGL ES 2.0)过时的老登
一般用于:
早期的安卓和ios设备,还有各种嵌入式设备(机顶盒,车机,小玩具)
他的主要定位就是兼容性高,能跑就行
主要缺点是没有MRT ComputeShader等现代渲染常用的特性,同时shader的的能力有限。所以现代渲染就没办法跑在这个平台上。
gles3(OpenGL ES 3.x)现在移动端最常用的
当前安卓的主要设备上,包括一些VR一体机之类的,还有WebGL2.0
按道理说gles3也支持MRT UBO/SSBO ES3.1+也支持computeShader ,gubffer可以更具shader来修改,Unity的默认延迟渲染为什么不支持呢?
核心问题:一致性与稳定性
所以我们聪明的unity直接让你默认不用了,要用自己改
与其在 GLES3 上「理论可行、实际翻车」,不如直接禁掉,如果有创作者要改就自己去避免移动GPU性能不够的这点问题
所以你看到的不是技术能力不足,而是工程取舍。
glcore(Desktop OpenGL):被时代甩下车的桌面王者
用在Windows,linux,macos(冻结在4.1)
这个是典型的状态机API,大部分功能是驱动做的,要修改得依赖驱动的厂商。
他的同步模型相当混乱,是驱动隐式的barrier就会导致我们常用的barrier不起作用,导致渲染的排序异常,出现莫名奇妙的bug,再加上大伙桌面端都用vulkan和dx12,所以就不用这个了。
d3d11:工程师最喜欢的“省心选项
主要还是运行于Windows桌面端(大部分3a都是跑在d3d11和d3d12上,这也是为什么mac玩不了这些游戏)
他的API设计相当的成熟,还有驱动兜底,而且非常便于debug,我们用renderDoc在这个平台上debug非常轻松,可以看到渲染的顺序,写入的信息,相当的方便
适合前向渲染管线和延迟渲染管线,还有一些中大型的项目,也比较适合游戏引擎的编辑器和工具链
相比d3d12而言cpu开销大了点,多线程的录制能力有限,导致现代的gpu跑不满
具体的可以看微软的这篇文章从 Direct3D 11 到 Direct3D 12 的重要更改 - Win32 apps | Microsoft Learn
但是相对而言,他的API支持的好,所以在开发一些特殊平台的时候还是用d3d11(比如我最近开发PICOVR的应用的时候UE5需要设置为d3d11才能正常的运行live preview来实时debug)
d3d12:为延迟渲染而生的时代产物
主要跑在windows 10+
相较于d3d11主要添加了显示的资源管理,用commandList和Queue来减少cpu发的捆绑包从而优化cpu让gpu跑满
而且他的G-Buffer周期完全可控,Barrier明确,可以多线程录制Command buffer
Vulkan:跨平台的“DX12 思想实现”
支持windows和android,switch这些平台
和d3d12 一样:完全显式,没有驱动魔法,延迟渲染、Clustered、Forward+ 都很友好
Metal:苹果的“官方唯一答案”
专门给苹果开发的所以支持ios,macos,visionos
据说是设计及其干净和d3d12/vulkan类似,对于苹果的gpu有深度的优化。(不开发苹果可能一辈子用不上.jpg)
回看最初那个 #pragma exclude_renderers
其实逻辑就非常清楚了:
$$
#pragma exclude_renderers gles3 glcore
$$
Unity 想表达的不是:
而是:
“我不想为这些平台维护一个高风险、低收益的 Deferred 实现”
这是一个工程现实 + 平台差异 + 维护成本综合博弈后的结果。