GLSL NVidia方形文物

Sus*_*lik 6 c++ opengl artifacts glsl

当GLSL着色器在以下GPU上生成错误图像时遇到问题:
GT 430
GT 770
GTX 570
GTX 760

但正常工作:
Intel HD Graphics 2500
Intel HD 4000
Intel 4400
GTX 740M
Radeon HD 6310M
Radeon HD 8850

着色器代码如下:

bool PointProjectionInsideTriangle(vec3 p1, vec3 p2, vec3 p3, vec3 point)
{
  vec3 n = cross((p2 - p1), (p3 - p1));

  vec3 n1 = cross((p2 - p1), n);
  vec3 n2 = cross((p3 - p2), n);
  vec3 n3 = cross((p1 - p3), n);

  float proj1 = dot((point - p2), n1);
  float proj2 = dot((point - p3), n2);
  float proj3 = dot((point - p1), n3);

  if(proj1 > 0.0)
    return false;
  if(proj2 > 0.0)
    return false;
  if(proj3 > 0.0)
    return false;
  return true;
}

struct Intersection
{
    vec3 point;
    vec3 norm;
    bool valid;
};

Intersection GetRayTriangleIntersection(vec3 rayPoint, vec3 rayDir, vec3 p1, vec3 p2, vec3 p3)
{
    vec3 norm = normalize(cross(p1 - p2, p1 - p3));

    Intersection res;
    res.norm = norm;
    res.point = vec3(rayPoint.xy, 0.0);
    res.valid = PointProjectionInsideTriangle(p1, p2, p3, res.point);
    return res;
}

struct ColoredIntersection
{
    Intersection geomInt;
    vec4 color;
};

#define raysCount 15
void main(void)
{
    vec2 radius = (gl_FragCoord.xy / vec2(800.0, 600.0)) - vec2(0.5, 0.5);

    ColoredIntersection ints[raysCount];

    vec3 randomPoints[raysCount];
    int i, j;


    for(int i = 0; i < raysCount; i++)
    {
        float theta = 0.5 * float(i);
        float phi = 3.1415 / 2.0;
        float r = 1.0;
        randomPoints[i] = vec3(r * sin(phi) * cos(theta),  r * sin(phi)*sin(theta), r * cos(phi));

        vec3 tangent = normalize(cross(vec3(0.0, 0.0, 1.0), randomPoints[i]));
        vec3 trianglePoint1 = randomPoints[i] * 2.0 + tangent * 0.2;
        vec3 trianglePoint2 = randomPoints[i] * 2.0 - tangent * 0.2;

        ints[i].geomInt = GetRayTriangleIntersection(vec3(radius, -10.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, 0.0), trianglePoint1, trianglePoint2);
        if(ints[i].geomInt.valid)
        {
            float c = length(ints[i].geomInt.point);
            ints[i].color = vec4(c, c, c, 1.0);
        }
    }

    for(i = 0; i < raysCount; i++)
    {
        for(j = i + 1; j < raysCount; j++)
        {
            if(ints[i].geomInt.point.z < ints[i].geomInt.point.z - 10.0)
            {
                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
                ColoredIntersection tmp = ints[j];
                ints[j] = ints[i];
                ints[i] = tmp;
            }
        }
    }

    vec4 resultColor = vec4(0.0, 0.0, 0.0, 0.0);
    for(i = 0; i < raysCount + 0; i++)
    {
        if(ints[i].geomInt.valid)
            resultColor += ints[i].color;
    }

    gl_FragColor = clamp(resultColor, 0.0, 1.0);
}
Run Code Online (Sandbox Code Playgroud)

Upd:我用内置函数替换了向量规范化,并添加了gl_FragColor claming以防万一.

代码是实际着色器的简化版本,预期图像是:
http://img.owely.com/screens/131316/original_owely20140426-19006-1w4w4ye.?1398554177
但我得到的是:
http://img.owely.com/screens/131315/original_owely20140426-18968-a7fuxu.?1398553652

代码的随机旋转完全消除了伪像.例如,如果我改变线

if(ints[i].geomInt.valid) //1
Run Code Online (Sandbox Code Playgroud)

if(ints[i].geomInt.valid == true) //1
Run Code Online (Sandbox Code Playgroud)

显然不应该以任何方式影响逻辑或完全消除不做任何事情(标记为2)的双重循环消失.请注意,双重循环完全没有任何条件

if(ints[i].geomInt.point.z < ints[i].geomInt.point.z - 10.0)
{
  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
  return;
  ColoredIntersection tmp = ints[j];
  ints[j] = ints[i];
  ints[i] = tmp;
}
Run Code Online (Sandbox Code Playgroud)

永远不会满足(左右两侧有索引i,而不是i,j)并且没有NaN.这段代码绝对没有任何东西以某种方式产生工件.

您可以使用此项目自行测试着色器和演示(完整的MSVS 2010项目+源代码+已编译的二进制文件和着色器,使用包含的SFML):https://dl.dropboxusercontent.com/u/25635148/ShaderTest.zip

我在这个测试项目中使用sfml,但这是100%不相关的,因为我遇到这个问题的实际项目不使用这个lib.

我想知道的是为什么这些工件出现以及如何可靠地避免它们.

Sus*_*lik 1

如果有人仍然感兴趣,我在许多专业网站上提出了这个问题,包括 opengl.org 和 devtalk.nvidia.com。我没有收到关于我的着色器问题的任何具体答案,只是收到一些如何解决我的问题的建议。就像使用 if(condition == true) 而不是 if(condition) 一样,使用尽可能简单的算法等。最后,我选择了最简单的代码轮换之一来消除问题:我刚刚替换

struct Intersection  
{  
    vec3 point;  
    vec3 norm;  
    bool valid;  
};  
Run Code Online (Sandbox Code Playgroud)

struct Intersection  
{  
    bool valid;  
    vec3 point;  
    vec3 norm;  
};  
Run Code Online (Sandbox Code Playgroud)

还有许多其他代码轮换使工件消失,但我选择了这个,因为我能够在我之前遇到问题的大多数其他系统上进行测试。