public Texture2D DoRenderAtlas(GameObject gameObject, int width, int height, int padding, Rect[] rss, List<MB3_TextureCombiner.MB_TexSet> textureSetss, int indexOfTexSetToRenders, bool isNormalMap, bool fixOutOfBoundsUVs, MB3_TextureCombiner texCombiner, MB2_LogLevel LOG_LEV)
 {
     this.LOG_LEVEL = LOG_LEV;
     this.textureSets = textureSetss;
     this.indexOfTexSetToRender = indexOfTexSetToRenders;
     this._padding = padding;
     this._isNormalMap = isNormalMap;
     this._fixOutOfBoundsUVs = fixOutOfBoundsUVs;
     this.combiner = texCombiner;
     this.rs = rss;
     Shader shader;
     if (this._isNormalMap)
     {
         shader = Shader.Find("MeshBaker/NormalMapShader");
     }
     else
     {
         shader = Shader.Find("MeshBaker/AlbedoShader");
     }
     if (shader == null)
     {
         UnityEngine.Debug.LogError("Could not find shader for RenderTexture. Try reimporting mesh baker");
         return null;
     }
     this.mat = new Material(shader);
     this._destinationTexture = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32);
     this._destinationTexture.filterMode = FilterMode.Point;
     this.myCamera = gameObject.GetComponent<Camera>();
     this.myCamera.orthographic = true;
     this.myCamera.orthographicSize = (float)(height >> 1);
     this.myCamera.aspect = (float)(width / height);
     this.myCamera.targetTexture = this._destinationTexture;
     this.myCamera.clearFlags = CameraClearFlags.Color;
     Transform component = this.myCamera.GetComponent<Transform>();
     component.localPosition = new Vector3((float)width / 2f, (float)height / 2f, 3f);
     component.localRotation = Quaternion.Euler(0f, 180f, 180f);
     this._doRenderAtlas = true;
     if (this.LOG_LEVEL >= MB2_LogLevel.debug)
     {
         UnityEngine.Debug.Log(string.Format("Begin Camera.Render destTex w={0} h={1} camPos={2}", width, height, component.localPosition));
     }
     this.myCamera.Render();
     this._doRenderAtlas = false;
     MB_Utility.Destroy(this.mat);
     MB_Utility.Destroy(this._destinationTexture);
     if (this.LOG_LEVEL >= MB2_LogLevel.debug)
     {
         UnityEngine.Debug.Log("Finished Camera.Render ");
     }
     Texture2D result = this.targTex;
     this.targTex = null;
     return result;
 }
	public Texture2D DoRenderAtlas(GameObject gameObject, int width, int height, int padding, Rect[] rss, List<MB3_TextureCombiner.MB_TexSet> textureSetss, int indexOfTexSetToRenders, bool isNormalMap, bool fixOutOfBoundsUVs, MB3_TextureCombiner texCombiner, MB2_LogLevel LOG_LEV){
		LOG_LEVEL = LOG_LEV;
		textureSets = textureSetss;
		indexOfTexSetToRender = indexOfTexSetToRenders;
		_padding = padding;
		_isNormalMap = isNormalMap;
        _fixOutOfBoundsUVs = fixOutOfBoundsUVs;
        combiner = texCombiner;
		rs = rss;
		Shader s;
		if (_isNormalMap){
			s = Shader.Find ("MeshBaker/NormalMapShader");
		} else {
			s = Shader.Find ("MeshBaker/AlbedoShader");
		}
		if (s == null){
			Debug.LogError ("Could not find shader for RenderTexture. Try reimporting mesh baker");
			return null;
		}
		mat = new Material(s);
		_destinationTexture = new RenderTexture(width,height,24,RenderTextureFormat.ARGB32);
		_destinationTexture.filterMode = FilterMode.Point;
		
		myCamera = gameObject.GetComponent<Camera>();
		myCamera.orthographic = true;
		myCamera.orthographicSize = height >> 1;
		myCamera.aspect = width / height;
		myCamera.targetTexture = _destinationTexture;
		myCamera.clearFlags = CameraClearFlags.Color;
		
		Transform camTransform = myCamera.GetComponent<Transform>();
		camTransform.localPosition = new Vector3(width/2.0f, height/2f, 3);
		camTransform.localRotation = Quaternion.Euler(0, 180, 180);
		
		_doRenderAtlas = true;
		if (LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log(string.Format ("Begin Camera.Render destTex w={0} h={1} camPos={2}", width, height, camTransform.localPosition));
        //This triggers the OnRenderObject callback
		myCamera.Render();
		_doRenderAtlas = false;
		
		MB_Utility.Destroy(mat);
		MB_Utility.Destroy(_destinationTexture);
		
		if (LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log ("Finished Camera.Render ");

		Texture2D tempTex = targTex;
		targTex = null;
		return tempTex;
	}
        public IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
            MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
            AtlasPackingResult packedAtlasRects,
            Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
            MB2_LogLevel LOG_LEVEL)
        {
            Debug.Assert(data.OnlyOneTextureInAtlasReuseTextures());
            if (LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("Only one image per atlas. Will re-use original texture");
            for (int i = 0; i < data.numAtlases; i++)
            {
                MeshBakerMaterialTexture dmt = data.distinctMaterialTextures[0].ts[i];
                atlases[i] = dmt.GetTexture2D();
                if (data.resultType == MB2_TextureBakeResults.ResultType.atlas)
                {
                    data.resultMaterial.SetTexture(data.texPropertyNames[i].name, atlases[i]);
                    data.resultMaterial.SetTextureScale(data.texPropertyNames[i].name, Vector2.one);
                    data.resultMaterial.SetTextureOffset(data.texPropertyNames[i].name, Vector2.zero);
                }
            }

            yield break;
        }
        public static void MakeProceduralTexturesReadable(ProgressUpdateDelegate progressInfo,
                                                          MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult result,
                                                          MB3_TextureCombinerPipeline.TexturePipelineData data,
                                                          MB3_TextureCombiner combiner,
                                                          MB2_EditorMethodsInterface textureEditorMethods,
                                                          MB2_LogLevel LOG_LEVEL)
        {
            Debug.LogError("TODO this should be done as close to textures being used as possible due to memory issues.");
            //make procedural materials readable

            /*
             * for (int i = 0; i < combiner._proceduralMaterials.Count; i++)
             * {
             *  if (!combiner._proceduralMaterials[i].proceduralMat.isReadable)
             *  {
             *      combiner._proceduralMaterials[i].originalIsReadableVal = combiner._proceduralMaterials[i].proceduralMat.isReadable;
             *      combiner._proceduralMaterials[i].proceduralMat.isReadable = true;
             *      //textureEditorMethods.AddProceduralMaterialFormat(_proceduralMaterials[i].proceduralMat);
             *      combiner._proceduralMaterials[i].proceduralMat.RebuildTexturesImmediately();
             *  }
             * }
             * //convert procedural textures to RAW format
             *
             * for (int i = 0; i < distinctMaterialTextures.Count; i++)
             * {
             *  for (int j = 0; j < texPropertyNames.Count; j++)
             *  {
             *      if (distinctMaterialTextures[i].ts[j].IsProceduralTexture())
             *      {
             *          if (LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("Converting procedural texture to Textur2D:" + distinctMaterialTextures[i].ts[j].GetTexName() + " property:" + texPropertyNames[i]);
             *          Texture2D txx = distinctMaterialTextures[i].ts[j].ConvertProceduralToTexture2D(_temporaryTextures);
             *          distinctMaterialTextures[i].ts[j].t = txx;
             *      }
             *  }
             * }
             */
        }
 public abstract IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                           MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                           AtlasPackingResult packedAtlasRects,
                                           Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                           MB2_LogLevel LOG_LEVEL);
Example #6
0
        /// <summary>
        /// Creates one texture array per texture property.
        /// </summary>
        /// <returns></returns>
        internal static Texture2DArray[] CreateTextureArraysForResultMaterial(TexturePropertyData texPropertyData, List <ShaderTextureProperty> masterListOfTexProperties, MB_AtlasesAndRects[] resultAtlasesAndRectSlices,
                                                                              bool[] hasTexForProperty, MB3_TextureCombiner combiner, MB2_LogLevel LOG_LEVEL)
        {
            Debug.Assert(texPropertyData.sizes.Length == hasTexForProperty.Length);

            // ASSUMPTION all slices in the same format and the same size, alpha channel and mipMapCount
            string[] texPropertyNames = resultAtlasesAndRectSlices[0].texPropertyNames;
            Debug.Assert(texPropertyNames.Length == hasTexForProperty.Length);
            Texture2DArray[] texArrays = new Texture2DArray[texPropertyNames.Length];

            // Each texture property (_MainTex, _Bump, ...) becomes a Texture2DArray
            for (int propIdx = 0; propIdx < texPropertyNames.Length; propIdx++)
            {
                if (!hasTexForProperty[propIdx])
                {
                    continue;
                }
                string        propName  = texPropertyNames[propIdx];
                int           numSlices = resultAtlasesAndRectSlices.Length;
                int           w         = (int)texPropertyData.sizes[propIdx].x;
                int           h         = (int)texPropertyData.sizes[propIdx].y;
                int           numMips   = (int)texPropertyData.numMipMaps[propIdx];
                TextureFormat format    = texPropertyData.formats[propIdx];
                bool          doMipMaps = texPropertyData.doMips[propIdx];

                Debug.Assert(QualitySettings.desiredColorSpace == QualitySettings.activeColorSpace, "Wanted to use color space " + QualitySettings.desiredColorSpace + " but the activeColorSpace was " + QualitySettings.activeColorSpace + " hardware may not support the desired color space.");

                bool isLinear = MBVersion.GetProjectColorSpace() == ColorSpace.Linear;
                {
                    if (IsLinearProperty(masterListOfTexProperties, propName))
                    {
                        isLinear = true;
                    }
                    else
                    {
                        isLinear = false;
                    }
                }

                Texture2DArray texArray = new Texture2DArray(w, h, numSlices, format, doMipMaps, isLinear);
                if (LOG_LEVEL >= MB2_LogLevel.info)
                {
                    Debug.LogFormat("Creating Texture2DArray for property: {0} w: {1} h: {2} format: {3} doMips: {4} isLinear: {5}", propName, w, h, format, doMipMaps, isLinear);
                }
                for (int sliceIdx = 0; sliceIdx < numSlices; sliceIdx++)
                {
                    Debug.Assert(resultAtlasesAndRectSlices[sliceIdx].atlases.Length == texPropertyNames.Length);
                    Debug.Assert(resultAtlasesAndRectSlices[sliceIdx].texPropertyNames[propIdx] == propName);
                    Texture2D srcTex = resultAtlasesAndRectSlices[sliceIdx].atlases[propIdx];

                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.LogFormat("Slice: {0}  texture: {1}", sliceIdx, srcTex);
                    }
                    bool isCopy = false;
                    if (srcTex == null)
                    {
                        if (LOG_LEVEL >= MB2_LogLevel.trace)
                        {
                            Debug.LogFormat("Texture is null for slice: {0} creating temporary texture", sliceIdx);
                        }
                        // Slices might not have all textures create a dummy if needed.
                        srcTex = combiner._createTemporaryTexture(propName, w, h, format, doMipMaps, isLinear);
                    }

                    Debug.Assert(srcTex.width == texArray.width, "Source texture is not the same width as the texture array '" + srcTex + " srcWidth:" + srcTex.width + " texArrayWidth:" + texArray.width);
                    Debug.Assert(srcTex.height == texArray.height, "Source texture is not the same height as the texture array " + srcTex + " srcWidth:" + srcTex.height + " texArrayWidth:" + texArray.height);
                    Debug.Assert(srcTex.mipmapCount == numMips, "Source texture does have not the same number of mips as the texture array: " + srcTex + " numMipsTex: " + srcTex.mipmapCount + " numMipsTexArray: " + numMips + " texDims: " + srcTex.width + "x" + srcTex.height);
                    Debug.Assert(srcTex.format == format, "Formats should have been converted before this. Texture: " + srcTex + "Source: " + srcTex.format + " Targ: " + format);

                    for (int mipIdx = 0; mipIdx < numMips; mipIdx++)
                    {
                        Graphics.CopyTexture(srcTex, 0, mipIdx, texArray, sliceIdx, mipIdx);
                    }

                    if (isCopy)
                    {
                        MB_Utility.Destroy(srcTex);
                    }
                }

                texArray.Apply();
                texArrays[propIdx] = texArray;
            }

            return(texArrays);
        }
        public IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                         MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                         AtlasPackingResult packedAtlasRects,
                                         Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                         MB2_LogLevel LOG_LEVEL)
        {
            Rect[] uvRects = packedAtlasRects.rects;
            if (uvRects.Length == 1)
            {
                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("Only one image per atlas. Will re-use original texture");
                }
                for (int i = 0; i < data.numAtlases; i++)
                {
                    MeshBakerMaterialTexture dmt = data.distinctMaterialTextures[0].ts[i];
                    atlases[i] = dmt.GetTexture2D();
                    data.resultMaterial.SetTexture(data.texPropertyNames[i].name, atlases[i]);
                    data.resultMaterial.SetTextureScale(data.texPropertyNames[i].name, dmt.matTilingRect.size);
                    data.resultMaterial.SetTextureOffset(data.texPropertyNames[i].name, dmt.matTilingRect.min);
                }
            }
            else
            {
                int atlasSizeX = packedAtlasRects.atlasX;
                int atlasSizeY = packedAtlasRects.atlasY;
                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY);
                }

                //create a game object
                GameObject renderAtlasesGO = null;
                try
                {
                    renderAtlasesGO = new GameObject("MBrenderAtlasesGO");
                    MB3_AtlasPackerRenderTexture atlasRenderTexture = renderAtlasesGO.AddComponent <MB3_AtlasPackerRenderTexture>();
                    renderAtlasesGO.AddComponent <Camera>();
                    if (data._considerNonTextureProperties)
                    {
                        if (LOG_LEVEL >= MB2_LogLevel.warn)
                        {
                            Debug.LogWarning("Blend Non-Texture Properties has limited functionality when used with Mesh Baker Texture Packer Fast.");
                        }
                    }
                    for (int i = 0; i < data.numAtlases; i++)
                    {
                        Texture2D atlas = null;
                        if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(i, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                        {
                            atlas = null;
                            if (LOG_LEVEL >= MB2_LogLevel.debug)
                            {
                                Debug.Log("Not creating atlas for " + data.texPropertyNames[i].name + " because textures are null and default value parameters are the same.");
                            }
                        }
                        else
                        {
                            GC.Collect();
                            if (progressInfo != null)
                            {
                                progressInfo("Creating Atlas '" + data.texPropertyNames[i].name + "'", .01f);
                            }
                            // ===========
                            // configure it
                            if (LOG_LEVEL >= MB2_LogLevel.debug)
                            {
                                Debug.Log("About to render " + data.texPropertyNames[i].name + " isNormal=" + data.texPropertyNames[i].isNormalMap);
                            }
                            atlasRenderTexture.LOG_LEVEL                    = LOG_LEVEL;
                            atlasRenderTexture.width                        = atlasSizeX;
                            atlasRenderTexture.height                       = atlasSizeY;
                            atlasRenderTexture.padding                      = data._atlasPadding;
                            atlasRenderTexture.rects                        = uvRects;
                            atlasRenderTexture.textureSets                  = data.distinctMaterialTextures;
                            atlasRenderTexture.indexOfTexSetToRender        = i;
                            atlasRenderTexture.texPropertyName              = data.texPropertyNames[i];
                            atlasRenderTexture.isNormalMap                  = data.texPropertyNames[i].isNormalMap;
                            atlasRenderTexture.fixOutOfBoundsUVs            = data._fixOutOfBoundsUVs;
                            atlasRenderTexture.considerNonTextureProperties = data._considerNonTextureProperties;
                            atlasRenderTexture.resultMaterialTextureBlender = data.nonTexturePropertyBlender;
                            // call render on it
                            atlas = atlasRenderTexture.OnRenderAtlas(combiner);

                            // destroy it
                            // =============
                            if (LOG_LEVEL >= MB2_LogLevel.debug)
                            {
                                Debug.Log("Saving atlas " + data.texPropertyNames[i].name + " w=" + atlas.width + " h=" + atlas.height + " id=" + atlas.GetInstanceID());
                            }
                        }
                        atlases[i] = atlas;
                        if (progressInfo != null)
                        {
                            progressInfo("Saving atlas: '" + data.texPropertyNames[i].name + "'", .04f);
                        }
                        if (data._saveAtlasesAsAssets && textureEditorMethods != null)
                        {
                            textureEditorMethods.SaveAtlasToAssetDatabase(atlases[i], data.texPropertyNames[i], i, data.resultMaterial);
                        }
                        else
                        {
                            data.resultMaterial.SetTexture(data.texPropertyNames[i].name, atlases[i]);
                        }
                        data.resultMaterial.SetTextureOffset(data.texPropertyNames[i].name, Vector2.zero);
                        data.resultMaterial.SetTextureScale(data.texPropertyNames[i].name, Vector2.one);
                        combiner._destroyTemporaryTextures(); // need to save atlases before doing this
                    }
                }
                catch (Exception ex)
                {
                    //Debug.LogError(ex);
                    Debug.LogException(ex);
                }
                finally
                {
                    if (renderAtlasesGO != null)
                    {
                        MB_Utility.Destroy(renderAtlasesGO);
                    }
                }
            }
            yield break;
        }
    private void CopyScaledAndTiledToAtlas(MB3_TextureCombiner.MeshBakerMaterialTexture source, Rect rec, int _padding, bool _fixOutOfBoundsUVs, int maxSize, bool isNormalMap)
    {
        Rect r = rec;
        r.x += _padding;
        r.y += _padding;
        r.width -= _padding * 2;
        r.height -= _padding * 2;

        //fill the _padding
        Rect srcPrTex = new Rect();
        Rect targPr = new Rect();

        srcPrTex.width = source.scale.x;
        srcPrTex.height = source.scale.y;
        srcPrTex.x = source.offset.x;
        srcPrTex.y = source.offset.y;
        if (_fixOutOfBoundsUVs){
            srcPrTex.width *= source.obUVscale.x;
            srcPrTex.height *= source.obUVscale.y;
            srcPrTex.x += source.obUVoffset.x;
            srcPrTex.y += source.obUVoffset.y;
        }
        Texture tex = source.t;

        //main texture
        TextureWrapMode oldTexWrapMode = tex.wrapMode;
        if (srcPrTex.width == 1f && srcPrTex.height == 1f && srcPrTex.x == 0f && srcPrTex.y == 0f){
            //fixes bug where there is a dark line at the edge of the texture
            tex.wrapMode = TextureWrapMode.Clamp;
        } else {
            tex.wrapMode = TextureWrapMode.Repeat;
        }
        Graphics.DrawTexture(r, tex, srcPrTex, 0, 0, 0, 0, mat);

        //TODO fill the _padding

        Rect srcPr = new Rect();

        //top margin
        srcPr.x = srcPrTex.x;
        srcPr.y = srcPrTex.y + 1f - 1f / tex.height;
        srcPr.width = srcPrTex.width;
        srcPr.height = 1f / tex.height;
        targPr.x = rec.x + _padding;
        targPr.y = rec.y;
        targPr.width = r.width;
        targPr.height = _padding;
        Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);

        //bot margin
        srcPr.x = srcPrTex.x;
        srcPr.y = srcPrTex.y;
        srcPr.width = srcPrTex.width;
        srcPr.height = 1f / tex.height;
        targPr.x = rec.x + _padding;
        targPr.y = rec.y + r.height + _padding;
        targPr.width = r.width;
        targPr.height = _padding;
        Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);

        //left margin
        srcPr.x = srcPrTex.x;
        srcPr.y = srcPrTex.y;
        srcPr.width = 1f / tex.width;
        srcPr.height = srcPrTex.height;
        targPr.x = rec.x;
        targPr.y = rec.y + _padding;
        targPr.width = _padding;
        targPr.height = r.height;
        Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);

        //right margin
        srcPr.x = srcPrTex.x + 1f - 1f / tex.width;
        srcPr.y = srcPrTex.y;
        srcPr.width = 1f / tex.width;
        srcPr.height = srcPrTex.height;
        targPr.x = rec.x + r.width + _padding;
        targPr.y = rec.y + _padding;
        targPr.width = _padding;
        targPr.height = r.height;
        Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);

        //top left corner
        srcPr.x = srcPrTex.x;
        srcPr.y = srcPrTex.y;
        srcPr.width = 1f / tex.width;
        srcPr.height = 1f / tex.height;
        targPr.x = rec.x;
        targPr.y = rec.y;
        targPr.width = _padding;
        targPr.height = _padding;
        Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);

        tex.wrapMode = oldTexWrapMode;
    }
