1

ユニフォーム名の最大長が必要です。uniform testつまり、ユニフォームとを使用した使用済みプログラムを指定するとuniform myuniformglGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, outParam)10の出力が得られるはずです(「myuniform」の場合)。

1つの定義されたユニフォームでセットアップされた非常に単純なテストシェーダーがあります。uniform float time

glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, outParam)の長さである5を返しますtime。「time」を別のものに変更すると、変更された長さが返されます(例:「timer」に変更すると6が返されます)。

glGetProgramivGL_ACTIVE_UNIFORMSは、2つのユニフォームがあることを教えてくれます。レポートしている2番目のユニフォームはgl_ModelViewProjectionMatrixです。

リストにgl_ModelViewProjectionMatrixを含めても問題ありません。シェーダーで使用していますが、他の戻り値と組み合わせると問題が発生します。「gl_ModelViewProjectionMatrix」がリストに含まれている場合、glGetProgramivが「gl_ModelViewProjectionMatrix」の長さを返さないのはなぜですか?アプリケーションの属性と変数のフルネームが必要ですが、最大長が5になっているため、glGetActiveUniform「gl_M」という統一された名前が返されます。これは受け入れられません。

名前の最大長にMVPマトリックスを含めるか、名前のリストに含めないでください。リストに名前を含めることは意味がありませんが、名前の最大長の計算には含めません。

これは私だけに起こっているのですか?グーグルを使ってそれについて他に何も見つけることができませんでした。最大長のクエリを放棄し、常に非常に大きなバッファを使用することもできますが、以前に非常に長い変数名をいくつか見たことがあるため、エラーが発生しないようにするには、バッファを大きくする必要があります。とにかく、それは本当の修正ではありません。

このテストは、属性に対して正しく機能しています。私はgl_Vertexを使用しており、他の属性はありません。システムは、長さが10で名前がgl_Vertexの1つの現在の属性を正しく報告します。時間ユニフォームを完全に削除すると、MVPマトリックスが唯一の使用済みユニフォームとして残り、システムは1つの現在のユニフォーム、最大名の長さ0を報告するため、返された最大長で名前を取得しても何も得られません。

完全を期すために、以下のコードを含めます。コードはJavaであり、JOGLを使用してOpenGLバインディングにアクセスします。関連する領域を強調するために、この問題に関係のない行を削除しました。これは、ここで取得した値を実際に表示するGUI部分を含め、ほとんどがGUIの更新でした。上記のように、属性を取得する部分も正常に機能するため、削除しました。

Java主義に警戒しているCの人々のための参考までに:バッファ(、、IntBuffer)をポインタのように、のように、そしてのように考えてByteBufferください。私はCとC++でもOpenGLを使用しているので、ここのGLSLの達人がそれを好む場合は、これをCで書き直すことができます。FloatBufferbuffer.get()buffer[n++]buffer = IntBuffer.allocate(n)malloc()

助言がありますか?

// add options to panelShaderParameters
public void updateShaderParameters(GLAutoDrawable surface)
{
    GL2 gl = surface.getGL().getGL2();

    IntBuffer outParam = IntBuffer.allocate(1);
    int numParameters = 0,
        maxNameLength = 0;

    IntBuffer size = null,
        type = null;
    ByteBuffer name = null;

    gl.glGetProgramiv(shader.getName(), GL2.GL_ACTIVE_UNIFORMS, outParam);
    numParameters = outParam.get();
    outParam = IntBuffer.allocate(1);
    gl.glGetProgramiv(shader.getName(), GL2.GL_ACTIVE_UNIFORM_MAX_LENGTH, outParam);
    maxNameLength = outParam.get();

    for(int i = 0; i < numParameters; i += 1)
    {
        size = IntBuffer.allocate(1);
        type = IntBuffer.allocate(1);
        name = ByteBuffer.allocate(maxNameLength);
        gl.glGetActiveUniform(shader.getName(), i, maxNameLength, (IntBuffer)null, size, type, name);
        byte[] nameBuffer = new byte[maxNameLength];
        name.position(0);
        name.get(nameBuffer);
    }
}
4

2 に答える 2

1

ドライバーのバグが見つかりました。報告を試みることはできますが (このフォーラムは、それが見られる場所です)、正しく機能させるためにできることは何もありません。だから、それを回避してください。

単一の最大サイズを指定するのではなく、各ユニフォームに順番に長さを尋ねてください. C/C++ では、バッファの NULL を に渡すことでこれを行いますglGetActiveUniformName

GLsizei length;
glGetActiveUniformName(program, index, 1000 /*large number*/, &length, NULL);
//Use length to allocate a buffer of the appropriate size.

これが JOGL を使用してどのように機能するかはわかりません。おそらく、この関数のより合理的な Java 実装を備えた LWJGL に切り替える必要があります。

また、文字列をバイト配列として格納するのをやめます。それらを適切な Java 文字列に変換します (LWJGL を使用するもう 1 つの理由)。

于 2012-09-23T19:24:06.330 に答える
0

まさにこの問題がありました。他の人がここで説明しているのを見ました:

http://www.opengl.org/discussion_boards/showthread.php/179117-Driver-bug-causing-incorrect-glGetProgramiv-output

私の場合、さまざまな GPU モデルで nvidia 295.40 ドライバーから 304.64 ドライバーにアップグレードした後に問題が発生しました。上記のフォーラムで、Intel ドライバーのバグが報告されました。どのドライバーを使用していますか?

おそらく「gl_」で始まる組み込み属性は、名前の最大長の計算では考慮されていないと思いますが、これが真実であっても、この動作はバグ IMHO と見なす必要があります。

回避策のアイデアをくれた Nicol に感謝します。

于 2012-11-14T09:55:46.567 に答える