#### CODE EDITING IN PROGRESS - BIT MESSY STILL #### float ratio2(float a, float b) { if ((a==0) && (b==0)) return 1.0; if ((a==0) || (b==0)) return 0.0; if (a>b) return b/a; else return a/b; } float ratio4(float a, float b, float c, float d) { float q1 = ratio2(a,b); float q2 = ratio2(c,d); if (q1<q2) return q1; else return q2; } procedure CalcLightMap() vector normal = LightMap.Surface_Normal float Xres = LightMap.X_resolution float Yres = LightMap.Y_resolution point3D SamplePoint light I1, I2, I3, I4 Accuracy = Some value greater than 0.0, and less than 1.0. Higher values give a better quality Light Map (and a slower render). 0.5 is ok for the first passes of the renderer. 0.98 is good for the final pass. Spacing = 4 Higher values of Spacing give a slightly faster render, but will be more likely to miss fine details. I find that 4 is a pretty reasonable compromise. // 1: Initially, calculate an even grid of pixels across the Light Map. // For each pixel calculate the 3D coordinates of the centre of the patch that // corresponds to this pixel. Render a hemicube at that point, and add up // the incident light. Write that value into the Light Map. // The spacing in this grid is fixed. The code only comes here once per Light // Map, per render pass. for (y=0; y<Yres; y+=Spacing) for (x=0; x<Xres; x+=Spacing) { SamplePoint = Calculate coordinates of centre of patch incidentLight = Calc_Incident_Light(SamplePoint, normal) LightMap[x, y] = incidentLight } // return here when another pass is required Passes_Loop: threshold = pow(Accuracy, Spacing) // 2: Part 1. HalfSpacing = Spacing/2; for (y=HalfSpacing; y<=Yres+HalfSpacing; y+=Spacing) { for (x=HalfSpacing; x<=Xres+HalfSpacing; x+=Spacing) { // Calculate the inbetween pixels, whose neighbours are above and below this pixel if (x<Xres) // Don't go off the edge of the Light Map now { x1 = x y1 = y-HalfSpacing // Read the 2 (left and right) neighbours from the Light Map I1 = LightMap[x1+HalfSpacing, y1] I2 = LightMap[x1-HalfSpacing, y1] // If the neighbours are very similar, then just interpolate. if ( (ratio2(I1.R,I2.R) > threshold) && (ratio2(I1.G,I2.G) > threshold) && (ratio2(I1.B,I2.B) > threshold) ) { incidentLight.R = (I1.R+I2.R) * 0.5 incidentLight.G = (I1.G+I2.G) * 0.5 incidentLight.B = (I1.B+I2.B) * 0.5 LightMap[x1, y1] = incidentLight } // Otherwise go to the effort of rendering a hemicube, and adding it all up. else { SamplePoint = Calculate coordinates of centre of patch incidentLight = Calc_Incident_Light(SamplePoint, normal) LightMap[x1, y1] = incidentLight } } // Calculate the inbetween pixels, whose neighbours are left and right of this pixel if (y<Yres) // Don't go off the edge of the Light Map now { x1 = x-HalfSpacing y1 = y // Read the 2 (up and down) neighbours from the Light Map I1 = LightMap[x1,y1-HalfSpacing]; I2 = LightMap[x1,y1+HalfSpacing]; // If the neighbours are very similar, then just interpolate. if ( (ratio2(I1.R,I2.R) > threshold) && (ratio2(I1.G,I2.G) > threshold) && (ratio2(I1.B,I2.B) > threshold) ) { incidentLight.R = (I1.R+I2.R) * 0.5 incidentLight.G = (I1.G+I2.G) * 0.5 incidentLight.B = (I1.B+I2.B) * 0.5 LightMap[x1,y1] = incidentLight } // Otherwise go to the effort of rendering a hemicube, and adding it all up. else { SamplePoint = Calculate coordinates of centre of patch incidentLight = Calc_Incident_Light(SamplePoint, normal) LightMap[x1, y1] = incidentLight } }//end if }//end x loop }//end y loop // 3: Part 2 // Calculate the pixels, whose neighbours are on all 4 sides of this pixel for (y=HalfSpacing; y<=(Yres-HalfSpacing); y+=Spacing) { for (x=HalfSpacing; x<=(Xres-HalfSpacing); x+=Spacing) { I1 = LightMap[x, y-HalfSpacing] I2 = LightMap[x, y+HalfSpacing] I3 = LightMap[x-HalfSpacing, y] I4 = LightMap[x+HalfSpacing, y] if ( (ratio4(I1.R,I2.R,I3.R,I4.R) > threshold) && (ratio4(I1.G,I2.G,I3.G,I4.G) > threshold) && (ratio4(I1.B,I2.B,I3.B,I4.B) > threshold) ) { incidentLight.R = (I1.R + I2.R + I3.R + I4.R) * 0.25 incidentLight.G = (I1.G + I2.G + I3.G + I4.G) * 0.25 incidentLight.B = (I1.B + I2.B + I3.B + I4.B) * 0.25 LightMap[x,y] = incidentLight } else { SamplePoint = Calculate coordinates of centre of patch incidentLight = Calc_Incident_Light(SamplePoint, normal) LightMap[x, y] = incidentLight; } } } Spacing = Spacing / 2 Stop if Spacing = 1, otherwise go to Passes_Loop |