gpt4 book ai didi

ios - 从 iPad Air 开始的 GLSL small float value truncation

转载 作者:行者123 更新时间:2023-11-29 10:32:47 26 4
gpt4 key购买 nike

在我尝试修复在 iPad3(PowerVR SGX543MP4,iOS 8.1)和旧硬件上运行良好但在 iPad Air(PowerVR G6430,iOS 8.1)上失败的液体模拟应用程序时......我偶然发现了非常“好奇”的处理后者的小浮点值。它归结为这样的测试用例:

片段着色器1(写入测试值):

precision highp float;
const highp float addValue = 0.000013;

uniform highp sampler2D maskField;
varying mediump vec2 pixelUv;

void main()
{
highp vec4 mask = texture2D(maskField, pixelUv);

gl_FragColor = vec4(addValue * mask.x);
}

片段着色器2(检查值并输出红色)

precision highp float;
uniform highp sampler2D testTexture;
varying highp vec2 pixelUv;

void main()
{
highp vec4 test = texture2D(testTexture, pixelUv);

gl_FragColor = vec4(test.a > 0.000012, 0.0, 0.0, 1.0);
}

第一个着色器正在写入 HALF_FLOAT_OES 纹理。结果在 Ipad3 上是红色,在 ipad air 上是黑色。并且不要急于发布有关 mask.x 值的信息。通过两个设备上的调试器验证它是正确的 (1.0)。

更奇怪的是,如果我将“addValue”的值增加到 0.000062,它会成功写入。但如果它低于该值并且变量与常量以外的任何值交替出现,则它会在 iPad Air 上截断为 0.0。所以...这有效:

const highp float addValue = 0.000013;

void main()
{
gl_FragColor = vec4(addValue * 1.0);
}

但这不是:

uniform highp float one; //= 1.0
const highp float addValue = 0.000013;

void main()
{
gl_FragColor = vec4(addValue * one);
}

与添加相同。如果我尝试像这样积累值(value),它不会增加任何东西:

const highp float addValue = 0.000013;
uniform highp sampler2D pressureField;

varying mediump vec2 pixelUv;

void main()
{
highp vec4 pressureData = texture2D(pressureField, pixelUv);
pressureData.a += addValue;
gl_FragColor = vec4(addValue);
}

欢迎就正在发生的事情以及如何修复它提出任何建议!使用的算法确实需要高精度 float 。现在我正处于向苹果提交错误报告并等待永恒的边缘。

最佳答案

将 0.000013 存储为 GL_HALF_FLOAT 时,您处理的是非规范化数字。可以用标准表示的最小归一化数 half float (IEEE 754-2008) 为 2^-14,大约为 0.000061,或大于您所代表的值。

OpenGL 规范在如何处理非规范化 16 位 float 方面为实现留出了一定的自由度。这在 extension spec 中的记录非常相似适用于 ES 2.0 和 ES 3.0 规范。

扩展规范使用它作为指数为 0 的情况的主要定义,这是非规范化数字的情况:

(-1)^S * 2^-14 * (M / 2^10),         if E == 0 and M != 0,

这个精度足以解决 0.000012 和 0.000013 之间的差异。但它也说“实现也被允许使用以下任何替代编码”:

(-1)^S * 0.0,                        if E == 0 and M != 0,

使用这种编码,0.000012 和 0.000013 都四舍五入为 0.0,因此变得相等。

ES 3.0 规范有第一个定义,但随后在文本中添加:

Providing a denormalized number or negative zero to GL must yield predictable results, whereby the value is either preserved or forced to positive or negative zero.

这也允许将这些值四舍五入为 0.0。

至于为什么不同代的硬件会有不同的表现,我没有任何详细的见解。但在我看来,这两种实现都符合规范,因为它们使用了规范明确允许的两种不同变体。

如果您想确保这些值以您所需的范围/精度表示,则必须使用类型为 GL_FLOAT 的纹理,它将以完整的 32 位格式存储这些值范围/精度。

关于ios - 从 iPad Air 开始的 GLSL small float value truncation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28763410/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com