static void VisualizeSeams() { if (!CheckNonOptimizedLightmaps()) { return; } var lightmapMappings = GatherLightmaps(); foreach (var lightmapMapping in lightmapMappings) { var lightmap = lightmapMapping.lightmap; var pixels = ReadPixels(lightmap); List <SeamOptimizer.so_seam_t> seams = new List <SeamOptimizer.so_seam_t>(); foreach (var lightmapMesh in lightmapMapping.meshes) { seams.AddRange(SeamOptimizer.so_seams_find(lightmapMesh.mesh, pixels, lightmapMesh.lightmapST, lightmap.width, lightmap.height, 3, cosNormalThreshold)); } // visualize var debugPixels = new Color[pixels.Length]; #if false var seam = seams[4]; #else foreach (var seam in seams) #endif { var stichingPoint = seam.stitchingPoints; var texels = seam.texels; for (int i = 0; i < stichingPoint.capacity; i++) { var point = stichingPoint.points[i]; for (int j = 0; j < 2; j++) { var side = point.sides[j]; for (int k = 0; k < 4; k++) { int idx = side.texels[k].y * lightmap.width + side.texels[k].x; //Debug.LogFormat("(" + side.texels[k].x + "," + side.texels[k].y + ")" + side.weights[k]); //Debug.Assert(side.weights[k] > 0); debugPixels[idx].r += side.weights[k]; } } } // Kanglai: here texels.texels are just texels from stichingPoint.points.side for (int i = 0; i < texels.capacity; i++) { var texel = texels.texels[i]; if (texel.x == -1) { continue; } int idx = texel.y * lightmap.width + texel.x; //Debug.LogFormat("(" + texel.x + "," + texel.y + ")"); debugPixels[idx].g += 0.5f; } } var debug = new Texture2D(lightmap.width, lightmap.height, TextureFormat.RGBAFloat, false); for (int i = 0; i < debugPixels.Length; i++) { //if (debugPixels[i].r + debugPixels[i].g < 1e-6) // debugPixels[i] = pixels[i]; debugPixels[i].a = 1; } debug.SetPixels(debugPixels); debug.Apply(); var filename = AssetDatabase.GetAssetPath(lightmap); var newfilename = Path.GetDirectoryName(filename) + "/" + Path.GetFileNameWithoutExtension(filename) + "_visualize_seams.exr"; File.WriteAllBytes(newfilename, debug.EncodeToEXR(Texture2D.EXRFlags.CompressZIP)); Object.DestroyImmediate(debug); } Debug.Log("Visualize Seams Done"); AssetDatabase.Refresh(); }
static void OptimizeLightmaps() { if (!CheckNonOptimizedLightmaps()) { return; } var lightmapMappings = GatherLightmaps(); foreach (var lightmapMapping in lightmapMappings) { var lightmap = lightmapMapping.lightmap; var pixels = ReadPixels(lightmap); List <SeamOptimizer.so_seam_t> seams = new List <SeamOptimizer.so_seam_t>(); foreach (var lightmapMesh in lightmapMapping.meshes) { seams.AddRange(SeamOptimizer.so_seams_find(lightmapMesh.mesh, pixels, lightmapMesh.lightmapST, lightmap.width, lightmap.height, 3, cosNormalThreshold)); } #if false var seam = seams[4]; #else foreach (var seam in seams) #endif { if (!SeamOptimizer.so_seam_optimize(seam, pixels, lightmap.width, lightmap.height, 3, lambda)) { Debug.LogWarning("Seam Optimize Failed"); } } var result = new Texture2D(lightmap.width, lightmap.height, TextureFormat.RGBAFloat, false, true); result.SetPixels(pixels); result.Apply(); var filename = AssetDatabase.GetAssetPath(lightmap); var newfilename = Path.GetDirectoryName(filename) + "/" + Path.GetFileNameWithoutExtension(filename) + optimizedSuffix + ".exr"; File.WriteAllBytes(newfilename, result.EncodeToEXR(Texture2D.EXRFlags.CompressZIP)); Object.DestroyImmediate(result); Debug.Log("Seam Optimize Done"); AssetDatabase.Refresh(); bool needApply = false; var tiOld = AssetImporter.GetAtPath(filename) as TextureImporter; var tiNew = AssetImporter.GetAtPath(newfilename) as TextureImporter; if (tiNew.textureType != TextureImporterType.Lightmap) { tiNew.textureType = TextureImporterType.Lightmap; needApply = true; } if (tiNew.textureCompression != tiOld.textureCompression) { tiNew.textureCompression = tiOld.textureCompression; needApply = true; } if (tiNew.anisoLevel != tiOld.anisoLevel) { tiNew.anisoLevel = tiOld.anisoLevel; needApply = true; } if (needApply) { tiNew.SaveAndReimport(); } } }