我正在尝试在基于32位浮点数的WebGL或WebGL2着色器上实现64位算术。其中一个需要的基本函数是将任何浮点数拆分为两个“不重叠”的浮点数的函数。第一个浮点数包含原始浮点数分数位的前半部分,而第二个浮点数则包含后半部分。以下是该函数的实现:
precision highp float;
...
...
vec2 split(const float a)
{
const float split = 4097.0; // 2^12 + 1
vec2 result;
float t = a * split; // almost 4097 * a
float diff = t - a; // almost 4096 * a
result.x = t - diff; // almost a
result.y = a - result.x; //very small number
return result;
}
如果我将着色器中定义的参数传递给该函数,则该函数按预期工作:
precision highp float;
...
...
float number = 0.1;
vec2 splittedNumber = split(number);
if (splittedNumber.y != 0.0)
{
// color with white
// we step here and see the white screen
}
else
{
//color with black
}
但是,无论何时数字与任何均匀物相关,一切都会变得不同:
precision highp float;
uniform float uniformNumber;
...
...
float number = 0.2;
if (uniformNumber > 0.0)
{
// uniform number is positive,
// so we step here
number = 0.1;
}
vec2 splittedNumber = split(number);
if (splittedNumber.y != 0.0)
{
// color with white
}
else
{
//color with black
// we step here and see the black screen
}
在第二种情况下,当“数字”取决于统一分割函数会进行优化,并返回y值为零的vec2。
在类似OpenGL问题的stackoverflow上有一个类似的问题Differing floating point behaviour between uniform and constants in GLSL。那里的建议是在函数“split”内使用“precise”修饰符。不幸的是,在WebGL/WebGL2着色器中没有这样的修饰符。
您有什么建议可以摆脱我的情况中的优化并实现“split”函数吗?