Jump to content
  • Advertisement
Sign in to follow this  
DrX

Software renderer Matrix trouble

This topic is 4933 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 Im making a small software renderer, it works fine until I implemented Gouraud shading. I think its my normals that becomes corrupted when I rotate them. here is a image of how it looks: www.drx.dk/images/software/software03.jpg (The lines are the vertex normals, as you can see the same vertex has diferent normals) There is only one light source and its located betwen the pyramid and user. This is how i calculate the light intensity:
		float intensity = 0;
		for (int i=0; i < numLights; i++)
		{
			Vector3 lineOfSight = lights->pos - p;
			
			// Should precompute this length
			// FIXME! normals should be normalized when they get here
			float len = normal.Magnitude();
			float dot = lineOfSight.Dot(normal);

			if (dot > 0)
				intensity += dot/(len * lineOfSight.Magnitude());
		}

		if (intensity > 1.0f)
			intensity = 1.0f;

		return intensity;
I got it from an old book i have "Black art of 3d game programmig" by Andre LaMothe, too me this calculations doesn't seem right but that might be because im thinking of a omni light source while this computes a point light source. moving along.. I setup my pyram like this:
	Color col2(255,255,255);

	Vector3 v0(0,100,0);
	Vector3 v1(100,-100,100);
	Vector3 v2(100,-100,-100);
	Vector3 v3(-100,-100,-100);
	Vector3 v4(-100,-100,100);

	Vector3 verts[12] = {v0, v2, v1,
						 v0, v3, v2,
						 v0, v4, v3,
						 v0, v1, v4};
	Color colors[12] = {col, col, col, 
						col, col, col,
						col, col, col,
						col, col, col};

	Vector3 n0 = (verts[0] - verts[2]).Cross( (verts[0] - verts[1]) );
	Vector3 n1 = (verts[3] - verts[5]).Cross( (verts[3] - verts[4]) );
	Vector3 n2 = (verts[6] - verts[8]).Cross( (verts[6] - verts[7]) );
	Vector3 n3 = (verts[9] - verts[11]).Cross( (verts[9] - verts[10]) );
	//--
	Vector3 nv0 = (n0 + n1 + n2 + n3) / 4;
	nv0.Normalize();
	Vector3 nv1 = (n0 + n3) / 2;
	nv1.Normalize();
	Vector3 nv2 = (n0 + n1) / 2;
	nv2.Normalize();
	Vector3 nv3 = (n1 + n2) / 2;
	nv3.Normalize();
	Vector3 nv4 = (n2 + n3) / 2;
	nv4.Normalize();
	//--
	Vector3 normals[12] = { nv0, nv2, nv1,
							nv0, nv3, nv2,
							nv0, nv4, nv3,
							nv0, nv1, nv4};

	renderer->drawTriangles(4,verts,normals,colors);
It is translated to (0,0,500) later. now to the part where i think the problem is, the matrix. I found this from the OGL Red book: http://fly.cc.fer.hr/~unreal/theredbook/appendixg.html that states that the normals are transformed with the matrix (T^-1)^* ( that is the invers of T transposed). My matrix class looks like this: www.drx.dk/images/software/Matrix.h && www.drx.dk/images/software/Matrix.cpp I multiply my rotations matrices like this R = X * Y * Z To me it feels wrong to translate normals, should i really do that ? At the moment i don't, and then T = R and (R^-1)^* = X * Y * Z, the same as R (I think thats correct, i did a proof of it on paper). So my drawTriangles() method looks like this:
void Renderer::drawTriangles(int numTriangles, Vector3 *verts,Vector3 *normals, const Color *colors)
{
	Vector2i projVerts[3];
	Vector3 transVerts[3];
	Vector3 transNormals[3];
	Vector3 *ptrV = verts;
	Vector3 *ptrN = normals;
	const Color *ptrC = colors;

	for (int i=0; i < numTriangles; i++, ptrV += 3, ptrN += 3, ptrC += 3)
	{
		transVerts[0] = matrix * ptrV[0] + translation;
		transVerts[1] = matrix * ptrV[1] + translation;
		transVerts[2] = matrix * ptrV[2] + translation;

		if (isTriangleVisible(transVerts))
		{
			transNormals[0] = matrix * ptrN[0];
			transNormals[1] = matrix * ptrN[1];
			transNormals[2] = matrix * ptrN[2];

			projVerts[0] = projectPoint(transVerts[0]);
			projVerts[1] = projectPoint(transVerts[1]);
			projVerts[2] = projectPoint(transVerts[2]);

			graphics->drawTriangle2D(transVerts,transNormals, ptrC, projVerts);
		}
	}
}
graphics->drawTriangle2D() does the actualy draving of the triangle. I put up the main classes of my project if i didn't suply enough information: www.drx.dk/images/software/Renderer.h && www.drx.dk/images/software/Renderer.cpp www.drx.dk/images/software/Graphics.h && www.drx.dk/images/software/Graphics.cpp www.drx.dk/images/software/ShaderGouraud.h (I know virtual functions are a bit slow but it makes the code sooooo much cleaner and easier to change) There are a lot of commented code in those files, its old/new design ideas that haven't yet been removed/implemented, i hope it doesn't make it to messy. [Edited by - DrX on January 18, 2005 9:18:20 AM]

Share this post


Link to post
Share on other sites
Advertisement
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!