用GLKit绘图

时间:2011-10-18 12:16:26

标签: ios opengl-es ios5 glkit

我正在尝试使用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的信息。

5 个答案:

答案 0 :(得分: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,则启用 适当的顶点attrib指针)。
  4. 使用glDrawArrays()glDrawElements()
  5. 绘制数据

    GLKView自动将其上下文设置为current,并在每个绘制周期之前绑定其framebuffer对象。

    或许尝试将GLKView更像是常规UIView。它为您处理幕后的大部分openGL代码,让您只需告诉它需要绘制的内容。它的drawRect:代码与常规UIView一样 - 在UIView中有一个常规的drawRect:,您只需告诉它应绘制的内容,例如使用Core Graphics函数 - 您不要告诉它出现。

    然后最好将GLKViewController视为处理幕后渲染循环的机制。您不需要实现计时器,甚至担心暂停进入后台的应用程序上的动画。您只需要覆盖update glkViewControllerUpdate:方法(取决于您是子类还是委托)来更新openGL对象或视图矩阵的状态。

答案 1 :(得分:1)

我发了一篇关于使用GLKit设置基本项目模板的方法的帖子。你可以在这里找到它:

Steve Zissou's Programming Blog

答案 2 :(得分:0)

我还没有使用过GLKit,但似乎在绘制之后你没有出现你的帧缓冲。 在iOs下使用OpenGL ES 2但没有GLKit的应用程序中,我使用在渲染循环结束时调用以下代码。

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

}

正如我所说,我还没有使用过GLKit所以我希望这可能有用。

答案 3 :(得分:0)

我想你忘了打电话了

[self.effect prepareToDraw];

之前

glDrawArrays(GL_POINTS, 0, 4);

答案 4 :(得分:0)

由于GLKit模仿OpenGL ES 1.1渲染管道,因此您无需包含用于定义Shader的例程。如果你想使用像OpenGL ES1.1这样的基本管道

,GLKit实际上是为你做的