16位浮点纹理

时间:2013-10-30 10:05:57

标签: android c++ opengl-es

我正在使用OpenGL ES 3.0在GPU上创建流体动力学效果。 使用16位浮点FBO,我可以使效果正常工作。

我的问题是我的目标是不支持浮点纹理的GPU。在缺乏精确度的情况下,效果会崩溃。

这个效果只是二维的,所以我只读取和写入FBO的前两个通道。所以,我想知道是否有人成功使用了两个unsigned int纹理通道来增加额外的精度,以及如何实现这一点。

我目前的解决方案如下(GLSL片段着色器片段),它根本不能正常工作:

#define read(vec) ((((vec).xy * 255.0) - 127.0) / 127.0) + (vec).zw / 255.0

vec4 write(vec2 vec)
{
    vec2 temp = ((vec * 127.0) + 127.0);
    vec2 a = floor(temp) / 255.0;
    vec2 b = mod(temp, 255.0);
    return vec4(a,b);
}

我认为主要问题可能是任何这样的方案都不可能写零。

我希望有人已经解决了这个问题,或者可以看到解决这个问题的方法:)

1 个答案:

答案 0 :(得分:0)

我假设您要存储的值介于0.0和1.0之间,但是您希望使用两个有效字节的数据来获得更高的精度吗?

float read(vec2 rawData) 
{
    return rawData.x + rawData.y / 256.0;
}

vec2 write(float value)
{
    return vec2(value, floor(value * 256.0));
}

将输入/输出浮点数的限制设置为不同于[0,1]的任何值只需要将输出值映射到范围[0,1]并调用write,或映射输入值来自[0,1] ]到[min,max]很简单:

// maps val from [fromMin,fromMax] to [toMin,toMax]
float lerp(float val, float fromMin, float fromMax, float toMin, float toMax)
{
    return toMin + (toMax - toMin) * (val - fromMin) / (fromMax - fromMin);
}

const vec2 minMax = vec2(-5.0, 10.0);

float readMapped(vec2 rawData)
{
    return lerp(read(rawData), 0.0, 1.0, minMax.x, minMax.y);
}

vec2 writeMapped(float value)
{
    return write(lerp(value, minMax.x, minMax.y, 0.0, 1.0));
}

只需将这些功能调用两次,即可进行双通道输入/输出。