Sign in to follow this  
Jayinmn

Render only the Depth Buffer

Recommended Posts

Jayinmn    100
Hey all, Is there anyway to render a particular scene, such that the depth buffer is visualize. From a normal scene like this: to a scene like this based on its depth buffer: I wanted to show the depth buffer of a particular scene side by side with the original render. Thanks all. Image source from Wikipedia

Share this post


Link to post
Share on other sites
Ignifex    520
In GLSL, just do a regular tex2D texture lookup with a depth texture. Depending on your setting of GL_DEPTH_TEXTURE_MODE_ARB, this should result in some color value. Try using glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY); for your depth texture.

Getting your depth buffer to a texture can be done using an FBO with a depth attachment or, alternatively and slower, using glCopyTexSubImage2D.

Share this post


Link to post
Share on other sites
Jayinmn    100
Thanks Ignifex,

I manage to try out getting the depth data from the back buffer using the glCopyTexImage2D method.

Below are the codes that I've use to do this.

//screenwidth and screenheight are the width and height of the window respectively.

GLuint i;
unsigned int* data;

glGenTextures(1, &(i));
glBindTexture(GL_TEXTURE_2D,i);

data = (unsigned int*)new GLuint[((512 * 512)* 4 * sizeof(unsigned int))];
ZeroMemory(data,((512 * 512)* 4 * sizeof(unsigned int)));
glTexImage2D(GL_TEXTURE_2D, 0, 4, 512, 512, 0,GL_DEPTH_COMPONENT,GL_UNSIGNED_BYTE, data);
delete []data;

glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT , 0,0,screenwidth,screenheight, 0);

//Drawing the texture i.


Thing is, what I saw on the screen was a white 512 by 512 square, while I've a scene at the back of this. I'm guessing its because the function returns a texture with values clamp between 0 to 1? I'm not sure though.

Share this post


Link to post
Share on other sites
Ignifex    520
White quads for textures generally means the texture could not be read or the texture id is invalid. In the case of depth textures, the values might also be very close to 1 though. Try playing around with your z-near value in your projection matrix. Setting it further away will get you depth values closer to 0.

There is something about your code you might want to take a look at.
You are creating a 0 filled array of pixeldata. Instead of passing this to OpenGL, you might want to try using a null pointer. This will also internally allocate the texture data, but leaves the data undefined. Then, once you have some depth values in your buffer, you can call glCopyTexSubImage2D (note the Sub) on the whole texture to update all the values. This operation will not reallocate anything. In the end, it saves reallocation and data transfer to the GPU.

If setting your z-near to a higher value doesn't give you more grey-ish tones, then the problem is likely with your texture creation and the fact that it is a depth texture. In that case you might want to try creating a GL_INTENSITY texture instead, skip your copying of the depth, and check to see what the output is.

Share this post


Link to post
Share on other sites
dpadam450    2357
glColor3f(1.0,1.0,1.0);
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, m_shadowMap);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glDisable(GL_DEPTH_TEST);
glBegin(GL_QUADS);
glTexCoord2f(0,1);glVertex3f(-1.0f, 1.0f, -.2);
glTexCoord2f(0,0);glVertex3f(-1.0f, -1.0f, -.2);
glTexCoord2f(1,0);glVertex3f(1.0f, -1.0f, -.2);
glTexCoord2f(1,1);glVertex3f(1.0f, 1.0f, -.2);
glEnd();

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

Just use the texture parameters as such. You wont need to use a shader.

Share this post


Link to post
Share on other sites
Jayinmn    100
I changed the code a little and tested whether if the texture creation was working.
When I use GL_RGB instead of GL_INTENSITY or GL_DEPTH_COMPONENT
and using the glCopyTexImage2D (without the sub), it
draws what is in the background, which works.
But when I replaced it with the one with subs. Its black.

Then I tried replacing GL_RGB with GL_DEPTH_COMPONENT in glTexImage2D
and then, still using the glCopyTexImage2D(without sub) with GL_RGB replaced with GL_DEPTH_COMPONENT.
A gray texture is observed.

Hmmm?


//screenwidth and screenheight are the width and height of the window respectively.

GLuint i;
GLubyte* data=NULL;

glGenTextures(1, &(i));
glBindTexture(GL_TEXTURE_2D,i);

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_RGB, 512, 512, 0,GL_RGB, GL_UNSIGNED_BYTE, data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY , 512, 512, 0,GL_INTENSITY , GL_UNSIGNED_BYTE, data);

//glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, screenwidth,screenheight), 0)
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0,0 , 0,0,screenwidth,screenheight);

//Drawing the texture i.

Share this post


