6

私は今何日もできない本当に奇妙な問題を抱えていpin downます。単純な頂点ごとのライティングを作成しており、 で正常に動作Nvidiaしますが、ライト オンでシェーディングされたものはレンダリングされませんAMD/ATI。属性、特に色属性に関係する問題を突き止めました。
これは私の頂点シェーダーです:

#version 140
uniform mat4 modelViewProjectionMatrix;
in vec3 in_Position;                 // (x,y,z)
in vec4 in_Color;                    // (r,g,b,a)
in vec2 in_TextureCoord;             // (u,v)

out vec2 v_TextureCoord;
out vec4 v_Color;

uniform bool en_ColorEnabled;
uniform bool en_LightingEnabled;

void main()
{
   if (en_LightingEnabled == true){
      v_Color = vec4(0.0,1.0,0.0,1.0);
   }else{
      if (en_ColorEnabled == true){
         v_Color = in_Color;
      }else{ 
         v_Color = vec4(0.0,0.0,1.0,1.0);
      }
   }
   gl_Position = modelViewProjectionMatrix * vec4( in_Position.xyz, 1.0);

   v_TextureCoord = in_TextureCoord;
}

これはピクセル シェーダーです。

#version 140
uniform sampler2D en_TexSampler;
uniform bool en_TexturingEnabled;
uniform bool en_ColorEnabled;
uniform vec4 en_bound_color;
in vec2 v_TextureCoord;
in vec4 v_Color;
out vec4 out_FragColor;

void main()
{
   vec4 TexColor;
   if (en_TexturingEnabled == true){
      TexColor = texture2D( en_TexSampler, v_TextureCoord.st ) * v_Color;
   }else if (en_ColorEnabled == true){
      TexColor = v_Color;
   }else{
      TexColor = en_bound_color;
   }
   out_FragColor = TexColor;
}

したがって、このシェーダーは、ライトを使用する場合、ライトを使用せずに頂点カラーを使用する場合、およびすべての頂点に単一のカラーを使用する場合の 3 つの状態を許可します。問題を特定の属性まで突き止めたため、簡単な計算コードをすべて削除しました。これはシェーダーからの出力
バグのあるシェーダー です: ご覧のとおり、すべてが青色です (したがって、シェーディングまたは色を持たないすべてがレンダリングされます(en_LightingEnabled == false and en_ColorEnabled == false))。

頂点シェーダーでこのコードを置き換えると:

