13

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.

Community
  • 1
  • 1
prplehaze
  • 459
  • 4
  • 15
  • 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 May 17 '12 at 13:00
  • 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 May 17 '12 at 15:03
  • 3
    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 May 17 '12 at 15:21
  • 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 May 17 '12 at 16:43
  • 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 May 19 '12 at 15:20

2 Answers2

18

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!

prplehaze
  • 459
  • 4
  • 15
  • 1
    I'm seeing the same thing -- unless the clearColor is all zeroes it won't actually erase the way I expect. Nice find! – John Stephen Dec 12 '12 at 20:19
  • 4
    this just makes the background black, not transparent – zurbergram Nov 21 '13 at 16:57
  • 1
    It will be black unless you explicitly set the view's layer opaque property to NO as shown above in the question's code snippet. – tlbrack Apr 25 '14 at 22:25
  • 6
    To be clear, you need: `opaque = NO`, `backgroundColor = [UIColor clearColor]` AND `glClearColor(0, 0, 0, 0)`. – Ephemera Apr 28 '14 at 09:29
  • 1
    Tried to set opaque to NO in IE builder but it didn't work - only in code. Does anyone know what may be the problem? – vir us Feb 17 '15 at 19:13
6

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.

Matthijs
  • 1,315
  • 12
  • 12