Example #9
0
        public static IEnumerator _CreateAtlasesCoroutineSingleResultMaterial(int resMatIdx,
                                                                              MB_TextureArrayResultMaterial bakedMatsAndSlicesResMat,
                                                                              MB_MultiMaterialTexArray resMatConfig,
                                                                              List <GameObject> objsToMesh,
                                                                              MB3_TextureCombiner combiner,
                                                                              MB_TextureArrayFormatSet[] textureArrayOutputFormats,
                                                                              MB_MultiMaterialTexArray[] resultMaterialsTexArray,
                                                                              List <ShaderTextureProperty> customShaderProperties,
                                                                              ProgressUpdateDelegate progressInfo,
                                                                              MB3_TextureCombiner.CreateAtlasesCoroutineResult coroutineResult,
                                                                              bool saveAtlasesAsAssets = false,
                                                                              MB2_EditorMethodsInterface editorMethods = null,
                                                                              float maxTimePerFrame = .01f)
        {
            MB2_LogLevel LOG_LEVEL = combiner.LOG_LEVEL;

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("Baking atlases for result material " + resMatIdx + " num slices:" + resMatConfig.slices.Count);
            }
            // Each result material can be one set of slices per textureProperty. Each slice can be an atlas.
            // Create atlases for each slice.
            List <MB3_TextureCombiner.TemporaryTexture> generatedTemporaryAtlases = new List <MB3_TextureCombiner.TemporaryTexture>();

            {
                combiner.saveAtlasesAsAssets = false; // Don't want generated atlas slices to be assets
                List <MB_TexArraySlice> slicesConfig = resMatConfig.slices;
                for (int sliceIdx = 0; sliceIdx < slicesConfig.Count; sliceIdx++)
                {
                    Material resMatToPass = null;
                    List <MB_TexArraySliceRendererMatPair> srcMatAndObjPairs = slicesConfig[sliceIdx].sourceMaterials;

                    if (LOG_LEVEL >= MB2_LogLevel.trace)
                    {
                        Debug.Log(" Baking atlases for result material:" + resMatIdx + " slice:" + sliceIdx);
                    }
                    resMatToPass = resMatConfig.combinedMaterial;
                    combiner.fixOutOfBoundsUVs = slicesConfig[sliceIdx].considerMeshUVs;
                    MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult coroutineResult2 = new MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult();
                    MB_AtlasesAndRects sliceAtlasesAndRectOutput = bakedMatsAndSlicesResMat.slices[sliceIdx];
                    List <Material>    usedMats = new List <Material>();
                    slicesConfig[sliceIdx].GetAllUsedMaterials(usedMats);

                    yield return(combiner.CombineTexturesIntoAtlasesCoroutine(progressInfo, sliceAtlasesAndRectOutput, resMatToPass, slicesConfig[sliceIdx].GetAllUsedRenderers(objsToMesh), usedMats, editorMethods, coroutineResult2, maxTimePerFrame,
                                                                              onlyPackRects: false, splitAtlasWhenPackingIfTooBig: false));

                    coroutineResult.success = coroutineResult2.success;
                    if (!coroutineResult.success)
                    {
                        coroutineResult.isFinished = true;
                        yield break;
                    }

                    // Track which slices are new generated texture instances. Atlases could be original texture assets (one tex per atlas) or temporary texture instances in memory that will need to be destroyed.
                    {
                        for (int texPropIdx = 0; texPropIdx < sliceAtlasesAndRectOutput.atlases.Length; texPropIdx++)
                        {
                            Texture2D atlas = sliceAtlasesAndRectOutput.atlases[texPropIdx];
                            if (atlas != null)
                            {
                                bool atlasWasASourceTexture = false;
                                for (int srcMatIdx = 0; srcMatIdx < srcMatAndObjPairs.Count; srcMatIdx++)
                                {
                                    Material srcMat = srcMatAndObjPairs[srcMatIdx].sourceMaterial;
                                    if (srcMat.HasProperty(sliceAtlasesAndRectOutput.texPropertyNames[texPropIdx]) &&
                                        srcMat.GetTexture(sliceAtlasesAndRectOutput.texPropertyNames[texPropIdx]) == atlas)
                                    {
                                        atlasWasASourceTexture = true;
                                        break;
                                    }
                                }

                                if (!atlasWasASourceTexture)
                                {
                                    generatedTemporaryAtlases.Add(new MB3_TextureCombiner.TemporaryTexture(sliceAtlasesAndRectOutput.texPropertyNames[texPropIdx], atlas));
                                }
                            }
                        }
                    } // end visit slices

                    Debug.Assert(combiner._getNumTemporaryTextures() == 0, "Combiner should have no temporary textures.");
                }

                combiner.saveAtlasesAsAssets = saveAtlasesAsAssets; // Restore original setting.
            }

            // Generated atlas textures are temporary for texture arrays. They exist only in memory. Need to be cleaned up after we create slices.
            for (int i = 0; i < generatedTemporaryAtlases.Count; i++)
            {
                combiner.AddTemporaryTexture(generatedTemporaryAtlases[i]);
            }

            List <ShaderTextureProperty> texPropertyNames = new List <ShaderTextureProperty>();

            MB3_TextureCombinerPipeline._CollectPropertyNames(texPropertyNames, customShaderProperties, resMatConfig.combinedMaterial, LOG_LEVEL);

            // The slices are built from different source-material-lists. Each slice can have different sets of texture properties missing (nulls).
            // Build a master list of texture properties.
            bool[] hasTexForProperty = MB_TextureArrays.DetermineWhichPropertiesHaveTextures(bakedMatsAndSlicesResMat.slices);

            List <Texture2D> temporaryTextureAssets = new List <Texture2D>();

            try
            {
                MB_MultiMaterialTexArray resMaterial = resMatConfig;
                Dictionary <string, MB_TexArrayForProperty> resTexArraysByProperty = new Dictionary <string, MB_TexArrayForProperty>();
                {
                    // Initialize so I don't need to check if properties exist later.
                    for (int propIdx = 0; propIdx < texPropertyNames.Count; propIdx++)
                    {
                        if (hasTexForProperty[propIdx])
                        {
                            resTexArraysByProperty[texPropertyNames[propIdx].name] =
                                new MB_TexArrayForProperty(texPropertyNames[propIdx].name, new MB_TextureArrayReference[textureArrayOutputFormats.Length]);
                        }
                    }
                }


                MB3_TextureCombinerNonTextureProperties textureBlender = null;
                textureBlender = new MB3_TextureCombinerNonTextureProperties(LOG_LEVEL, combiner.considerNonTextureProperties);
                textureBlender.LoadTextureBlendersIfNeeded(resMatConfig.combinedMaterial);
                textureBlender.AdjustNonTextureProperties(resMatConfig.combinedMaterial, texPropertyNames, editorMethods);

                // Vist each TextureFormatSet
                for (int texFormatSetIdx = 0; texFormatSetIdx < textureArrayOutputFormats.Length; texFormatSetIdx++)
                {
                    MB_TextureArrayFormatSet textureArrayFormatSet = textureArrayOutputFormats[texFormatSetIdx];
                    editorMethods.Clear();

                    MB_TextureArrays.TexturePropertyData texPropertyData = new MB_TextureArrays.TexturePropertyData();
                    MB_TextureArrays.FindBestSizeAndMipCountAndFormatForTextureArrays(texPropertyNames, combiner.maxAtlasSize, textureArrayFormatSet, bakedMatsAndSlicesResMat.slices, texPropertyData);

                    // Create textures we might need to create if they don't exist.
                    {
                        for (int propIdx = 0; propIdx < hasTexForProperty.Length; propIdx++)
                        {
                            if (hasTexForProperty[propIdx])
                            {
                                TextureFormat format       = texPropertyData.formats[propIdx];
                                int           numSlices    = bakedMatsAndSlicesResMat.slices.Length;
                                int           targetWidth  = (int)texPropertyData.sizes[propIdx].x;
                                int           targetHeight = (int)texPropertyData.sizes[propIdx].y;
                                for (int sliceIdx = 0; sliceIdx < numSlices; sliceIdx++)
                                {
                                    if (bakedMatsAndSlicesResMat.slices[sliceIdx].atlases[propIdx] == null)
                                    {
                                        // Can only setSolidColor on truecolor textures. First create a texture in trucolor format
                                        Texture2D sliceTex = new Texture2D(targetWidth, targetHeight, TextureFormat.ARGB32, texPropertyData.doMips[propIdx]);
                                        Color     col      = textureBlender.GetColorForTemporaryTexture(resMatConfig.slices[sliceIdx].sourceMaterials[0].sourceMaterial, texPropertyNames[propIdx]);
                                        MB_Utility.setSolidColor(sliceTex, col);
                                        // Now create a copy of this texture in target format.
                                        bakedMatsAndSlicesResMat.slices[sliceIdx].atlases[propIdx] = editorMethods.CreateTemporaryAssetCopy(texPropertyNames[propIdx], sliceTex, targetWidth, targetHeight, format, LOG_LEVEL);
                                        temporaryTextureAssets.Add(bakedMatsAndSlicesResMat.slices[sliceIdx].atlases[propIdx]);
                                        MB_Utility.Destroy(sliceTex);
                                    }
                                }
                            }
                        }
                    }


                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("Converting source textures to readable formats.");
                    }
                    if (MB_TextureArrays.ConvertTexturesToReadableFormat(texPropertyData, bakedMatsAndSlicesResMat.slices, hasTexForProperty, texPropertyNames, combiner, LOG_LEVEL, temporaryTextureAssets, editorMethods))
                    {
                        // We now have a set of slices (one per textureProperty). Build these into Texture2DArray's.
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Creating texture arrays");
                        }
                        if (LOG_LEVEL >= MB2_LogLevel.info)
                        {
                            Debug.Log("THERE MAY BE ERRORS IN THE CONSOLE ABOUT 'Rebuilding mipmaps ... not supported'. THESE ARE PROBABLY FALSE POSITIVES AND CAN BE IGNORED.");
                        }
                        Texture2DArray[] textureArrays = MB_TextureArrays.CreateTextureArraysForResultMaterial(texPropertyData, texPropertyNames, bakedMatsAndSlicesResMat.slices, hasTexForProperty, combiner, LOG_LEVEL);


                        // Now have texture arrays for a result material, for all props. Save it.
                        for (int propIdx = 0; propIdx < textureArrays.Length; propIdx++)
                        {
                            if (hasTexForProperty[propIdx])
                            {
                                MB_TextureArrayReference texRef = new MB_TextureArrayReference(textureArrayFormatSet.name, textureArrays[propIdx]);
                                resTexArraysByProperty[texPropertyNames[propIdx].name].formats[texFormatSetIdx] = texRef;
                                if (saveAtlasesAsAssets)
                                {
                                    editorMethods.SaveTextureArrayToAssetDatabase(textureArrays[propIdx],
                                                                                  textureArrayFormatSet.GetFormatForProperty(texPropertyNames[propIdx].name),
                                                                                  bakedMatsAndSlicesResMat.slices[0].texPropertyNames[propIdx],
                                                                                  propIdx, resMaterial.combinedMaterial);
                                }
                            }
                        }
                    }
                } // end vist format set

                resMaterial.textureProperties = new List <MB_TexArrayForProperty>();
                foreach (MB_TexArrayForProperty val in resTexArraysByProperty.Values)
                {
                    resMaterial.textureProperties.Add(val);
                }
            }
            catch (Exception e)
            {
                Debug.LogError(e.Message + "\n" + e.StackTrace.ToString());
                coroutineResult.isFinished = true;
                coroutineResult.success    = false;
            }
            finally
            {
                editorMethods.RestoreReadFlagsAndFormats(progressInfo);
                combiner._destroyAllTemporaryTextures();
                for (int i = 0; i < temporaryTextureAssets.Count; i++)
                {
                    editorMethods.DestroyAsset(temporaryTextureAssets[i]);
                }
                temporaryTextureAssets.Clear();
            }
        }