Link to post
Share on other sites
Erik Rufelt    5901
Do you actually need to put these values in a texture for later use, or do you just want to display a gray-scale image fading from black to white based on distance?

Share this post


Link to post
Share on other sites
Erik Rufelt    5901
There's an easy way to do this with texture coordinate generation. OpenGL can automatically generate texture-coords from position, and if you create a 1D texture fading from black to white, and tell OpenGL to generate the texture coordinate in that texture depending on Z distance, and render your scene with only that texture bound, u get an image where color is based on distance.

Set it up something like this:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// -1/100 is because the far-plane is at 100, use the actual far-plane value
GLfloat splane[4] = {0.0f, 0.0f, -1.0f/100.0f, 0.0f};
glTexGenfv(GL_S, GL_EYE_PLANE, splane);
glEnable(GL_TEXTURE_GEN_S);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);

glEnable(GL_TEXTURE_1D);
glBindTexture(GL_TEXTURE_1D, fadeTextureId);


// Now set up camera etc. and draw model, and it automatically will fade on distance



I can post a complete example if you want.

Share this post


Link to post
Share on other sites
Erik Rufelt    5901
What OS/compiler are you on?

This is for Windows, should compile in VC++ in an empty Windows project.

#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glext.h>

#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glu32.lib")


LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);


// Main
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
// Register windowclass
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(wc));
wc.cbSize = sizeof(wc);
wc.lpszClassName = TEXT("MyClass");
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wc);

// Create window
HWND hWnd = CreateWindowEx(
0,
wc.lpszClassName,
TEXT("OpenGL Depth Display"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);

// Get DC
HDC hDC = GetDC(hWnd);

// Pixelformat
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags =
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER |
PFD_SUPPORT_COMPOSITION;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;

int pf = ChoosePixelFormat(hDC, &pfd);

SetPixelFormat(hDC, pf, &pfd);

// OpenGL context
HGLRC hGLRC = wglCreateContext(hDC);

wglMakeCurrent(hDC, hGLRC);

// Create a 1D texture fading from black to white
GLuint fadeTextureId;
glGenTextures(1, &fadeTextureId);
glBindTexture(GL_TEXTURE_1D, fadeTextureId);

glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

unsigned int fadeTextureData[256];
for(int i=0;i<256;++i)
fadeTextureData[i] = 0xff000000 | (i << 16) | (i << 8) | i;
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, fadeTextureData);

// Main loop
ShowWindow(hWnd, nCmdShow);

while(true) {
MSG msg;
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
if(msg.message == WM_QUIT)
break;
else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else {
// Clear
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_DEPTH_TEST);

// Reset modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// Set texture coord generation plane based on Z
// Takes current matrix into account, so do it now with identity set
// -1/100 is because the far-plane is at 100, use the actual far-plane value
GLfloat splane[4] = {0.0f, 0.0f, -1.0f/100.0f, 0.0f};
glTexGenfv(GL_S, GL_EYE_PLANE, splane);

// Enable texture-coord generation. The texture S coordinate will be set to
// the same relative position in [0, 1] as the Z-value is in [0, far-plane]
// Since the 1D-texture fades from black to white, colors will fade from black
// to white based on distance when using this texture with tex-coord generation
glEnable(GL_TEXTURE_1D);
glEnable(GL_TEXTURE_GEN_S);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);

// Camera
glRotatef(20.0f, 1.0f, 0.0f, 0.0f);
glRotatef(-20.0f, 0.0f, 1.0f, 0.0f);
glTranslatef(-10.0f, -10.0f, -20.0f);

// Draw test cubes
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);

const GLfloat cubeVertices[] = {
-1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
};
const int cubeIndices[] = {0, 1, 3, 2, 6, 1, 5, 0, 4, 3, 7, 6, 4, 5};

glTranslatef(0.0f, 0.0f, -80.0f);
for(int cubeIndex=0;cubeIndex<20;++cubeIndex) {
glTranslatef(0.0f, 0.0f, 5.0f);

glBegin(GL_TRIANGLE_STRIP);
for(int i=0;i<14;++i)
glVertex3fv(cubeVertices+cubeIndices[i]*3);
glEnd();
}

// Swap
SwapBuffers(hDC);
}
}

glDeleteTextures(1, &fadeTextureId);
wglDeleteContext(hGLRC);

UnregisterClass(wc.lpszClassName, hInstance);

return 0;
}

// Window procedure
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {
case WM_DESTROY:
PostQuitMessage(0);
break;

case WM_SIZE:
glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (GLdouble)LOWORD(lParam) / HIWORD(lParam), 1.0, 100.0);
break;
}

return DefWindowProc(hWnd, msg, wParam, lParam);
}

Share this post


