Skip to main content
GameDev.net gamedev.net
🔒 Locked

2D Shadow problem

Started by Cipher3D Jan 12, 2004 at 10:16 PM 4 replies 450+ views
Original Post
Cipher3D
Cipher3D
Hi, I''m trying to implement 2D shadows based on Orangy Tang''s 2D shadow article, and I''ve implemented most of things right, except for the actual shadow generation. his article was good, but I''m somewhat of a noob to vector calculations, and I''ve hacked together an implementation that doesn''t work the way it should. Here is my shadow creation algorithm/code: The part you should focus on is in between the second FOR loop... Sorry, it may seem like a ton of code, but its what i have. Thank you so very much in advance, Cipher3D

void cLightManager::DrawObjectShadows(cLight* light)
{
	if (!light)
		return;

	for (int c=0;c<m_vertexList.size();c++)
	{
		
		int numEdges = sizeof(m_vertexList[c]);
		vector<typVertex> shadowGeometry;
		bool *frontfacing = new bool[numEdges];

		for (int g=0;g<numEdges;g++)
			frontfacing[g] = false;

		for (g=0;g<numEdges;g++)
		{
			if (light->x == 50)
			{
				int body;
    			body++;
			}

			int prev = (g == 0 ? numEdges-1 : g-1);

						//for each edge

			int x,y;

			x = m_vertexList[c][g].x-m_vertexList[c][prev].x;
			y = m_vertexList[c][g].y-m_vertexList[c][prev].y;

			
			if (light->x > m_vertexList[c][g].x)
			{
				x = -x;
			}
			if (light->y > m_vertexList[c][g].y)
			{
				y = -y;
			} //end if


			float dot = (x*light->x)+(y*light->y);

			//check whats the result of dot

			if (dot < 0)
			{
				float vertx,verty,projx,projy;

				//boundary = true;

				frontfacing[g] = true;
				
				//then we add to shadow geometry

				shadowGeometry.push_back(m_vertexList[c][prev]);

				projx = m_vertexList[c][prev].x-light->x;
				projy = m_vertexList[c][prev].y-light->y;

				vertx = m_vertexList[c][prev].x;
				verty = m_vertexList[c][prev].y;

				projx *= light->size/100.0f; projy *= light->size/100.0f;
				vertx+=projx;
				verty+=projy;
				typVertex s = {vertx,verty};

				shadowGeometry.push_back(s);
				
			} //end if

			else
			{
				if (frontfacing[prev])
				{
					shadowGeometry.push_back(m_vertexList[c][prev]);
				} //end if

			} //end else



				
		} //done 


		if (frontfacing)
			delete frontfacing;

		//NOW draw the frickin shadow

		glBlendFunc(GL_ZERO,GL_ZERO);

		glBegin(GL_TRIANGLE_STRIP);
		glColor4f(0,0,0,1.0f);
		for (int ang = 0;ang<shadowGeometry.size();ang++)
		{
			int x = shadowGeometry[ang].x;
			int y = shadowGeometry[ang].y;

			if (x < 0)
				x = 0;
			if (y < 0)
				y = 0;
			if (x > g_pVideo->GetWidth())
				x = g_pVideo->GetWidth();
			if (y > g_pVideo->GetHeight())
				y = g_pVideo->GetHeight();

			glVertex2f(x,y);
		}

	glEnd();

	shadowGeometry.empty();

	} //end for



} //end



I eat heart attacks
Cipher3D
Cipher3D
of all things, i forgot to state the problem...

there are several weird shadow "artifacts..." I''ll post a screen shot tommorow...ugh...
I eat heart attacks
OrangyTang
OrangyTang
Hmm, I''m not totally sure if I''m reading your code right, but the one thing that jumps out at me is in the last drawing loop:
if (x < 0)
x = 0;
if (y < 0)
y = 0;

if (x > g_pVideo->GetWidth())
x = g_pVideo->GetWidth();

if (y > g_pVideo->GetHeight())
y = g_pVideo->GetHeight();

Clamping the x and the y like that will restrict them to the screen edges, but it will mess up the angle of the shadow because you''re changing one but not the other appropriatly.

I don''t actually calculate this accuratly, I just find the distance across the screen diagonal and shift them back by this amount. This way I get something thats guaranteed to be off the screen edges, but not by huge amounts.

If thats not the only problem my suggestion is to start drawing debug geometry like lines to show the intermediate results (like drawing the faces you tag as front facing in wireframe and a different colour).
Cipher3D
Cipher3D
here're the screen shots









[edited by - Cipher3D on January 13, 2004 8:25:04 PM]
I eat heart attacks
Cipher3D
Cipher3D
I've decided to explain my code a little bit...

the first FOR loop just loops through all the objects I added in the list so it can create a shadow for each object.

the second for loop is where it creates the actual shadow for the object.

ignore the

if (light->x == 50)
{
int body;
body++;
}

its just a debugging thing..


int prev = (g == 0 ? numEdges-1 : g-1);

this just gets the previous vertex...some mundane boolean stuff..

the

int x,y;
x = m_vertexList[c][g].x-m_vertexList[c][prev].x;
y = m_vertexList[c][g].y-m_vertexList[c][prev].y;

just calculates the normal between a point and the previous point...basiclaly the normal for the edge of the figure..

if (light->x > m_vertexList[c][g].x)
{
x = -x;
}
ditto for Y component

this inverts x..because I have to compute the dot product of the normal and the light vector..and it the normal for the edge has to be in a counterclockwise thingy RELATIVE to the light..

float dot = (x*light->x)+(y*light->y);

here's where I compute the actuall dot

the next if body just adds two vertices to the shadow geometry "array" (a STL vector) to draw.

first it adds the previous point (because the shadow point starts at the previous point, or the first point of the edge),
(if you don't understand what I mean, just imagine a square and run through my algorithm in your head),

then it projects to the end of the screen for the shadow, and adds that vertex

and the else is supposed to account for the last vertex...however it comes up with a bunch of weird shadow artifacts, such as the second picture...

and if I remove that statement, there are no more weird artifacts, except for one thing: its missing the last triangle stip, so it doesn't render the whole shadow...just look at the last screen shot and you'll see what i mean...

[edited by - Cipher3D on January 13, 2004 8:41:13 PM]
I eat heart attacks
Cipher3D
Cipher3D
Hmm...guess I''ll have to wait for Orangy Tang''s code...
I eat heart attacks

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.