Example #10
0
        public IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                         MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                         AtlasPackingResult packedAtlasRects,
                                         Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                         MB2_LogLevel LOG_LEVEL)
        {
            Debug.Assert(!data.OnlyOneTextureInAtlasReuseTextures());
            Rect[] uvRects = packedAtlasRects.rects;

            int atlasSizeX = packedAtlasRects.atlasX;
            int atlasSizeY = packedAtlasRects.atlasY;

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY);
            }

            int layer = data._layerTexturePackerFastV2;

            Debug.Assert(layer >= 0 && layer <= 32);

            //create a game object
            mesh             = new Mesh();
            renderAtlasesGO  = null;
            cameraGameObject = null;
            try
            {
                System.Diagnostics.Stopwatch db_time_MB3_TextureCombinerPackerMeshBakerFastV2_CreateAtlases = new System.Diagnostics.Stopwatch();
                db_time_MB3_TextureCombinerPackerMeshBakerFastV2_CreateAtlases.Start();
                renderAtlasesGO  = new GameObject("MBrenderAtlasesGO");
                cameraGameObject = new GameObject("MBCameraGameObject");
                MB3_AtlasPackerRenderTextureUsingMesh atlasRenderer = new MB3_AtlasPackerRenderTextureUsingMesh();
                OneTimeSetup(atlasRenderer, renderAtlasesGO, cameraGameObject, atlasSizeX, atlasSizeY, data._atlasPadding, layer, LOG_LEVEL);

                if (data._considerNonTextureProperties && LOG_LEVEL >= MB2_LogLevel.warn)
                {
                    Debug.LogWarning("Blend Non-Texture Properties has limited functionality when used with Mesh Baker Texture Packer Fast.");
                }

                List <Material> mats = new List <Material>();
                for (int propIdx = 0; propIdx < data.numAtlases; propIdx++)
                {
                    Texture2D atlas = null;
                    if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(propIdx, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                    {
                        atlas = null;
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Not creating atlas for " + data.texPropertyNames[propIdx].name + " because textures are null and default value parameters are the same.");
                        }
                    }
                    else
                    {
                        if (progressInfo != null)
                        {
                            progressInfo("Creating Atlas '" + data.texPropertyNames[propIdx].name + "'", .01f);
                        }

                        // configure it
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("About to render " + data.texPropertyNames[propIdx].name + " isNormal=" + data.texPropertyNames[propIdx].isNormalMap);
                        }

                        // Create the mesh
                        mats.Clear();

                        MB3_AtlasPackerRenderTextureUsingMesh.MeshAtlas.BuildAtlas(packedAtlasRects, data.distinctMaterialTextures, propIdx, packedAtlasRects.atlasX, packedAtlasRects.atlasY, mesh, mats, data.texPropertyNames[propIdx], data, combiner, textureEditorMethods, LOG_LEVEL);
                        {
                            MeshFilter mf = renderAtlasesGO.GetComponent <MeshFilter>();
                            mf.sharedMesh = mesh;
                            MeshRenderer mrr = renderAtlasesGO.GetComponent <MeshRenderer>();
                            Material[]   mrs = mats.ToArray();
                            mrr.sharedMaterials = mrs;
                        }

                        // Render
                        atlas = atlasRenderer.DoRenderAtlas(cameraGameObject, packedAtlasRects.atlasX, packedAtlasRects.atlasY, data.texPropertyNames[propIdx].isNormalMap, data.texPropertyNames[propIdx]);

                        {
                            for (int i = 0; i < mats.Count; i++)
                            {
                                MB_Utility.Destroy(mats[i]);
                            }
                            mats.Clear();
                        }

                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Saving atlas " + data.texPropertyNames[propIdx].name + " w=" + atlas.width + " h=" + atlas.height + " id=" + atlas.GetInstanceID());
                        }
                    }
                    atlases[propIdx] = atlas;
                    if (progressInfo != null)
                    {
                        progressInfo("Saving atlas: '" + data.texPropertyNames[propIdx].name + "'", .04f);
                    }
                    if (data.resultType == MB2_TextureBakeResults.ResultType.atlas)
                    {
                        MB3_TextureCombinerPackerRoot.SaveAtlasAndConfigureResultMaterial(data, textureEditorMethods, atlases[propIdx], data.texPropertyNames[propIdx], propIdx);
                    }

                    combiner._destroyTemporaryTextures(data.texPropertyNames[propIdx].name); // need to save atlases before doing this
                }

                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.LogFormat("Timing MB3_TextureCombinerPackerMeshBakerFastV2.CreateAtlases={0}",
                                    db_time_MB3_TextureCombinerPackerMeshBakerFastV2_CreateAtlases.ElapsedMilliseconds * .001f);
                }
            }
            catch (Exception ex)
            {
                Debug.LogError(ex.Message + "\n" + ex.StackTrace.ToString());
            }
            finally
            {
                if (renderAtlasesGO != null)
                {
                    MB_Utility.Destroy(renderAtlasesGO);
                }
                if (cameraGameObject != null)
                {
                    MB_Utility.Destroy(cameraGameObject);
                }
                if (mesh != null)
                {
                    MB_Utility.Destroy(mesh);
                }
            }
            yield break;
        }
Example #11
0
        // used by Unity texture packer to handle tiled textures.
        // may create a new texture that has the correct tiling to handle fix out of bounds UVs
        internal static Texture2D GetAdjustedForScaleAndOffset2(string propertyName, MeshBakerMaterialTexture source, Vector2 obUVoffset, Vector2 obUVscale, MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner, MB2_LogLevel LOG_LEVEL)
        {
            Texture2D sourceTex = source.GetTexture2D();

            if (source.matTilingRect.x == 0f && source.matTilingRect.y == 0f && source.matTilingRect.width == 1f && source.matTilingRect.height == 1f)
            {
                if (data._fixOutOfBoundsUVs)
                {
                    if (obUVoffset.x == 0f && obUVoffset.y == 0f && obUVscale.x == 1f && obUVscale.y == 1f)
                    {
                        return(sourceTex); //no adjustment necessary
                    }
                }
                else
                {
                    return(sourceTex); //no adjustment necessary
                }
            }
            Vector2 dim = MB3_TextureCombinerPipeline.GetAdjustedForScaleAndOffset2Dimensions(source, obUVoffset, obUVscale, data, LOG_LEVEL);

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.LogWarning("GetAdjustedForScaleAndOffset2: " + sourceTex + " " + obUVoffset + " " + obUVscale);
            }
            float newWidth  = dim.x;
            float newHeight = dim.y;
            float scx       = (float)source.matTilingRect.width;
            float scy       = (float)source.matTilingRect.height;
            float ox        = (float)source.matTilingRect.x;
            float oy        = (float)source.matTilingRect.y;

            if (data._fixOutOfBoundsUVs)
            {
                scx *= obUVscale.x;
                scy *= obUVscale.y;
                ox   = (float)(source.matTilingRect.x * obUVscale.x + obUVoffset.x);
                oy   = (float)(source.matTilingRect.y * obUVscale.y + obUVoffset.y);
            }
            Texture2D newTex = combiner._createTemporaryTexture(propertyName, (int)newWidth, (int)newHeight, TextureFormat.ARGB32, true);

            for (int i = 0; i < newTex.width; i++)
            {
                for (int j = 0; j < newTex.height; j++)
                {
                    float u = i / newWidth * scx + ox;
                    float v = j / newHeight * scy + oy;
                    newTex.SetPixel(i, j, sourceTex.GetPixelBilinear(u, v));
                }
            }
            newTex.Apply();
            return(newTex);
        }
