MB3_TextureCombinerPackerMeshBaker.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using System;
  5. namespace DigitalOpus.MB.Core
  6. {
  7. internal class MB3_TextureCombinerPackerMeshBaker : MB3_TextureCombinerPackerRoot
  8. {
  9. public override IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
  10. MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
  11. AtlasPackingResult packedAtlasRects,
  12. Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
  13. MB2_LogLevel LOG_LEVEL)
  14. {
  15. Rect[] uvRects = packedAtlasRects.rects;
  16. int atlasSizeX = packedAtlasRects.atlasX;
  17. int atlasSizeY = packedAtlasRects.atlasY;
  18. if (LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY);
  19. for (int propIdx = 0; propIdx < data.numAtlases; propIdx++)
  20. {
  21. Texture2D atlas = null;
  22. ShaderTextureProperty property = data.texPropertyNames[propIdx];
  23. if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(propIdx, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
  24. {
  25. atlas = null;
  26. if (LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("=== Not creating atlas for " + property.name + " because textures are null and default value parameters are the same.");
  27. }
  28. else
  29. {
  30. if (LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("=== Creating atlas for " + property.name);
  31. GC.Collect();
  32. CreateTemporaryTexturesForAtlas(data.distinctMaterialTextures, combiner, propIdx, data);
  33. //use a jagged array because it is much more efficient in memory
  34. Color[][] atlasPixels = new Color[atlasSizeY][];
  35. for (int j = 0; j < atlasPixels.Length; j++)
  36. {
  37. atlasPixels[j] = new Color[atlasSizeX];
  38. }
  39. bool isNormalMap = false;
  40. if (property.isNormalMap) isNormalMap = true;
  41. for (int texSetIdx = 0; texSetIdx < data.distinctMaterialTextures.Count; texSetIdx++)
  42. {
  43. MB_TexSet texSet = data.distinctMaterialTextures[texSetIdx];
  44. MeshBakerMaterialTexture matTex = texSet.ts[propIdx];
  45. string s = "Creating Atlas '" + property.name + "' texture " + matTex.GetTexName();
  46. if (progressInfo != null) progressInfo(s, .01f);
  47. if (LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log(string.Format("Adding texture {0} to atlas {1} for texSet {2} srcMat {3}", matTex.GetTexName(), property.name, texSetIdx, texSet.matsAndGOs.mats[0].GetMaterialName()));
  48. Rect r = uvRects[texSetIdx];
  49. Texture2D t = texSet.ts[propIdx].GetTexture2D();
  50. int x = Mathf.RoundToInt(r.x * atlasSizeX);
  51. int y = Mathf.RoundToInt(r.y * atlasSizeY);
  52. int ww = Mathf.RoundToInt(r.width * atlasSizeX);
  53. int hh = Mathf.RoundToInt(r.height * atlasSizeY);
  54. if (ww == 0 || hh == 0) Debug.LogError("Image in atlas has no height or width " + r);
  55. if (progressInfo != null) progressInfo(s + " set ReadWrite flag", .01f);
  56. if (textureEditorMethods != null) textureEditorMethods.SetReadWriteFlag(t, true, true);
  57. if (progressInfo != null) progressInfo(s + "Copying to atlas: '" + matTex.GetTexName() + "'", .02f);
  58. DRect samplingRect = texSet.ts[propIdx].GetEncapsulatingSamplingRect();
  59. Debug.Assert(!texSet.ts[propIdx].isNull, string.Format("Adding texture {0} to atlas {1} for texSet {2} srcMat {3}", matTex.GetTexName(), property.name, texSetIdx, texSet.matsAndGOs.mats[0].GetMaterialName()));
  60. yield return CopyScaledAndTiledToAtlas(texSet.ts[propIdx], texSet, property, samplingRect, x, y, ww, hh, packedAtlasRects.padding[texSetIdx], atlasPixels, isNormalMap, data, combiner, progressInfo, LOG_LEVEL);
  61. }
  62. yield return data.numAtlases;
  63. if (progressInfo != null) progressInfo("Applying changes to atlas: '" + property.name + "'", .03f);
  64. atlas = new Texture2D(atlasSizeX, atlasSizeY, TextureFormat.ARGB32, true);
  65. for (int j = 0; j < atlasPixels.Length; j++)
  66. {
  67. atlas.SetPixels(0, j, atlasSizeX, 1, atlasPixels[j]);
  68. }
  69. atlas.Apply();
  70. if (LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("Saving atlas " + property.name + " w=" + atlas.width + " h=" + atlas.height);
  71. }
  72. atlases[propIdx] = atlas;
  73. if (progressInfo != null) progressInfo("Saving atlas: '" + property.name + "'", .04f);
  74. System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
  75. sw.Start();
  76. if (data._saveAtlasesAsAssets && textureEditorMethods != null)
  77. {
  78. textureEditorMethods.SaveAtlasToAssetDatabase(atlases[propIdx], data.texPropertyNames[propIdx], propIdx, data.resultMaterial);
  79. }
  80. else
  81. {
  82. data.resultMaterial.SetTexture(data.texPropertyNames[propIdx].name, atlases[propIdx]);
  83. }
  84. data.resultMaterial.SetTextureOffset(data.texPropertyNames[propIdx].name, Vector2.zero);
  85. data.resultMaterial.SetTextureScale(data.texPropertyNames[propIdx].name, Vector2.one);
  86. combiner._destroyTemporaryTextures(data.texPropertyNames[propIdx].name);
  87. }
  88. yield break;
  89. }
  90. internal static IEnumerator CopyScaledAndTiledToAtlas(MeshBakerMaterialTexture source, MB_TexSet sourceMaterial,
  91. ShaderTextureProperty shaderPropertyName, DRect srcSamplingRect, int targX, int targY, int targW, int targH,
  92. AtlasPadding padding,
  93. Color[][] atlasPixels, bool isNormalMap,
  94. MB3_TextureCombinerPipeline.TexturePipelineData data,
  95. MB3_TextureCombiner combiner,
  96. ProgressUpdateDelegate progressInfo = null,
  97. MB2_LogLevel LOG_LEVEL = MB2_LogLevel.info)
  98. {
  99. //HasFinished = false;
  100. Texture2D t = source.GetTexture2D();
  101. if (LOG_LEVEL >= MB2_LogLevel.debug)
  102. {
  103. Debug.Log(String.Format("CopyScaledAndTiledToAtlas: {0} inAtlasX={1} inAtlasY={2} inAtlasW={3} inAtlasH={4} paddX={5} paddY={6} srcSamplingRect={7}",
  104. t, targX, targY, targW, targH, padding.leftRight, padding.topBottom, srcSamplingRect));
  105. }
  106. float newWidth = targW;
  107. float newHeight = targH;
  108. float scx = (float)srcSamplingRect.width;
  109. float scy = (float)srcSamplingRect.height;
  110. float ox = (float)srcSamplingRect.x;
  111. float oy = (float)srcSamplingRect.y;
  112. int w = (int)newWidth;
  113. int h = (int)newHeight;
  114. if (data._considerNonTextureProperties)
  115. {
  116. t = combiner._createTextureCopy(shaderPropertyName.name, t);
  117. t = data.nonTexturePropertyBlender.TintTextureWithTextureCombiner(t, sourceMaterial, shaderPropertyName);
  118. }
  119. for (int i = 0; i < w; i++)
  120. {
  121. if (progressInfo != null && w > 0) progressInfo("CopyScaledAndTiledToAtlas " + (((float)i / (float)w) * 100f).ToString("F0"), .2f);
  122. for (int j = 0; j < h; j++)
  123. {
  124. float u = i / newWidth * scx + ox;
  125. float v = j / newHeight * scy + oy;
  126. atlasPixels[targY + j][targX + i] = t.GetPixelBilinear(u, v);
  127. }
  128. }
  129. //bleed the border colors into the padding
  130. for (int i = 0; i < w; i++)
  131. {
  132. for (int j = 1; j <= padding.topBottom; j++)
  133. {
  134. //top margin
  135. atlasPixels[(targY - j)][targX + i] = atlasPixels[(targY)][targX + i];
  136. //bottom margin
  137. atlasPixels[(targY + h - 1 + j)][targX + i] = atlasPixels[(targY + h - 1)][targX + i];
  138. }
  139. }
  140. for (int j = 0; j < h; j++)
  141. {
  142. for (int i = 1; i <= padding.leftRight; i++)
  143. {
  144. //left margin
  145. atlasPixels[(targY + j)][targX - i] = atlasPixels[(targY + j)][targX];
  146. //right margin
  147. atlasPixels[(targY + j)][targX + w + i - 1] = atlasPixels[(targY + j)][targX + w - 1];
  148. }
  149. }
  150. //corners
  151. for (int i = 1; i <= padding.leftRight; i++)
  152. {
  153. for (int j = 1; j <= padding.topBottom; j++)
  154. {
  155. atlasPixels[(targY - j)][targX - i] = atlasPixels[targY][targX];
  156. atlasPixels[(targY + h - 1 + j)][targX - i] = atlasPixels[(targY + h - 1)][targX];
  157. atlasPixels[(targY + h - 1 + j)][targX + w + i - 1] = atlasPixels[(targY + h - 1)][targX + w - 1];
  158. atlasPixels[(targY - j)][targX + w + i - 1] = atlasPixels[targY][targX + w - 1];
  159. yield return null;
  160. }
  161. yield return null;
  162. }
  163. // Debug.Log("copyandscaledatlas finished too!");
  164. //HasFinished = true;
  165. yield break;
  166. }
  167. }
  168. }