Jump to content
  • Advertisement
Sign in to follow this  
jonathanc

Stencil Shadow question

This topic is 3788 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all, I am trying to implement shadow to my model using a very basic stencil shadowing method. However, I noticed that when I update model.position.y (model's height) values, the shadow effect goes wrong. I can't get the shadow matrix's y-plane values to update as well. Basically any values other than model.position.y = 0.9 makes the whole thing go wrong. I have included the relevent codes here and I hope someone could offer some advice. Thanks.

float g_lightPos[4] = {10, 10, 0, 1};							
CModelMD3 g_Model; 
Entity model; // the model
CVector3 Camera(0.0,5.0,2.0); // the Camera Position Vector
CVector3 View(0.0,2.0,0.0); // the Camera View Vector
CVector3 Heading(0.0,0.0,-1.0); // the Camera Heading Vector
Model *pModel = NULL;

///////////////////////////////// INIT GAME WINDOW \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

void Init(HWND hWnd)
{
	model.position.x = 0.0;
	model.position.y = 0.9;
  	model.position.z = 0.0;
	glEnable(GL_LIGHTING);
 	glEnable(GL_NORMALIZE); 
 	glEnable(GL_LIGHT0);
	Camera.x = -20;
	Camera.y = 10;
	Camera.z = -20;		
	float plane[4] = { 0.0, 1, 0.0, 0.0 };
	SetShadowMatrix(g_shadowMatrix, g_lightPos, plane);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);		
}

/////////////////////////////////// DRAW GROUND BASED ON HEIGHT MAP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

void DrawGround()
{
	glDisable(GL_LIGHTING);glEnable(GL_TEXTURE_2D);
	glPushMatrix();
	glTranslatef(-50,-3,-50); 
	glScalef(0.1f,0.1f,0.1f); 	
	RenderHeightMap(g_HeightMap);
	glPopMatrix(); glEnable(GL_LIGHTING);
	glDisable(GL_TEXTURE_2D);
}

///////////////////////////////// RENDER SCENE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

void RenderScene() 
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);	
	glLoadIdentity();		
		Direction += (model.direction-Direction)/15;
		Heading.x = cos(90-Direction);
		Heading.z = sin(90-Direction);	
	View.x = model.position.x;	
	View.y = model.position.y+1;	
	View.z = model.position.z;
	model.heading.x = cos(90-model.direction);
	model.heading.z = sin(90-model.direction);
	Camera.x += ((View.x + Heading.x * -6) - Camera.x) / 3;
	Camera.y += ((View.y + Heading.y * -6 + 1) - Camera.y) / 3; 	
	Camera.z += ((View.z + Heading.z * -6) - Camera.z) / 3;	
	model.position.x+=model.speed.x;
	model.position.z+=model.speed.z;		
	model.speed.x /= airdrag;
	model.speed.y /= airdrag;
	model.speed.z /= airdrag;		
	gluLookAt(Camera.x, Camera.y, Camera.z, // the position 
	View.x, View.y, View.z, //the View
	0.0f,1.0f,0.0f); //the Up-Vector
        // This averages the Height reading so it wont be so choppy when I
        // translate the model.position.y value

	int ModelPosX = (int)model.position.x;
	int ModelPosZ = (int)model.position.z;
        float h00 = (float)Height(g_HeightMap, ModelPosX, ModelPosZ) ;
        float h10 = (float)Height(g_HeightMap, ModelPosX+1, ModelPosZ);
        float h01 = (float)Height(g_HeightMap, ModelPosX, ModelPosZ+1) ;
        float h11 = (float)Height(g_HeightMap, ModelPosX+1, ModelPosZ+1) ;
        float FracModelPosX = model.position.x - ModelPosX;
        float FracModelPosZ = model.position.z - ModelPosZ;
        float ave = h00*(1.0f-FracModelPosX)*(1.0f-FracModelPosZ) +  h10*FracModelPosX*(1.0f-FracModelPosZ) + h01*(1.0f-FracModelPosX)*FracModelPosZ + h11*FracModelPosX*FracModelPosZ;
        // so if i'm near X.Z, then result is h00, near X+1.Z > h10, X.Z+1 >  h01, X+1.Z+1 > h11;
        // if i'm half way between h00 and h10; FracPosX = 0.5 FracPosZ = 0,  result is 0.5*h00 + 0.5*h10, seems to be ok.
        // Two options here to update the model.position.y values according to
        // terrain height, so model doesn't go into terrain
        // model.position.y = ((model.position.y * 4.0f + ave)/5.0f);
        //model.position.y = ave+2.5;
	glPushMatrix();
	glLightfv( GL_LIGHT0, GL_POSITION, g_lightPos);
	glPopMatrix();	
	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
        glEnable(GL_STENCIL_TEST);
        glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);         
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        glDepthMask(GL_TRUE);
        glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 
        DrawGround();
        glPushMatrix();
        glDisable(GL_TEXTURE_2D);
        glDisable(GL_LIGHTING);
        glDisable(GL_DEPTH_TEST);
        glEnable(GL_BLEND);
        glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
        glColor4f(0.0, 0.0, 0.0, 1.0f);
        // project the model through the shadow matrix
        glMultMatrixf(g_shadowMatrix);
        glEnable(GL_CULL_FACE); // Turn back face culling on
        glCullFace(GL_FRONT);	
