aud*_*i02 0 shader colors vulkan
我知道着色器中的浮点颜色值范围 [0..1] 映射到 UCHAR 缓冲区中的 [0..255] 范围。
据此,我预计 UCHAR 缓冲区中的每次更改的着色器颜色值的步长为 1/255。
但结果却出人意料地不同。这是前两个步骤:
Shader 中的红色浮点值 -> 读取缓冲区中的 UCHAR 值
0.000000 -> 0
0.002197 -> 0
0.002198 -> 1
0.006102 -> 1
0.006105 -> 2
前两个步长约为 0.002197 和 0.006102,与预期步长 0.00392 和 0.00784 不同。
那么映射公式是什么呢?
无符号整数归一化基于公式f = i/INT_MAX,其中f是浮点值(钳位到 [0, 1] 后),i是整数值,INT_MAX是本例中整数位深度 (255) 的最大整数值。
因此,如果您有一个浮点数,并且想要它的无符号、标准化整数值,则可以使用i = f * INT_MAX. 当然...整数不具有与浮点数相同的精度。那么如果 的结果f * INT_MAX是 0.5,那么它的整数值是多少?它可能是 0,也可能是 1,具体取决于四舍五入的方式。
允许实现以它们喜欢的任何方式舍入整数值。鼓励他们使用最接近的舍入(转换后 0.49 将变为 0,0.5 将变为 1),但这不是必需的。唯一的要求是它必须选择两个最接近的值之一(它不能将 0.5 变成 3),并且 0.0 和 1.0 的精确浮点值(包括固定到它们的任何值)必须精确表示为整数 0 和INT_MAX.
如果您明确需要直接舍入,您始终可以自己进行标准化。事实上,GLSL 有特定的函数可以帮助您。下面假设您正在尝试使用 Vulkan 格式写入纹理R8G8B8A8_UNORM,并且我们假设您正在写入存储图像,而不是通过片段着色器的输出(您也可以这样做,但会失去混合) 。
因此,第一步是将layout格式更改为r32ui. 也就是说,您现在正在写入一个无符号 32 位值,而不是 4 个无符号 8 位标准化值。这是完全正确的。
第 2 步是使用该packUNorm4x8函数。此函数执行浮点到整数标准化,但规范明确地正确执行舍入。在您的函数中使用该函数的返回值imageStore,就可以了。
如果您想写入片段着色器输出,那就有点复杂了。在那里,您将需要使用不同的图像视图,即使用该R32_UINT格式的图像视图。因此,您正在创建 4x8 位标准化纹理的 32 位无符号整数视图。它必须成为渲染目标,因此您必须进行子通道手术。从那里,只需写出 的结果packUNorm4x8。
当然,您会立即失去混合和类似的操作,因为您正在写入整数值。由于您必须执行该子通道手术,因此任何写入它的着色器可能也需要执行此操作。
另请注意,在这两种情况下,您可能需要调整所写入值的组成部分的顺序。packUNorm4x8被明确定义为小端,而(我相信?)R8G8B8A8被指定为按从最高到最低的顺序。因此,您可能需要本质上进行字节序交换packUNorm4x8(value.abgr)。
| 归档时间: |
|
| 查看次数: |
659 次 |
| 最近记录: |