Example #12
0
 public void CreateColoredTexToReplaceNull(string propName, int propIdx, bool considerMeshUVs, MB3_TextureCombiner combiner, Color col)
 {
     MeshBakerMaterialTexture matTex = ts[propIdx];
     matTex.t = combiner._createTemporaryTexture(propName, 16, 16, TextureFormat.ARGB32, true);
     MB_Utility.setSolidColor(matTex.GetTexture2D(), col);
 }
        internal static IEnumerator CopyScaledAndTiledToAtlas(MeshBakerMaterialTexture source, MB_TexSet sourceMaterial,
                                                              ShaderTextureProperty shaderPropertyName, DRect srcSamplingRect, int targX, int targY, int targW, int targH,
                                                              AtlasPadding padding,
                                                              Color[][] atlasPixels, bool isNormalMap,
                                                              MB3_TextureCombinerPipeline.TexturePipelineData data,
                                                              MB3_TextureCombiner combiner,
                                                              ProgressUpdateDelegate progressInfo = null,
                                                              MB2_LogLevel LOG_LEVEL = MB2_LogLevel.info)
        {
            //HasFinished = false;
            Texture2D t = source.GetTexture2D();

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("CopyScaledAndTiledToAtlas: " + t + " inAtlasX=" + targX + " inAtlasY=" + targY + " inAtlasW=" + targW + " inAtlasH=" + targH);
            }
            float newWidth  = targW;
            float newHeight = targH;
            float scx       = (float)srcSamplingRect.width;
            float scy       = (float)srcSamplingRect.height;
            float ox        = (float)srcSamplingRect.x;
            float oy        = (float)srcSamplingRect.y;
            int   w         = (int)newWidth;
            int   h         = (int)newHeight;

            if (t == null)
            {
                if (LOG_LEVEL >= MB2_LogLevel.trace)
                {
                    Debug.Log("No source texture creating a 16x16 texture.");
                }
                t   = combiner._createTemporaryTexture(16, 16, TextureFormat.ARGB32, true);
                scx = 1;
                scy = 1;
                if (data._considerNonTextureProperties && data.nonTexturePropertyBlender != null)
                {
                    Color col = data.nonTexturePropertyBlender.GetColorIfNoTexture(sourceMaterial.matsAndGOs.mats[0].mat, shaderPropertyName);
                    if (LOG_LEVEL >= MB2_LogLevel.trace)
                    {
                        Debug.Log("Setting texture to solid color " + col);
                    }
                    MB_Utility.setSolidColor(t, col);
                }
                else
                {
                    Color col = MB3_TextureCombinerNonTextureProperties.GetColorIfNoTexture(shaderPropertyName);
                    MB_Utility.setSolidColor(t, col);
                }
            }
            if (data._considerNonTextureProperties && data.nonTexturePropertyBlender != null)
            {
                t = combiner._createTextureCopy(t);
                t = data.nonTexturePropertyBlender.TintTextureWithTextureCombiner(t, sourceMaterial, shaderPropertyName);
            }
            for (int i = 0; i < w; i++)
            {
                if (progressInfo != null && w > 0)
                {
                    progressInfo("CopyScaledAndTiledToAtlas " + (((float)i / (float)w) * 100f).ToString("F0"), .2f);
                }
                for (int j = 0; j < h; j++)
                {
                    float u = i / newWidth * scx + ox;
                    float v = j / newHeight * scy + oy;
                    atlasPixels[targY + j][targX + i] = t.GetPixelBilinear(u, v);
                }
            }
            //bleed the border colors into the padding
            for (int i = 0; i < w; i++)
            {
                for (int j = 1; j <= padding.topBottom; j++)
                {
                    //top margin
                    atlasPixels[(targY - j)][targX + i] = atlasPixels[(targY)][targX + i];
                    //bottom margin
                    atlasPixels[(targY + h - 1 + j)][targX + i] = atlasPixels[(targY + h - 1)][targX + i];
                }
            }
            for (int j = 0; j < h; j++)
            {
                for (int i = 1; i <= padding.leftRight; i++)
                {
                    //left margin
                    atlasPixels[(targY + j)][targX - i] = atlasPixels[(targY + j)][targX];
                    //right margin
                    atlasPixels[(targY + j)][targX + w + i - 1] = atlasPixels[(targY + j)][targX + w - 1];
                }
            }
            //corners
            for (int i = 1; i <= padding.leftRight; i++)
            {
                for (int j = 1; j <= padding.topBottom; j++)
                {
                    atlasPixels[(targY - j)][targX - i]                 = atlasPixels[targY][targX];
                    atlasPixels[(targY + h - 1 + j)][targX - i]         = atlasPixels[(targY + h - 1)][targX];
                    atlasPixels[(targY + h - 1 + j)][targX + w + i - 1] = atlasPixels[(targY + h - 1)][targX + w - 1];
                    atlasPixels[(targY - j)][targX + w + i - 1]         = atlasPixels[targY][targX + w - 1];
                    yield return(null);
                }
                yield return(null);
            }
            //			Debug.Log("copyandscaledatlas finished too!");
            //HasFinished = true;
            yield break;
        }
	private void CopyScaledAndTiledToAtlas(MB3_TextureCombiner.MeshBakerMaterialTexture source, Rect rec){			
		Rect r = rec;

		myCamera.backgroundColor = source.colorIfNoTexture;

		if (source.t == null){
			source.t = combiner._createTemporaryTexture(16,16,TextureFormat.ARGB32, true);
            Debug.Log("Creating texture with color " + source.colorIfNoTexture + " isNormal" + _isNormalMap);
			MB_Utility.setSolidColor(source.t,source.colorIfNoTexture);
		}

		r.y = 1f - (r.y + r.height); // DrawTexture uses topLeft 0,0, Texture2D uses bottomLeft 0,0 
		r.x *= _destinationTexture.width;
		r.y *= _destinationTexture.height;
		r.width *= _destinationTexture.width;
		r.height *= _destinationTexture.height;

		Rect rPadded = r;
		rPadded.x -= _padding;
		rPadded.y -= _padding;
		rPadded.width += _padding * 2;
		rPadded.height += _padding * 2;

		Rect srcPrTex = new Rect();
		Rect targPr = new Rect();
		
		srcPrTex.width = source.scale.x;        
		srcPrTex.height = source.scale.y;
		srcPrTex.x = source.offset.x;
		srcPrTex.y = source.offset.y;
		if (_fixOutOfBoundsUVs){
			srcPrTex.width *= source.obUVscale.x;
			srcPrTex.height *= source.obUVscale.y;
			srcPrTex.x += source.obUVoffset.x;
			srcPrTex.y += source.obUVoffset.y;
			if (LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log ("Fixing out of bounds UVs for tex " + source.t);
		}

		Texture tex = source.t;
		
		//main texture
		TextureWrapMode oldTexWrapMode = tex.wrapMode;
		if (srcPrTex.width == 1f && srcPrTex.height == 1f && srcPrTex.x == 0f && srcPrTex.y == 0f){
			//fixes bug where there is a dark line at the edge of the texture
			tex.wrapMode = TextureWrapMode.Clamp;
		} else {
			tex.wrapMode = TextureWrapMode.Repeat;
		}


		if (LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log ("DrawTexture tex=" + tex.name + " destRect=" + r + " srcRect=" + srcPrTex + " Mat=" + mat);


		//fill the padding first
		Rect srcPr = new Rect();
        
		//top margin
		srcPr.x = srcPrTex.x;
		srcPr.y = srcPrTex.y + 1 - 1f / tex.height;
		srcPr.width = srcPrTex.width;
		srcPr.height = 1f / tex.height;
		targPr.x = r.x;
		targPr.y = rPadded.y;
		targPr.width = r.width;
		targPr.height = _padding;
		Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);

		//bot margin
		srcPr.x = srcPrTex.x;
		srcPr.y = srcPrTex.y;
		srcPr.width = srcPrTex.width;
		srcPr.height = 1f / tex.height;
		targPr.x = r.x;
		targPr.y = r.y + r.height;
		targPr.width = r.width;
		targPr.height = _padding;
		Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);


		//left margin
		srcPr.x = srcPrTex.x;
		srcPr.y = srcPrTex.y;
		srcPr.width = 1f / tex.width;
		srcPr.height = srcPrTex.height;
		targPr.x = rPadded.x;
		targPr.y = r.y;
		targPr.width = _padding;
		targPr.height = r.height;
		Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);
		
		//right margin
		srcPr.x = srcPrTex.x + 1f - 1f / tex.width;
		srcPr.y = srcPrTex.y;
		srcPr.width = 1f / tex.width;
		srcPr.height = srcPrTex.height;
		targPr.x = r.x + r.width;
		targPr.y = r.y;
		targPr.width = _padding;
		targPr.height = r.height;
		Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);


		//top left corner
		srcPr.x = srcPrTex.x;
		srcPr.y = srcPrTex.y + 1 - 1f / tex.height ;
		srcPr.width = 1f / tex.width;
		srcPr.height = 1f / tex.height;
		targPr.x = rPadded.x; 
		targPr.y = rPadded.y;
		targPr.width = _padding;
		targPr.height = _padding;
		Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);

		//top right corner
		srcPr.x = srcPrTex.x + 1f - 1f / tex.width;
		srcPr.y = srcPrTex.y + 1 - 1f / tex.height ;
		srcPr.width = 1f / tex.width;
		srcPr.height = 1f / tex.height;
		targPr.x = r.x + r.width; 
		targPr.y = rPadded.y;
		targPr.width = _padding;
		targPr.height = _padding;
		Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);

		//bot left corner
		srcPr.x = srcPrTex.x;
		srcPr.y = srcPrTex.y;
		srcPr.width = 1f / tex.width;
		srcPr.height = 1f / tex.height;
		targPr.x = rPadded.x; 
		targPr.y = r.y + r.height;
		targPr.width = _padding;
		targPr.height = _padding;
		Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);
		
		//bot right corner
		srcPr.x = srcPrTex.x + 1f - 1f / tex.width;
		srcPr.y = srcPrTex.y ;
		srcPr.width = 1f / tex.width;
		srcPr.height = 1f / tex.height;
		targPr.x = r.x + r.width; 
		targPr.y = r.y + r.height;
		targPr.width = _padding;
		targPr.height = _padding;
		Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);
 
		//now the texture
		Graphics.DrawTexture(r, tex, srcPrTex, 0, 0, 0, 0, mat);

		tex.wrapMode = oldTexWrapMode;
	}
        internal static IEnumerator _CreateAtlasesCoroutineTextureArray(MB3_TextureBaker tb, MB3_TextureCombiner combiner, ProgressUpdateDelegate progressInfo, MB3_TextureBaker.CreateAtlasesCoroutineResult coroutineResult, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null, float maxTimePerFrame = .01f)
        {
            MB_TextureArrayResultMaterial[] bakedMatsAndSlices = null;

            // Validate the formats
            if (tb.textureArrayOutputFormats == null || tb.textureArrayOutputFormats.Length == 0)
            {
                Debug.LogError("No Texture Array Output Formats. There must be at least one entry.");
                coroutineResult.isFinished = true;
                yield break;
            }

            for (int i = 0; i < tb.textureArrayOutputFormats.Length; i++)
            {
                if (!tb.textureArrayOutputFormats[i].ValidateTextureImporterFormatsExistsForTextureFormats(editorMethods, i))
                {
                    Debug.LogError("Could not map the selected texture format to a Texture Importer Format. Safest options are ARGB32, or RGB24.");
                    coroutineResult.isFinished = true;
                    yield break;
                }
            }

            for (int resMatIdx = 0; resMatIdx < tb.resultMaterialsTexArray.Length; resMatIdx++)
            {
                MB_MultiMaterialTexArray textureArraySliceConfig = tb.resultMaterialsTexArray[resMatIdx];
                if (textureArraySliceConfig.combinedMaterial == null)
                {
                    Debug.LogError("Material is null for Texture Array Slice Configuration: " + resMatIdx + ".");
                    coroutineResult.isFinished = true;
                    yield break;
                }


                List <MB_TexArraySlice> slices = textureArraySliceConfig.slices;
                for (int sliceIdx = 0; sliceIdx < slices.Count; sliceIdx++)
                {
                    for (int srcMatIdx = 0; srcMatIdx < slices[sliceIdx].sourceMaterials.Count; srcMatIdx++)
                    {
                        MB_TexArraySliceRendererMatPair sourceMat = slices[sliceIdx].sourceMaterials[srcMatIdx];
                        if (sourceMat.sourceMaterial == null)
                        {
                            Debug.LogError("Source material is null for Texture Array Slice Configuration: " + resMatIdx + " slice: " + sliceIdx);
                            coroutineResult.isFinished = true;
                            yield break;
                        }

                        if (slices[sliceIdx].considerMeshUVs)
                        {
                            if (sourceMat.renderer == null)
                            {
                                Debug.LogError("Renderer is null for Texture Array Slice Configuration: " + resMatIdx + " slice: " + sliceIdx + ". If considerUVs is enabled then a renderer must be supplied for each source material. The same source material can be used multiple times.");
                                coroutineResult.isFinished = true;
                                yield break;
                            }
                        }
                        else
                        {
                            // TODO check for duplicate source mats.
                        }
                    }
                }
            }

            for (int resMatIdx = 0; resMatIdx < tb.resultMaterialsTexArray.Length; resMatIdx++)
            {
                MB_MultiMaterialTexArray textureArraySliceConfig = tb.resultMaterialsTexArray[resMatIdx];
            }

            // initialize structure to store results. For texture arrays the structure is two layers deep.
            // First layer is resultMaterial / submesh (each result material can use a different shader)
            // Second layer is a set of TextureArrays for the TextureProperties on that result material.
            int numResultMats = tb.resultMaterialsTexArray.Length;

            bakedMatsAndSlices = new MB_TextureArrayResultMaterial[numResultMats];
            for (int resMatIdx = 0; resMatIdx < bakedMatsAndSlices.Length; resMatIdx++)
            {
                bakedMatsAndSlices[resMatIdx] = new MB_TextureArrayResultMaterial();
                int numSlices = tb.resultMaterialsTexArray[resMatIdx].slices.Count;
                MB_AtlasesAndRects[] slices = bakedMatsAndSlices[resMatIdx].slices = new MB_AtlasesAndRects[numSlices];
                for (int j = 0; j < numSlices; j++)
                {
                    slices[j] = new MB_AtlasesAndRects();
                }
            }

            // Some of the slices will be atlases (more than one atlas per slice).
            // Do the material combining for these. First loop over the result materials (1 per submeshes).
            for (int resMatIdx = 0; resMatIdx < bakedMatsAndSlices.Length; resMatIdx++)
            {
                yield return(_CreateAtlasesCoroutineSingleResultMaterial(resMatIdx, bakedMatsAndSlices[resMatIdx], tb.resultMaterialsTexArray[resMatIdx],
                                                                         tb, combiner, progressInfo, coroutineResult, saveAtlasesAsAssets, editorMethods, maxTimePerFrame));

                if (!coroutineResult.success)
                {
                    yield break;
                }
            }

            if (coroutineResult.success)
            {
                // Save the results into the TextureBakeResults.
                tb.unpackMat2RectMap(bakedMatsAndSlices);
                tb.textureBakeResults.resultType              = MB2_TextureBakeResults.ResultType.textureArray;
                tb.textureBakeResults.resultMaterials         = new MB_MultiMaterial[0];
                tb.textureBakeResults.resultMaterialsTexArray = tb.resultMaterialsTexArray;
                if (tb.LOG_LEVEL >= MB2_LogLevel.info)
                {
                    Debug.Log("Created Texture2DArrays");
                }
            }
            else
            {
                if (tb.LOG_LEVEL >= MB2_LogLevel.info)
                {
                    Debug.Log("Failed to create Texture2DArrays");
                }
            }
        }
        /// <summary>
        /// Creates one texture array per texture property.
        /// </summary>
        /// <returns></returns>
        internal static Texture2DArray[] CreateTextureArraysForResultMaterial(TexturePropertyData texPropertyData, MB_AtlasesAndRects[] resultAtlasesAndRectSlices,
                                                                              bool[] hasTexForProperty, MB3_TextureCombiner combiner, MB2_LogLevel LOG_LEVEL)
        {
            Debug.Assert(texPropertyData.sizes.Length == hasTexForProperty.Length);

            // ASSUMPTION all slices in the same format and the same size, alpha channel and mipMapCount
            string[] texPropertyNames = resultAtlasesAndRectSlices[0].texPropertyNames;
            Debug.Assert(texPropertyNames.Length == hasTexForProperty.Length);
            Texture2DArray[] texArrays = new Texture2DArray[texPropertyNames.Length];

            // Each texture property (_MainTex, _Bump, ...) becomes a Texture2DArray
            for (int propIdx = 0; propIdx < texPropertyNames.Length; propIdx++)
            {
                if (!hasTexForProperty[propIdx])
                {
                    continue;
                }

                int            numSlices = resultAtlasesAndRectSlices.Length;
                int            w         = (int)texPropertyData.sizes[propIdx].x;
                int            h         = (int)texPropertyData.sizes[propIdx].y;
                int            numMips   = (int)texPropertyData.numMipMaps[propIdx];
                TextureFormat  format    = texPropertyData.formats[propIdx];
                bool           doMipMaps = texPropertyData.doMips[propIdx];
                Texture2DArray texArray  = new Texture2DArray(w, h, numSlices, format, doMipMaps);
                if (LOG_LEVEL >= MB2_LogLevel.info)
                {
                    Debug.LogFormat("Creating Texture2DArray for property: {0} w: {1} h: {2} format: {3} doMips: {4}", texPropertyNames[propIdx], w, h, format, doMipMaps);
                }
                for (int sliceIdx = 0; sliceIdx < numSlices; sliceIdx++)
                {
                    Debug.Assert(resultAtlasesAndRectSlices[sliceIdx].atlases.Length == texPropertyNames.Length);
                    Debug.Assert(resultAtlasesAndRectSlices[sliceIdx].texPropertyNames[propIdx] == texPropertyNames[propIdx]);
                    Texture2D srcTex = resultAtlasesAndRectSlices[sliceIdx].atlases[propIdx];

                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.LogFormat("Slice: {0}  texture: {1}", sliceIdx, srcTex);
                    }
                    bool isCopy = false;
                    if (srcTex == null)
                    {
                        // Slices might not have all textures create a dummy if needed.
                        srcTex = combiner._createTemporaryTexture(texPropertyNames[propIdx], w, h, format, doMipMaps);
                    }

                    Debug.Assert(srcTex.width == texArray.width, "Source texture is not the same width as the texture array " + srcTex);
                    Debug.Assert(srcTex.height == texArray.height, "Source texture is not the same height as the texture array " + srcTex);
                    Debug.Assert(srcTex.mipmapCount == numMips, "Source texture does have not the same number of mips as the texture array: " + srcTex + " numMipsTex: " + srcTex.mipmapCount + " numMipsTexArray: " + numMips + " texDims: " + srcTex.width + "x" + srcTex.height);
                    Debug.Assert(srcTex.format == format, "Formats should have been converted before this. Texture: " + srcTex + "Source: " + srcTex.format + " Targ: " + format);

                    for (int mipIdx = 0; mipIdx < numMips; mipIdx++)
                    {
                        Graphics.CopyTexture(srcTex, 0, mipIdx, texArray, sliceIdx, mipIdx);
                    }

                    if (isCopy)
                    {
                        MB_Utility.Destroy(srcTex);
                    }
                }

                texArray.Apply();
                texArrays[propIdx] = texArray;
            }

            return(texArrays);
        }
 private void CopyScaledAndTiledToAtlas(MB3_TextureCombiner.MeshBakerMaterialTexture source, Rect rec)
 {
     Rect rect = rec;
     this.myCamera.backgroundColor = source.colorIfNoTexture;
     if (source.t == null)
     {
         source.t = this.combiner._createTemporaryTexture(16, 16, TextureFormat.ARGB32, true);
         UnityEngine.Debug.Log(string.Concat(new object[]
         {
             "Creating texture with color ",
             source.colorIfNoTexture,
             " isNormal",
             this._isNormalMap
         }));
         MB_Utility.setSolidColor(source.t, source.colorIfNoTexture);
     }
     rect.y = 1f - (rect.y + rect.height);
     rect.x *= (float)this._destinationTexture.width;
     rect.y *= (float)this._destinationTexture.height;
     rect.width *= (float)this._destinationTexture.width;
     rect.height *= (float)this._destinationTexture.height;
     Rect rect2 = rect;
     rect2.x -= (float)this._padding;
     rect2.y -= (float)this._padding;
     rect2.width += (float)(this._padding * 2);
     rect2.height += (float)(this._padding * 2);
     Rect rect3 = default(Rect);
     Rect screenRect = default(Rect);
     rect3.width = source.scale.x;
     rect3.height = source.scale.y;
     rect3.x = source.offset.x;
     rect3.y = source.offset.y;
     if (this._fixOutOfBoundsUVs)
     {
         rect3.width *= source.obUVscale.x;
         rect3.height *= source.obUVscale.y;
         rect3.x += source.obUVoffset.x;
         rect3.y += source.obUVoffset.y;
         if (this.LOG_LEVEL >= MB2_LogLevel.trace)
         {
             UnityEngine.Debug.Log("Fixing out of bounds UVs for tex " + source.t);
         }
     }
     Texture t = source.t;
     TextureWrapMode wrapMode = t.wrapMode;
     if (rect3.width == 1f && rect3.height == 1f && rect3.x == 0f && rect3.y == 0f)
     {
         t.wrapMode = TextureWrapMode.Clamp;
     }
     else
     {
         t.wrapMode = TextureWrapMode.Repeat;
     }
     if (this.LOG_LEVEL >= MB2_LogLevel.trace)
     {
         UnityEngine.Debug.Log(string.Concat(new object[]
         {
             "DrawTexture tex=",
             t.name,
             " destRect=",
             rect,
             " srcRect=",
             rect3,
             " Mat=",
             this.mat
         }));
     }
     Rect sourceRect = default(Rect);
     sourceRect.x = rect3.x;
     sourceRect.y = rect3.y + 1f - 1f / (float)t.height;
     sourceRect.width = rect3.width;
     sourceRect.height = 1f / (float)t.height;
     screenRect.x = rect.x;
     screenRect.y = rect2.y;
     screenRect.width = rect.width;
     screenRect.height = (float)this._padding;
     Graphics.DrawTexture(screenRect, t, sourceRect, 0, 0, 0, 0, this.mat);
     sourceRect.x = rect3.x;
     sourceRect.y = rect3.y;
     sourceRect.width = rect3.width;
     sourceRect.height = 1f / (float)t.height;
     screenRect.x = rect.x;
     screenRect.y = rect.y + rect.height;
     screenRect.width = rect.width;
     screenRect.height = (float)this._padding;
     Graphics.DrawTexture(screenRect, t, sourceRect, 0, 0, 0, 0, this.mat);
     sourceRect.x = rect3.x;
     sourceRect.y = rect3.y;
     sourceRect.width = 1f / (float)t.width;
     sourceRect.height = rect3.height;
     screenRect.x = rect2.x;
     screenRect.y = rect.y;
     screenRect.width = (float)this._padding;
     screenRect.height = rect.height;
     Graphics.DrawTexture(screenRect, t, sourceRect, 0, 0, 0, 0, this.mat);
     sourceRect.x = rect3.x + 1f - 1f / (float)t.width;
     sourceRect.y = rect3.y;
     sourceRect.width = 1f / (float)t.width;
     sourceRect.height = rect3.height;
     screenRect.x = rect.x + rect.width;
     screenRect.y = rect.y;
     screenRect.width = (float)this._padding;
     screenRect.height = rect.height;
     Graphics.DrawTexture(screenRect, t, sourceRect, 0, 0, 0, 0, this.mat);
     sourceRect.x = rect3.x;
     sourceRect.y = rect3.y + 1f - 1f / (float)t.height;
     sourceRect.width = 1f / (float)t.width;
     sourceRect.height = 1f / (float)t.height;
     screenRect.x = rect2.x;
     screenRect.y = rect2.y;
     screenRect.width = (float)this._padding;
     screenRect.height = (float)this._padding;
     Graphics.DrawTexture(screenRect, t, sourceRect, 0, 0, 0, 0, this.mat);
     sourceRect.x = rect3.x + 1f - 1f / (float)t.width;
     sourceRect.y = rect3.y + 1f - 1f / (float)t.height;
     sourceRect.width = 1f / (float)t.width;
     sourceRect.height = 1f / (float)t.height;
     screenRect.x = rect.x + rect.width;
     screenRect.y = rect2.y;
     screenRect.width = (float)this._padding;
     screenRect.height = (float)this._padding;
     Graphics.DrawTexture(screenRect, t, sourceRect, 0, 0, 0, 0, this.mat);
     sourceRect.x = rect3.x;
     sourceRect.y = rect3.y;
     sourceRect.width = 1f / (float)t.width;
     sourceRect.height = 1f / (float)t.height;
     screenRect.x = rect2.x;
     screenRect.y = rect.y + rect.height;
     screenRect.width = (float)this._padding;
     screenRect.height = (float)this._padding;
     Graphics.DrawTexture(screenRect, t, sourceRect, 0, 0, 0, 0, this.mat);
     sourceRect.x = rect3.x + 1f - 1f / (float)t.width;
     sourceRect.y = rect3.y;
     sourceRect.width = 1f / (float)t.width;
     sourceRect.height = 1f / (float)t.height;
     screenRect.x = rect.x + rect.width;
     screenRect.y = rect.y + rect.height;
     screenRect.width = (float)this._padding;
     screenRect.height = (float)this._padding;
     Graphics.DrawTexture(screenRect, t, sourceRect, 0, 0, 0, 0, this.mat);
     Graphics.DrawTexture(rect, t, rect3, 0, 0, 0, 0, this.mat);
     t.wrapMode = wrapMode;
 }
        public IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                         MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                         AtlasPackingResult packedAtlasRects,
                                         Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                         MB2_LogLevel LOG_LEVEL)
        {
            Debug.Assert(!data.OnlyOneTextureInAtlasReuseTextures());
            Rect[] uvRects = packedAtlasRects.rects;

            int atlasSizeX = packedAtlasRects.atlasX;
            int atlasSizeY = packedAtlasRects.atlasY;

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY);
            }

            //create a game object
            GameObject renderAtlasesGO = null;

            try
            {
                renderAtlasesGO = new GameObject("MBrenderAtlasesGO");
                MB3_AtlasPackerRenderTexture atlasRenderTexture = renderAtlasesGO.AddComponent <MB3_AtlasPackerRenderTexture>();
                renderAtlasesGO.AddComponent <Camera>();
                if (data._considerNonTextureProperties && LOG_LEVEL >= MB2_LogLevel.warn)
                {
                    Debug.LogError("Blend Non-Texture Properties has limited functionality when used with Mesh Baker Texture Packer Fast. If no texture is pesent, then a small texture matching the non-texture property will be created and used in the atlas. But non-texture properties will not be blended into texture.");
                }

                for (int propIdx = 0; propIdx < data.numAtlases; propIdx++)
                {
                    Texture2D atlas = null;
                    if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(propIdx, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                    {
                        atlas = null;
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Not creating atlas for " + data.texPropertyNames[propIdx].name + " because textures are null and default value parameters are the same.");
                        }
                    }
                    else
                    {
                        GC.Collect();

                        MB3_TextureCombinerPackerRoot.CreateTemporaryTexturesForAtlas(data.distinctMaterialTextures, combiner, propIdx, data);

                        if (progressInfo != null)
                        {
                            progressInfo("Creating Atlas '" + data.texPropertyNames[propIdx].name + "'", .01f);
                        }
                        // ===========
                        // configure it
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("About to render " + data.texPropertyNames[propIdx].name + " isNormal=" + data.texPropertyNames[propIdx].isNormalMap);
                        }
                        atlasRenderTexture.LOG_LEVEL                    = LOG_LEVEL;
                        atlasRenderTexture.width                        = atlasSizeX;
                        atlasRenderTexture.height                       = atlasSizeY;
                        atlasRenderTexture.padding                      = data._atlasPadding;
                        atlasRenderTexture.rects                        = uvRects;
                        atlasRenderTexture.textureSets                  = data.distinctMaterialTextures;
                        atlasRenderTexture.indexOfTexSetToRender        = propIdx;
                        atlasRenderTexture.texPropertyName              = data.texPropertyNames[propIdx];
                        atlasRenderTexture.isNormalMap                  = data.texPropertyNames[propIdx].isNormalMap;
                        atlasRenderTexture.fixOutOfBoundsUVs            = data._fixOutOfBoundsUVs;
                        atlasRenderTexture.considerNonTextureProperties = data._considerNonTextureProperties;
                        atlasRenderTexture.resultMaterialTextureBlender = data.nonTexturePropertyBlender;
                        // call render on it
                        atlas = atlasRenderTexture.OnRenderAtlas(combiner);

                        // destroy it
                        // =============
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Saving atlas " + data.texPropertyNames[propIdx].name + " w=" + atlas.width + " h=" + atlas.height + " id=" + atlas.GetInstanceID());
                        }
                    }
                    atlases[propIdx] = atlas;
                    if (progressInfo != null)
                    {
                        progressInfo("Saving atlas: '" + data.texPropertyNames[propIdx].name + "'", .04f);
                    }
                    if (data.resultType == MB2_TextureBakeResults.ResultType.atlas)
                    {
                        MB3_TextureCombinerPackerRoot.SaveAtlasAndConfigureResultMaterial(data, textureEditorMethods, atlases[propIdx], data.texPropertyNames[propIdx], propIdx);
                    }

                    combiner._destroyTemporaryTextures(data.texPropertyNames[propIdx].name); // need to save atlases before doing this
                }
            }
            catch (Exception ex)
            {
                //Debug.LogError(ex);
                Debug.LogError(ex.Message + "\n" + ex.StackTrace.ToString());
            }
            finally
            {
                if (renderAtlasesGO != null)
                {
                    MB_Utility.Destroy(renderAtlasesGO);
                }
            }
            yield break;
        }
 internal static void CreateTemporaryTexturesForAtlas(List <MB_TexSet> distinctMaterialTextures, MB3_TextureCombiner combiner, int propIdx, MB3_TextureCombinerPipeline.TexturePipelineData data)
 {
     for (int texSetIdx = 0; texSetIdx < data.distinctMaterialTextures.Count; texSetIdx++)
     {
         MB_TexSet txs = data.distinctMaterialTextures[texSetIdx];
         MeshBakerMaterialTexture matTex = txs.ts[propIdx];
         if (matTex.isNull)
         {
             //create a small 16 x 16 texture to use in the atlas
             Color col = data.nonTexturePropertyBlender.GetColorForTemporaryTexture(txs.matsAndGOs.mats[0].mat, data.texPropertyNames[propIdx]);
             txs.CreateColoredTexToReplaceNull(data.texPropertyNames[propIdx].name, propIdx, data._fixOutOfBoundsUVs, combiner, col);
         }
     }
 }
