Sign in to follow this  
s3mt3x

Lightmap Resolution

Recommended Posts

Hi Guys, I'm trying to implement lightmapping in my application which is all going fine. I have implemented planar mapping and can successfully create lightmaps for each of my polygons. However, there is one downside - in all the articles and tutorials i've come accross, each lightmap is generated at a fixed resolution i.e. 16x16 or 32x32 etc. However, the nature of the polys in my scene means that some are much larger than others. I was wondering if anyone could point me in the direction of creating lightmaps at a resolution based on the size of the polygon? The method I am using is below:

public static void Generate(PolyFace face, Vector3[] polygon, Level level, bool smoothMap, bool fillInvalidLumels) 
		{
			
			Vector3 pointonplane = polygon[0];
			Vector3 poly_normal = Vector3.CalculateNormal(polygon[0], polygon[1], polygon[2]);

			face.LightMap = new Lightmap();
			int flag;

			if (Math.Abs(poly_normal.x) > Math.Abs(poly_normal.y) && 
				Math.Abs(poly_normal.x) > Math.Abs(poly_normal.z))
			{
				flag = 1;
				face.LightMap.Vertex[0].u = polygon[0].y;
				face.LightMap.Vertex[0].v = polygon[0].z;
				face.LightMap.Vertex[1].u = polygon[1].y;
				face.LightMap.Vertex[1].v = polygon[1].z;
				face.LightMap.Vertex[2].u = polygon[2].y;
				face.LightMap.Vertex[2].v = polygon[2].z;
			}
			else if (Math.Abs(poly_normal.y) > Math.Abs(poly_normal.x) && 
				Math.Abs(poly_normal.y) > Math.Abs(poly_normal.z))
			{
				flag = 2;
				face.LightMap.Vertex[0].u = polygon[0].x;
				face.LightMap.Vertex[0].v = polygon[0].z;
				face.LightMap.Vertex[1].u = polygon[1].x;
				face.LightMap.Vertex[1].v = polygon[1].z;
				face.LightMap.Vertex[2].u = polygon[2].x;
				face.LightMap.Vertex[2].v = polygon[2].z;
			}
			else
			{
				flag = 3;
				face.LightMap.Vertex[0].u = polygon[0].x;
				face.LightMap.Vertex[0].v = polygon[0].y;
				face.LightMap.Vertex[1].u = polygon[1].x;
				face.LightMap.Vertex[1].v = polygon[1].y;
				face.LightMap.Vertex[2].u = polygon[2].x;
				face.LightMap.Vertex[2].v = polygon[2].y;
			}

			face.LightMap.MapMode = flag;

			float Min_U = face.LightMap.Vertex[0].u;
			float Min_V = face.LightMap.Vertex[0].v;
			float Max_U = face.LightMap.Vertex[0].u;
			float Max_V = face.LightMap.Vertex[0].v;

			for (int i = 0; i < 3; i++)
			{
				if (face.LightMap.Vertex[i].u < Min_U )
					Min_U = face.LightMap.Vertex[i].u;
				if (face.LightMap.Vertex[i].v < Min_V )
					Min_V = face.LightMap.Vertex[i].v;
				if (face.LightMap.Vertex[i].u > Max_U )
					Max_U = face.LightMap.Vertex[i].u;
				if (face.LightMap.Vertex[i].v > Max_V )
					Max_V = face.LightMap.Vertex[i].v;
			}

			float Delta_U = Max_U - Min_U;
			float Delta_V = Max_V - Min_V;

			for (int i = 0; i < 3; i++)
			{
				face.LightMap.Vertex[i].u -= Min_U;
				face.LightMap.Vertex[i].v -= Min_V;
				face.LightMap.Vertex[i].u /= Delta_U;
				face.LightMap.Vertex[i].v /= Delta_V;
			}


			float X, Y, Z;

			float Distance = - (poly_normal.x * pointonplane.x + poly_normal.y * pointonplane.y + poly_normal.z * pointonplane.z);

			Vector3 UVVector = new Vector3();
			Vector3 Vect1 = new Vector3();
			Vector3 Vect2 = new Vector3();

			switch (flag)
			{
				case 1: //YZ Plane
					X = - ( poly_normal.y * Min_U + poly_normal.z * Min_V + Distance )
						/ poly_normal.x;
					UVVector.x = X;
					UVVector.y = Min_U;
					UVVector.z = Min_V;
					X = - ( poly_normal.y * Max_U + poly_normal.z * Min_V + Distance )
						/ poly_normal.x;
					Vect1.x = X;
					Vect1.y = Max_U;
					Vect1.z = Min_V;
					X = - ( poly_normal.y * Min_U + poly_normal.z * Max_V + Distance )
						/ poly_normal.x;
					Vect2.x = X;
					Vect2.y = Min_U;
					Vect2.z = Max_V;
					break;

				case 2: //XZ Plane
					Y = - ( poly_normal.x * Min_U + poly_normal.z * Min_V + Distance )
						/ poly_normal.y;
					UVVector.x = Min_U;
					UVVector.y = Y;
					UVVector.z = Min_V;
					Y = - ( poly_normal.x * Max_U + poly_normal.z * Min_V + Distance )
						/ poly_normal.y;
					Vect1.x = Max_U;
					Vect1.y = Y;
					Vect1.z = Min_V;
					Y = - ( poly_normal.x * Min_U + poly_normal.z * Max_V + Distance )
						/ poly_normal.y;
					Vect2.x = Min_U;
					Vect2.y = Y;
					Vect2.z = Max_V;
					break;

				case 3: //XY Plane
					Z = - ( poly_normal.x * Min_U + poly_normal.y * Min_V + Distance )
						/ poly_normal.z;
					UVVector.x = Min_U;
					UVVector.y = Min_V;
					UVVector.z = Z;
					Z = - ( poly_normal.x * Max_U + poly_normal.y * Min_V + Distance )
						/ poly_normal.z;
					Vect1.x = Max_U;
					Vect1.y = Min_V;
					Vect1.z = Z;
					Z = - ( poly_normal.x * Min_U + poly_normal.y * Max_V + Distance )
						/ poly_normal.z;
					Vect2.x = Min_U;
					Vect2.y = Max_V;
					Vect2.z = Z;
					break;
			}

			Vector3 edge1 = new Vector3();
			Vector3 edge2 = new Vector3();

			edge1.x = Vect1.x - UVVector.x;
			edge1.y = Vect1.y - UVVector.y;
			edge1.z = Vect1.z - UVVector.z;
			edge2.x = Vect2.x - UVVector.x;
			edge2.y = Vect2.y - UVVector.y;
			edge2.z = Vect2.z - UVVector.z;

			int Width = level.Scene.LightMapWidthHeight;
			int Height = level.Scene.LightMapWidthHeight;

			face.LightMap.Lumels = new Lumel[Width * Height];
			face.LightMap.Width = Width;
			face.LightMap.Height = Height;

			bool allShaded = true;
			bool allLit = true;

			for(int iY = 0; iY < Height; iY++)
			{
				for(int iX = 0; iX < Width; iX++)
				{
					Lumel lumel = new Lumel();

					//we are on the border of pixels at this point, not the center
					float ufactor = (iX / (float)Width) + 1.0f / (Width * 2.0f);
					float vfactor = (iY / (float)Height) + 1.0f / (Height * 2.0f);

					lumel.IsValid = true;
					Vector3 newedge1 = new Vector3();
					Vector3 newedge2 = new Vector3();

					newedge1.x = edge1.x * ufactor;
					newedge1.y = edge1.y * ufactor;
					newedge1.z = edge1.z * ufactor;
					newedge2.x = edge2.x * vfactor;
					newedge2.y = edge2.y * vfactor;
					newedge2.z = edge2.z * vfactor;

					lumel.Position = new Vector3();

					lumel.Position.x = UVVector.x + newedge2.x + newedge1.x;
					lumel.Position.y = UVVector.y + newedge2.y + newedge1.y;
					lumel.Position.z = UVVector.z + newedge2.z + newedge1.z;

					LevelLight testLight = level.LevelLight;

					Vector3 dir = level.LevelLight.Position - lumel.Position;

					float dot = poly_normal * dir;

					if (dot > 0.0f) 
					{	
						float RAY_LENGTH = 10000;
						
						Vector3 lightDirection = lumel.Position - level.LevelLight.Position;
						lightDirection.Normalize();
						float lumel_t = Vector3.Distance(testLight.Position, lumel.Position) / RAY_LENGTH;
						lightDirection = lightDirection * RAY_LENGTH;



						bool intersects = false;
						for (int objIndex = 0; objIndex < level.SceneObjects.Count; objIndex++) 
						{	
							if (level.SceneObjects[objIndex].ObjectType == IPlanObjectType.Mesh && level.SceneObjects[objIndex] != face.Parent) 
							{
								PolyMesh mesh = (PolyMesh) level.SceneObjects[objIndex];
								float mesh_t = mesh.IntersectsWithRay(testLight.Position, lightDirection);
								float tolerence = 0.001f;
								if (mesh_t != Intersections.NO_INTERSECTION && mesh_t < lumel_t) 
								{
									float deltaT = Math.Abs(mesh_t - lumel_t);
									if (deltaT > tolerence) 
									{
										intersects = true;
									}
								}
							}
						}

						if (intersects) 
						{
							lumel.Value = level.Scene.ShadowIntensity;
							allLit = false;
							lumel.Shaded = true;
						} 
						else 
						{
							lumel.Value = 0xFF;
							allShaded = false;
							lumel.Shaded = false;
						}	
					} 
					face.LightMap[iX, iY] = lumel;
				}//end lightmap x loop
			}//end lightmap y loop
			

			if (fillInvalidLumels)
				FillInvalidPixels(face.LightMap);
			if (smoothMap) 
				SmoothLightMap(face.LightMap);
			
		}


