private static Xen.Ex.SphericalHarmonicL2RGB ExtractSphericalHarmonicForCubeFace(Matrix faceTransform, Vector3[] colourDataRGB, int faceSize) { Xen.Ex.SphericalHarmonicL2RGB sh = new Xen.Ex.SphericalHarmonicL2RGB(); //For each pixel in the face, generate it's SH contribution. //Treat each pixel in the cube as a light source, which gets added to the SH. //This is used to generate an indirect lighting SH for the scene. //See the remarks in SphericalHarmonicL2RGB for more detals. float directionStep = 2.0f / (faceSize - 1.0f); int pixelIndex = 0; float dirY = 1.0f; for (int y = 0; y < faceSize; y++) { Xen.Ex.SphericalHarmonicL2RGB lineSh = new Xen.Ex.SphericalHarmonicL2RGB(); float dirX = -1.0f; for (int x = 0; x < faceSize; x++) { //the direction to the pixel in the cube Vector3 direction = new Vector3(dirX, dirY, 1); Vector3.TransformNormal(ref direction, ref faceTransform, out direction); //length of the direction vector float length = direction.Length(); //approximate area of the pixel (pixels close to the cube edges appear smaller when projected) float weight = 1.0f / length; //normalise: direction.X *= weight; direction.Y *= weight; direction.Z *= weight; //decode the RGBM colour Vector3 rgb = colourDataRGB[pixelIndex++]; //Add it to the SH lineSh.AddLight(ref rgb, ref direction, weight); dirX += directionStep; } //average the SH if (lineSh.Weighting > 0) { lineSh /= lineSh.Weighting; } //add the line to the full SH //(SH is generated line by line to ease problems with floating point accuracy loss) sh += lineSh; dirY -= directionStep; } if (sh.Weighting > 0) { sh /= sh.Weighting; } return(sh); }
private static Xen.Ex.SphericalHarmonicL2RGB ExtractSphericalHarmonicForCubeFace(Matrix faceTransform, Vector3[] colourDataRGB, int faceSize) { Xen.Ex.SphericalHarmonicL2RGB sh = new Xen.Ex.SphericalHarmonicL2RGB(); //For each pixel in the face, generate it's SH contribution. //Treat each pixel in the cube as a light source, which gets added to the SH. //This is used to generate an indirect lighting SH for the scene. //See the remarks in SphericalHarmonicL2RGB for more detals. float directionStep = 2.0f / (faceSize - 1.0f); int pixelIndex = 0; float dirY = 1.0f; for (int y = 0; y < faceSize; y++) { Xen.Ex.SphericalHarmonicL2RGB lineSh = new Xen.Ex.SphericalHarmonicL2RGB(); float dirX = -1.0f; for (int x = 0; x < faceSize; x++) { //the direction to the pixel in the cube Vector3 direction = new Vector3(dirX, dirY, 1); Vector3.TransformNormal(ref direction, ref faceTransform, out direction); //length of the direction vector float length = direction.Length(); //approximate area of the pixel (pixels close to the cube edges appear smaller when projected) float weight = 1.0f / length; //normalise: direction.X *= weight; direction.Y *= weight; direction.Z *= weight; //decode the RGBM colour Vector3 rgb = colourDataRGB[pixelIndex++]; //Add it to the SH lineSh.AddLight(ref rgb, ref direction, weight); dirX += directionStep; } //average the SH if (lineSh.Weighting > 0) lineSh /= lineSh.Weighting; //add the line to the full SH //(SH is generated line by line to ease problems with floating point accuracy loss) sh += lineSh; dirY -= directionStep; } if (sh.Weighting > 0) sh /= sh.Weighting; return sh; }