// If I change the model.position.y values here the shadow won't update as needed  on the y plane. So I can't update the shadow's y-plane position if I 
// were to change the model's y position accordingly to the terrain's height.
        glTranslatef(model.position.x, model.position.y, model.position.z);
        glScalef(0.04f,0.04f,0.04f);
        glRotatef(model.direction*180/PI-110 ,0.0,1.0,0.0);
        g_Model.DrawModel();
        glDisable(GL_CULL_FACE);
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_DEPTH_TEST);
        glDisable(GL_BLEND);
        glEnable(GL_LIGHTING);
        glPopMatrix();
        glDisable(GL_STENCIL_TEST);
        glPushMatrix();
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_CULL_FACE); // Turn back face culling on
        glCullFace(GL_FRONT);
        glTranslatef(model.position.x, model.position.y, model.position.z);
        glScalef(0.04f,0.04f,0.04f);
        glRotatef(model.direction*180/PI -110,0.0,1.0,0.0);
        glColor3ub(255, 255, 255);
        g_Model.DrawModel();
        glDisable(GL_CULL_FACE);
        glDisable(GL_TEXTURE_2D);
        glPopMatrix();	
	SwapBuffers(g_hDC);
}	

void SetShadowMatrix(GLfloat destMat[16], float lightPos[4], float plane[4])
{
	GLfloat dot;
	// dot product of plane and light position
	dot = plane[0] * lightPos[0] + plane[1] * lightPos[1] + plane[1] * lightPos[2] + plane[3] * lightPos[3]; // first column
	destMat[0] = dot - lightPos[0] * plane[0];
	destMat[4] = 0.0f - lightPos[0] * plane[1];
	destMat[8] = 0.0f - lightPos[0] * plane[2];
	destMat[12] = 0.0f - lightPos[0] * plane[3]; 
	// second column
	destMat[1] = 0.0f - lightPos[1] * plane[0];
	destMat[5] = dot - lightPos[1] * plane[1];
	destMat[9] = 0.0f - lightPos[1] * plane[2];
	destMat[13] = 0.0f - lightPos[1] * plane[3];
	// third column
	destMat[2] = 0.0f - lightPos[2] * plane[0];
	destMat[6] = 0.0f - lightPos[2] * plane[1];
	destMat[10] = dot - lightPos[2] * plane[2];
	destMat[14] = 0.0f - lightPos[2] * plane[3];
	// fourth column
	destMat[3] = 0.0f - lightPos[3] * plane[0];
	destMat[7] = 0.0f - lightPos[3] * plane[1];
	destMat[11] = 0.0f - lightPos[3] * plane[2];
	destMat[15] = dot - lightPos[3] * plane[3];
}


Share this post


Link to post
Share on other sites
Advertisement
Hmm ok after looking though some webpages it got me thinking.

What is the best way of rendering shadows if I have an uneven terrain and several MS3D and MD3 models on the terrain? My camera will be centered on one of the MD3 models and I have a simple collision detection algo to stop my model from going into the terrain.

I am trying out the stencil shadow and also the simpler planar shadow method, but I can't seem to get things working. If my terrain height is of negligable values, can I just implement the simpler planar shadow method and treat the surface as even?

Wonder if thats a good approach for a beginner like me .

Share this post


Link to post
Share on other sites
Try using this order. Do all your normal world transforms on your model, draw the model normally, then apply your shadow transform, and draw the planar shadow.

Basically the shadow transform should be applied on a model already in worldspace.

Share this post


Link to post
Share on other sites
Quote:
Original post by Khaos Dragon
Try using this order. Do all your normal world transforms on your model, draw the model normally, then apply your shadow transform, and draw the planar shadow.

Basically the shadow transform should be applied on a model already in worldspace.


Thanks for the idea. I will try it out. I also noticed that with this method other objects on my terrain doesn't have shadows :( I have been reading up and I must implement a fairly complicated method of obtaining shadows for all objects on the terrain.

I wonder if there is a simpler way ... :S

Share this post


Link to post
Share on other sites
Without doing a thorough review of your code, I notice that you calling trig functions without converting to radians.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!