三星Galaxy SIII(GLES)中的噪声算法失败

时间:2012-07-02 12:23:14

标签: android opengl-es glsl shader

我正在努力让下一个简单的算法在三星Galaxy SIII中运行

float rand(vec2 co)
{
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

....
vec3 color = texture2D(u_texture, v_texcoord);
gl_FragColor.rgb = color + vec3(rand(gl_FragCoord.xy + time / 1000.0));
....

该代码在三星Galaxy S1和谷歌Nexus S中完美地产生了预期的噪音。但是在使用ARM的Mali-400 / MP4的新智能手机中完全失败了。

任何人都可以发现此算法有什么问题吗?或者也许明白为什么会失败?

2 个答案:

答案 0 :(得分:9)

您的问题可能来自于获取大数字的sin。这样做的结果取决于sin的确切实现,这是不可用的。显然,Mali芯片使用的sin函数具有更多可预测的结果,其数量大于其他函数。

在我看来,你应该使用an actual noise function,而不是这个。至少它会在硬件上产生可预测的结果。

答案 1 :(得分:4)

在ARM论坛上对此问题进行了一些讨论:http://forums.arm.com/index.php?/topic/16364-random-number-with-mali-400-mp/

问题在于Mali GPU上片段着色器的FP16精度。基本上,调用时间fract时没有剩余小数位(因为乘数很大),所以你根本不会得到任何“噪声”。如果你使常量变小,你将开始得到非零值,但它们不会产生噪音。 (我不完全确定如何选择值及其not clear where this algorithm came from)。

从技术上讲,这种噪声算法依赖于更高(中等?高?)精度浮点运算,这在片段着色器中是可选的。根据{{​​3}},您可以通过检查glGetString(GL_EXTENSIONS)中的“OES_fragment_precision_high”扩展名来检查片段着色器中平台支持的精度。

Nicol的答案中的this other post项目似乎不容易受到浮点截断问题的影响(它似乎使事情更加严格)。但是,它有大约300的周期,它会产生比你目前得到的“白色”(或“粉红色”)噪音更“结构化”的噪音。它是一个优秀的库,所以即使它不是替代品,它也值得你的代码使用。