【问题标题】:Render the depth buffer in OpenGL without shaders在没有着色器的情况下在 OpenGL 中渲染深度缓冲区
【发布时间】:2014-08-07 15:26:04
【问题描述】:

我有以下 C++ OpenGL 代码,用于渲染场景中像素的 RGB 值:

glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, _windowWidth, _windowHeight);

glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);

glMatrixMode( GL_PROJECTION );
glLoadIdentity();

float aspectRatio = float(_windowWidth) / float(_windowHeight);
gluPerspective(60.0f, aspectRatio, 0.1f, 1000.0f);

glMatrixMode(GL_MODELVIEW);
_camera.Update();
glLoadMatrixf(_camera.Matrix()[0]);

_scene.Render();

glutSwapBuffers();

但是,我想渲染场景的深度缓冲区,即每个像素值都是相机前面的 z 距离。

也就是说,我目前正在获取顶部图像,但我想要底部图像(图片来自here):

我应该怎么做?我不认为我在使用着色器(是吗?)——here 给出的建议似乎表明这可能只有使用着色器才能实现。

还有this code,虽然这看起来也像是在使用着色器。修改我的代码以使用着色器有多难?

【问题讨论】:

  • 我不是图形专家,但那个球似乎是一个 phong-blinn,可能也是猴子和立方体。我相信你正在使用着色器,但重点是:我们如何提供帮助没有代码?

标签: c++ opengl depth-buffer


【解决方案1】:

您可以通过 glReadPixels()GL_DEPTH_COMPONENT 将深度缓冲区 slurp 到主机内存,然后将缓冲区重新上传为 GL_LUMINANCE 纹理:


#include <GL/glew.h>
#include <GL/glut.h>

#include <vector>
using namespace std;

void display()
{
    int w = glutGet( GLUT_WINDOW_WIDTH );
    int h = glutGet( GLUT_WINDOW_HEIGHT );

    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    double ar = w / static_cast< double >( h );
    const float zNear = 0.1;
    const float zFar = 10.0;
    gluPerspective( 60, ar, zNear, zFar );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    glTranslatef( 0, 0, -4 );

    static float angle = 0;
    angle += 3;

    glPushMatrix();
    glRotatef( angle, 0.1, 0.5, 0.3 );
    glColor3ub( 255, 0, 0 );
    glutSolidTeapot( 1 );
    glPopMatrix();

    vector< GLfloat > depth( w * h, 0 );
    glReadPixels( 0, 0, w, h, GL_DEPTH_COMPONENT, GL_FLOAT, &depth[0] ); 

    // linearize depth
    // http://www.geeks3d.com/20091216/geexlab-how-to-visualize-the-depth-buffer-in-glsl/
    for( size_t i = 0; i < depth.size(); ++i )
    {
        depth[i] = ( 2.0 * zNear ) / ( zFar + zNear - depth[i] * ( zFar - zNear ) );
    }

    static GLuint tex = 0;
    if( tex > 0 )
        glDeleteTextures( 1, &tex );
    glGenTextures(1, &tex);
    glBindTexture( GL_TEXTURE_2D, tex);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_FLOAT, &depth[0] );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho( 0, w, 0, h, -1, 1 );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glEnable( GL_TEXTURE_2D );
    glColor3ub( 255, 255, 255 );
    glScalef( 0.3, 0.3, 1 );
    glBegin( GL_QUADS );
    glTexCoord2i( 0, 0 );
    glVertex2i( 0, 0 );
    glTexCoord2i( 1, 0 );
    glVertex2i( w, 0 );
    glTexCoord2i( 1, 1 );
    glVertex2i( w, h);
    glTexCoord2i( 0, 1 );
    glVertex2i( 0, h );
    glEnd();
    glDisable( GL_TEXTURE_2D );

    glutSwapBuffers();
}

void timer( int value )
{
    glutPostRedisplay();
    glutTimerFunc( 16, timer, 0 );
}

int main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
    glutInitWindowSize( 600, 600 );
    glutCreateWindow( "GLUT" );
    glewInit();
    glutDisplayFunc( display );
    glutTimerFunc( 0, timer, 0 );
    glEnable( GL_DEPTH_TEST );
    glutMainLoop();
    return 0;
}

到 CPU 的往返并不是非常快(尤其是在主机端线性化的情况下)。您可以使用 PBOs 使其成为 GPU 到 GPU 的传输,但您会失去线性化。

【讨论】:

    【解决方案2】:

    您可以使用Framebuffer Object (fbo) 将深度值渲染到纹理中。然后在第二个渲染过程中在整个视口上绘制一个四边形并在其上应用深度纹理。

    或者您可以编写一个片段着色器,根据片段的深度输出片段颜色,这可以单次渲染。

    请参阅here 一些示例。您可以通过搜索“fbo”找到更多信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-18
      • 2016-11-27
      • 2016-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多