Example #20
0
        internal static Texture2D _copyTexturesIntoAtlas(Texture2D[] texToPack, int padding, Rect[] rs, int w, int h, MB3_TextureCombiner combiner)
        {
            Texture2D ta = new Texture2D(w, h, TextureFormat.ARGB32, true);

            MB_Utility.setSolidColor(ta, Color.clear);
            for (int i = 0; i < rs.Length; i++)
            {
                Rect      r      = rs[i];
                Texture2D t      = texToPack[i];
                Texture2D tmpTex = null;
                int       x      = Mathf.RoundToInt(r.x * w);
                int       y      = Mathf.RoundToInt(r.y * h);
                int       ww     = Mathf.RoundToInt(r.width * w);
                int       hh     = Mathf.RoundToInt(r.height * h);
                if (t.width != ww && t.height != hh)
                {
                    tmpTex = t = MB_Utility.resampleTexture(t, ww, hh);
                }
                ta.SetPixels(x, y, ww, hh, t.GetPixels());
                if (tmpTex != null)
                {
                    MB_Utility.Destroy(tmpTex);
                }
            }
            ta.Apply();
            return(ta);
        }
	public Texture2D OnRenderAtlas(MB3_TextureCombiner combiner){
		fastRenderer = new MB_TextureCombinerRenderTexture();
		_doRenderAtlas = true;
		Texture2D atlas = fastRenderer.DoRenderAtlas(this.gameObject,width,height,padding,rects,textureSets,indexOfTexSetToRender, isNormalMap, fixOutOfBoundsUVs, combiner, LOG_LEVEL);
		_doRenderAtlas = false;
		return atlas;
	}
