Immediate rendering to GLKView

850 views Asked by At

Let's say I have some C++ code that renders stuff in OpenGL ES. This code has it's own render loop which is the same on all platforms. One of the things that are OS dependent and have to be written for each platform separately is creating a window that is linked to an OpenGL context that is then used for drawing. I used the GLKView placed as a subview to the UIWindow but from what I've noticed the first attempt to render results in nothing and all that is visible for a while is a black screen.

The next iterations of the loop however render just fine. To see the problem more clearly here is a minimal code that behaves similarly:

EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
assert(context);

GLKView *glView = [[GLKView alloc] initWithFrame:[[self window] frame] context:context];
[[self window] addSubview:glView];

[EAGLContext setCurrentContext:context];

prepareOpengl();
drawTriangle(); //GL_INVALID_FRAMEBUFFER_OPERATION

[self performSelector:@selector(drawTriangleWithContext:) withObject:context afterDelay:1.0]; //nice triangle

The prepareOpengl() function creates the buffers for vertices and whatnot and the drawTraingle() clears the buffers and draws a traingle. The first call results in GL_INVALID_FRAMEBUFFER_OPERATION and the one called by performSelector:afterDelay: draws just fine. This probably means that the GLKView defers the creation of it's renderbuffer.

I would really like to not have to wait for the first rendering and instead be able to draw immediately to the created context. Here is the whole demo project that shows the issue.

1

There are 1 answers

0
riodoro1 On

I think I got it. The trick is to explicitly call bindDrawable on the GLKView after creating it. This in turn forces the creation of the renderbuffer.

This is how it should be:

GLKView *glView = [[GLKView alloc] initWithFrame:[[self window] frame] context:context];
[glView bindDrawable];
[[self window] addSubview:glView];

[EAGLContext setCurrentContext:context]
prepareOpengl();
drawTriangle();
[context presentRenderbuffer:GL_RENDERBUFFER];