在桌面GPU和移动GPU上打开GL不同的结果

时间:2015-01-09 19:53:04

标签: android opengl graphics opengl-es textures

我一直在尝试将this着色器移植到移动设备上。我在OpenGL ES 2.0的Android设备上执行此操作。这里是来自上面网站的片段着色器代码供参考:

void main(void)
{
// clamp pixel posiiton in [-1,1]
vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
vec2 uv;

// calculate angle of current pixel from origin
// atan return values are in [-pi, pi]
float a = atan(p.y,p.x);

// distance of point from origin
//float r = sqrt(dot(p,p));

float power = 7.0;

// http://en.wikipedia.org/wiki/Minkowski_distance
float r = pow( pow(p.x*p.x,power) + pow(p.y*p.y,power), 1.0/(2.0*power) );

// add global time for a moving tunnel
uv.x = .2/r + iGlobalTime/2.0;
uv.y = a/(3.1416);

// multiplication by r to give a darkened effect  in center
vec3 col = texture2D(iChannel0, uv).xyz * (1.0-r);
//vec3 col = vec3(uv.y, 0.0,0.0);


gl_FragColor = vec4(col,1.0);
}

我在手机上获得了以下结果(Moto G,三星Galaxy S Advance)。注意纹理是如何平坦的并且夹在中间 Image in actual device (Moto G gen 1)

并在仿真器(Nexus 5 API 21)上运行相同的代码时跟随(使用模拟主机gpu选项) Image in Emulator/WebGL 这是预期的产出。

我的纹理包装模式设置为GL_REPEAT。什么可能是错的?

1 个答案:

答案 0 :(得分:1)

这是一个精确的问题。 mediump是ES 2.0着色器中保证支持的最高精度,其浮点幅度范围为[2 ^ -14,2 ^ 14],如第33页的表中所列。 spec(“OpenGL ES着色语言”,版本1.00,可在https://www.khronos.org/registry/gles/找到)。

以下语句序列将很快产生下溢:

float power = 7.0;
float r = pow( pow(p.x*p.x,power) + pow(p.y*p.y,power), 1.0/(2.0*power) );

看看这个子表达式:

pow(p.x*p.x,power)

根据着色器开头的计算/注释,p.x的范围为[-1,1]。使用0.1作为值:

pow(0.1 * 0.1, 7.0) = pow(0.01, 7.0) = 10^-14

这正好是medium下溢值的限制。因此,p.xp.y接近范围[-0.1,0.1]时,这些子表达式将下溢至零。

最好的解决方法是什么并不明显。一些想法尝试:

  • 如果您的设备支持,请使用highp精度。 highp支持在ES 2.0中是可选的,仅在定义GL_FRAGMENT_PRECISION_HIGH时可用。
  • 尝试低于7.0的指数,并查看视觉效果是否仍符合您的要求。
  • 对下溢的像素使用某种形式的钳位。您可以丢弃它们,也可以将它们涂成黑色。虽然它不会使他的墙壁在中心,但它至少会避免丑陋的文物。