2014-12-25 4 views
0

У меня есть приложение Java, использующее OpenGL 3 через JOGL, и пытаюсь реализовать мультисэмплинг. Я следую this учебному пособию, и до сих пор он работает, за исключением одной строки. Когда я звоню gl.glBackBuffer(GL3.GL_BACK), он генерирует ошибку GL_INVALID_OPERATION. Если программа продолжается, она, как представляется, обращается только к одному буферу, независимо от того, является ли она в настоящее время фронт- или обратным буфером, и переключается между желаемым выходом и данными мусора всякий раз, когда он перерисовывается.Почему glDrawBuffer генерирует GL_INVALID_OPERATION?

Согласно документации:

GL_INVALID_OPERATION генерируется, если фреймбуфера по умолчанию влияет и ни один из буферов не указано ЬиЕ существует.

GL_INVALID_OPERATION генерируется, если объект фреймбуфера затронут, а buf не равен GL_NONE или GL_COLOR_ATTACHMENT $ m $, где $ m $ - значение между 0 и GL_MAX_COLOR_ATTACHMENTS.

Я не думаю что-либо из них моя проблема, но один из них должен быть, потому что они являются единственными сценарии, в которых генерируется эта ошибка.

Вот соответствующий код:

@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); 

} 

Кроме того, я знаю, что я не сделал много очистки, но это не должно повлиять на эту проблему.

EDIT: В соответствии с просьбой, вот код, в котором создается GLCanvas:

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); 
+1

Является ли ваш стандартный фреймбуфер двойной буферизацией? Симптомы предполагают, что вы можете использовать один буферный фреймбуфер. –

+0

У вас даже есть двойной буферизированный фреймбуфер? Обратите внимание, что 'gl.glEnable (GL3.GL_DOUBLEBUFFER);' недопустимо и не будет создавать его. – derhass

+0

Я не уверен, но, похоже, он имеет двойную буферизацию, так как изображение переключается между желаемым результатом и данными мусора при его обновлении. Это означает, что должны быть два буфера, один из которых нарисован. Поправьте меня, если я ошибаюсь, я все еще учусь. – Ontonator

ответ

0

Я подозреваю, что ошибка происходит от более раннего вызова. По крайней мере, должно быть многочисленные ошибки, например, из glBindFramebuffer() вызова, непосредственно предшествующий glDrawBuffer() вызов:

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 не является объектом фреймбуфера. Он был создан как это:

gl.glGenBuffers(1, pointer, 0); 
multisampleFbo = pointer[0]; 

glGenBuffers() создает буфер объектов, не фреймбуфера объектов. Чтобы создать FBO, вам необходимо позвонить glGenFramebuffers():

gl.glGenFramebuffers(1, pointer, 0); 
multisampleFbo = pointer[0]; 
+0

Оказывается, это была проблема. Ошибка заключалась в отсутствии двойной буферизации, но она не оказывала никакого влияния на симптомы, которые я испытывал. – Ontonator

Смежные вопросы