Link to post
Share on other sites
nycsamurai    100
I'm having the same issue.

Doing


glutSolidTeapot(4);

glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexImage2D(GL_TEXTURE_2D, 0, 3,
WIDTH, HEIGHT, 0,
GL_RGB, GL_UNSIGNED_BYTE, 0);

glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, WIDTH, HEIGHT, 0);

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -17);

//render quad with texture, etc



results in a solid gray teapot. It's the same color no matter how far the teapot is and you can't see any features. Here is an image:

Share this post


Link to post
Share on other sites
nycsamurai    100
Actually I just read ignifex's reply and I set the near and far clip planes from 1 and 100 to 12 and 20 respectively

code:
gluPerspective( 60.0, ratio, 12.0, 20.0 );

which resulted in this nice render:



@Jayinmn I think your problem has to do with the near and far clip planes cause you mentioned getting a gray texture. That's probably from the z buffer inaccuracies issue I had.

@Erik Rufelt Your code produced some funky results. The teapot ended up looking all striped and crazy.

Share this post


Link to post
Share on other sites
Jayinmn    100
@nycsamurai Hey, great progress you've got there. You mind showing me your texture creation code too? I've tried your method there and still my output was still a solid gray box, I did decrease the near and the far range. Not even a slight hint of bands in the output.

I'm guessing the texture creation was the problem.
Below are my codes. I'm not sure where I've gone wrong.


//This is my texture creation part.
GLuint texid;
GLubyte *imageData=NULL;
glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_2D, texid);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 256, 256, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE,imageData);


//The part where I drew the depth image.
//My screen resolution is 800x600.
glBindTexture(GL_TEXTURE_2D, texid);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexImage2D(GL_TEXTURE_2D, 0, 3,800, 600, 0,GL_RGB, GL_UNSIGNED_BYTE, 0);

glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, 800, 600, 0);


My resulting scene.


If I changed GL_DEPTH_COMPONENT in glCopyTexImage2D to GL_RGB, my output will be the scene itself, which means the texture creation shouldn't be a problem. I'm not sure though.

I'm using Glut by the way. Could it be some buffers that I didn't enable that causes my depth not showing? I did include this line.

glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ACCUM | GLUT_MULTISAMPLE | GLUT_STENCIL);

Share this post


Link to post
Share on other sites
Erik Rufelt    5901
Quote:
Original post by nycsamurai
@Erik Rufelt Your code produced some funky results. The teapot ended up looking all striped and crazy.


I see, strange, works fine for me. Perhaps you have 2D texturing or lighting or some other render states enabled?
The point of that method is to draw to the color-buffer based on distance, and it doesn't actually use the depth-buffer. Therefore all render-states must be set to only have 1D texturing enabled.

It's probably better to get the texture from the depth-buffer, just found it a simple method. =)
Looks like this for me:

Share this post


Link to post
Share on other sites
nycsamurai    100
Here it is:


//creation:
GLuint texture[2];

glGenTextures(2, texture);

//here is my draw function

static void draw_screen(float time_elapsed)
{
//clear screen
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

//select modelview matrix
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

glTranslatef(0.0, 0.0, -17);

glColor4f(1.0, 0.0, 1.0, 1.0);

glutSolidTeapot(4);

glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexImage2D(GL_TEXTURE_2D, 0, 3,
WIDTH, HEIGHT, 0,
GL_RGB, GL_UNSIGNED_BYTE, 0);

glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, WIDTH, HEIGHT, 0);


//clear screen
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -17);

glColor4f(1.0, 1.0, 1.0, 1.0);

glTexParameteri( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE );
glBegin(GL_QUADS);
glNormal3f(0.0, 0.0, 1.0);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-10.0f,-10.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 10.0f,-10.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 10.0f, 10.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-10.0f, 10.0f, 0.0f);
glEnd();


glFlush();


SDL_GL_SwapBuffers();

}

//and here is my setup code:

static void setup_opengl( int width, int height )
{
//load depth map
if(!load_textures()) exit(2);
//generate_image();
float ratio = (float) width / (float) height;

//clear color
glClearColor( 1.0, 1.0, 1.0, 1.0 );

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

//set up viewport
glViewport( 0, 0, width, height );

glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);

glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
//set up projection matrix
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
gluPerspective( 60.0, ratio, 12.0, 20.0 );

}



Dont' know about GLUT, I'm using SDL for my windowing with the following settings:

//set attributes
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

flags = SDL_OPENGL | SDL_RESIZABLE;

Are you calling glClear(GL_DEPTH_BUFFER_BIT) before you draw your scene?

@Erik Rufelt Yeah I did have texturing enabled, sorry, disregard what I said about it.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this