着色器数据类型和精度

Posted gameDesigner

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了着色器数据类型和精度相关的知识,希望对你有一定的参考价值。

在unity中,标准的shader语言是HLSL,一般的HLSL数据类型都是支持的。然而,Unity有一些额外的HLSL类型,对移动平台有更好的支持。

基础数据类型

在shader中,主要的计算数据类型是 浮点数据(在普通的变成语言中,比如C#中等于float)。几种浮点类型的变种是: float、half 和 fixed(和 它们的向量/矩阵一样,变种为 half3,float4x4)。这些类型精度不同(而且,因此,性能或者功效使用):

高精度:float

最高精度的浮点数值;一般来说是32位值。

全浮点数值精度类型一般用来表达世界空间位置,贴图坐标或者涉及复杂运算的函数标量,比如三角函数、幂运算。

中精度:half

中等精度浮点数值;一般为16位值。

半精度类型一般用来表示短向量、方向、物体空间坐标,高动态范围颜色。

低精度:fixed

最低精度固定点数值。一般为11位值,范围为-2.0~+2.0和 1/256精度。

固定精度用来表示普通颜色和对颜色简单的操作。

整型数据类型

整型数据经常用来表示循环计数或者数组指数。为此,他们通常在不同平台上都能够很好的工作。

根据平台不同,整型数据可能不被GPU所兼容。比如,D3D9和 OpenGL ES2.0 GPU只能够操作浮点数据,而简单整数表达式(涉及位或逻辑运算)则可能使用相当复杂的浮点数学指令来模拟。

D3D 11,OpenGL ES 3,Metal和其它现代平台则对整型数据类型拥有较好的支持,所以使用位移位和位掩蔽可以如预期一样工作。

复合 向量/矩阵类型

HLSL有内置的由基础数据类型衍生而来的向量和矩阵类型。比如,float3是一个拥有x、y、z分量的三维向量,half4则是中等精度的拥有x、y、z、w分量的4维向量。当然,向量也可以被用来表达 颜色的r、g、b、a分量。

矩阵类型和向量类型差不多。比如,一个float4x4就是 4x4 维度的矩阵。注意一些平台只支持正方形矩阵,特别是OpenGL ES 2.0.

贴图/采样器类型

典型的你在HLSL代码中声明贴图变量和下面类似:

sampler2D _MainTex;
samplerCUBE _Cubemap;

对于移动平台,这些将翻译成“低精度采样器”,比如,纹理被期望具有低精度的数据。如果你知道你的贴图包含了HDR颜色,那么你需要用半精度采样器:

sampler2D_half _MainTex;
samplerCUBE_half _Cubemap;

如果你的贴图包含全浮点精度数据(比如 深度贴图),使用全精度采样器:

sampler2D_float _MainTex;
samplerCUBE_float _Cubemap;

精度、硬件支持和表现

在PC 的GPU上使用 float/half/fixed数据类型时,会出现一个问题,那就是全部都会变成高精度。也就是说,对于所有的 PC GPU,你在shader中使用啥子数据类型根本没什么影响。他们在计算时,总是使用32位的全精度浮点数。

只有当针对移动gpu的时候,一半和固定的类型才会变得有意义,这些数据类型主要是从耗电量来考虑。记住你需要在移动平台上测试你的shader,来看看有没有精度问题。

即便在移动GPU上,不同的GPU家族对精度支持也不同。下面是一些数据:

GPU Familyfloathalffixed
PowerVR Series 6/7 32 16
PowerVR SGX 5xx 32 16 11
Qualcomm Adreno 4xx/3xx 32 16
Qualcomm Adreno 2xx 32 vertex 24 fragment
ARM Mali T6xx/7xx 32 16
ARM Mali 400/450 32 vertex 16 fragment
NVIDIA X1 32 16
NVIDIA K1 32
NVIDIA Tegra 3/4 32 16

大部分现代移动GPU实际上只支持 32位(float)或者16位(half/fixed)类型。一些老的GPU则对顶点shader和片段shader计算指令有不同的精度。

使用较低的精度通常会更快,这可能是由于GPU寄存器分配的改进,或者是由于特殊的“快速路径”执行单元,用于某些较低精度的数学运算。即使没有原始的性能优势,使用更低的精度也会减少GPU上的电量,从而提高电池的使用寿命。

一般的经验法则是,除了位置和纹理坐标之外,所有的东西都要有half精度。如果half精度不足以计算,才提高精度。

对无穷大、不是数值或者其他特殊浮点值的支持

对于特殊浮点值的支持,这要根据你的GPU来分别讨论。

所有支持 D3D 10的 PC GPU都能很好地支持IEEE 754浮点数据标准。这也就意味着浮点数在GPU上表现和在编程语言在CPU中表现一样的好。

移动GPU则有一些轻微的不同等级的支持。在一些平台上, 0除以0结果不是一个数值;在其它平台则可能结果为无穷大,0或者任何其它随机的值。一定要在你的目标平台上测试你的shader来确保他们是被支持的。

外部的GPU文档

GPU供应商对于他们的GPU提供了一个全方位的说明文档,包括GPU的表现和能力,详细情况请看下面:

 

以上是关于着色器数据类型和精度的主要内容,如果未能解决你的问题,请参考以下文章

为啥我需要在 webgl 着色器中定义一个精度值?

损坏的顶点和片段着色器

Vertex and FragmentShader顶点与片段着色器

Shader2.0的顶点着色器和片段着色器

✠OpenGL-2-图像管线

片段着色器中未使用纹理数据 - OpenGL