【Unity】着色器平台差异笔记
【Unity】着色器平台差异笔记
https://docs.unity.cn/cn/2022.3/Manual/SL-PlatformDifferences.html
部分情况下,不同的图形 API 之间的渲染行为存在差异。通常 Unity 会隐藏这些差异,但有时候仍需要手动处理。
Unity 以 OpenGL 类平台约定作为标准,默认情况下会自动进行转换。
渲染纹理坐标
- Direct3D 类:顶部坐标为 0 并向下增加。适用于 Direct3D、Metal 和游戏主机。
- OpenGL 类:底部坐标为 0 并向上增加。适用于 OpenGL 和 OpenGL ES。
受此影响采样的贴图可能上下翻转,并且创建的切线空间的也可能手系错误。
裁剪空间坐标
- Direct3D 类:近平面为 1,远平面为 0。
- OpenGL 类:近平面为-1,远平面为 1。
着色器计算精度
- PC GPU:所有浮点类型统一视为 float 处理。
- 移动 GPU:不同浮点类型精度不同,且可能不支持 IEEE754 浮点标准。
建议确保在目标测试着色器。
着色器中的 const 声明
- HLSL:与 c# 相同,指在当前作用域变量只读,可按任何方式初始化。
- GLSL:表示变量是编译时常量,不能使用运行时数据初始化。
建议以 GLSL 规则为准。
常量缓冲区布局
部分平台会对缓冲区内的数据进行内存对齐,导致如float3
变成了float4
,因而写入数据时可能会发生错误。
因此建议缓冲区布局应遵照如下规则。
- 使用
float4
类型,代替float3
,float4
在各平台都是一致的。 - 变量声明顺序应从大到小,如
float4
然后float2
最后float
。
着色器使用的语义
要让着色器在所有平台上运行,一些着色器值应该使用以下语义:
- 顶点着色器输出(裁剪空间位置):
SV_POSITION
。有时也可能是POSITION
。注意这不适用于 Sony PS4 或曲面细分情况。 - 片元着色器输出(颜色):
SV_Target
。有时也可能是COLOR
或COLOR0
。注意这不适用于 Sony PS4。 - 将网格渲染为点时,必须从顶点着色器输出:
PSIZE
。某些平台(如 OpenGL ES 或 Metal)若未提供PSIZE
会将点大小视为未定义。
Direct3D 着色器编译器语法
Direct3D 平台的 HLSL 着色器编译器相比其他编译器更加严格。
- 变量在输出前必须完全初始化,包括分量值。
- 不可在顶点着色器使用
tex2D
,因为顶点阶段不存在 uv 导数。需要改用着色器模型 3.0 中的tex2Dlod
。
着色器中的 DirectX 11 语法
表面着色器编译管线的某些部分不能理解 DirectX 11 语法。
如果用到了这些特别的语法,需将其包裹在SHADER_API_D3D11
预处理器宏中。
使用着色器帧缓冲提取
一些 GPU(最明显的是 iOS 上基于 PowerVR 的 GPU)允许您通过提供当前片元颜色作为片元着色器的输入来实现某种可编程的混合阶段。
详细参见官方文档。
着色器中的深度方向
DirectX 11, DirectX 12, Metal: Reversed direction
- 深度缓冲区值:在近平面为 1,在远平面为 0。
- 裁剪空间范围:
其他平台:传统方向
- 深度缓冲区值:在近平面为 0,在远平面为 1。
- 裁剪空间范围:
- 在 Direct3D 类平台:
- 在 OpenGL 类平台:
有关深度的处理和其他信息,详见官方文档。
【Unity】着色器平台差异笔记
https://bdffzi-blog.pages.dev/posts/3262553639.html