Floor Reflections

Started by
4 comments, last by d h k 18 years, 7 months ago
Hello everyone, I read the brief article about reflections with OpenGL here at gamedev.net and am trying to include this cool looking effect into my own project. My game uses 3-dimensional tiles ( 5 x 20 for now with each a size of 2 x 1 x 3 [some exceptions] ) - will adding the reflection to all those tiles decrease performance (a lot)? Is the current "draw_scene ( )" funtion correct or do I have some mistake in there that I don't know of? This function makes my game first minimize and then when I maximize it, it is really slow...

void draw_scene ( void )
{

  // clear the screen
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

  // reset the matrix
  glLoadIdentity ( );

  // draw the user
  user.draw ( );

  glLoadIdentity ( );
  /* Don't update color or depth. */
  glDisable(GL_DEPTH_TEST);
  glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

  /* Draw 1 into the stencil buffer. */
  glEnable(GL_STENCIL_TEST);
  glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
  glStencilFunc(GL_ALWAYS, 1, 0xffffffff);

  /* Now drawing the floor just tags the floor pixels
     as stencil value 1. */
  // draw the tiles
	for ( int x = 0; x < MAP_WIDTH; x++ )
	{
		for ( int y = 0; y < MAP_LENGTH; y++ )
		{
			tile[x][y].position.x = (float) x;
			tile[x][y].position.y = 0.0f;
			tile[x][y].position.z = (float) y;
			tile[x][y].draw ( );
		}
	}

  /* Re-enable update of color and depth. */ 
  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  glEnable(GL_DEPTH_TEST);

  /* Now, only render where stencil is set to 1. */
  glStencilFunc(GL_EQUAL, 1, 0xffffffff);  /* draw if stencil ==1 */
  glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

  /* Draw reflected ninja, but only where floor is. */
  glPushMatrix();
    glScalef(1.0, -1.0, 1.0);
    // draw the user
	user.draw ( );
  glPopMatrix();

  glDisable(GL_STENCIL_TEST);
}

Advertisement
For reflections, I'd say you need to draw your entire scene (more or less) two-three times more... so, take the time needed for one frame, and simply multiply by three... :D

but then again, that's the result of my engine, not facts.. hehe.

cheers!

"Game Maker For Life, probably never professional thou." =)
Update: It turned out that minimization thing was caused by something different... I have cleaned up the "draw_scene" function now and tested several things, but nothing has worked entirely correct yet...

This is the best version so far:

void draw_scene ( void ){	// clear the screen	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);	glEnable(GL_STENCIL_TEST);	glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);	glStencilFunc(GL_ALWAYS, 1, 0xffffffff);	glLoadIdentity ( );	// draw the tiles	for ( int x = 0; x < MAP_WIDTH; x++ )	{		for ( int y = 0; y < MAP_LENGTH; y++ )		{			if ( tile[x][y].type == STANDARD )			{				tile[x][y].position.x = (float) x;				tile[x][y].position.y = 0.0f;				tile[x][y].position.z = (float) y;				tile[x][y].draw ( );			}		}	}	glLoadIdentity ( );	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);		glStencilFunc(GL_EQUAL, 1, 0xffffffff);	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);		glScalef(1.0, -1.0, 1.0);	glTranslatef ( 0.0f, 5.0f, 0.0f );	glEnable(GL_BLEND );	glColor4f(1.0f,1.0f,1.0f,0.4f);	glBlendFunc(GL_SRC_ALPHA,GL_ONE);    	user.draw ( );	glDisable(GL_BLEND);		glPopMatrix();	glDisable(GL_STENCIL_TEST);	glLoadIdentity ( );	user.draw ( );	glLoadIdentity ( );	// move camera behind the ball	glTranslatef ( user.sphere.position.x, -CAM_HEIGHT, user.sphere.position.z );	// draw the tiles	for ( x = 0; x < MAP_WIDTH; x++ )	{		for ( int y = 0; y < MAP_LENGTH; y++ )		{			if ( tile[x][y].type == STANDARD )			{				glEnable(GL_BLEND );				glColor4f(1.0f,1.0f,1.0f,0.2f);				glBlendFunc(GL_SRC_ALPHA,GL_ONE);			}			tile[x][y].position.x = (float) x;			tile[x][y].position.y = 0.0f;			tile[x][y].position.z = (float) y;			tile[x][y].draw ( );			if ( tile[x][y].type == STANDARD )			{				glDisable(GL_BLEND);			}		}	}}


This is really slow and it draws the reflection everywhere - not only on the tile ground... So it seems like the whole stencil buffer thing is not working, but what exactly is wrong?

Thanks for your reply though - keep them coming please.
Something you may want to do is look into drawing the scene inverted to a texture (via pbuffer or glTexSubImage). Then though projective texturing you can multi texture your tiles or what ever with this reflection. This is the same method used for doing a vast majority of the reflective water you see every one doing.
Sounds similar to an issue I had when I didn't read the nehe stencil test article properly. Have you specified the number of stencil buffer bits in the pixelformatdescriptor of your window setup code?

taken from the NeHe article:

static	PIXELFORMATDESCRIPTOR pfd=					// pfd Tells Windows How We Want Things To Be	{		sizeof(PIXELFORMATDESCRIPTOR),					// Size Of This Pixel Format Descriptor		1,								// Version Number		PFD_DRAW_TO_WINDOW |						// Format Must Support Window		PFD_SUPPORT_OPENGL |						// Format Must Support OpenGL		PFD_DOUBLEBUFFER,						// Must Support Double Buffering		PFD_TYPE_RGBA,							// Request An RGBA Format		bits,								// Select Our Color Depth		0, 0, 0, 0, 0, 0,						// Color Bits Ignored		0,								// No Alpha Buffer		0,								// Shift Bit Ignored		0,								// No Accumulation Buffer		0, 0, 0, 0,							// Accumulation Bits Ignored		16,								// 16Bit Z-Buffer (Depth Buffer)		1,								// Use Stencil Buffer ( * Important * )		0,								// No Auxiliary Buffer		PFD_MAIN_PLANE,							// Main Drawing Layer		0,								// Reserved		0, 0, 0								// Layer Masks Ignored};
"I must not fear. Fear is the mindkiller. Fear is the little death that brings total obliteration. I will face my fear. I will permit it to pass over me and through me. And when it has gone past me I will turn to see fear's path. Where the fear has gone there will be nothing. Only I will remain." ~Frank Herbert, DuneMy slice of the web
Thanks a bunch, that did the trick. Now I feel like such a poor copy&paster...

This topic is closed to new replies.

Advertisement