4

gl コンテキストで CAEAGLLayer サブクラスをセットアップしようとしています。つまり、CAEAGLLayer を返す UIView サブクラスを作成し、UIView サブクラス内から gl コンテキストをこのレイヤーにバインドする代わりに、レイヤーを直接サブクラス化し、レイヤーの init でコンテキストをセットアップしようとしています。

- (id)init
{
    self = [super init];
    if (self) {
        self.opaque = YES;

        _glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
        NSAssert([EAGLContext setCurrentContext:_glContext], @"");

        glGenRenderbuffers(1, &_colorRenderBuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
        [_glContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:self];

        glGenFramebuffers(1, &_framebuffer);
        glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);

        /// . . .

その時点まではすべて問題ないようです。ただし、「パススルー」頂点/フラグメント シェーダー ペアを使用してシェーダー プログラムを作成しようとすると、プログラムをリンクしてもエラーは返されませんが、「現在の描画フレーム バッファーが無効です」というメッセージが表示されて検証に失敗します。

シェーダー プログラムをリンクして検証するコード (シェーダーをアタッチした後) は、次のようになります。

- (BOOL)linkAndValidateProgram
{
    GLint status;
    glLinkProgram(_shaderProgram);

#ifdef DEBUG
    GLint infoLogLength;
    GLchar *infoLog = NULL;
    glGetProgramiv(_shaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength);
    if (infoLogLength > 0) {
        infoLog = (GLchar *)malloc(infoLogLength);
        glGetProgramInfoLog(_shaderProgram, infoLogLength, &infoLogLength, infoLog);
        NSLog(@"Program link log:\n%s", infoLog);
        free(infoLog);
    }
#endif

    glGetProgramiv(_shaderProgram, GL_LINK_STATUS, &status);
    if (!status) {
        return NO;
    }

    glValidateProgram(_shaderProgram);

#ifdef DEBUG
    glGetProgramiv(_shaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength);
    if (infoLogLength > 0) {
        infoLog = (GLchar *)malloc(infoLogLength);
        glGetProgramInfoLog(_shaderProgram, infoLogLength, &infoLogLength, infoLog);
        NSLog(@"Program validation log:\n%s", infoLog);
        free(infoLog);
    }
#endif

    glGetProgramiv(_shaderProgram, GL_VALIDATE_STATUS, &status);
    if (!status) {
        return NO;
    }

    glUseProgram(_shaderProgram);
    return YES;
}

CAEAGLLayer のライフサイクルのある時点で、気づいていないかもしれない追加のセットアップがあり、init で GL をセットアップしようとしてスキップしている可能性があるのではないかと思っています。

4

2 に答える 2

1

問題は、初期化のその時点でレイヤーに次元がないことでした。これにより、レンダー バッファー ストレージをレイヤーに設定しようとすると、バッファーが 0 になることがわかります。

更新:私の現在の最善の考えは、init にサイズを課す代わりに (テスト目的では問題なく動作しましたが、ハックです)、レイヤーのサイズが変更されるたびにバッファー ストレージを再設定する必要があるということです。だから私は-setBounds:次のようにオーバーライドしています:

- (void)setBounds:(CGRect)bounds
{
    [super setBounds:bounds];
    [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:self];
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &someVariableToHoldWidthIfYouNeedIt);
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &someVariableToHoldHeightIfYouNeedIt);
}
于 2013-08-12T18:20:47.953 に答える
0

私が知る限り、このようにビューのlayerClassメソッドを上書きする必要があります

    + (Class)layerClass
    {
       return [MYCEAGLLayer class];
    }

また、MYCEAGLLayer で drawableProperties を設定する必要があります。

于 2013-08-12T17:31:31.650 に答える