片段着色器在不同的计算机上执行不同

时间:2013-02-03 22:20:55

标签: c++ opengl graphics glsl

当我在我的计算机上运行程序时,它的工作原理与我预期的一样。但是,当我尝试在我的校园实验室计算机上运行它时,片段着色器是各种奇怪的。

现在它只是一个简单的Phong照明计算,在原点处有一个点光源。然而,在实验室计算机上,它看起来更像是一个奇特的阴影和手电筒之间的交叉。我运行ATI显卡,实验室计算机运行NVIDIA。阴影在Mac上也能正常工作(不知道显卡)。

NVIDIA显卡支持OpenGL 3.1,不过我在2.1的Linux发行版上运行它。我已经尝试将着色器版本钳制到1.2(GLSL),在其他一些东西中,但它们实现了相同的结果。最奇怪的是,当我进行顶点着色而不是像素着色时,两台计算机上的结果都是一样的......我已经用尽了关于如何解决这个问题的想法。

这是顶点着色器:

#version 120

  attribute vec2 aTexCoord;
  attribute vec3 aPosition;
  attribute vec3 aNormal;
  attribute vec3 camLoc;
  attribute float mat;

  varying vec3 vColor;
  varying vec2 vTexCoord;
  varying vec3 normals;
  varying vec3 lightPos;
  varying vec3 camPos;
  varying float material;


uniform mat4 uProjMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uModelMatrix;
uniform mat4 uNormMatrix;

uniform vec3 uLight;
uniform vec3 uColor;

void main()
{
  //set up object position in world space
  vec4 vPosition = uModelMatrix * vec4(aPosition, 1.0);
  vPosition = uViewMatrix * vPosition;
  vPosition = uProjMatrix * vPosition;
  gl_Position = vPosition;

  //set up light vector in world space
  vec4 vLight = vec4(uLight, 1.0) * uViewMatrix;
  lightPos = vLight.xyz - vPosition.xyz;

  //set up normal vector in world space
  normals = (vec4(aNormal,1.0) * uNormMatrix).xyz;

  //set up view vector in world space
  camPos = camLoc.xyz - vPosition.xyz;

  //set up material shininess
  material = mat;

  //pass color and vertex
  vColor = uColor;
  vTexCoord = aTexCoord;
}

片段着色器:

#version 120

  varying vec3 lightPos;
  varying vec3 normals;
  varying vec3 camPos;
  varying vec2 vTexCoord;
  varying vec3 vColor;
  varying float material;

uniform sampler2D uTexUnit;

uniform mat4 uProjMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uModelMatrix;

void main(void) 
{
  float diffuse;
  float diffuseRed, diffuseBlue, diffuseGreen;
  float specular;
  float specRed, specBlue, specGreen;
  vec3 lightColor = vec3(0.996, 0.412, 0.706); //color of light (HOT PINK) **UPDATE WHEN CHANGED**
  vec4 L; //light vector
  vec4 N; //normal vector
  vec4 V; //view vector
  vec4 R; //reflection vector
  vec4 H; //halfway vector
  float red;
  float green;
  float blue;
  vec4 texColor1 = texture2D(uTexUnit, vTexCoord);

      //diffuse calculations
        L = vec4(normalize(lightPos),0.0);
        N = vec4(normalize(normals),0.0);
        N = uModelMatrix * N;

        //calculate RGB of diffuse light
        diffuse = max(dot(N,L),0.0);
        diffuseRed = diffuse*lightColor[0];
        diffuseBlue = diffuse*lightColor[1];
        diffuseGreen = diffuse*lightColor[2];

      //specular calculations
        V = vec4(normalize(camPos),0.0);
        V = uModelMatrix * V;

        R = vec4(-1.0 * L.x, -1.0 * L.y, -1.0 * L.z, 0.0);
        float temp = 2.0*dot(L,N);
        vec3 tempR = vec3(temp * N.x, temp * N.y, temp * N.z);
        R = vec4(R.x + tempR.x, R.y + tempR.y, R.z + tempR.z, 0.0);
        R = normalize(R);

        H = normalize(L + V);

        specular = dot(H,R);
        specular = pow(specular,material);
        specRed = specular*lightColor[0];
        specBlue = specular*lightColor[1];
        specGreen = specular*lightColor[2];

      //set new colors
        //textures
        red = texColor1[0]*diffuseRed + texColor1[0]*specRed*0.7 + texColor1[0]*.05;
        green = texColor1[1]*diffuseBlue + texColor1[1]*specBlue*0.7 + texColor1[1]*.05;
        blue = texColor1[2]*diffuseGreen + texColor1[2]*specGreen*0.7 + texColor1[2]*.05;

        //colors
        red = vColor[0]*diffuseRed + vColor[0]*specRed*0.7 + vColor[0]*.05;
        green = vColor[1]*diffuseBlue + vColor[1]*specBlue*0.7 + vColor[1]*.05;
        blue = vColor[2]*diffuseGreen + vColor[2]*specGreen*0.7 + vColor[2]*.05;

      gl_FragColor = vec4(red, green, blue, 1.0);
}

1 个答案:

答案 0 :(得分:3)

您的代码在很多方面都有错误。

以下代码错误。评论具有误导性(它在剪辑空间,而不是世界空间)。但是主要的问题是你在使用它时用剪辑空间坐标覆盖vPosition,就好像它在视图空间中的几行之后一样。

//set up object position in world space
vec4 vPosition = uModelMatrix * vec4(aPosition, 1.0);
vPosition = uViewMatrix * vPosition;
vPosition = uProjMatrix * vPosition;
gl_Position = vPosition;

以下代码也是错误的。首先,您需要matrix * vector,而不是vector * matrix。此外,评论说世界空间,但您在视图空间中计算vLight并添加剪辑空间<中的vPosition / EM>!

//set up light vector in world space
vec4 vLight = vec4(uLight, 1.0) * uViewMatrix;
lightPos = vLight.xyz - vPosition.xyz;

此处再次matrix * vector

//set up normal vector in world space
normals = (vec4(aNormal,1.0) * uNormMatrix).xyz;

现在这是什么? camPos以世界坐标计算,但您应用模型矩阵将模型空间转换为世界空间。

//specular calculations
V = vec4(normalize(camPos),0.0);
V = uModelMatrix * V;

我不知道为什么你的着色器在不同的计算机上表现不同,但我很确定这些计算机都没有显示远远接近预期结果的任何东西。

真的需要再次阅读你的着色器,每次看到一个向量时,问问自己“这个向量在哪个坐标空间有意义?”并且每次看到矩阵时,问问自己“这个矩阵从哪个坐标空间转换成?”