Fixed Pipeline and Shadow Mapping

Started by
13 comments, last by Geri 12 years, 8 months ago
Hi,

i am working on a OpenGL project and have problems with my shadows. They are not displayed and i dont know why. The code, which i use, is from http://www.paulsproj...ls/smt/smt.html .
The idea is:
I draw the scene three times. In the first draw, i write the depth values in a FBO from the lightview direction.
In the second draw, i draw the scene normal with (0.2, 0.2, 0.2, 1) light intensity.
In the third step i draw the scene with bright light and make a comparison with the depth values. Here is the code: The first part is my shadow class and the second part my viewer class. In the viewer class all draws etc. are handled.


void Shadows::generateShadowBuffer()
{
shadowMapSize = 512;

// Init texture
glGenTextures(1, &_depthTextureId);
glBindTexture(GL_TEXTURE_2D, _depthTextureId);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_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, GL_DEPTH_COMPONENT24, shadowMapSize, shadowMapSize,
0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glBindTexture(GL_TEXTURE_2D, 0);

// Init buffer
glGenFramebuffersEXT(1, &_fboId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fboId);

// attach the texture to FBO color attachment point
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_TEXTURE_2D, _depthTextureId, 0);

// Instruct openGL that we won't bind a color texture with the currently binded FBO
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);

// check FBO status
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
printf("Buffer init wasnt correct.\n");

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

// Check for Error
GLenum error = glGetError();
if(error != 0)
{
printf("Error occured in Shadows::generateShadowBuffer: %d\n", error);
if(GL_STACK_OVERFLOW == error)
printf("GL_STACK_OVERFLOW\n");
if(GL_STACK_UNDERFLOW == error)
printf("GL_STACK_UNDERFLOW\n");
}
}

// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void Shadows::drawFromLight(Vector lightPosition)
{
// Activate Buffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fboId);

// clear buffers
glClear(GL_DEPTH_BUFFER_BIT);
glColorMask(0, 0, 0, 0);

// Init matrices
glPushMatrix();
glLoadIdentity();
gluPerspective(60.0f, 1.0f, 0.1f, lightPosition.y + 10);
glGetFloatv(GL_MODELVIEW_MATRIX, _projectionMatrix);
glPopMatrix();

glPushMatrix();
glLoadIdentity();
gluLookAt(lightPosition.x, lightPosition.y, lightPosition.z,
lightPosition.x, 0, lightPosition.z,
0, 0, 1.0f);
glGetFloatv(GL_MODELVIEW_MATRIX, _lightviewMatrix);
glPopMatrix();

//Draw from the light's point of view
glViewport(0, 0, shadowMapSize, shadowMapSize);

glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadMatrixf(_projectionMatrix);

glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(_lightviewMatrix);

glPolygonOffset(8.0f, 1.1f);
glEnable(GL_POLYGON_OFFSET_FILL);

// Check for Error
GLenum error = glGetError();
if(error != 0)
{
printf("Error occured in Shadows::drawFromLight: %d\n", error);
if(GL_STACK_OVERFLOW == error)
printf("GL_STACK_OVERFLOW\n");
if(GL_STACK_UNDERFLOW == error)
printf("GL_STACK_UNDERFLOW\n");
}
}

// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void Shadows::drawWithShadows(int width, int height, Vector position, Vector direction, Vector up, float yPos)
{
// Deactivate buffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
/*glPopAttrib();
glBindTexture(GL_TEXTURE_2D, _depthTextureId);
GLfloat* buffer = new GLfloat[shadowMapSize * shadowMapSize];
glReadPixels(0, 0, shadowMapSize, shadowMapSize, GL_DEPTH_COMPONENT, GL_FLOAT, buffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, shadowMapSize, shadowMapSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, buffer);

std::vector<float> pixbuf;
for(int i = 0; i < shadowMapSize*shadowMapSize; i++)
pixbuf.push_back(buffer);
for(int i = 0; i < pixbuf.size(); i++)
if(pixbuf != 1)
{
std::cout << pixbuf << std::endl;
}
delete[] buffer;*/

//Clear depth buffer

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Enable colorwriting
glColorMask(1, 1, 1, 1);

//reset viewport
glViewport(0, 0, width, height);

//Reset projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();

//Draw from camera's point of view
glMatrixMode(GL_MODELVIEW);
//glLoadMatrixf(viewMatrix);
glLoadIdentity();
gluLookAt(position.x, position.y, position.z,
direction.x, -direction.y, direction.z,
up.x, up.y, up.z);
glTranslatef(0, yPos, 0);

// Check for Error
GLenum error = glGetError();
if(error != 0)
{
printf("Error occured in Shadows::drawWithShadows: %d\n", error);
if(GL_STACK_OVERFLOW == error)
printf("GL_STACK_OVERFLOW\n");
if(GL_STACK_UNDERFLOW == error)
printf("GL_STACK_UNDERFLOW\n");
if(GL_INVALID_OPERATION == error)
printf("GL_INVALID_OPERATION\n");
if(GL_INVALID_VALUE == error)
printf("GL_INVALID_VALUE\n");
}
}

// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void Shadows::drawWithoutShadows()
{
//glActiveTexture(GL_TEXTURE7);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _depthTextureId);

// Get matrix


GLfloat bias[16] = {
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0};

// concatinating all matrice into one.
MyMatrix dummy;
dummy = MyMatrix(bias) * MyMatrix(_projectionMatrix) * MyMatrix(_lightviewMatrix);

const GLfloat first[4] = {dummy[0], dummy[4], dummy[8], dummy[12]};
const GLfloat second[4] = {dummy[1], dummy[5], dummy[9], dummy[13]};
const GLfloat third[4] = {dummy[2], dummy[6], dummy[10], dummy[14]};
const GLfloat fourth[4] = {dummy[3], dummy[7], dummy[11], dummy[15]};

//Set up tex coord generation - all 4 coordinates required
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGenfv(GL_S, GL_EYE_PLANE, first);
glEnable(GL_TEXTURE_GEN_S);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGenfv(GL_T, GL_EYE_PLANE, second);
glEnable(GL_TEXTURE_GEN_T);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGenfv(GL_R, GL_EYE_PLANE, third);
glEnable(GL_TEXTURE_GEN_R);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGenfv(GL_Q, GL_EYE_PLANE, fourth);
glEnable(GL_TEXTURE_GEN_Q);

//Use SGIX_shadow comparison
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_SGIX, true);

glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);

//glBlendEquationEXT(GL_MAX_EXT);
//glEnable(GL_BLEND);
//Set alpha test to discard false comparisons
glAlphaFunc(GL_GEQUAL, 0.99f);
glEnable(GL_ALPHA_TEST);

// Check for Error
GLenum error = glGetError();
if(error != 0)
{
printf("Error occured in Shadows::drawWithoutShadows: %d\n", error);
error = 0;
}
}



// FPS
frame++;
time=glutGet(GLUT_ELAPSED_TIME);

if (time - timebase > 1000) {
printf("FPS:%4.2f\n", frame*1000.0/(time-timebase));
timebase = time;
frame = 0;
}

// Reset to draw again
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);

// ++ ---------------------------------------------------------------------------------------------------- ++ //
// First step for shadows
glPushAttrib(GL_ALL_ATTRIB_BITS);
_shadow->drawFromLight(_sun->getPosition());

// Draw the drawables the first time
for(std::list<Drawable*>::iterator it = _drawables.begin(); it != _drawables.end(); it++)
{
(*it)->draw();
}


// ++ ---------------------------------------------------------------------------------------------------- ++ //
// Second step for shadows
_shadow->drawWithShadows(_windowWidth, _windowHeight, _cPosition , _cView, _cUp, _positionY);
_sun->shadowLight();

// Draw the drawables the second time with shadows
for(std::list<Drawable*>::iterator it = _drawables.begin(); it != _drawables.end(); it++)
{
(*it)->draw();
}

// ++ ---------------------------------------------------------------------------------------------------- ++ //
// Second step for shadows
glPushAttrib(GL_ALL_ATTRIB_BITS);
_sun->brightLight();
_shadow->drawWithoutShadows();

// Skybox
//_skybox->draw();


// Draw the drawables the third time with shadows
for(std::list<Drawable*>::iterator it = _drawables.begin(); it != _drawables.end(); it++)
{
(*it)->draw();
}

glPopAttrib();

// Water, grass
//_water->draw();
//_grass->draw();

//_shadow->debug();

// Light out
glDisable(GL_LIGHT0); glDisable(GL_LIGHTING);

// Draw and clear Buffer
glutSwapBuffers();

// Check for Error
GLenum error = glGetError();
if(error == GL_INVALID_OPERATION)
{
printf("Error occured in Viewer: %d\n", error);
error = 0;
}


The sun class only sets the light intesity and holds the position of the light. MyMatrix multiplys the matrices correct.

P.S. I know i should use Shaders for this topic, but it is my first project and i started with the fixed pipeline.
Advertisement
screenshot plz
The lightposition is on (0, 200, 0) and the cube is on (0, 30, 0). The plane under the cube is from (-100,0, -100) to (100, 0, 100). So the shadow should be under the cube.
[attachment=4448:screen.png]
[color="#0000FF"][color="#000000"]try a

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);


on the shadow tex's
It doesnt change anything :-/
ok, leave it there, its necessary.

now try to upload some random memory garbage as shadow map texture. it should give you some strange result. lets see if the cmp is working.
This three lines should do a rnd garbage upload or?
glBindTexture(GL_TEXTURE_2D, _depthTextureId);
GLfloat* buffer = new GLfloat[shadowMapSize * shadowMapSize];
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, shadowMapSize, shadowMapSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, buffer);

The result is a black line through the picture, so i think its no rnd garbage.
[attachment=4450:screen.png]
Switch to srand timer and try to run through a (rand()%10000000)/1000.0 on your memory area.
Ok, the result ist the same as in the first picture. (Most of the time, sometimes, there are lines as in picture two)
in this case i think your shadowmap matrix is bad.

This topic is closed to new replies.

Advertisement