Any help or comments would be really appreciated, Kind Regards, Chris

Share this post


Link to post
Share on other sites
u can take the magnitude of the cross-vector (see Normalcalculation) as the size that a poly gets.

if u know all magnitudes, u can scale all polys relative to each other based on that value and give them their maps.

btw. dont use one map per poly, but put several lightmaps into one texturepage (textureatlas).

greets
rapso

Share this post


Link to post
Share on other sites
Hi Raspo - thanks for replying,

How do you mean scale the poly? I want to increase or decrease the reolution of my lightmap based on the size of the polygon?

Kind Reagards,

Chris

Share this post


Link to post
Share on other sites
Hi Sunray - thanks for the reply

I've tried this (in my limited understanding).

I tried the following:

float LUMEL_WORLD_SIZE = 20.0f;

Width = (Delta_U / LUMEL_WORLD_SIZE);
Height = (Delta_V / LUMEL_WORLD_SIZE);

Generating the lumel positions using the above now messes up the orientation of the map.

Any ideas how I can sort this using the code above?

Kind Regards,

Chris Evans

Share this post


Link to post
Share on other sites
Quote:
Original post by s3mt3x
Hi Raspo - thanks for replying,

How do you mean scale the poly? I want to increase or decrease the reolution of my lightmap based on the size of the polygon?

Kind Reagards,

Chris

it's not raspo ;)

i meant u can scale the texelcount u reserve for each poly. u could do this by e.g. give the biggest poly 256*256 texels and if u have a poly that just has 50% of the its size, then just give it 128*128 texels.

if u use just one texture for all polys, u could scale the deltaU and deltaV of the polys, relative to the biggest poly.


Share this post


Link to post
Share on other sites
You could precomute your texture coords or the lightmap in an editor. This way you could assign higher resolutions to specific places that you know will be close to the camera. I do this by unwrapping the mesh in studio max, and referring to those texcoords when processing the light mapping.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this