Ios 使用GLKit绘图

Ios 使用GLKit绘图,ios,opengl-es,ios5,glkit,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

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

我还没有使用glkit,但您似乎在使用它之后没有显示帧缓冲区。 在iOs下使用OpenGL ES 2但没有GLKit的应用程序中,我使用在渲染循环结束时调用以下代码

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


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

我在您的安装代码中没有看到任何加载着色器的内容-我猜您是在代码的某个地方这样做的

此外,在设置代码中,您正在创建帧缓冲区。
GLKView
可以为您执行此操作-实际上,您正在告诉视图在
viewDidLoad
方法中使用24位深度缓冲区:

GLKView *view = (GLKView *)self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
因此,上面的
glkView:drawInRect:
代码所做的是:“绑定我手工制作的帧缓冲区,并在其中绘制一些内容”。然后,
GLKView
会自动显示,但没有任何内容被绘制到其中,您只绘制到了手工制作的缓冲区中。除非在渲染到纹理等任务中需要其他帧缓冲区对象,否则根本不需要关心帧缓冲区的创建-让
GLKView
自动完成

setupGL
方法中(或在设置中的任何位置)应该做的是创建顶点数组对象,以记住执行绘制所需的openGL状态。然后,在
glkView:drawInRect:
方法中,您应该:

  • 使用
    glClear()
    清除
  • 启用您的程序
  • 绑定顶点数组对象(或者,如果未使用VAO,则启用 适当的顶点属性(指针)
  • 使用
    glDrawArrays()
    glDrawElements()
    绘制数据
  • GLKView
    自动将其上下文设置为当前,并在每个绘制周期之前绑定其帧缓冲区对象

    也许试着把
    GLKView
    想象成一个常规的
    UIView
    。它在幕后为您处理大部分openGL代码,让您只需告诉它需要绘制什么。它的
    drawRect:
    代码与常规的
    UIView
    -在
    drawRect:
    中有一个常规的
    UIView
    ,您只需告诉它应该绘制什么,例如使用核心图形函数-然后您就不会告诉它呈现自己


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

    我想您忘了调用

    [self.effect prepareToDraw];
    
    就在之前

    glDrawArrays(GL_POINTS, 0, 4);
    

    由于GLKit模仿OpenGL ES 1.1渲染管道,因此不需要包含用于定义着色器的例程。如果您希望使用OpenGL ES1.1之类的基本管道,GLKit实际上是为您做这件事的。我发表了一篇关于如何使用GLKit设置基本项目模板的帖子。你可以在这里找到它:


    我以前见过并尝试过这种方法,但xcode拒绝编译。带着这个信息。”EAGLContext“例如,消息未声明带有选择器“presentRenderbuffer:”的方法导入QuartzCore修复了我的构建问题,但我仍然无法绘制任何内容。在GLKit中,GLKView将自动显示自己,并在每个渲染周期结束时丢弃不需要的RenderBuffer。这不是代码的问题。有关详细信息,请参阅我的答案。这是不正确的。如果使用OpenGL ES 2.0(用于默认OpenGL ES模板)和GLKView,则仍然需要提供着色器。有些默认效果是可用的,但您必须使用GLKBaseEffect等在GLKit中设置它们。以上代码中没有这些内容。是的,从某种意义上说,您是对的,我们将使用GLKit的GLKBaseEffect设置这些参数。我的观点是,“如果希望使用基本管道,则不必显式地编写着色器。