MB3_TextureCombinerPackerMeshBaker.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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.resultType == MB2_TextureBakeResults.ResultType.atlas)
  77. {
  78. if (data._saveAtlasesAsAssets && textureEditorMethods != null)
  79. {
  80. textureEditorMethods.SaveAtlasToAssetDatabase(atlases[propIdx], data.texPropertyNames[propIdx], propIdx, data.resultMaterial);
  81. }
  82. else
  83. {
  84. data.resultMaterial.SetTexture(data.texPropertyNames[propIdx].name, atlases[propIdx]);
  85. }
  86. data.resultMaterial.SetTextureOffset(data.texPropertyNames[propIdx].name, Vector2.zero);
  87. data.resultMaterial.SetTextureScale(data.texPropertyNames[propIdx].name, Vector2.one);
  88. }
  89. combiner._destroyTemporaryTextures(data.texPropertyNames[propIdx].name);
  90. }
  91. yield break;
  92. }
  93. internal static IEnumerator CopyScaledAndTiledToAtlas(MeshBakerMaterialTexture source, MB_TexSet sourceMaterial,
  94. ShaderTextureProperty shaderPropertyName, DRect srcSamplingRect, int targX, int targY, int targW, int targH,
  95. AtlasPadding padding,
  96. Color[][] atlasPixels, bool isNormalMap,
  97. MB3_TextureCombinerPipeline.TexturePipelineData data,
  98. MB3_TextureCombiner combiner,
  99. ProgressUpdateDelegate progressInfo = null,
  100. MB2_LogLevel LOG_LEVEL = MB2_LogLevel.info)
  101. {
  102. //HasFinished = false;
  103. Texture2D t = source.GetTexture2D();
  104. if (LOG_LEVEL >= MB2_LogLevel.debug)
  105. {
  106. Debug.Log(String.Format("CopyScaledAndTiledToAtlas: {0} inAtlasX={1} inAtlasY={2} inAtlasW={3} inAtlasH={4} paddX={5} paddY={6} srcSamplingRect={7}",
  107. t, targX, targY, targW, targH, padding.leftRight, padding.topBottom, srcSamplingRect));
  108. }
  109. float newWidth = targW;
  110. float newHeight = targH;
  111. float scx = (float)srcSamplingRect.width;
  112. float scy = (float)srcSamplingRect.height;
  113. float ox = (float)srcSamplingRect.x;
  114. float oy = (float)srcSamplingRect.y;
  115. int w = (int)newWidth;
  116. int h = (int)newHeight;
  117. if (data._considerNonTextureProperties)
  118. {
  119. t = combiner._createTextureCopy(shaderPropertyName.name, t);
  120. t = data.nonTexturePropertyBlender.TintTextureWithTextureCombiner(t, sourceMaterial, shaderPropertyName);
  121. }
  122. for (int i = 0; i < w; i++)
  123. {
  124. if (progressInfo != null && w > 0) progressInfo("CopyScaledAndTiledToAtlas " + (((float)i / (float)w) * 100f).ToString("F0"), .2f);
  125. for (int j = 0; j < h; j++)
  126. {
  127. float u = i / newWidth * scx + ox;
  128. float v = j / newHeight * scy + oy;
  129. atlasPixels[targY + j][targX + i] = t.GetPixelBilinear(u, v);
  130. }
  131. }
  132. //bleed the border colors into the padding
  133. for (int i = 0; i < w; i++)
  134. {
  135. for (int j = 1; j <= padding.topBottom; j++)
  136. {
  137. //top margin
  138. atlasPixels[(targY - j)][targX + i] = atlasPixels[(targY)][targX + i];
  139. //bottom margin
  140. atlasPixels[(targY + h - 1 + j)][targX + i] = atlasPixels[(targY + h - 1)][targX + i];
  141. }
  142. }
  143. for (int j = 0; j < h; j++)
  144. {
  145. for (int i = 1; i <= padding.leftRight; i++)
  146. {
  147. //left margin
  148. atlasPixels[(targY + j)][targX - i] = atlasPixels[(targY + j)][targX];
  149. //right margin
  150. atlasPixels[(targY + j)][targX + w + i - 1] = atlasPixels[(targY + j)][targX + w - 1];
  151. }
  152. }
  153. //corners
  154. for (int i = 1; i <= padding.leftRight; i++)
  155. {
  156. for (int j = 1; j <= padding.topBottom; j++)
  157. {
  158. atlasPixels[(targY - j)][targX - i] = atlasPixels[targY][targX];
  159. atlasPixels[(targY + h - 1 + j)][targX - i] = atlasPixels[(targY + h - 1)][targX];
  160. atlasPixels[(targY + h - 1 + j)][targX + w + i - 1] = atlasPixels[(targY + h - 1)][targX + w - 1];
  161. atlasPixels[(targY - j)][targX + w + i - 1] = atlasPixels[targY][targX + w - 1];
  162. yield return null;
  163. }
  164. yield return null;
  165. }
  166. // Debug.Log("copyandscaledatlas finished too!");
  167. //HasFinished = true;
  168. yield break;
  169. }
  170. }
  171. }