GLSL上的球 - 射线交点。不同的行为取决于设备

时间:2016-10-20 14:23:57

标签: ios opengl-es glsles

我一直在尝试开发一些着色代码,用于在iOS设备上渲染大气效果。这个GLSL代码在很大程度上依赖于我用这种方式实现的球面光线交叉计算,基于http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection

highp vec2 intersectionsWithSphere(highp vec3 o,
                               highp vec3 d,
                               highp float r){
highp float a = dot(d,d);
highp float b = 2.0 * dot(o,d);
highp float c = dot(o,o) - pow(r, 2.0);

highp float q = pow(b,2.0) - 4.0 * a * c;
if (q < 0.0){
  return vec2(-1.0, -1.0);
}

highp float sq = sqrt(q);
highp float t1 = (-b - sq) / (2.0*a);
highp float t2 = (-b + sq) / (2.0*a);

if (t1 > t2){
  highp float a = t2;
  t2 = t1;
  t1 = a;
}
return vec2(t1,t2);
}

该代码在我的iPad Pro 9,7和运行iOS 10.0.2的iPhone 6上运行得非常好。

然而,尝试使用iPad 2(iOS 9.3)和iPad 4(iOS 10)时,该功能不会返回相同(预期)的结果。在我寻找解决方案的过程中,我还遇到了一个非常奇怪的glDrawArray()OpenGL命令行为,它似乎有时会崩溃,看似完全有效且可编译的着色代码。

我检查过两个平台对于highp浮点数(27位)具有相同的精度,并且还使用小规模球体进行检查。例如:

intersectionsWithSphere(vec3(0.0,0.0,2.0),vec3(0.0,1.0,-1.0), 1.0);

根本不应该返回任何交叉点,但确实如此。

我在着色器编程方面有点新手,我们将不胜感激。

1 个答案:

答案 0 :(得分:0)

检查你的战俘功能。如果x为负,则pow(x,y)未定义。

我想认为编译器足够智能将pow(x,2.0)转换为x * x,但我不想指望它。

如果指数是一个常数整数,你也可以自己做乘法。在它变量的地方,你应该做一些像pow(max(0.0,x),y)。

不能确定这是个问题。

glDrawArray中的崩溃可能是一个完全独立的问题,与着色器代码无关,它更有可能尝试从一些无效的缓冲区或内存位置使用顶点。