13
votes

Is there a way to make the background of a GLKView transparent? I've tried the solution here but that isn't working for me.

*EDIT: I need help making it completely transparent. The background is mostly white and gray, but I just tested it with more vibrant colors, and sure enough you can vaguely see through to the background. Any ideas why it would be partly transparent but not fully with the following code?

Here's the code in my view controller:

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.context = [[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2] autorelease];
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.view.layer;
    eaglLayer.opaque = NO;

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

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

    view.backgroundColor = [UIColor clearColor];

    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;

    [self setupGL];
}

- (void)setupGL
{
    [EAGLContext setCurrentContext:self.context];

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

    glDisable(GL_DEPTH_TEST);

    glGenVertexArraysOES(1, &_vertexArray);
    glBindVertexArrayOES(_vertexArray);

    glGenBuffers(1, &_vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_DYNAMIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, VERTEX_POS_DATA_SIZE, GL_FLOAT, GL_FALSE, VERTEX_DATA_SIZE * sizeof(GLfloat), BUFFER_OFFSET(0));

    glEnableVertexAttribArray(GLKVertexAttribColor);
    glVertexAttribPointer(GLKVertexAttribColor, VERTEX_COLOR_DATA_SIZE, GL_FLOAT, GL_FLOAT, VERTEX_DATA_SIZE * sizeof(GLfloat), BUFFER_OFFSET(VERTEX_POS_DATA_SIZE * sizeof(GLfloat)));    

    glLineWidth(10.0);
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    if (!needsRedraw) return;
    needsRedraw = NO;

    glClearColor(0.65f, 0.65f, 0.65f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    [self.effect prepareToDraw];

    glDrawArrays(GL_LINE_STRIP, 0, vertexCount);    
}

I've tried setting the backgroundColor of the to [UIColor clearColor] and setting the eaglLayer to not be opaque. Heck, I even tried setting the backgroundColor of the eaglLayer to CGColorRef with 0 opacity.

2
Are you sure you're not filling the scene background at the time of painting the scene? I know it sounds goofy but I've seen that happen to people who were trying to do the same thing.mprivat
I'm completely new with this, so it's possible, but I'm 99% sure I'm only drawing the one line strip. The clear color is set to have an alpha of 0.0f, but I've even noticed if I try to draw vertices whose color attributes set the alpha to 0.0f, they still draw. Does that make any sense / help you brainstorm?prplehaze
One comment I might make here is that I'd avoid using a non-opaque OpenGL ES hosting view if you can. This will dramatically slow down your rendering compared to a normal opaque OpenGL ES view. If you can, pull the background content you want to render over within your OpenGL ES scene and render all that to an opaque view.Brad Larson♦
Brad, I've really tried to be creative to avoid this, but alas I can't think of a way around transparency. I've got a view with dynamic content the user can drag and drop upon which I need this GLKView to allow them to draw. Even taking a screen shot so to speak and using that as the background won't work because once they toggle drawing off, the drawing needs to stay, but the content below is dynamic. I'm only rendering lines, so it's not heavy lifting in terms of rendering. Any ideas? Ironically, it was, in fact, your talks at cocoaconf that made me decide to try OpenGL. No pressure :)prplehaze
Yeah, it might be your only choice here. Sometimes, it's unavoidable. For a 2-D drawing on top of a user interface element, you might not even notice the slowdown. It's only when you get into more intense rendering that this becomes apparent. Worst case, try it out and see. It's just something to watch out for when profiling this.Brad Larson♦

2 Answers

18
votes

Well, I didn't think this would matter because the alpha was already at 0.0f, but when I changed

glClearColor(0.65f, 0.65f, 0.65f, 0.0f);

to

glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

it made the background perfectly transparent.

Thanks everyone for your suggestions and help!

6
votes

For me it helped to make the view not opaque:

view.opaque = NO

in addition to the glClearColor call with transparancy of course.

A transparancy of 0.5f perfectly blends the background over another UIImageview with half opacity.