我一直在尝试将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)。注意纹理是如何平坦的并且夹在中间
并在仿真器(Nexus 5 API 21)上运行相同的代码时跟随(使用模拟主机gpu选项) 这是预期的产出。
我的纹理包装模式设置为GL_REPEAT
。什么可能是错的?
答案 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.x
或p.y
接近范围[-0.1,0.1]时,这些子表达式将下溢至零。
最好的解决方法是什么并不明显。一些想法尝试:
highp
精度。 highp
支持在ES 2.0中是可选的,仅在定义GL_FRAGMENT_PRECISION_HIGH
时可用。