JOGL 2.0, отрисовка буфера глубины в текстуру

Я пытаюсь реализовать простую технику наложения теней в JOGL 2.0, и у меня возникают проблемы с отображением значений глубины в текстуру. Возможно, я делаю это совершенно неправильно, но странно, что рендеринг сцены в цвете работает правильно. Я также нашел здесь, в stackoverflow, аналогичный вопрос, который задают здесь: Преобразовать буфер глубины в текстуру с помощью буфера кадра

и проблема решается звонком

gl.glDrawBuffer(GL2.GL_NONE);
gl.glReadBuffer(GL2.GL_NONE);

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

Визуализировать сцену в текстуру (RGBA)

Однако после попытки визуализации значений глубины он просто отображает белый цвет (и что-то, что вообще не соответствует сцене).

Проблема отображения значений глубины

---- ОБНОВЛЕННЫЙ код, который теперь работает нормально:

private void initializeFBO3(GL2 gl) {

//Create frame buffer
gl.glGenFramebuffers(1, frameBufferID, 0);
gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, frameBufferID[0]);

// ------------- Depth buffer texture --------------
gl.glGenTextures(1,depthBufferID,0);
gl.glBindTexture(GL2.GL_TEXTURE_2D, depthBufferID[0]);

gl.glTexImage2D(GL2.GL_TEXTURE_2D,          // target texture type
        0,                                  // mipmap LOD level
        GL2.GL_DEPTH_COMPONENT,         // internal pixel format
                                            //GL2.GL_DEPTH_COMPONENT
        shadowMapWidth,                     // width of generated image
        shadowMapHeight,                    // height of generated image
        0,                          // border of image
        GL2.GL_DEPTH_COMPONENT,     // external pixel format 
        GL2.GL_UNSIGNED_INT,        // datatype for each value
        null);  // buffer to store the texture in memory

//Some parameters
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);     


//Attach 2D texture to this FBO
gl.glFramebufferTexture2D(GL2.GL_FRAMEBUFFER,
        GL2.GL_DEPTH_ATTACHMENT,
        GL2.GL_TEXTURE_2D,
        depthBufferID[0],0);

gl.glBindTexture(GL2.GL_TEXTURE_2D, 0);

//Disable color buffer
//https://stackoverflow.com/questions/12546368/render-the-depth-buffer-into-a-texture-using-a-frame-buffer
gl.glDrawBuffer(GL2.GL_NONE);
gl.glReadBuffer(GL2.GL_NONE);

//Set pixels ((width*2)* (height*2))
//It has to have twice the size of shadowmap size
pixels = GLBuffers.newDirectByteBuffer(shadowMapWidth*shadowMapHeight*4);

//Set default frame buffer before doing the check
//http://www.opengl.org/wiki/FBO#Completeness_Rules
gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);

int status = gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER);

// Always check that our framebuffer is ok
if(gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER) != GL2.GL_FRAMEBUFFER_COMPLETE)
{
    System.err.println("Can not use FBO! Status error:" + status);
} 
}

public void display(GLAutoDrawable drawable) {
    GL2 gl = drawable.getGL().getGL2(); // get the OpenGL graphics context
    gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); 

    gl.glLoadIdentity();  // reset the model-view matrix

    //Render scene into Frame buffer first
    gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, frameBufferID[0]);
        renderSmallScene(gl);

    //Read pixels from buffer
    gl.glBindFramebuffer(GL2.GL_READ_FRAMEBUFFER, frameBufferID[0]);
    //Read pixels 
    gl.glReadPixels(0, 0, shadowMapWidth, shadowMapHeight, GL2.GL_DEPTH_COMPONENT , GL2.GL_UNSIGNED_BYTE, pixels);

    //Switch back to default FBO
    gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);
        drawSceneObjects(gl);


    //Draw pixels, format has to have only one 
    gl.glDrawPixels(shadowMapWidth, shadowMapHeight, GL2.GL_LUMINANCE , GL2.GL_UNSIGNED_BYTE, pixels);

   }

Рабочий результат:

Компонент глубины рендеринга


person jay    schedule 03.05.2013    source источник
comment
ты включил тест глубины? glEnable (GL_DEPTH_TEST)?   -  person Dirk    schedule 03.05.2013
comment
Да, проверка глубины включена.   -  person jay    schedule 05.05.2013


Ответы (1)


Вы должны прочитать об использовании FBO и OpenGL в целом.

В вашем коде вы создаете FBO и его вложения в каждом кадре. Это неправильно. Это огромные накладные расходы. Создавайте свои FBO при инициализации только один раз. Во-вторых, вы должны привязать FBO, чтобы рисовать в нем (или читать из него), иначе OpenGL будет рисовать FBO по умолчанию. Взгляните здесь и здесь

Итак, когда ваш FBO готов, вы выполняете рендеринг в нем следующим образом:

glBindFrameBuffer((GL_DRAW_FRAMEBUFFER, yourFbo);

   drawSceneObjects(gl);

glBindFrameBuffer((GL_READ_FRAMEBUFFER, yourFbo);

   readPixelsHere()


 glBindFrameBuffer((GL_FRAMEBUFFER, 0);///switch to default FBO

Фактически, в вашем случае, когда вы покидаете FBO, просто позвоните

    glBindFrameBuffer((GL_READ_FRAMEBUFFER, yourFbo);

после рисования вашей геометрии.

Кроме того, если вы не используете шейдеры, нет причин использовать текстуры в качестве вложений FBO. Вместо этого создайте буфер рендеринга.

person Michael IV    schedule 03.05.2013
comment
Мне потребовалось некоторое время, чтобы вернуться к этому. Я оптимизировал код по вашему совету, и теперь он намного лучше. Было несколько проблем, которые мне пришлось преодолеть, чтобы заставить работать текстуру карты глубины. Я обновлю свой вопрос и добавлю некоторые выводы. - person jay; 05.07.2013