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

标签 c++ opengl graphics glsl

当我在我的计算机上运行该程序时,它完全按照我的预期运行。然而,当我尝试在我的校园实验室计算机上运行它时,片段着色器有各种各样的奇怪之处。

现在它只是一个简单的 Phong 光照计算,在原点有一个点光源。然而,在实验室计算机上,它看起来更像是 cel shading 和手电筒之间的一些奇怪的交叉。我运行 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);
}

最佳答案

您的代码在很多很多方面看起来都是错误的。

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

//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。而且,评论说 world space,但您在 view space 中计算 vLight 并添加 vPosition 剪辑空间!

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

同样,矩阵 * 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;

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

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

关于c++ - 片段着色器在不同的计算机上执行不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14677992/

相关文章:

c++ - 为什么对按值传递的参数使用 const?

c++ - 利用 vector 的元素存储在堆中的事实?

c++ - base-R seq 的 Rcpp 版本丢弃值

c++ - C++ STL 容器(浮点 vector )的 SWIG 模板类型特征错误

c++ - Gamma 校正看起来没有正确校正,这是线性的吗?

c++ - OpenGL Ubuntu 13.10 QtCreator - 未定义对 `glutMainLoop` 的引用

c++ - 如何在 OpenGL 中绘制显示在 alpha 纹理后面的线框?

java - 更新作为 JFrame 组件的 java Canvas

image - 如何在不更改 Matlab colorbar 中的值的情况下反转图片的颜色

android - 在 android 中查看和使用 3d 模型和文件类型的解决方案