Example #22
0
            internal static void BuildAtlas(
                AtlasPackingResult packedAtlasRects,
                List <MB_TexSet> distinctMaterialTextures,
                int propIdx,
                int atlasSizeX, int atlasSizeY,
                Mesh m,
                List <Material> generatedMats,
                ShaderTextureProperty property,
                MB3_TextureCombinerPipeline.TexturePipelineData data,
                MB3_TextureCombiner combiner,
                MB2_EditorMethodsInterface textureEditorMethods,
                MB2_LogLevel LOG_LEVEL)
            {
                // Collect vertices and quads for mesh that we will use for the atlas.
                Debug.Assert(generatedMats.Count == 0, "Previous mats should have been destroyed");
                generatedMats.Clear();
                List <Vector3> vs  = new List <Vector3>();
                List <Vector2> uvs = new List <Vector2>();

                // One submesh and material per texture that we are packing
                List <int>[] ts = new List <int> [distinctMaterialTextures.Count];
                for (int i = 0; i < ts.Length; i++)
                {
                    ts[i] = new List <int>();
                }

                MeshBakerMaterialTexture.readyToBuildAtlases = true;
                GC.Collect();
                MB3_TextureCombinerPackerRoot.CreateTemporaryTexturesForAtlas(data.distinctMaterialTextures, combiner, propIdx, data);

                Rect[] uvRects = packedAtlasRects.rects;
                for (int texSetIdx = 0; texSetIdx < distinctMaterialTextures.Count; texSetIdx++)
                {
                    MB_TexSet texSet = distinctMaterialTextures[texSetIdx];
                    MeshBakerMaterialTexture matTex = texSet.ts[propIdx];

                    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()));
                    }
                    Rect      r  = uvRects[texSetIdx];
                    Texture2D t  = matTex.GetTexture2D();
                    int       x  = Mathf.RoundToInt(r.x * atlasSizeX);
                    int       y  = Mathf.RoundToInt(r.y * atlasSizeY);
                    int       ww = Mathf.RoundToInt(r.width * atlasSizeX);
                    int       hh = Mathf.RoundToInt(r.height * atlasSizeY);
                    r = new Rect(x, y, ww, hh);
                    if (ww == 0 || hh == 0)
                    {
                        Debug.LogError("Image in atlas has no height or width " + r);
                    }
                    DRect samplingRect = texSet.ts[propIdx].GetEncapsulatingSamplingRect();
                    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()));

                    AtlasPadding padding = packedAtlasRects.padding[texSetIdx];
                    AddNineSlicedRect(r, padding.leftRight, padding.topBottom, samplingRect.GetRect(), vs, uvs, ts[texSetIdx], t.width, t.height, t.name);

                    Material mt = new Material(Shader.Find("MeshBaker/Unlit/UnlitWithAlpha"));

                    bool isSavingAsANormalMapAssetThatWillBeImported = property.isNormalMap && data._saveAtlasesAsAssets;
                    MBVersion.PipelineType pipelineType = MBVersion.DetectPipeline();
                    if (pipelineType == MBVersion.PipelineType.URP)
                    {
                        ConfigureMaterial_DefaultPipeline(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL);
                        //ConfigureMaterial_URP(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL);
                    }
                    else if (pipelineType == MBVersion.PipelineType.HDRP)
                    {
                        ConfigureMaterial_DefaultPipeline(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL);
                    }
                    else
                    {
                        ConfigureMaterial_DefaultPipeline(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL);
                    }

                    generatedMats.Add(mt);
                }

                // Apply to the mesh
                m.Clear();
                m.vertices     = vs.ToArray();
                m.uv           = uvs.ToArray();
                m.subMeshCount = ts.Length;
                for (int i = 0; i < m.subMeshCount; i++)
                {
                    m.SetIndices(ts[i].ToArray(), MeshTopology.Triangles, i);
                }
                MeshBakerMaterialTexture.readyToBuildAtlases = false;
            }
        public IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                         MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                         AtlasPackingResult packedAtlasRects,
                                         Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                         MB2_LogLevel LOG_LEVEL)
        {
            Rect[] uvRects = packedAtlasRects.rects;
            if (data.distinctMaterialTextures.Count == 1 && data._fixOutOfBoundsUVs == false)
            {
                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("Only one image per atlas. Will re-use original texture");
                }
                uvRects    = new Rect[1];
                uvRects[0] = new Rect(0f, 0f, 1f, 1f);
                for (int i = 0; i < data.numAtlases; i++)
                {
                    MeshBakerMaterialTexture dmt = data.distinctMaterialTextures[0].ts[i];
                    atlases[i] = dmt.GetTexture2D();
                    data.resultMaterial.SetTexture(data.texPropertyNames[i].name, atlases[i]);
                    data.resultMaterial.SetTextureScale(data.texPropertyNames[i].name, dmt.matTilingRect.size);
                    data.resultMaterial.SetTextureOffset(data.texPropertyNames[i].name, dmt.matTilingRect.min);
                }
            }
            else
            {
                long estArea    = 0;
                int  atlasSizeX = 1;
                int  atlasSizeY = 1;
                uvRects = null;
                for (int i = 0; i < data.numAtlases; i++)
                { //i is an atlas "MainTex", "BumpMap" etc...
                  //-----------------------
                    Texture2D atlas = null;
                    if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(i, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                    {
                        atlas = null;
                    }
                    else
                    {
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.LogWarning("Beginning loop " + i + " num temporary textures " + combiner._temporaryTextures.Count);
                        }
                        for (int j = 0; j < data.distinctMaterialTextures.Count; j++)
                        { //j is a distinct set of textures one for each of "MainTex", "BumpMap" etc...
                            MB_TexSet txs = data.distinctMaterialTextures[j];

                            int tWidth  = txs.idealWidth;
                            int tHeight = txs.idealHeight;

                            Texture2D tx = txs.ts[i].GetTexture2D();
                            if (tx == null)
                            {
                                tx = txs.ts[i].t = combiner._createTemporaryTexture(tWidth, tHeight, TextureFormat.ARGB32, true);
                                if (data._considerNonTextureProperties && data.nonTexturePropertyBlender != null)
                                {
                                    Color col = data.nonTexturePropertyBlender.GetColorIfNoTexture(txs.matsAndGOs.mats[0].mat, data.texPropertyNames[i]);
                                    if (LOG_LEVEL >= MB2_LogLevel.trace)
                                    {
                                        Debug.Log("Setting texture to solid color " + col);
                                    }
                                    MB_Utility.setSolidColor(tx, col);
                                }
                                else
                                {
                                    Color col = MB3_TextureCombinerNonTextureProperties.GetColorIfNoTexture(data.texPropertyNames[i]);
                                    MB_Utility.setSolidColor(tx, col);
                                }
                            }

                            if (progressInfo != null)
                            {
                                progressInfo("Adjusting for scale and offset " + tx, .01f);
                            }
                            if (textureEditorMethods != null)
                            {
                                textureEditorMethods.SetReadWriteFlag(tx, true, true);
                            }
                            tx = GetAdjustedForScaleAndOffset2(txs.ts[i], txs.obUVoffset, txs.obUVscale, data, combiner, LOG_LEVEL);

                            //create a resized copy if necessary
                            if (tx.width != tWidth || tx.height != tHeight)
                            {
                                if (progressInfo != null)
                                {
                                    progressInfo("Resizing texture '" + tx + "'", .01f);
                                }
                                if (LOG_LEVEL >= MB2_LogLevel.debug)
                                {
                                    Debug.LogWarning("Copying and resizing texture " + data.texPropertyNames[i].name + " from " + tx.width + "x" + tx.height + " to " + tWidth + "x" + tHeight);
                                }
                                tx = combiner._resizeTexture((Texture2D)tx, tWidth, tHeight);
                            }

                            txs.ts[i].t = tx;
                        }

                        Texture2D[] texToPack = new Texture2D[data.distinctMaterialTextures.Count];
                        for (int j = 0; j < data.distinctMaterialTextures.Count; j++)
                        {
                            Texture2D tx = data.distinctMaterialTextures[j].ts[i].GetTexture2D();
                            estArea += tx.width * tx.height;
                            if (data._considerNonTextureProperties)
                            {
                                //combine the tintColor with the texture
                                tx = combiner._createTextureCopy(tx);
                                data.nonTexturePropertyBlender.TintTextureWithTextureCombiner(tx, data.distinctMaterialTextures[j], data.texPropertyNames[i]);
                            }
                            texToPack[j] = tx;
                        }

                        if (textureEditorMethods != null)
                        {
                            textureEditorMethods.CheckBuildSettings(estArea);
                        }

                        if (Math.Sqrt(estArea) > 3500f)
                        {
                            if (LOG_LEVEL >= MB2_LogLevel.warn)
                            {
                                Debug.LogWarning("The maximum possible atlas size is 4096. Textures may be shrunk");
                            }
                        }
                        atlas = new Texture2D(1, 1, TextureFormat.ARGB32, true);
                        if (progressInfo != null)
                        {
                            progressInfo("Packing texture atlas " + data.texPropertyNames[i].name, .25f);
                        }
                        if (i == 0)
                        {
                            if (progressInfo != null)
                            {
                                progressInfo("Estimated min size of atlases: " + Math.Sqrt(estArea).ToString("F0"), .1f);
                            }
                            if (LOG_LEVEL >= MB2_LogLevel.info)
                            {
                                Debug.Log("Estimated atlas minimum size:" + Math.Sqrt(estArea).ToString("F0"));
                            }

                            if (data.distinctMaterialTextures.Count == 1 && data._fixOutOfBoundsUVs == false)
                            { //don't want to force power of 2 so tiling will still work
                                uvRects = new Rect[1] {
                                    new Rect(0f, 0f, 1f, 1f)
                                };
                                atlas = _copyTexturesIntoAtlas(texToPack, data._atlasPadding, uvRects, texToPack[0].width, texToPack[0].height, combiner);
                            }
                            else
                            {
                                int maxAtlasSize = 4096;
                                uvRects = atlas.PackTextures(texToPack, data._atlasPadding, maxAtlasSize, false);
                            }

                            if (LOG_LEVEL >= MB2_LogLevel.info)
                            {
                                Debug.Log("After pack textures atlas size " + atlas.width + " " + atlas.height);
                            }
                            atlasSizeX = atlas.width;
                            atlasSizeY = atlas.height;
                            atlas.Apply();
                        }
                        else
                        {
                            if (progressInfo != null)
                            {
                                progressInfo("Copying Textures Into: " + data.texPropertyNames[i].name, .1f);
                            }
                            atlas = _copyTexturesIntoAtlas(texToPack, data._atlasPadding, uvRects, atlasSizeX, atlasSizeY, combiner);
                        }
                    }
                    atlases[i] = atlas;
                    //----------------------

                    if (data._saveAtlasesAsAssets && textureEditorMethods != null)
                    {
                        textureEditorMethods.SaveAtlasToAssetDatabase(atlases[i], data.texPropertyNames[i], i, data.resultMaterial);
                    }
                    data.resultMaterial.SetTextureOffset(data.texPropertyNames[i].name, Vector2.zero);
                    data.resultMaterial.SetTextureScale(data.texPropertyNames[i].name, Vector2.one);

                    combiner._destroyTemporaryTextures(); // need to save atlases before doing this
                    GC.Collect();
                }
            }
            packedAtlasRects.rects = uvRects;
            yield break;
        }
Example #24
0
        public override IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                                  MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                                  AtlasPackingResult packedAtlasRects,
                                                  Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                                  MB2_LogLevel LOG_LEVEL)
        {
            Rect[] uvRects = packedAtlasRects.rects;

            int atlasSizeX = packedAtlasRects.atlasX;
            int atlasSizeY = packedAtlasRects.atlasY;

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY);
            }

            for (int propIdx = 0; propIdx < data.numAtlases; propIdx++)
            {
                Texture2D             atlas    = null;
                ShaderTextureProperty property = data.texPropertyNames[propIdx];
                if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(propIdx, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                {
                    atlas = null;
                    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.");
                    }
                }
                else
                {
                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("=== Creating atlas for " + property.name);
                    }

                    GC.Collect();

                    CreateTemporaryTexturesForAtlas(data.distinctMaterialTextures, combiner, propIdx, data);

                    //use a jagged array because it is much more efficient in memory
                    Color[][] atlasPixels = new Color[atlasSizeY][];
                    for (int j = 0; j < atlasPixels.Length; j++)
                    {
                        atlasPixels[j] = new Color[atlasSizeX];
                    }

                    bool isNormalMap = false;
                    if (property.isNormalMap)
                    {
                        isNormalMap = true;
                    }

                    for (int texSetIdx = 0; texSetIdx < data.distinctMaterialTextures.Count; texSetIdx++)
                    {
                        MB_TexSet texSet = data.distinctMaterialTextures[texSetIdx];
                        MeshBakerMaterialTexture matTex = texSet.ts[propIdx];
                        string s = "Creating Atlas '" + property.name + "' texture " + matTex.GetTexName();
                        if (progressInfo != null)
                        {
                            progressInfo(s, .01f);
                        }
                        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()));
                        }
                        Rect      r  = uvRects[texSetIdx];
                        Texture2D t  = texSet.ts[propIdx].GetTexture2D();
                        int       x  = Mathf.RoundToInt(r.x * atlasSizeX);
                        int       y  = Mathf.RoundToInt(r.y * atlasSizeY);
                        int       ww = Mathf.RoundToInt(r.width * atlasSizeX);
                        int       hh = Mathf.RoundToInt(r.height * atlasSizeY);
                        if (ww == 0 || hh == 0)
                        {
                            Debug.LogError("Image in atlas has no height or width " + r);
                        }
                        if (progressInfo != null)
                        {
                            progressInfo(s + " set ReadWrite flag", .01f);
                        }
                        if (textureEditorMethods != null)
                        {
                            textureEditorMethods.SetReadWriteFlag(t, true, true);
                        }
                        if (progressInfo != null)
                        {
                            progressInfo(s + "Copying to atlas: '" + matTex.GetTexName() + "'", .02f);
                        }
                        DRect samplingRect = texSet.ts[propIdx].GetEncapsulatingSamplingRect();
                        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()));
                        yield return(CopyScaledAndTiledToAtlas(texSet.ts[propIdx], texSet, property, samplingRect, x, y, ww, hh, packedAtlasRects.padding[texSetIdx], atlasPixels, isNormalMap, data, combiner, progressInfo, LOG_LEVEL));
                    }

                    yield return(data.numAtlases);

                    if (progressInfo != null)
                    {
                        progressInfo("Applying changes to atlas: '" + property.name + "'", .03f);
                    }
                    atlas = new Texture2D(atlasSizeX, atlasSizeY, TextureFormat.ARGB32, true);
                    for (int j = 0; j < atlasPixels.Length; j++)
                    {
                        atlas.SetPixels(0, j, atlasSizeX, 1, atlasPixels[j]);
                    }

                    atlas.Apply();
                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("Saving atlas " + property.name + " w=" + atlas.width + " h=" + atlas.height);
                    }
                }

                atlases[propIdx] = atlas;
                if (progressInfo != null)
                {
                    progressInfo("Saving atlas: '" + property.name + "'", .04f);
                }
                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                sw.Start();
                if (data.resultType == MB2_TextureBakeResults.ResultType.atlas)
                {
                    SaveAtlasAndConfigureResultMaterial(data, textureEditorMethods, atlases[propIdx], data.texPropertyNames[propIdx], propIdx);
                }

                combiner._destroyTemporaryTextures(data.texPropertyNames[propIdx].name);
            }

            yield break;
        }
        public IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                         MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                         AtlasPackingResult packedAtlasRects,
                                         Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                         MB2_LogLevel LOG_LEVEL)
        {
            Rect[] uvRects = packedAtlasRects.rects;
            if (uvRects.Length == 1)
            {
                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("Only one image per atlas. Will re-use original texture");
                }
                for (int i = 0; i < data.numAtlases; i++)
                {
                    MeshBakerMaterialTexture dmt = data.distinctMaterialTextures[0].ts[i];
                    atlases[i] = dmt.GetTexture2D();
                    data.resultMaterial.SetTexture(data.texPropertyNames[i].name, atlases[i]);
                    data.resultMaterial.SetTextureScale(data.texPropertyNames[i].name, dmt.matTilingRect.size);
                    data.resultMaterial.SetTextureOffset(data.texPropertyNames[i].name, dmt.matTilingRect.min);
                }
            }
            else
            {
                int atlasSizeX = packedAtlasRects.atlasX;
                int atlasSizeY = packedAtlasRects.atlasY;
                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY);
                }
                for (int propIdx = 0; propIdx < data.numAtlases; propIdx++)
                {
                    Texture2D atlas = null;
                    if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(propIdx, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                    {
                        atlas = null;
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("=== Not creating atlas for " + data.texPropertyNames[propIdx].name + " because textures are null and default value parameters are the same.");
                        }
                    }
                    else
                    {
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("=== Creating atlas for " + data.texPropertyNames[propIdx].name);
                        }
                        GC.Collect();

                        //use a jagged array because it is much more efficient in memory
                        Color[][] atlasPixels = new Color[atlasSizeY][];
                        for (int j = 0; j < atlasPixels.Length; j++)
                        {
                            atlasPixels[j] = new Color[atlasSizeX];
                        }
                        bool isNormalMap = false;
                        if (data.texPropertyNames[propIdx].isNormalMap)
                        {
                            isNormalMap = true;
                        }

                        for (int texSetIdx = 0; texSetIdx < data.distinctMaterialTextures.Count; texSetIdx++)
                        {
                            string s = "Creating Atlas '" + data.texPropertyNames[propIdx].name + "' texture " + data.distinctMaterialTextures[texSetIdx];
                            if (progressInfo != null)
                            {
                                progressInfo(s, .01f);
                            }
                            MB_TexSet texSet = data.distinctMaterialTextures[texSetIdx];
                            if (LOG_LEVEL >= MB2_LogLevel.trace)
                            {
                                Debug.Log(string.Format("Adding texture {0} to atlas {1}", texSet.ts[propIdx].GetTexture2D() == null ? "null" : texSet.ts[propIdx].GetTexName(), data.texPropertyNames[propIdx]));
                            }
                            Rect      r  = uvRects[texSetIdx];
                            Texture2D t  = texSet.ts[propIdx].GetTexture2D();
                            int       x  = Mathf.RoundToInt(r.x * atlasSizeX);
                            int       y  = Mathf.RoundToInt(r.y * atlasSizeY);
                            int       ww = Mathf.RoundToInt(r.width * atlasSizeX);
                            int       hh = Mathf.RoundToInt(r.height * atlasSizeY);
                            if (ww == 0 || hh == 0)
                            {
                                Debug.LogError("Image in atlas has no height or width " + r);
                            }
                            if (progressInfo != null)
                            {
                                progressInfo(s + " set ReadWrite flag", .01f);
                            }
                            if (textureEditorMethods != null)
                            {
                                textureEditorMethods.SetReadWriteFlag(t, true, true);
                            }
                            if (progressInfo != null)
                            {
                                progressInfo(s + "Copying to atlas: '" + texSet.ts[propIdx].GetTexName() + "'", .02f);
                            }
                            DRect samplingRect = texSet.ts[propIdx].encapsulatingSamplingRect;
                            yield return(CopyScaledAndTiledToAtlas(texSet.ts[propIdx], texSet, data.texPropertyNames[propIdx], samplingRect, x, y, ww, hh, packedAtlasRects.padding[texSetIdx], atlasPixels, isNormalMap, data, combiner, progressInfo, LOG_LEVEL));
                            //							Debug.Log("after copyScaledAndTiledAtlas");
                        }
                        yield return(data.numAtlases);

                        if (progressInfo != null)
                        {
                            progressInfo("Applying changes to atlas: '" + data.texPropertyNames[propIdx].name + "'", .03f);
                        }
                        atlas = new Texture2D(atlasSizeX, atlasSizeY, TextureFormat.ARGB32, true);
                        for (int j = 0; j < atlasPixels.Length; j++)
                        {
                            atlas.SetPixels(0, j, atlasSizeX, 1, atlasPixels[j]);
                        }
                        atlas.Apply();
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Saving atlas " + data.texPropertyNames[propIdx].name + " w=" + atlas.width + " h=" + atlas.height);
                        }
                    }
                    atlases[propIdx] = atlas;
                    if (progressInfo != null)
                    {
                        progressInfo("Saving atlas: '" + data.texPropertyNames[propIdx].name + "'", .04f);
                    }
                    System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                    sw.Start();

                    if (data._saveAtlasesAsAssets && textureEditorMethods != null)
                    {
                        textureEditorMethods.SaveAtlasToAssetDatabase(atlases[propIdx], data.texPropertyNames[propIdx], propIdx, data.resultMaterial);
                    }
                    else
                    {
                        data.resultMaterial.SetTexture(data.texPropertyNames[propIdx].name, atlases[propIdx]);
                    }
                    data.resultMaterial.SetTextureOffset(data.texPropertyNames[propIdx].name, Vector2.zero);
                    data.resultMaterial.SetTextureScale(data.texPropertyNames[propIdx].name, Vector2.one);
                    combiner._destroyTemporaryTextures(); // need to save atlases before doing this
                }
            }
            //data.rectsInAtlas = uvRects;
            //			Debug.Log("finished!");
            yield break;
        }
