【问题标题】:Drawing with GLKit使用 GLKit 绘图
【发布时间】:2011-12-10 01:26:54
【问题描述】:

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

【问题讨论】:

    标签: ios opengl-es ios5 glkit


    【解决方案1】:

    我在您的设置代码中没有看到任何加载着色器的内容 - 我想您是在代码中的某个地方执行此操作?

    此外,在您的设置代码中,您正在创建帧缓冲区。 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 一样——在drawRect: 中有一个普通的UIView,你只需告诉它应该绘制什么,例如使用核心图形函数——然后你不会告诉它呈现自己。

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

    【讨论】:

      【解决方案2】:

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

      Steve Zissou's Programming Blog

      【讨论】:

        【解决方案3】:

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

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

        }

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

        【讨论】:

        • 我以前见过并尝试过这个,但是 xcode 拒绝编译。与消息。 'EAGLContext' 例如消息没有声明带有选择器'presentRenderbuffer:'的方法
        • 导入 QuartzCore 修复了我的构建问题,但我仍然无法绘制任何东西。
        • 在 GLKit 中,GLKView 将自动呈现自己并在每个渲染周期结束时丢弃不需要的渲染缓冲区。这不是代码的问题。详情见我的回答。
        【解决方案4】:

        我想你忘了打电话

        [self.effect prepareToDraw];
        

        就在之前

        glDrawArrays(GL_POINTS, 0, 4);
        

        【讨论】:

          【解决方案5】:

          由于 GLKit 模仿 OpenGL ES 1.1 渲染管道,您不需要包含例程来定义着色器。如果您希望使用 OpenGL ES1.1 等基本管道,GLKit 实际上会为您完成此操作

          【讨论】:

          • 这是不正确的。如果使用 OpenGL ES 2.0(用于默认的 OpenGL ES 模板)和 GLKView,您仍然需要提供着色器。一些默认效果是可用的,但您必须在 GLKit 中使用 GLKBaseEffect 等设置它们。上面的代码中都没有。
          • 是的,在某种意义上你是对的,我们将使用 GLKit 的 GLKBaseEffect 设置这些参数。我的观点是“如果您希望使用基本管道,您不必明确地编写着色器。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-24
          • 2023-03-13
          • 1970-01-01
          • 1970-01-01
          • 2016-10-16
          相关资源
          最近更新 更多