I have a Java application using OpenGL 3 through JOGL, and am trying to implement multi-sampling. I am following this tutorial, and so far, it seems to work, except for one line. When I call gl.glBackBuffer(GL3.GL_BACK)
, it generates a GL_INVALID_OPERATION
error. If the program continues, it appears to draw to only one buffer, regardless of whether it is currently the front- or the back-buffer, and switches between the desired output and garbage data whenever it is redrawn.
According to the documentation:
GL_INVALID_OPERATION is generated if the default framebuffer is affected and none of the buffers indicated by buf exists.
GL_INVALID_OPERATION is generated if a framebuffer object is affected and buf is not equal to GL_NONE or GL_COLOR_ATTACHMENT$m$, where $m$ is a value between 0 and GL_MAX_COLOR_ATTACHMENTS.
I don't think that either of these is my problem, but one of them must be, because they are the only scenarios in which that error is generated.
Here is the relevant code:
@Override
public void init(GLAutoDrawable drawable) {
GL3 gl = drawable.getGL().getGL3();
int[] pointer = new int[1];
sl = new ShaderLoader();
sl.loadShader(gl);
gl.glEnable(GL3.GL_DOUBLEBUFFER);
gl.glEnable(GL3.GL_MULTISAMPLE);
gl.glClearColor(1, 1, 1, 1);
gl.glGenTextures(1, pointer, 0);
multisampleTex = pointer[0];
gl.glGenBuffers(1, pointer, 0);
multisampleFbo = pointer[0];
gl.glGenRenderbuffers(1, pointer, 0);
multisampleRbo = pointer[0];
main.init(drawable);
gl.glGetIntegerv(GL3.GL_MAX_SAMPLES, pointer, 0);
System.out.println(pointer[0]);
}
@Override
public void dispose(GLAutoDrawable drawable) {
GL3 gl = drawable.getGL().getGL3();
sl.destroy(gl);
}
@Override
public void display(GLAutoDrawable drawable) {
// GL3 gl = new DebugGL3(drawable.getGL().getGL3());
GL3 gl = drawable.getGL().getGL3();
// drawable.setGL(gl);
gl.glClear(GL3.GL_COLOR_BUFFER_BIT);
gl.glBindFramebuffer(GL3.GL_FRAMEBUFFER, multisampleFbo);
gl.glClear(GL3.GL_COLOR_BUFFER_BIT);
main.render(drawable);
gl.glBindFramebuffer(GL3.GL_DRAW_FRAMEBUFFER, GL3.GL_NONE);
gl.glBindFramebuffer(GL3.GL_READ_FRAMEBUFFER, multisampleFbo);
checkGLError();
gl.glDrawBuffer(GL3.GL_BACK); // Throws GL_INVALID_OPERATION
checkGLError("OpenGL error at glDrawBuffer: 0x%h%n");
gl.glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
GL3.GL_COLOR_BUFFER_BIT, GL3.GL_NEAREST);
checkGLError();
}
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width,
int height) {
GL3 gl = drawable.getGL().getGL3();
this.width = width;
this.height = height;
updateMultisampleObjects(gl);
gl.glViewport(0, 0, width, height);
updatePMatrix();
}
private void updateMultisampleObjects(GL3 gl) {
gl.glBindTexture(GL3.GL_TEXTURE_2D_MULTISAMPLE, multisampleTex);
gl.glTexImage2DMultisample(GL3.GL_TEXTURE_2D_MULTISAMPLE,
NUM_OF_SAMPLES, GL3.GL_RGBA8, width, height, true);
gl.glBindFramebuffer(GL3.GL_FRAMEBUFFER, multisampleFbo);
gl.glFramebufferTexture2D(GL3.GL_FRAMEBUFFER, GL3.GL_COLOR_ATTACHMENT0,
GL3.GL_TEXTURE_2D_MULTISAMPLE, multisampleTex, 0);
gl.glBindRenderbuffer(GL3.GL_RENDERBUFFER, multisampleRbo);
gl.glRenderbufferStorageMultisample(GL3.GL_RENDERBUFFER,
NUM_OF_SAMPLES, GL3.GL_DEPTH24_STENCIL8, width, height);
gl.glFramebufferRenderbuffer(GL3.GL_FRAMEBUFFER,
GL3.GL_DEPTH_STENCIL_ATTACHMENT, GL3.GL_RENDERBUFFER,
multisampleRbo);
}
Also, I know I haven't done much cleanup, but that should not impact this problem.
EDIT: As requested, here is the code where the GLCanvas is created:
glp = GLProfile.get("GL3");
caps = new GLCapabilities(glp);
caps.setDoubleBuffered(true);
canvas = new GLCanvas(caps);
canvas.setPreferredSize(new Dimension(800, 600));
canvas.addGLEventListener(glListener);
frame.add(canvas);
I suspect that the error comes from an earlier call. At least there should be numerous errors, for example from the glBindFramebuffer()
call immediately preceding the glDrawBuffer()
call:
gl.glBindFramebuffer(GL3.GL_READ_FRAMEBUFFER, multisampleFbo);
checkGLError();
gl.glDrawBuffer(GL3.GL_BACK); // Throws GL_INVALID_OPERATION
checkGLError("OpenGL error at glDrawBuffer: 0x%h%n");
multisampleFbo
is not a framebuffer object. It was created like this:
gl.glGenBuffers(1, pointer, 0);
multisampleFbo = pointer[0];
glGenBuffers()
creates buffer objects, not framebuffer objects. To create an FBO, you need to call glGenFramebuffers()
:
gl.glGenFramebuffers(1, pointer, 0);
multisampleFbo = pointer[0];