GLSL NVidia方形文物 [英] GLSL NVidia square artifacts

查看:95
本文介绍了GLSL NVidia方形文物的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当GLSL着色器在以下GPU上生成不正确的图像时,我遇到了一个问题:
GT 430
GT 770
GTX 570
GTX 760

但是在以下这些上正常工作:
英特尔高清显卡2500
英特尔HD 4000
英特尔4400
GTX 740M
Radeon HD 6310M
Radeon HD 8850

着色器代码如下:

  bool PointProjectionInsideTriangle(vec3 p1,vec3 p2,vec3 p3,vec3点){vec3 n =交叉((p2-p1),(p3-p1));vec3 n1 =交叉((p2-p1),n);vec3 n2 =交叉((p3-p2),n);vec3 n3 =交叉((p1- p3),n);浮点数proj1 = dot((point-p2),n1);浮点数proj2 = dot((point-p3),n2);浮点数proj3 = dot((point-p1),n3);如果(proj1> 0.0)返回false;如果(proj2> 0.0)返回false;如果(proj3> 0.0)返回false;返回true;}结构交集{vec3点;vec3规范;布尔有效;};交集GetRayTriangleIntersection(vec3 rayPoint,vec3 rayDir,vec3 p1,vec3 p2,vec3 p3){vec3 norm = normalize(cross(p1- p2,p1- p3));交叉口资源;res.norm =规范;res.point = vec3(rayPoint.xy,0.0);res.valid = PointProjectionInsideTriangle(p1,p2,p3,res.point);返回资源;}结构ColoredIntersection{交点geomInt;vec4颜色;};#定义raysCount 15void main(无效){vec2半径=(gl_FragCoord.xy/vec2(800.0,600.0))-vec2(0.5,0.5);ColoredIntersection int [raysCount];vec3 randomPoints [raysCount];int i,j;for(int i = 0;我 

更新:我已用内置函数替换了矢量规范化,并添加了gl_FragColor要求以防万一.

代码是实际着色器的简化版本,预期图像为:

但是我得到的是:

代码的随机旋转可完全消除工件.例如,如果我更改行

  if(ints [i] .geomInt.valid)//1 

  if(ints [i] .geomInt.valid == true)//1 

显然不应该以任何方式影响逻辑或完全删除没有任何结果(标记为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);返回;ColoredIntersection tmp = ints [j];ints [j] = ints [i];ints [i] = tmp;} 

永远无法满足(左侧和右侧的索引为i,而不是i,j),并且没有NaN.这段代码绝对不会做任何事情,但会以某种方式产生工件.

您可以使用此项目自己测试着色器和演示(完整的MSVS 2010项目+源+编译的二进制文件和着色器,使用随附的SFML):解决方案

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

  struct交集{vec3点;vec3规范;布尔有效;}; 

  struct交集{布尔有效;vec3点;vec3规范;}; 

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

I have encountered a problem when GLSL shader generates incorrect image on following GPU's:
GT 430
GT 770
GTX 570
GTX 760

But works normally on these:
Intel HD Graphics 2500
Intel HD 4000
Intel 4400
GTX 740M
Radeon HD 6310M
Radeon HD 8850

Shader code is as follows:

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);
}

Upd: I have replaced vector normalizations with builtin functions and added gl_FragColor claming just in case.

The code is a simplified version of an actual shader, expected image is:

But what I get is:

Random rotations of the code remove artifacts completely. For example if I change the line

if(ints[i].geomInt.valid) //1

to

if(ints[i].geomInt.valid == true) //1

which apparently should not affect logic in any way or completely remove double cycle that does nothing (marked as 2) artifacts vanish. Please note that the double cycle does nothing at all since condition

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;
}

Can never be satisfied(left and right sides have index i, not i, j) and there's no NaN's. This code does absolutely nothing yet somehow produces artifacts.

You can test the shader and demo on your own using this project(full MSVS 2010 project + sources + compiled binary and a shader, uses included SFML): https://dl.dropboxusercontent.com/u/25635148/ShaderTest.zip

I use sfml in this test project, but that's 100% irrelevant because the actual project I've enountered this problem does not use this lib.

What I want to know is why these artifacts appear and how to reliably avoid them.

解决方案

If anyone's still interested I asked this question on numerous specialized sites including opengl.org and devtalk.nvidia.com. I did not receive any concrete answer on what's wrong with my shader, just some suggestions how to work around my problem. Like use if(condition == true) instead of if(condition), use as simple algorithms as possible and such. In the end I've chosen one of the easiest rotations of my code that gets rid of the problem: I just replaced

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

with

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

There were numerous other code rotations that made the artifacts disappear, but I've chosen this one because I was able to test in on most other systems I had trouble with before.

这篇关于GLSL NVidia方形文物的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