11

私は非常に基本的な GLSL プログラムを持っていますが、最初の描画呼び出しの後、均一な値を適切に更新できません。からエラーが受信されglGetErrorず、シェーダーのコンパイルおよびリンク時に情報ログにエラーが報告されず、すべての統一された場所が有効です。

頂点シェーダー:

#version 120

uniform mat4 mvp;
uniform mat3 nmv;

attribute vec3 position;
attribute vec3 normal;

varying vec3 v_normal;

void main()
{
    v_normal = normalize(nmv * normal);
    gl_Position = mvp * vec4(position, 1.0);
}

フラグメント シェーダー:

#version 120

uniform vec3 lightDir;
uniform vec3 lightColor;
uniform vec3 materialColor;

varying vec3 v_normal;

void main()
{
    vec3 n = normalize(v_normal);
    float nDotL = max(0.0, dot(n, lightDir));

    gl_FragColor = vec4(materialColor * lightColor * nDotL, 1.0);
}

レンダリング コード:

glUseProgram(program);
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, mvp);
glUniformMatrix3fv(nmvLoc, 1, GL_FALSE, nmv);
glUniform3fv(lightDirLoc, 1, lightDir);
glUniform3fv(lightColorLoc, 1, lightColor);

for (auto mesh: meshes)
{
    glUniform3fv(materialColorLoc, 1, mesh.color);
    mesh.draw();
}

レンダリングされたメッシュはすべて最初のメッシュの色で描画されます。これは、ユニフォームを最初に設定した後、materialColorユニフォームを変更するための後続の呼び出しが無視されることを示しています。ただし、ユニフォームが適切に更新されることを個別に許可する特別な条件のリストを次に示します。

  • glUseProgram(program)ループ内での呼び出し。
  • ループ内でmvpまたはユニフォームを設定します。nmv
  • lightDirループ内のユニフォームを設定します。
  • uniform vec3の 1 つをシェーダー プログラムから削除します。

lightColorループ内でユニフォームを設定しても、ユニフォームは更新されないことに注意してくださいmaterialColorGL_CURRENT_PROGRAMループ内もチェックしましたが、シェーダーはずっとバインドされたままです。

私はこれを何時間も修正しようとしてきましたが、絶対に問題を見つけることができません. このシェーダーのセットアップは非常に単純なので、ドライバーのバグではないと思います。NVIDIA GeForce 9400M を搭載した Mac OS X 10.8.3 で OpenGL 2.1 を使用しています。

単一フレームのコール トレースを次に示します。

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(1);
glUniformMatrix4fv(1, 1, 0, 0x7fff55512550); // mvp
glUniformMatrix3fv(5, 1, 0, 0x7fff55512528); // nmv
glUniform3fv(0, 1, 0x7fff55512670);          // lightDir
glUniform3fv(9, 1, 0x7fff555124e8);          // lightColor

// Mesh 0
glUniform3fv(8, 1, 0x7fab820cd7ec);          // materialColor
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 1);
glEnableVertexAttribArray(0);
glVertexAttribPointerARB(0, 3, GL_FLOAT, 0, 24, 0x00000000);
glEnableVertexAttribArray(2);
glVertexAttribPointerARB(2, 3, GL_FLOAT, 0, 24, 0x0000000c);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, 21);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

// Mesh 1
glUniform3fv(8, 1, 0x7fab823000bc);          // materialColor
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 2);
glEnableVertexAttribArray(0);
glVertexAttribPointerARB(0, 3, GL_FLOAT, 0, 24, 0x00000000);
glEnableVertexAttribArray(2);
glVertexAttribPointerARB(2, 3, GL_FLOAT, 0, 24, 0x0000000c);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, 24);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

// Mesh 2
glUniform3fv(8, 1, 0x7fab8231f8fc);          // materialColor
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 3);
glEnableVertexAttribArray(0);
glVertexAttribPointerARB(0, 3, GL_FLOAT, 0, 24, 0x00000000);
glEnableVertexAttribArray(2);
glVertexAttribPointerARB(2, 3, GL_FLOAT, 0, 24, 0x0000000c);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, 21);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

// Mesh 3
glUniform3fv(8, 1, 0x7fab820cf41c);          // materialColor
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 4);
glEnableVertexAttribArray(0);
glVertexAttribPointerARB(0, 3, GL_FLOAT, 0, 24, 0x00000000);
glEnableVertexAttribArray(2);
glVertexAttribPointerARB(2, 3, GL_FLOAT, 0, 24, 0x0000000c);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, 18);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

CGLFlushDrawable();

編集:これは、均一な場所を取得するために使用されるコードです。これは、シェーダーがコンパイルおよびリンクされた後に実行され、すべてのユニフォームが有効であることが検証されます。

GLint mvpLoc = glGetUniformLocation(program, "mvp");
GLint nmvLoc = glGetUniformLocation(program, "nmv");
GLint lightDirLoc = glGetUniformLocation(program, "lightDir");
GLint lightColorLoc = glGetUniformLocation(program, "lightColor");
GLint materialColorLoc = glGetUniformLocation(program, "materialColor");
4

3 に答える 3

0

トレース内のすべてのアドレスから、あなたが GL に送信した vec3 はすべてタイプfloat name[3]であると思いますね。これを仮定すると、コードのエラーを見つけることができません。あなたが述べたように、glGetError によって返されるエラー状態はありません。これはドライバーのバグである必要があります。

glBindBuffer(GL_ARRAY_BUFFER, 0) を実行しているすべてのメッシュを開始することをトレースで見ました - これは実際には必要ありません。しかし、どう考えてもこれが元ネタとは思えない。

残念ながら、リンクする前に glBindUniformLocation のようなものをテストすることはできません。これは OpenGL の一部ではないためです。

私の経験によると、glUniform3fv を発行し、すべてのパラメーターが正しい場合、ユニフォームが更新され、その変更がすぐに表示されます。そうではないので、ここではドライバーのバグに違いないので、あなたができる唯一のことは、レンダリングループに他の不要な呼び出しを追加して、変更を目に見えるようにすることです(これを正しく読んでいれば、すでに行っています) .

于 2014-09-25T08:31:28.030 に答える