Example #26
0
	MB_AtlasesAndRects[] _CreateAtlases(ProgressUpdateDelegate progressInfo, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods=null){
		//validation
		if (saveAtlasesAsAssets && editorMethods == null){
			Debug.LogError("Error in CreateAtlases If saveAtlasesAsAssets = true then editorMethods cannot be null.");
			return null;
		}
		if (saveAtlasesAsAssets && !Application.isEditor){
			Debug.LogError("Error in CreateAtlases If saveAtlasesAsAssets = true it must be called from the Unity Editor.");
			return null;			
		}
		MB2_ValidationLevel vl = Application.isPlaying ? MB2_ValidationLevel.quick : MB2_ValidationLevel.robust; 
		if (!DoCombinedValidate(this, MB_ObjsToCombineTypes.dontCare, editorMethods, vl)){
			return null;
		}
		if (_doMultiMaterial && !_ValidateResultMaterials()){
			return null;
		} else if (!_doMultiMaterial){
			if (_resultMaterial == null){
				Debug.LogError("Combined Material is null please create and assign a result material.");
				return null;
			}
			Shader targShader = _resultMaterial.shader;
			for (int i = 0; i < objsToMesh.Count; i++){
				Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]);
				for (int j = 0; j < ms.Length; j++){
					Material m = ms[j];
					if (m != null && m.shader != targShader){
						Debug.LogWarning("Game object " + objsToMesh[i] + " does not use shader " + targShader + " it may not have the required textures. If not 2x2 clear textures will be generated.");
					}

				}
			}
		}

		for (int i = 0; i < objsToMesh.Count; i++){
			Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]);
			for (int j = 0; j < ms.Length; j++){
				Material m = ms[j];
				if (m == null){
					Debug.LogError("Game object " + objsToMesh[i] + " has a null material. Can't build atlases");
					return null;
				}

			}
		}		
		
		MB3_TextureCombiner combiner = new MB3_TextureCombiner();
		combiner.LOG_LEVEL = LOG_LEVEL;
		combiner.atlasPadding = _atlasPadding;
		combiner.maxAtlasSize = _maxAtlasSize;
		combiner.customShaderPropNames = _customShaderProperties;
		combiner.fixOutOfBoundsUVs = _fixOutOfBoundsUVs;
		combiner.maxTilingBakeSize = _maxTilingBakeSize;
		combiner.packingAlgorithm = _packingAlgorithm;
		combiner.meshBakerTexturePackerForcePowerOfTwo = _meshBakerTexturePackerForcePowerOfTwo;
		combiner.resizePowerOfTwoTextures = _resizePowerOfTwoTextures;
		combiner.saveAtlasesAsAssets = saveAtlasesAsAssets;

		// if editor analyse meshes and suggest treatment
		if (!Application.isPlaying){
			Material[] rms;
			if (_doMultiMaterial){
				rms = new Material[resultMaterials.Length];
				for (int i = 0; i < rms.Length; i++) rms[i] = resultMaterials[i].combinedMaterial;
			} else {
				rms = new Material[1];
				rms[0] = _resultMaterial;
			}
			combiner.SuggestTreatment(objsToMesh, rms, combiner.customShaderPropNames);
		}		
		
		//initialize structure to store results
		int numResults = 1;
		if (_doMultiMaterial) numResults = resultMaterials.Length;
		MB_AtlasesAndRects[] resultAtlasesAndRects = new MB_AtlasesAndRects[numResults];
		for (int i = 0; i < resultAtlasesAndRects.Length; i++){
			resultAtlasesAndRects[i] = new MB_AtlasesAndRects();
		}
		
		//Do the material combining.
		for (int i = 0; i < resultAtlasesAndRects.Length; i++){
			Material resMatToPass = null;
			List<Material> sourceMats = null;			
			if (_doMultiMaterial) {
				sourceMats = resultMaterials[i].sourceMaterials;
				resMatToPass = resultMaterials[i].combinedMaterial;
			} else {
				resMatToPass = _resultMaterial;	
			}
			Debug.Log("Creating atlases for result material " + resMatToPass);
			if(!combiner.CombineTexturesIntoAtlases(progressInfo, resultAtlasesAndRects[i], resMatToPass, objsToMesh, sourceMats, editorMethods)){
				return null;
			}
		}
		
		//Save the results
		textureBakeResults.combinedMaterialInfo = resultAtlasesAndRects;
		textureBakeResults.doMultiMaterial = _doMultiMaterial;
		textureBakeResults.resultMaterial = _resultMaterial;
		textureBakeResults.resultMaterials = resultMaterials;
		textureBakeResults.fixOutOfBoundsUVs = combiner.fixOutOfBoundsUVs;
		unpackMat2RectMap(textureBakeResults);
		
		//set the texture bake resultAtlasesAndRects on the Mesh Baker component if it exists
		MB3_MeshBakerCommon[] mb = GetComponentsInChildren<MB3_MeshBakerCommon>();
		for (int i = 0; i < mb.Length; i++){
			mb[i].textureBakeResults = textureBakeResults;
		}
		
		if (LOG_LEVEL >= MB2_LogLevel.info) Debug.Log("Created Atlases");		
		return resultAtlasesAndRects;
	}		
