8

opengl を使用してゲームを作成しようとしていますが、新しい glkit クラスと iOS の既定のテンプレートで多くの問題が発生しています。

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

    if (!self.context) {
        NSLog(@"Failed to create ES context");
    }

    if(!renderer)
        renderer = [RenderManager sharedManager];
    tiles = [[TileSet alloc]init];

    GLKView *view = (GLKView *)self.view;
    view.context = self.context;
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;

    [self setupGL];
}

- (void)setupGL
{
    int width = [[self view] bounds].size.width;
    int height = [[self view] bounds].size.height;

    [EAGLContext setCurrentContext:self.context];

    self.effect = [[GLKBaseEffect alloc] init];
    self.effect.light0.enabled = GL_TRUE;
    self.effect.light0.diffuseColor = GLKVector4Make(0.4f, 0.4f, 0.4f, 1.0f);

    //Configure Buffers
    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

    glGenRenderbuffers(2, &colourRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, colourRenderBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, width, height);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colourRenderBuffer);

    glGenRenderbuffers(3, &depthRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderBuffer);

    //Confirm everything happened awesomely
    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER) ;
    if(status != GL_FRAMEBUFFER_COMPLETE) {
        NSLog(@"failed to make complete framebuffer object %x", status);
    }

    glEnable(GL_DEPTH_TEST);

    // Enable the OpenGL states we are going to be using when rendering
    glEnableClientState(GL_VERTEX_ARRAY);

}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glClearColor(0.4f, 0.4f, 0.4f, 1.0f);


    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);


    float iva[] = {
        0.0,0.0,0.0,
        0.0,1.0,0.0,
        1.0,1.0,0.0,
        1.0,0.0,0.0,
    };

    glVertexPointer(3, GL_FLOAT, sizeof(float) * 3, iva);

    glDrawArrays(GL_POINTS, 0, 4);

}
@end

これにより、バッファは (灰色に) クリアされますが、頂点配列からは何もレンダリングされません。ここから何をすればよいかわかりません。また、テクノロジーが古くなっているため、glkit の適切な使用方法に関する情報はあまりありません。

4

5 に答える 5

12

シェーダーをロードするセットアップ コードに何も表示されません。コードのどこかでこれを行っていると思いますか?

さらに、セットアップ コードでは、フレームバッファを作成しています。はGLKViewこれを行います-実際、viewDidLoadメソッドで24ビットの深度バッファーを使用するようにビューに指示しています:

GLKView *view = (GLKView *)self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;

したがって、glkView:drawInRect:上記のコードが行っていることは、「手作りのフレームバッファをバインドし、それに何かを描画する」ということです。その後GLKView、 は自動的に表示されますが、何も描画されていません。手作りのバッファーにのみ描画されています。テクスチャへのレンダリングなどのタスクに追加のフレーム バッファ オブジェクトが必要でない限り、フレーム バッファの作成を気にする必要はまったくありませんGLKView。自動的に行わせてください。

setupGLメソッド (またはセットアップの好きな場所) で行うべきことは、描画を実行するために必要な openGL の状態を記憶する頂点配列オブジェクトを作成することです。次に、glkView:drawInRect:メソッドで次のことを行う必要があります。

  1. でクリアglClear()
  2. プログラムを有効にします。
  3. 頂点配列オブジェクトをバインドします (または、VAO を使用しなかった場合は、適切な頂点属性ポインターを有効にします)。
  4. glDrawArrays()またはを使用してデータを描画しますglDrawElements()

は、コンテキストを現在のGLKViewコンテキストに自動的に設定し、各描画サイクルの前にそのフレーム バッファ オブジェクトをバインドします。

おそらく、GLKViewより通常のように考えてみてくださいUIView。OpenGL コードのほとんどは舞台裏で処理されるため、ユーザーは、何を描画する必要があるかを単純に伝えるだけです。drawRect:通常のコードと同じようにコードを持っています。UIView通常UIViewのコードではdrawRect:、Core Graphics 関数を使用するなど、何を描画するかを指定するだけです。

GLKViewControllerは、レンダリング ループのメカニズムを舞台裏で処理するものと考えるのが最適です。タイマーを実装する必要はなく、バックグラウンドに入るアプリケーションのアニメーションを一時停止することについても心配する必要はありません。update or メソッドをオーバーライドするだけでglkViewControllerUpdate:(サブクラス化するか委任するかによって異なります)、openGL オブジェクトまたはビュー マトリックスの状態を更新できます。

于 2011-10-19T01:16:03.487 に答える
1

GLKit を使用した基本的なプロジェクト テンプレートの設定方法について投稿しました。ここで見つけることができます:

Steve Zissou のプログラミング ブログ

于 2012-03-27T15:11:06.787 に答える
0

GLKitはまだ使用していませんが、描画後にフレームバッファを表示していないようです。iOSでOpenGLES2を使用しているが、GLKitを使用していないアプリケーションでは、レンダリングループの最後に次のコードを呼び出すために使用します。

if(context) {
  [EAGLContext setCurrentContext:context];
  glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
  [context presentRenderbuffer:GL_RENDERBUFFER];

}

私が言ったように、私はまだGLKitを使用していないので、これが役立つことを願っています。

于 2011-10-18T12:31:47.190 に答える
0

GLKit は OpenGL ES 1.1 レンダリング パイプラインを模倣しているため、シェーダーを定義するルーチンを含める必要はありません。OpenGL ES1.1 のような基本的なパイプラインを使用したい場合は、GLKit が実際にこれを行います。

于 2011-12-05T18:24:46.500 に答える
0

あなたは電話するのを忘れたと思う

[self.effect prepareToDraw];

直前

glDrawArrays(GL_POINTS, 0, 4);
于 2011-10-28T10:45:34.513 に答える