Lightmap Resolution

Started by
5 comments, last by Lopez 17 years, 11 months ago
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.u < Min_U )
					Min_U = face.LightMap.Vertex.u;
				if (face.LightMap.Vertex.v < Min_V )
					Min_V = face.LightMap.Vertex.v;
				if (face.LightMap.Vertex.u > Max_U )
					Max_U = face.LightMap.Vertex.u;
				if (face.LightMap.Vertex.v > Max_V )
					Max_V = face.LightMap.Vertex.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.u -= Min_U;
				face.LightMap.Vertex.v -= Min_V;
				face.LightMap.Vertex.u /= Delta_U;
				face.LightMap.Vertex.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
Advertisement
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
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
Hi,
Why not use the DeltaU, DeltaV values? Do some scaling and clamping.
[size="1"]Perl - Made by Idiots, Java - Made for Idiots, C++ - Envied by Idiots | http://sunray.cplusplus.se
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
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.


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.

This topic is closed to new replies.

Advertisement