if (en_ColorEnabled == true){
   v_Color = in_Color;
}else{ 

これとともに:

if (en_ColorEnabled == true){
   v_Color = vec4(1.0,0.0,0.0,1.0);
}else{

次の結果が得られます:
in_Color 属性なし
シェーディングなしですべてをレンダリングすることがわかりますが、ライト ( en_LightingEnabled == true) を使用するものはすべて緑色でレンダリングされます。そうあるべきです。問題は、in_Colorライトが有効になっている場合でもアトリビュートが実行されないため、アトリビュートがライトに干渉してはならないことです。また、画像内に赤い部分がないこともわかります。つまり、このシーンen_ColorEnabledでは常にfalse. ここin_Colorではまったく役に立ちませんが、論理的にすべきではない場所でバグを引き起こします。そのNvidia上で正常に動作し、緑色の領域は の有無にかかわらず描画されin_Colorます。

AMDサポートされていないものを使用していますか? GLSL仕様外のものを使用していますか? 私は仕様よりもAMD厳密であることを知っているので、未定義のことをする可能性があります。コードをできるだけシンプルにしましたが、まだ問題があるため、わかりません。また、頂点属性が無効 になっている場合 (no )、画面上に何も描画されない (青い領域でさえ) ことに気付きましたが、なぜですか? 色も使いません。無効な属性は、仕様によって ( ) を返す必要がありますよね? その色を変更しようとしましたが、それでも黒くなりました。コンパイラとリンカーはエラーや警告を返しません。属性 in_Color は、GLNvidia
in_ColorglEnableVertexAttribArray0,0,0,1glVertexAttrib4fglGetAttribLocation. しかし、私が言ったように、そのブランチは私のコードで実行されることはないので、これは問題ではありません。何か案は?

テスト済みでNvidia660Ti問題なく動作し、ATI mobility radeon HD 5000ラップトップでテストしたところ、このエラーが発生しました。私の唯一の考えは、(属性が多すぎるなど)の機能を超えている可能性があるということでしたがGPU、コードをこれに減らしたとき、それを信じるのをやめました。ここでは 3 つの属性のみを使用します。
また、私の友人の何人かは、より新しいAMDカードでテストしたところ、同じ問題が発生しました。

更新 1

頂点属性は次のようにバインドされます。

if (useColors){
   glUniform1i(uni_colorEnable,1);  
   glEnableVertexAttribArray(att_color);
   glVertexAttribPointer(att_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, STRIDE, OFFSET(offset));
}else{
   glUniform1i(uni_colorEnable,0);  
}

また、奇妙さをさらに簡単に表示する方法を見つけました。この頂点シェーダーを使用してください。

void main()
{
   v_Color = clamp(vec4(1.,1.,1.,1.) * vec4(0.5,0.5,0.25,1.),0.0,1.0) + in_Color;

   gl_Position = modelViewProjectionMatrix * vec4( in_Position.xyz, 1.0);

   v_TextureCoord = in_TextureCoord;
}

したがって、分岐はありません。そして、私はこれを取得します: 分岐がなければ、まだそのバグがあります そのコードをin_Color次のように削除して変更すると:

void main()
{
   v_Color = clamp(vec4(1.,1.,1.,1.) * vec4(0.5,0.5,0.25,1.),0.0,1.0);

   gl_Position = modelViewProjectionMatrix * vec4( in_Position.xyz, 1.0);

   v_TextureCoord = in_TextureCoord;
}

私はこれを得る: 予想通り分岐なし

この最後のものは私が期待するものですが、前のものは、+他の代わりに加算 ( ) を行っても何も描画しません。したがって、attribがバインドされておらず、( 0,0,0,0) または ( 0,0,0,1) が指定されている場合は、何もするべきではありません。それでもまだ失敗します。

また、コンパイル、リンク、および検証のすべてのログは空です。エラーや警告はありません。シェーダーのデバッグ情報AMD/ATIが提供するものよりもはるかに劣っていることに気付きましたNvidiaが。

更新 2

私が見つけた唯一の修正はattribarray、すべての場合に有効にすることでした(したがって、基本的に、色が有効になっていないときにジャンクを送信しますGPU)が、ユニフォームを使用して色をチェックするので、使用しません. したがって、次のようになります。

if (useColors){
   glUniform1i(uni_colorEnable,1);  
}else{
   glUniform1i(uni_colorEnable,0);  
}
glEnableVertexAttribArray(att_color);
glVertexAttribPointer(att_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, STRIDE, OFFSET(offset));

なぜそれが起こっているのか、なぜこれを使用する必要があるのか​​ わかりません。私はそれを必要としませんNvidia。だから、これは遅くて帯域幅を無駄にしていると思いますか? しかし、少なくともそれは機能します...これをより良く行う方法についてのヘルプは役に立ちます。

4

1 に答える 1

2

これはおそらく、シェーダーに 3 つの入力値 (in_Position、in_Color、in_TextureCoord) を指定しているが、頂点データに常に 3 つすべてが含まれているとは限らないために発生しています。頂点属性がこの形式と正確に一致しない場合、未定義の動作が発生します。テリトリーと各実装は、それが望むことを行うことができます。

Nvidia ドライバーが持っているものを適切な頂点属性にバインドし、それでレンダリングするように見えます。

つまり、データはシェーダーに対して以下の配置のように見えます。

in_Position      = Position.xyz
in_Color         = ???
in_TextureCoords = TextureCoords.xy

AMD ドライバーは、色が含まれていなくても、頂点データを 3 つの属性すべてとして解釈しようとしている可能性があります。最初の頂点の後、位置はデータ配列内の位置と同期していないため、ほとんどどこにでもレンダリングされます。in_Color 属性の使用を削除すると AMD で機能する理由は、シェーダー コンパイラが使用されていないことを認識し、指定したという事実を最適化するためだと思います。

in_Position      = Position[0].xyz
in_Color         = TextureCoords[0].xy,Position[1].xy
in_TextureCoords = Position[1].z,TextureCoords[1].x

考えられる解決策は、既に行ったことを実行し、必要のないときにガベージ カラー データを指定するか、頂点シェーダーを異なる頂点属性を持つ 2 つの別々のものに分割し、頂点があるかどうかに応じて適切なものをバインドすることです。カラーデータ。

于 2014-09-27T02:21:15.133 に答える