1

当我在我的计算机上运行该程序时,它完全按照我的预期工作。但是,当我尝试在我的校园实验室计算机上运行它时,片段着色器是各种奇怪的。

现在它只是一个简单的 Phong 光照计算,在原点有一个点光源。然而,在实验室计算机上,它看起来更像是 cel shading 和手电筒之间的某种奇怪的结合。我运行 ATI 显卡,而实验室计算机运行 NVIDIA。阴影在 Mac 上也按预期工作(不知道显卡)。

NVIDIA 卡最高支持 OpenGL 3.1,尽管我在这个 Linux 发行版上以 2.1 运行它。我已经尝试将着色器版本限制为 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);
}
4

1 回答 1

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中的内容!

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

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

真的需要再次阅读你的着色器,每次你看到一个向量时,问问自己“这个向量在什么坐标空间中是有意义的?” 每次你看到一个矩阵时,问问自己“这个矩阵从什么坐标空间转换到什么坐标空间?”</p>

于 2013-02-04T02:10:12.420 回答