public ImageData(string filePath) { FilePath = filePath; if (!File.Exists(FilePath)) { Debug.LogError("lightmap doesn't exist at path: '" + FilePath + "'"); } AssetPath = WpHelper.FilePathToAssetPath(FilePath); TextureImporter tImporter = AssetImporter.GetAtPath(AssetPath) as TextureImporter; if (tImporter != null) { tImporter.textureType = TextureImporterType.Default; tImporter.sRGBTexture = true; tImporter.SetPlatformTextureSettings(new TextureImporterPlatformSettings() { format = TextureImporterFormat.RGBA32 }); tImporter.isReadable = true; AssetDatabase.ImportAsset(AssetPath); } Texture2D tex = AssetDatabase.LoadAssetAtPath(AssetPath, typeof(Texture2D)) as Texture2D; if (null == tex) { Debug.LogError("Failed to load the lightmap at path: " + AssetPath); return; } Width = tex.width; Height = tex.height; SrcPixels = tex.GetPixels(); DstPixels = tex.GetPixels(); if (tImporter != null) { tImporter.textureType = TextureImporterType.Lightmap; tImporter.sRGBTexture = true; tImporter.textureCompression = TextureImporterCompression.CompressedLQ; tImporter.isReadable = false; AssetDatabase.ImportAsset(AssetPath); } //WPHelper.MakeTextureReadable( tex, false ); // dstPixels = new Color[width * height]; // // for (int i = 0; i < width*height; i++) { // dstPixels[i] = new Color(.5f, .5f, .5f, 1f); // } // for (int x = 0; x < width; x++) { // //Debug.Log(dstPixels[x].r * 255f + " " + dstPixels[x].g * 255f + " " + dstPixels[x].b * 255f); // } Save(); }
private static string[] PrepareLightmaps(GameObject[] affectedObjects) { // //Duplicate original lightmaps List <int> lightmapsToBackup = new List <int>(); foreach (GameObject obj in affectedObjects) { int lightmapIndex = -1; if (obj.GetComponent <Renderer>() != null) { lightmapIndex = obj.GetComponent <Renderer>().lightmapIndex; } else { Terrain terrain = obj.GetComponent <Terrain>(); if (terrain != null) { lightmapIndex = terrain.lightmapIndex; } } if (lightmapIndex < 0) { continue; } //Make sure that we keep only lightmapped objects if (lightmapIndex < 0 || lightmapIndex >= LightmapSettings.lightmaps.Length) { continue; } if (!lightmapsToBackup.Contains(lightmapIndex)) { if (LightmapSettings.lightmaps[lightmapIndex] != null) { lightmapsToBackup.Add(lightmapIndex); } } //Find to what triangle does the point belong to //UpdateLightmap(obj); } string[] lightmapPaths = new string[LightmapSettings.lightmaps.Length]; int lightmapsCount = 0; foreach (int lightmapIndex in lightmapsToBackup) { Texture2D lightmapFar = LightmapSettings.lightmaps[lightmapIndex].lightmapColor; if (lightmapFar == null) { continue; } string lightMapAssetPath = AssetDatabase.GetAssetPath(lightmapFar); //Debug.Log("lightMapAssetPath for " + lightmapIndex + " is " + lightMapAssetPath); if (lightMapAssetPath == null) { continue; } if (lightMapAssetPath.Length <= 0) { continue; } if (WpHelper.HasSuffix(lightMapAssetPath, "__WP")) { string originalLightmapPath = WpHelper.RemoveSuffixFromFilename(lightMapAssetPath, "__WP"); //Debug.Log("WaterPlus lightmap already exists. Will be using the original one at path " + originalLightmapPath); if (!File.Exists(originalLightmapPath)) { Debug.LogError("Cannot find the original lightmap at path " + originalLightmapPath + ". Aborting"); return(null); } lightMapAssetPath = originalLightmapPath; } string waterPlusLightmapAssetPath = WpHelper.AddSuffixToFilename(lightMapAssetPath, "__WP"); AssetDatabase.DeleteAsset(waterPlusLightmapAssetPath); AssetDatabase.CopyAsset(lightMapAssetPath, waterPlusLightmapAssetPath); AssetDatabase.ImportAsset(waterPlusLightmapAssetPath, ImportAssetOptions.ForceUpdate); AssetDatabase.Refresh(); lightmapPaths[lightmapIndex] = WpHelper.AssetPathToFilePath(waterPlusLightmapAssetPath); lightmapsCount++; //LightmapSettings.lightmaps[ lightmapIndex ].lightmapFar = AssetDatabase.LoadAssetAtPath( waterPlusLightmapAssetPath, // typeof(Texture2D) ) as Texture2D; } //Load the new lightmaps LightmapData[] lightmapsData = new LightmapData[LightmapSettings.lightmaps.Length]; for (int i = 0; i < lightmapPaths.Length; i++) { bool shouldUseOriginalLm = false; if (lightmapPaths[i] == null) { shouldUseOriginalLm = true; } else if (lightmapPaths[i].Length <= 0) { shouldUseOriginalLm = true; } if (!shouldUseOriginalLm) { LightmapData lmData = new LightmapData { lightmapColor = AssetDatabase.LoadAssetAtPath(WpHelper.FilePathToAssetPath(lightmapPaths[i]), typeof(Texture2D)) as Texture2D }; if (lmData.lightmapColor == null) { Debug.LogWarning("lmData.lightmapFar == null for " + WpHelper.FilePathToAssetPath(lightmapPaths[i])); lmData.lightmapColor = LightmapSettings.lightmaps[i].lightmapColor; } //if (LightmapSettings.lightmaps[i].lightmapNear != null) lmData.lightmapDir = LightmapSettings.lightmaps[i].lightmapDir; lightmapsData[i] = lmData; } else { lightmapsData[i] = LightmapSettings.lightmaps[i]; } } LightmapSettings.lightmaps = lightmapsData; if (lightmapsCount <= 0) { Debug.LogError("Nothing to bake - no lightmaps found."); return(null); } return(lightmapPaths); }
private static void BakeLightmaps(WPLightmapData lightmapData) { // Debug.Log ("waterLevel: " + lightmapData.waterLevel); // Debug.Log ("wetnessHeight: " + lightmapData.wetnessHeight); // Debug.Log ("wetnessAmount: " + lightmapData.wetnessAmount); // //Load all of the lightmaps ImageData[] imagesData = new ImageData[lightmapData.lightmapFiles.Length]; for (int lightmapIndex = 0; lightmapIndex < lightmapData.lightmapFiles.Length; lightmapIndex++) { bool shouldSkipFile = false; //Don't load non-used lightmaps if (lightmapData.lightmapFiles[lightmapIndex] == null) { shouldSkipFile = true; } else if (lightmapData.lightmapFiles.Length <= 0) { shouldSkipFile = true; } if (shouldSkipFile) { Debug.Log("Skipping lightmap " + lightmapIndex + " because the lightmap is non-used"); continue; } string filePath = lightmapData.lightmapFiles[lightmapIndex]; //string filePath = "C:/Users/Me/Desktop/Water+/iPhone4_hq_1.png"; //string filePath = "1/LightmapFar-0.exr"; //string filePath = "C:/Users/Me/waterplus/Assets/WaterPlus/Water_Island/LightmapFar-0.exr"; //Debug.Log("lightmap path: " + filePath); imagesData[lightmapIndex] = new ImageData(filePath); /*for (int i = 0; i < imagesData[lightmapIndex].width * imagesData[lightmapIndex].height; i++) { * imagesData[lightmapIndex].pixels[i].r = imagesData[lightmapIndex].pixels[i].r * imagesData[lightmapIndex].pixels[i].r * .5f; * imagesData[lightmapIndex].pixels[i].g = imagesData[lightmapIndex].pixels[i].g * imagesData[lightmapIndex].pixels[i].g * 2.0f; * imagesData[lightmapIndex].pixels[i].b = imagesData[lightmapIndex].pixels[i].b * imagesData[lightmapIndex].pixels[i].b; * }*/ //Debug.Log("Successfully loaded lightmap at path " + filePath); //break; } //Debug.Log ("Successfully loaded lightmaps."); //return; System.DateTime bakeStartTime = System.DateTime.Now; //int count = 0; //1. Go over all pixels of the mesh //2. Convert UV to vertex //3. If the vertex is within water line, update the lightmap. //Debug.Log ("Updating lightmaps."); //int totalObjectsToBake = lightmapData.meshes.Length + lightmapData.terrains.Length; // //Regular meshes foreach (WPMesh obj in lightmapData.meshes) { if (obj.lightmapIndex < 0 || obj.lightmapIndex >= imagesData.Length) { Debug.Log("skipping " + obj + " because of a wrong lightmapIndex: " + obj.lightmapIndex); continue; } //Calculate object's texel size ImageData lightmapUsed = imagesData[obj.lightmapIndex]; int lightmapResolution = lightmapUsed.Width; Vector4 tilingOffset = obj.tilingOffset; if (lightmapResolution == 0) { Debug.Log("error: lightmapResolution == 0"); continue; } if (tilingOffset.x == 0) { Debug.LogError("error: tilingOffset.x == 0"); continue; } float pixelSize = 1.0f / (tilingOffset.x * lightmapResolution); //Debug.Log("tilingOffset: " + tilingOffset.ToString() + " " + lightmapResolution); //Console //Debug.Log("2"); Vector2[] meshUVs = obj.uvs; if (meshUVs == null) { Debug.Log("No UVs found for " + obj.name); continue; } //Debug.Log("pixelSize: " + pixelSize); Matrix4x4 tempMatrix = new Matrix4x4(); tempMatrix.SetRow(0, obj.localToWorldMatrix[0]); tempMatrix.SetRow(1, obj.localToWorldMatrix[1]); tempMatrix.SetRow(2, obj.localToWorldMatrix[2]); tempMatrix.SetRow(3, obj.localToWorldMatrix[3]); //Debug.Log( tempMatrix.GetRow(3) ); //Debug.Log("1 * matrix: " + tempMatrix.MultiplyPoint(Vector3.one) ); for (float u = 0.0f; u < 1.0f; u += pixelSize) { //Progress for large objects //if (1.0f / (pixelSize * pixelSize) >= 10000.0f) { //Make sure to log only every percent, not less // if (u - previousProgress >= .01f) { // Console.Write("\r\t" + obj.name + " progress: " + (u * 100.0f).ToString("0") + "%"); // previousProgress = u; // } //} for (float v = 0.0f; v < 1.0f; v += pixelSize) { //totalPixels++; //Convert UV to vertex position Vector2 currentUv = new Vector2(u, v); bool vertexFound; Vector3 vertexPos; WpHelper.UvToVertex(currentUv, obj, meshUVs, out vertexFound, out vertexPos); //Update the lightmap //vertexFound = true; if (vertexFound) { vertexPos = tempMatrix.MultiplyPoint(vertexPos); //if (u >= .45f && u <= .55f) //if (1.0f / (pixelSize * pixelSize) >= 10000.0f) // Console.Write(vertexPos.y + "\t"); //Debug.Log("vertexPos.y: " + vertexPos.y); if (vertexPos.y <= lightmapData.waterLevel + lightmapData.wetnessHeight) { //Convert object's UV to lightmap's UV Vector2 lightmapUv = currentUv; lightmapUv.x *= tilingOffset.x; lightmapUv.y *= tilingOffset.y; lightmapUv.x += tilingOffset.z; lightmapUv.y += tilingOffset.w; int lightmapX = (int)(lightmapUv.x * lightmapResolution); int lightmapY = (int)(lightmapUv.y * lightmapResolution); if (lightmapX < 0 || lightmapX >= lightmapResolution || lightmapY < 0 || lightmapY >= lightmapResolution) { //Debug.LogWarning("lightmapX: " + lightmapX + " lightmapY: " + lightmapY); } else { //lightmapPixels[lightmapY * lightmapResolution + lightmapX] = Color.yellow; float gradientAmount; if (vertexPos.y <= lightmapData.waterLevel) { gradientAmount = 1.0f; } else if (vertexPos.y > lightmapData.waterLevel + lightmapData.wetnessHeight) { gradientAmount = 0.0f; } else { gradientAmount = 1.0f - (vertexPos.y - lightmapData.waterLevel) / lightmapData.wetnessHeight; } gradientAmount = 1.0f - gradientAmount * lightmapData.wetnessAmount; gradientAmount = Mathf.Clamp01(gradientAmount); //Just in case lightmapUsed.DstPixels[lightmapY * lightmapResolution + lightmapX].r = lightmapUsed.SrcPixels[lightmapY * lightmapResolution + lightmapX].r * gradientAmount; lightmapUsed.DstPixels[lightmapY * lightmapResolution + lightmapX].g = lightmapUsed.SrcPixels[lightmapY * lightmapResolution + lightmapX].g * gradientAmount; lightmapUsed.DstPixels[lightmapY * lightmapResolution + lightmapX].b = lightmapUsed.SrcPixels[lightmapY * lightmapResolution + lightmapX].b * gradientAmount; } } } } } } //Terrains foreach (WPTerrainData obj in lightmapData.terrains) { if (obj.lightmapIndex < 0 || obj.lightmapIndex >= imagesData.Length) { Debug.Log("skipping " + obj + " because of a wrong lightmapIndex: " + obj.lightmapIndex); continue; } //Calculate object's texel size ImageData lightmapUsed = imagesData[obj.lightmapIndex]; int lightmapResolution = lightmapUsed.Width; if (lightmapResolution == 0) { Debug.Log("error: lightmapResolution == 0"); continue; } float pixelSize = 1.0f / lightmapResolution; for (float u = 0.0f; u < 1.0f; u += pixelSize) { for (float v = 0.0f; v < 1.0f; v += pixelSize) { //Update the lightmap int heightmapX = (int)(v * obj.height); int heightmapY = (int)(u * obj.width); if (heightmapX < 0 || heightmapX >= obj.width || heightmapY < 0 || heightmapY >= obj.height) { continue; } int lightmapX = (int)(u * lightmapResolution); int lightmapY = (int)(v * lightmapResolution); if (lightmapX < 0 || lightmapX >= lightmapResolution || lightmapY < 0 || lightmapY >= lightmapResolution) { continue; } float yPos = obj.position.y + obj.heightmap[heightmapY * obj.height + heightmapX]; if (yPos <= lightmapData.waterLevel + lightmapData.wetnessHeight) { //if (yPos > 0) // Debug.Log("yPos: " + yPos + " waterLevel: " + lightmapData.waterLevel); float gradientAmount; if (yPos <= lightmapData.waterLevel) { gradientAmount = 1.0f; } else if (yPos > lightmapData.waterLevel + lightmapData.wetnessHeight) { gradientAmount = 0.0f; } else { gradientAmount = 1.0f - (yPos - lightmapData.waterLevel) / lightmapData.wetnessHeight; } gradientAmount = 1.0f - gradientAmount * lightmapData.wetnessAmount; gradientAmount = Mathf.Clamp01(gradientAmount); //Just in case lightmapUsed.DstPixels[lightmapY * lightmapResolution + lightmapX].r = lightmapUsed.SrcPixels[lightmapY * lightmapResolution + lightmapX].r * gradientAmount; lightmapUsed.DstPixels[lightmapY * lightmapResolution + lightmapX].g = lightmapUsed.SrcPixels[lightmapY * lightmapResolution + lightmapX].r * gradientAmount; lightmapUsed.DstPixels[lightmapY * lightmapResolution + lightmapX].b = lightmapUsed.SrcPixels[lightmapY * lightmapResolution + lightmapX].r * gradientAmount; } } } } //Save all the lightmaps foreach (ImageData data in imagesData) { if (null == data) { continue; } data.Save(); } Debug.Log("Successfully updated the lightmaps in " + (System.DateTime.Now - bakeStartTime).TotalSeconds + " seconds."); }