5

OpenGL ES 2.0 とカスタム フラグメント シェーダーを使用する複数の OpenGL-ES ビューを備えた iPad アプリがあります。現在、シェーダーは個々の OpenGL ビューごとにコンパイルおよびリンクされます。シェーダーを一度コンパイルしてリンクし、ビューごとに再利用したいと思います。理論的には、これは電話をかけるだけの問題です

gluseProgram(gProgramHandle);

私の render() メソッドで、レンダリングの前に gProgramHandle を 1 回読み込みますよね? しかし、これはうまくいきません。単一の gProgramHandle (初期化時に -1 に設定) の使用に切り替えると、1 つの OpenGL ビューのみが機能し、他のビューは濃い緑色の四角形として表示されます。私は何を間違っていますか?

- (void)loadShaders
{
   if (gProgramHandle == -1)
{
    NSLog(@"Compiling shaders...");

    GLuint vertexShader = [self compileShader:@"AIMGsiVertexShader" withType:GL_VERTEX_SHADER];
    GLuint fragmentShader = [self compileShader:@"AIMGsiFragmentShader" withType:GL_FRAGMENT_SHADER];

    gProgramHandle = glCreateProgram();
    glAttachShader(gProgramHandle, vertexShader);
    glAttachShader(gProgramHandle, fragmentShader);
    glLinkProgram(gProgramHandle);

    GLint linkSuccess;
    glGetProgramiv(gProgramHandle, GL_LINK_STATUS, &linkSuccess);
    if (linkSuccess == GL_FALSE)
    {
            // If there was an error when compiling the gsls shaders, report the compile error and quit.
        GLchar messages[256];
        glGetProgramInfoLog(gProgramHandle, sizeof(messages), 0, &messages[0]);
        NSString *messageString = [NSString stringWithUTF8String:messages];
        NSLog(@"%@", messageString);
        exit(1);
    }

    NSLog(@"Done compiling and linking shaders.");
}

    // We can efficiently switch between shaders by calling glUseProgram() to use the program with the shaders we want to use.
glUseProgram(gProgramHandle);

    // Gradient map values are sent in this vector: numValuesInCache, factor, offset
_gradientValsUniform = glGetUniformLocation(gProgramHandle, "GradientVals");
_numColorsInGradient = glGetUniformLocation(gProgramHandle, "NumColorsInCache");
_gradientColorsArray = glGetUniformLocation(gProgramHandle, "ColorsArray");


_positionSlot = glGetAttribLocation(gProgramHandle, "Position");

glEnableVertexAttribArray(_positionSlot);

_projectionUniform = glGetUniformLocation(gProgramHandle, "Projection");
_modelViewUniform = glGetUniformLocation(gProgramHandle, "Modelview");

_texCoordSlot = glGetAttribLocation(gProgramHandle, "TexCoordIn");
glEnableVertexAttribArray(_texCoordSlot);
_textureUniform = glGetUniformLocation(gProgramHandle, "Texture");

}
4

2 に答える 2

7

以下は、共有に関するEAGLSharegroup Class Referenceからの引用です。

現在、sharegroup はテクスチャ、バッファ、フレームバッファ、およびレンダバッファを管理しています。

ご覧のとおり、シェーダー/プログラム/パイプラインは言及されていません。

ただし、 Apple dev フォーラムからの引用は次のとおりです。

シェーダー/プログラム/パイプラインを共有することは合法ですが、実際に同じプログラムを同時に使用することは避けるべきものです。

問題は、Uniform 値がプログラム自体のプロパティであるため、複数のスレッドから同じプログラムを使用している場合、あるスレッドからオブジェクトを使用しながら別のスレッドからオブジェクトを変更することに対する規則に違反することです。

使用法が重複していない場合 (たとえば、1 つのコンテキストがプログラムを生成し、別のコンテキストがレンダリングするなど)、問題なく動作するはずです。

シェーダーとパイプラインの共有をテストするために、iPad 用の簡単なプロジェクトを開発しました: https://github.com/Gubarev/shared-shaders-test。そして、共有が機能することを確認できます!

于 2014-05-08T12:46:59.790 に答える
5

コンテキスト間でプログラムを共有することはできません。GL コンテキストは状態情報の集合であり、プログラムはその状態の一部です。すべてのビューに独自のコンテキストが必要かどうか疑問に思いますが、これは必要ないかもしれません。すべてのレンダリングをメイン スレッドで行う場合は、ビュー間でコンテキストを共有し、各ビューの各描画呼び出しで必要な状態を設定します。複数のスレッドでレンダリングしている場合は、コンテキストの作成を[[EAGLContext alloc] initWithAPI:... sharegroup:...]参照し、メイン コンテキストから共有グループを渡します。

于 2012-11-26T23:12:26.947 に答える