1

私が自分のコンピューターでプログラムを実行すると、それは私が期待したとおりに機能します。ただし、キャンパスラボのコンピューターで実行しようとすると、フラグメントシェーダーはあらゆる種類の奇妙なものになります。

今のところ、これは原点に点源ライトを使用した単純なフォン照明の計算です。ただし、ラボのコンピューターでは、セルシェーディングと懐中電灯の間の奇妙なクロスのように見えます。ラボコンピュータがNVIDIAを実行している間、私はATIグラフィックカードを実行します。シェーディングはMacでも期待どおりに機能します(グラフィックカードについてはわかりません)。

NVIDIAカードはOpenGL3.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);
}
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。また、コメントにはworld spaceと記載されていますが、ビュー空間で計算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 に答える