Example #27
0
        public override IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                                  MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                                  AtlasPackingResult packedAtlasRects,
                                                  Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                                  MB2_LogLevel LOG_LEVEL)
        {
            Debug.Assert(!data.OnlyOneTextureInAtlasReuseTextures());
            Rect[] uvRects = packedAtlasRects.rects;

            long estArea    = 0;
            int  atlasSizeX = 1;
            int  atlasSizeY = 1;

            uvRects = null;
            for (int propIdx = 0; propIdx < data.numAtlases; propIdx++)
            {
                //-----------------------
                ShaderTextureProperty prop  = data.texPropertyNames[propIdx];
                Texture2D             atlas = null;
                if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(propIdx, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                {
                    atlas = null;
                }
                else
                {
                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.LogWarning("Beginning loop " + propIdx + " num temporary textures " + combiner._getNumTemporaryTextures());
                    }
                    MB3_TextureCombinerPackerRoot.CreateTemporaryTexturesForAtlas(data.distinctMaterialTextures, combiner, propIdx, data);
                    Texture2D[] texToPack = new Texture2D[data.distinctMaterialTextures.Count];
                    for (int texSetIdx = 0; texSetIdx < data.distinctMaterialTextures.Count; texSetIdx++)
                    {
                        MB_TexSet txs     = data.distinctMaterialTextures[texSetIdx];
                        int       tWidth  = txs.idealWidth;
                        int       tHeight = txs.idealHeight;
                        Texture2D tx      = txs.ts[propIdx].GetTexture2D();
                        if (progressInfo != null)
                        {
                            progressInfo("Adjusting for scale and offset " + tx, .01f);
                        }

                        if (textureEditorMethods != null)
                        {
                            textureEditorMethods.SetReadWriteFlag(tx, true, true);
                        }

                        tx = GetAdjustedForScaleAndOffset2(prop.name, txs.ts[propIdx], txs.obUVoffset, txs.obUVscale, data, combiner, LOG_LEVEL);
                        //create a resized copy if necessary
                        if (tx.width != tWidth || tx.height != tHeight)
                        {
                            if (progressInfo != null)
                            {
                                progressInfo("Resizing texture '" + tx + "'", .01f);
                            }
                            if (LOG_LEVEL >= MB2_LogLevel.debug)
                            {
                                Debug.LogWarning("Copying and resizing texture " + prop.name + " from " + tx.width + "x" + tx.height + " to " + tWidth + "x" + tHeight);
                            }
                            tx = combiner._resizeTexture(prop.name, (Texture2D)tx, tWidth, tHeight);
                        }

                        estArea += tx.width * tx.height;
                        if (data._considerNonTextureProperties)
                        {
                            //combine the tintColor with the texture
                            tx = combiner._createTextureCopy(prop.name, tx);
                            data.nonTexturePropertyBlender.TintTextureWithTextureCombiner(tx, data.distinctMaterialTextures[texSetIdx], prop);
                        }

                        texToPack[texSetIdx] = tx;
                    }

                    if (textureEditorMethods != null)
                    {
                        textureEditorMethods.CheckBuildSettings(estArea);
                    }

                    if (Math.Sqrt(estArea) > 3500f)
                    {
                        if (LOG_LEVEL >= MB2_LogLevel.warn)
                        {
                            Debug.LogWarning("The maximum possible atlas size is 4096. Textures may be shrunk");
                        }
                    }

                    atlas = new Texture2D(1, 1, TextureFormat.ARGB32, true);
                    if (progressInfo != null)
                    {
                        progressInfo("Packing texture atlas " + prop.name, .25f);
                    }
                    if (propIdx == 0)
                    {
                        if (progressInfo != null)
                        {
                            progressInfo("Estimated min size of atlases: " + Math.Sqrt(estArea).ToString("F0"), .1f);
                        }
                        if (LOG_LEVEL >= MB2_LogLevel.info)
                        {
                            Debug.Log("Estimated atlas minimum size:" + Math.Sqrt(estArea).ToString("F0"));
                        }
                        int maxAtlasSize = 4096;
                        uvRects = atlas.PackTextures(texToPack, data._atlasPadding, maxAtlasSize, false);
                        if (LOG_LEVEL >= MB2_LogLevel.info)
                        {
                            Debug.Log("After pack textures atlas size " + atlas.width + " " + atlas.height);
                        }
                        atlasSizeX = atlas.width;
                        atlasSizeY = atlas.height;
                        atlas.Apply();
                    }
                    else
                    {
                        if (progressInfo != null)
                        {
                            progressInfo("Copying Textures Into: " + prop.name, .1f);
                        }
                        atlas = _copyTexturesIntoAtlas(texToPack, data._atlasPadding, uvRects, atlasSizeX, atlasSizeY, combiner);
                    }
                }

                atlases[propIdx] = atlas;
                //----------------------

                if (data._saveAtlasesAsAssets && textureEditorMethods != null)
                {
                    textureEditorMethods.SaveAtlasToAssetDatabase(atlases[propIdx], prop, propIdx, data.resultMaterial);
                }
                data.resultMaterial.SetTextureOffset(prop.name, Vector2.zero);
                data.resultMaterial.SetTextureScale(prop.name, Vector2.one);
                combiner._destroyTemporaryTextures(prop.name);
                GC.Collect();
            }
            packedAtlasRects.rects = uvRects;
            yield break;
        }
        internal static IEnumerator CopyScaledAndTiledToAtlas(MeshBakerMaterialTexture source, MB_TexSet sourceMaterial,
                                                              ShaderTextureProperty shaderPropertyName, DRect srcSamplingRect, int targX, int targY, int targW, int targH,
                                                              AtlasPadding padding,
                                                              Color[][] atlasPixels, bool isNormalMap,
                                                              MB3_TextureCombinerPipeline.TexturePipelineData data,
                                                              MB3_TextureCombiner combiner,
                                                              ProgressUpdateDelegate progressInfo = null,
                                                              MB2_LogLevel LOG_LEVEL = MB2_LogLevel.info)
        {
            //HasFinished = false;
            Texture2D t = source.GetTexture2D();

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log(String.Format("CopyScaledAndTiledToAtlas: {0} inAtlasX={1} inAtlasY={2} inAtlasW={3} inAtlasH={4} paddX={5} paddY={6} srcSamplingRect={7}",
                                        t, targX, targY, targW, targH, padding.leftRight, padding.topBottom, srcSamplingRect));
            }
            float newWidth  = targW;
            float newHeight = targH;
            float scx       = (float)srcSamplingRect.width;
            float scy       = (float)srcSamplingRect.height;
            float ox        = (float)srcSamplingRect.x;
            float oy        = (float)srcSamplingRect.y;
            int   w         = (int)newWidth;
            int   h         = (int)newHeight;

            if (data._considerNonTextureProperties)
            {
                t = combiner._createTextureCopy(shaderPropertyName.name, t);
                t = data.nonTexturePropertyBlender.TintTextureWithTextureCombiner(t, sourceMaterial, shaderPropertyName);
            }
            for (int i = 0; i < w; i++)
            {
                if (progressInfo != null && w > 0)
                {
                    progressInfo("CopyScaledAndTiledToAtlas " + (((float)i / (float)w) * 100f).ToString("F0"), .2f);
                }
                for (int j = 0; j < h; j++)
                {
                    float u = i / newWidth * scx + ox;
                    float v = j / newHeight * scy + oy;
                    atlasPixels[targY + j][targX + i] = t.GetPixelBilinear(u, v);
                }
            }

            //bleed the border colors into the padding
            for (int i = 0; i < w; i++)
            {
                for (int j = 1; j <= padding.topBottom; j++)
                {
                    //top margin
                    atlasPixels[(targY - j)][targX + i] = atlasPixels[(targY)][targX + i];
                    //bottom margin
                    atlasPixels[(targY + h - 1 + j)][targX + i] = atlasPixels[(targY + h - 1)][targX + i];
                }
            }
            for (int j = 0; j < h; j++)
            {
                for (int i = 1; i <= padding.leftRight; i++)
                {
                    //left margin
                    atlasPixels[(targY + j)][targX - i] = atlasPixels[(targY + j)][targX];
                    //right margin
                    atlasPixels[(targY + j)][targX + w + i - 1] = atlasPixels[(targY + j)][targX + w - 1];
                }
            }
            //corners
            for (int i = 1; i <= padding.leftRight; i++)
            {
                for (int j = 1; j <= padding.topBottom; j++)
                {
                    atlasPixels[(targY - j)][targX - i]                 = atlasPixels[targY][targX];
                    atlasPixels[(targY + h - 1 + j)][targX - i]         = atlasPixels[(targY + h - 1)][targX];
                    atlasPixels[(targY + h - 1 + j)][targX + w + i - 1] = atlasPixels[(targY + h - 1)][targX + w - 1];
                    atlasPixels[(targY - j)][targX + w + i - 1]         = atlasPixels[targY][targX + w - 1];
                    yield return(null);
                }
                yield return(null);
            }
            //			Debug.Log("copyandscaledatlas finished too!");
            //HasFinished = true;
            yield break;
        }
        //posibilities
        //  using fixOutOfBoundsUVs or not
        //
        public static void ConfigureMutiMaterialsFromObjsToCombine(MB3_TextureBaker mom, SerializedProperty resultMaterials, SerializedObject textureBaker)
        {
            if (mom.GetObjectsToCombine().Count == 0)
            {
                Debug.LogError("You need to add some objects to combine before building the multi material list.");
                return;
            }
            if (resultMaterials.arraySize > 0)
            {
                Debug.LogError("You already have some source to combined material mappings configured. You must remove these before doing this operation.");
                return;
            }
            if (mom.textureBakeResults == null)
            {
                Debug.LogError("Texture Bake Result asset must be set before using this operation.");
                return;
            }
            Dictionary <MultiMatSubmeshInfo, List <List <Material> > > shader2Material_map = new Dictionary <MultiMatSubmeshInfo, List <List <Material> > >();
            Dictionary <Material, Mesh> obUVobject2mesh_map = new Dictionary <Material, Mesh>();

            //validate that the objects to be combined are valid
            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                GameObject go = mom.GetObjectsToCombine()[i];
                if (go == null)
                {
                    Debug.LogError("Null object in list of objects to combine at position " + i);
                    return;
                }
                Renderer r = go.GetComponent <Renderer>();
                if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer)))
                {
                    Debug.LogError("GameObject at position " + i + " in list of objects to combine did not have a renderer");
                    return;
                }
                if (r.sharedMaterial == null)
                {
                    Debug.LogError("GameObject at position " + i + " in list of objects to combine has a null material");
                    return;
                }
            }

            //first pass put any meshes with obUVs on their own submesh if not fixing OB uvs
            if (mom.doMultiMaterialSplitAtlasesIfOBUVs)
            {
                for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
                {
                    GameObject go = mom.GetObjectsToCombine()[i];
                    Mesh       m  = MB_Utility.GetMesh(go);
                    MB_Utility.MeshAnalysisResult dummyMar = new MB_Utility.MeshAnalysisResult();
                    Renderer r = go.GetComponent <Renderer>();
                    for (int j = 0; j < r.sharedMaterials.Length; j++)
                    {
                        if (MB_Utility.hasOutOfBoundsUVs(m, ref dummyMar, j))
                        {
                            if (!obUVobject2mesh_map.ContainsKey(r.sharedMaterials[j]))
                            {
                                Debug.LogWarning("Object " + go + " submesh " + j + " uses UVs outside the range 0,0..1,1 to generate tiling. This object has been mapped to its own submesh in the combined mesh. It can share a submesh with other objects that use different materials if you use the fix out of bounds UVs feature which will bake the tiling");
                                obUVobject2mesh_map.Add(r.sharedMaterials[j], m);
                            }
                        }
                    }
                }
            }

            //second pass  put other materials without OB uvs in a shader to material map
            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                Renderer r = mom.GetObjectsToCombine()[i].GetComponent <Renderer>();
                for (int j = 0; j < r.sharedMaterials.Length; j++)
                {
                    if (!obUVobject2mesh_map.ContainsKey(r.sharedMaterials[j]))
                    { //if not already added
                        if (r.sharedMaterials[j] == null)
                        {
                            continue;
                        }
                        List <List <Material> > binsOfMatsThatUseShader = null;
                        MultiMatSubmeshInfo     newKey = new MultiMatSubmeshInfo(r.sharedMaterials[j].shader, r.sharedMaterials[j]);
                        if (!shader2Material_map.TryGetValue(newKey, out binsOfMatsThatUseShader))
                        {
                            binsOfMatsThatUseShader = new List <List <Material> >();
                            binsOfMatsThatUseShader.Add(new List <Material>());
                            shader2Material_map.Add(newKey, binsOfMatsThatUseShader);
                        }
                        if (!binsOfMatsThatUseShader[0].Contains(r.sharedMaterials[j]))
                        {
                            binsOfMatsThatUseShader[0].Add(r.sharedMaterials[j]);
                        }
                    }
                }
            }

            int numResMats = shader2Material_map.Count;

            //third pass for each shader grouping check how big the atlas would be and group into bins that would fit in an atlas
            if (mom.doMultiMaterialSplitAtlasesIfTooBig)
            {
                if (mom.packingAlgorithm == MB2_PackingAlgorithmEnum.UnitysPackTextures)
                {
                    Debug.LogWarning("Unity texture packer does not support splitting atlases if too big. Atlases will not be split.");
                }
                else
                {
                    numResMats = 0;
                    foreach (MultiMatSubmeshInfo sh in shader2Material_map.Keys)
                    {
                        List <List <Material> > binsOfMatsThatUseShader = shader2Material_map[sh];
                        List <Material>         allMatsThatUserShader   = binsOfMatsThatUseShader[0];//at this point everything is in the same list
                        binsOfMatsThatUseShader.RemoveAt(0);
                        MB3_TextureCombiner combiner = mom.CreateAndConfigureTextureCombiner();
                        combiner.saveAtlasesAsAssets = false;
                        if (allMatsThatUserShader.Count > 1)
                        {
                            combiner.fixOutOfBoundsUVs = mom.fixOutOfBoundsUVs;
                        }
                        else
                        {
                            combiner.fixOutOfBoundsUVs = false;
                        }

                        // Do the texture pack
                        List <AtlasPackingResult> packingResults = new List <AtlasPackingResult>();
                        Material tempMat = new Material(sh.shader);
                        combiner.CombineTexturesIntoAtlases(null, null, tempMat, mom.GetObjectsToCombine(), allMatsThatUserShader, null, packingResults, true);
                        for (int i = 0; i < packingResults.Count; i++)
                        {
                            List <MatsAndGOs> matsData = (List <MatsAndGOs>)packingResults[i].data;
                            List <Material>   mats     = new List <Material>();
                            for (int j = 0; j < matsData.Count; j++)
                            {
                                for (int kk = 0; kk < matsData[j].mats.Count; kk++)
                                {
                                    if (!mats.Contains(matsData[j].mats[kk].mat))
                                    {
                                        mats.Add(matsData[j].mats[kk].mat);
                                    }
                                }
                            }
                            binsOfMatsThatUseShader.Add(mats);
                        }
                        numResMats += binsOfMatsThatUseShader.Count;
                    }
                }
            }

            //build the result materials
            if (shader2Material_map.Count == 0 && obUVobject2mesh_map.Count == 0)
            {
                Debug.LogError("Found no materials in list of objects to combine");
            }
            mom.resultMaterials = new MB_MultiMaterial[numResMats + obUVobject2mesh_map.Count];
            string pth        = AssetDatabase.GetAssetPath(mom.textureBakeResults);
            string baseName   = Path.GetFileNameWithoutExtension(pth);
            string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6);
            int    k          = 0;

            foreach (MultiMatSubmeshInfo sh in shader2Material_map.Keys)
            {
                foreach (List <Material> matsThatUse in shader2Material_map[sh])
                {
                    MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
                    mm.sourceMaterials = matsThatUse;
                    if (mm.sourceMaterials.Count == 1)
                    {
                        mm.considerMeshUVs = false;
                    }
                    else
                    {
                        mm.considerMeshUVs = mom.fixOutOfBoundsUVs;
                    }
                    string   matName = folderPath + baseName + "-mat" + k + ".mat";
                    Material newMat  = new Material(Shader.Find("Diffuse"));
                    if (matsThatUse.Count > 0 && matsThatUse[0] != null)
                    {
                        MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, matsThatUse[0]);
                    }
                    AssetDatabase.CreateAsset(newMat, matName);
                    mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                    k++;
                }
            }
            foreach (Material m in obUVobject2mesh_map.Keys)
            {
                MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
                mm.sourceMaterials = new List <Material>();
                mm.sourceMaterials.Add(m);
                mm.considerMeshUVs = false;
                string   matName = folderPath + baseName + "-mat" + k + ".mat";
                Material newMat  = new Material(Shader.Find("Diffuse"));
                MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, m);
                AssetDatabase.CreateAsset(newMat, matName);
                mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                k++;
            }
            MBVersionEditor.UpdateIfDirtyOrScript(textureBaker);
        }
Example #30
0
        internal static bool ConvertTexturesToReadableFormat(TexturePropertyData texturePropertyData,
                                                             MB_AtlasesAndRects[] resultAtlasesAndRectSlices,
                                                             bool[] hasTexForProperty, List <ShaderTextureProperty> textureShaderProperties,
                                                             MB3_TextureCombiner combiner,
                                                             MB2_LogLevel logLevel,
                                                             List <Texture2D> createdTemporaryTextureAssets,
                                                             MB2_EditorMethodsInterface textureEditorMethods)
        {
            for (int propIdx = 0; propIdx < hasTexForProperty.Length; propIdx++)
            {
                if (!hasTexForProperty[propIdx])
                {
                    continue;
                }

                TextureFormat format = texturePropertyData.formats[propIdx];

                if (!textureEditorMethods.TextureImporterFormatExistsForTextureFormat(format))
                {
                    Debug.LogError("Could not find target importer format matching " + format);
                    return(false);
                }

                int numSlices    = resultAtlasesAndRectSlices.Length;
                int targetWidth  = (int)texturePropertyData.sizes[propIdx].x;
                int targetHeight = (int)texturePropertyData.sizes[propIdx].y;
                for (int sliceIdx = 0; sliceIdx < numSlices; sliceIdx++)
                {
                    Texture2D sliceTex = resultAtlasesAndRectSlices[sliceIdx].atlases[propIdx];

                    Debug.Assert(sliceTex != null, "sliceIdx " + sliceIdx + " " + propIdx);
                    if (sliceTex != null)
                    {
                        if (!MBVersion.IsTextureReadable(sliceTex))
                        {
                            textureEditorMethods.SetReadWriteFlag(sliceTex, true, true);
                        }

                        bool isAsset = textureEditorMethods.IsAnAsset(sliceTex);
                        if (logLevel >= MB2_LogLevel.trace)
                        {
                            Debug.Log("Considering format of texture: " + sliceTex + " format:" + sliceTex.format);
                        }
                        if ((sliceTex.width != targetWidth || sliceTex.height != targetHeight) ||
                            (!isAsset && sliceTex.format != format))
                        {
                            // Do this the horrible hard way. It is only possible to resize textures in TrueColor formats,
                            // And only possible to switch formats using the Texture importer.
                            // Create a resized temporary texture asset in ARGB32 format. Then set its texture format and reimport
                            resultAtlasesAndRectSlices[sliceIdx].atlases[propIdx] = textureEditorMethods.CreateTemporaryAssetCopy(textureShaderProperties[propIdx], sliceTex, targetWidth, targetHeight, format, logLevel);
                            createdTemporaryTextureAssets.Add(resultAtlasesAndRectSlices[sliceIdx].atlases[propIdx]);
                        }
                        else if (sliceTex.format != format)
                        {
                            textureEditorMethods.ConvertTextureFormat_PlatformOverride(sliceTex, format, textureShaderProperties[propIdx].isNormalMap);
                        }
                    }
                    else
                    {
                    }

                    if (resultAtlasesAndRectSlices[sliceIdx].atlases[propIdx].format != format)
                    {
                        Debug.LogError("Could not convert texture to format " + format +
                                       ". This can happen if the target build platform in build settings does not support textures in this format." +
                                       " It may be necessary to switch the build platform in order to build texture arrays in this format.");
                        return(false);
                    }
                }
            }

            return(true);
        }