2014-06-17 114 views
4

在OpenGL深度緩衝器我有這使得在一個場景中的像素的RGB值以下C++的OpenGL代碼:渲染無着色

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圖像):

enter image description here

我應該如何去了解呢?我不認爲我使用着色器(我是嗎?) - 給出的建議here似乎表明這可能只有着色器纔有可能。

也有this code,雖然這也看起來像使用着色器。修改我的代碼以使用着色器有多困難?

+0

我不是一個圖形專家,但那個球似乎是一個phong-blinn,可能也是猴子和立方體..我相信你正在使用着色器,但重點是:我們如何無需代碼就可以提供幫助? –

回答

5

可以發出聲音的深度緩存通過glReadPixels()GL_DEPTH_COMPONENT和到主機內存重新上傳緩衝區作爲GL_LUMINANCE質地:

screenshot

#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的傳輸,但您將失去線性化。

5

您可以使用Framebuffer Object (fbo)將深度值渲染到紋理中。然後在第二個渲染通道中在整個視口上繪製一個四邊形並在其上應用深度紋理。

或者你可以編寫一個片段着色器,它將根據它們的深度輸出片段顏色,這可以單次渲染。

請參閱here一些例子。你可以找到更多關於'fbo'的搜索。

相關問題