I'm using an early 2011 MacBook Pro with macOS Sierra 10.12.4 and Intel HD Graphics 3000 512 MB, and I'm using JOGL. According to OS X 10.9 Core Profile OpenGL Information (unfortunately they don't have info for newer versions yet), my system supports 0, 16, or 24 bpp depth buffers and 0 or 8 bpp stencil buffers. Yet it seems like what actually works when I create a user framebuffer is anyone's guess:
- I can get it to work with a
GL_DEPTH_COMPONENT_32
render buffer. - I can't get it to work with a
GL_STENCIL_INDEX8
render buffer -- I always getGL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
orGL_FRAMEBUFFER_UNSUPPORTED
errors, regardless of whether I use a 16-, 24- or 32-bit depth buffer. - But I can get it to work with a
GL_DEPTH24_STENCIL8
render buffer.
I haven't been able to find a specific mention of GL_DEPTH24_STENCIL8
for OS X anywhere. I want to ensure my program will work on a wide variety of systems (Windows and Linux included, since it's a JOGL app), but it seems like all I can do is guess and check a variety of framebuffer configurations until I find one that works.
Is there really no better way to decide what framebuffer configuration to use? Are there sites with better documentation I just haven't found? Is it hard for vendors to document for some reason?
Code samples
Unsuccessful configuration int[] temps = new int[3];
this.width = width;
this.height = height;
gl3.glGenFramebuffers(1, temps, 0);
framebuffer = temps[0];
gl3.glBindFramebuffer(GL.GL_FRAMEBUFFER, framebuffer);
int numBuffers = 2;
if (desiredUseStencilBuffer) {
numBuffers++;
}
gl3.glGenRenderbuffers(numBuffers, temps, 0);
colorBuffer = temps[0];
depthBuffer = temps[1];
stencilBuffer = temps[2];
numSamples = targetNumSamples;
useStencilBuffer = desiredUseStencilBuffer;
if (numSamples > 1) {
gl3.glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL.GL_RGBA8,
width, height);
gl3.glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples,
GL.GL_DEPTH_COMPONENT24, width, height);
if (useStencilBuffer) {
gl3.glBindRenderbuffer(GL_RENDERBUFFER, stencilBuffer);
gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples,
GL3.GL_STENCIL_INDEX8, width, height);
}
} else {
gl3.glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_RGBA8, width, height);
gl3.glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT24, width, height);
if (useStencilBuffer) {
gl3.glBindRenderbuffer(GL_RENDERBUFFER, stencilBuffer);
gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL3.GL_STENCIL_INDEX8,
width, height);
}
}
gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL2ES3.GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depthBuffer);
if (useStencilBuffer) {
gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL2ES3.GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, stencilBuffer);
}
int status = gl3.glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch (status) {
case GL.GL_FRAMEBUFFER_COMPLETE:
break;
case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
throw new RuntimeException("An attachment could not be bound to frame buffer object!");
Successful configuration
int[] temps = new int[3];
this.width = width;
this.height = height;
gl3.glGenFramebuffers(1, temps, 0);
framebuffer = temps[0];
gl3.glBindFramebuffer(GL.GL_FRAMEBUFFER, framebuffer);
gl3.glGenRenderbuffers(2, temps, 0);
colorBuffer = temps[0];
depthBuffer = temps[1];
numSamples = targetNumSamples;
useStencilBuffer = desiredUseStencilBuffer;
if (numSamples > 1) {
gl3.glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL.GL_RGBA8,
width, height);
gl3.glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
if (useStencilBuffer) {
gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples,
GL.GL_DEPTH24_STENCIL8, width, height);
} else {
gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples,
GL.GL_DEPTH_COMPONENT32, width, height);
}
} else {
gl3.glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_RGBA8, width, height);
gl3.glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
if (useStencilBuffer) {
gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_DEPTH24_STENCIL8,
width, height);
} else {
gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT32,
width, height);
}
}
gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
if (useStencilBuffer) {
gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL2ES3.GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, depthBuffer);
} else {
gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depthBuffer);
}
int status = gl3.glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch (status) {
case GL.GL_FRAMEBUFFER_COMPLETE:
break;
case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
throw new RuntimeException("An attachment could not be bound to frame buffer object!");
...