/// <summary> /// Texture 合并管线第 3 步,创建 Atlas 并保存资源 /// </summary> /// <returns></returns> internal static void Step3_BuildAndSaveAtlasesAndStoreResults( TextureCombinePipelineData data, TextureCombineHandler combiner, ITextureCombineAtlasPacker packer, AtlasPackingResult atlasPackingResult, EditorMethodsInterface textureEditorMethods, AtlasesAndRects resultAtlasesAndRects) { //run the garbage collector to free up as much memory as possible before bake to reduce MissingReferenceException problems GC.Collect(); Texture2D[] atlases = new Texture2D[data.numAtlases]; //StringBuilder report = GenerateReport(data); //创建图集 packer.CreateAtlases(data, combiner, atlasPackingResult, atlases, textureEditorMethods); data.nonTexturePropertyBlender.AdjustNonTextureProperties(data.ResultMaterial, data.texPropertyNames, data.distinctMaterialTextures, textureEditorMethods); if (data.distinctMaterialTextures.Count > 0) { data.distinctMaterialTextures[0].AdjustResultMaterialNonTextureProperties(data.ResultMaterial, data.texPropertyNames); } List <MaterialAndUVRect> mat2rect_map = new List <MaterialAndUVRect>(); for (int i = 0; i < data.distinctMaterialTextures.Count; i++) { MaterialPropTexturesSet texSet = data.distinctMaterialTextures[i]; List <MatAndTransformToMerged> mats = texSet.matsAndGOs.mats; Rect allPropsUseSameTiling_encapsulatingSamplingRect; Rect propsUseDifferntTiling_obUVRect; texSet.GetRectsForTextureBakeResults(out allPropsUseSameTiling_encapsulatingSamplingRect, out propsUseDifferntTiling_obUVRect); for (int j = 0; j < mats.Count; j++) { Rect allPropsUseSameTiling_sourceMaterialTiling = texSet.GetMaterialTilingRectForTextureBakerResults(j); MaterialAndUVRect key = new MaterialAndUVRect( mats[j].mat, atlasPackingResult.rects[i], texSet.allTexturesUseSameMatTiling, allPropsUseSameTiling_sourceMaterialTiling, allPropsUseSameTiling_encapsulatingSamplingRect, propsUseDifferntTiling_obUVRect, texSet.tilingTreatment, mats[j].objName); if (!mat2rect_map.Contains(key)) { mat2rect_map.Add(key); } } } resultAtlasesAndRects.atlases = atlases; // one per texture on result shader resultAtlasesAndRects.texPropertyNames = ShaderTextureProperty.GetNames(data.texPropertyNames); // one per texture on source shader resultAtlasesAndRects.originMatToRect_map = mat2rect_map; combiner._destroyAllTemporaryTextures(); }
public void SetMaterialTextureProperty(Material target, ShaderTextureProperty texPropName, string texturePath) { // if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.Log(MB2_LogLevel.debug,"Assigning atlas " + texturePath + " to result material " + target + " for property " + texPropName,LOG_LEVEL); if (texPropName.isNormalMap) { SetNormalMap((Texture2D)(AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D)))); } if (target.HasProperty(texPropName.name)) { target.SetTexture(texPropName.name, (Texture2D)(AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D)))); } }
/** * pass in System.IO.File.WriteAllBytes for parameter fileSaveFunction. This is necessary because on Web Player file saving * functions only exist for Editor classes */ public void SaveAtlasToAssetDatabase(Texture2D atlas, ShaderTextureProperty texPropertyName, int atlasNum, Material resMat) { if (atlas == null) { SetMaterialTextureProperty(resMat, texPropertyName, null); } else { string prefabPth = AssetDatabase.GetAssetPath(resMat); if (prefabPth == null || prefabPth.Length == 0) { Debug.LogError("Could save atlas. Could not find result material in AssetDatabase."); return; } string baseName = Path.GetFileNameWithoutExtension(prefabPth); string folderPath = prefabPth.Substring(0, prefabPth.Length - baseName.Length - 4); string fullFolderPath = Application.dataPath + folderPath.Substring("Assets".Length, folderPath.Length - "Assets".Length); string pth = fullFolderPath + baseName + "-" + texPropertyName.name + "-atlas" + atlasNum; string relativePath = folderPath + baseName + "-" + texPropertyName.name + "-atlas" + atlasNum; //need to create a copy because sometimes the packed atlases are not in ARGB32 format Texture2D newTex = MeshBakerUtility.createTextureCopy(atlas); int size = Mathf.Max(newTex.height, newTex.width); if (SAVE_FORMAT == saveTextureFormat.png) { pth += ".png"; relativePath += ".png"; byte[] bytes = newTex.EncodeToPNG(); System.IO.File.WriteAllBytes(pth, bytes); } else { pth += ".tga"; relativePath += ".tga"; if (File.Exists(pth)) { File.Delete(pth); } //Create the file. FileStream fs = File.Create(pth); MB_TGAWriter.Write(newTex.GetPixels(), newTex.width, newTex.height, fs); } UnityEditor.Editor.DestroyImmediate(newTex); AssetDatabase.Refresh(); Debug.Log(String.Format("Wrote atlas for {0} to file:{1}", texPropertyName.name, pth)); Texture2D txx = (Texture2D)(AssetDatabase.LoadAssetAtPath(relativePath, typeof(Texture2D))); SetTextureSize(txx, size); SetMaterialTextureProperty(resMat, texPropertyName, relativePath); } }
public static void TestRender(Texture2D input, Texture2D output) { int numAtlases = 1; ShaderTextureProperty[] texPropertyNames = new ShaderTextureProperty[] { new ShaderTextureProperty("_BumpMap", false) }; int atlasSizeX = input.width; int atlasSizeY = input.height; int _padding = 0; Rect[] uvRects = new Rect[] { new Rect(0f, 0f, 1f, 1f) }; List <MB_TexSet> distinctMaterialTextures = new List <MB_TexSet>(); MeshBakerMaterialTexture[] dmts = new MeshBakerMaterialTexture[] { new MeshBakerMaterialTexture(input) }; MB_TexSet texSet = new MB_TexSet(dmts, Vector2.zero, Vector2.one); distinctMaterialTextures.Add(texSet); GameObject renderAtlasesGO = null; renderAtlasesGO = new GameObject("MBrenderAtlasesGO"); MB3_AtlasPackerRenderTexture atlasRenderTexture = renderAtlasesGO.AddComponent <MB3_AtlasPackerRenderTexture>(); renderAtlasesGO.AddComponent <Camera>(); for (int i = 0; i < numAtlases; i++) { Texture2D atlas = null; Debug.Log("About to render " + texPropertyNames[i].name + " isNormal=" + texPropertyNames[i].isNormalMap); atlasRenderTexture.LOG_LEVEL = MB2_LogLevel.trace; atlasRenderTexture.width = atlasSizeX; atlasRenderTexture.height = atlasSizeY; atlasRenderTexture.padding = _padding; atlasRenderTexture.rects = uvRects; atlasRenderTexture.textureSets = distinctMaterialTextures; atlasRenderTexture.indexOfTexSetToRender = i; atlasRenderTexture.isNormalMap = texPropertyNames[i].isNormalMap; // call render on it atlas = atlasRenderTexture.OnRenderAtlas(null); Debug.Log("Created atlas " + texPropertyNames[i].name + " w=" + atlas.width + " h=" + atlas.height + " id=" + atlas.GetInstanceID()); Debug.Log("Color " + atlas.GetPixel(5, 5) + " " + Color.red); #if !UNITY_WEBPLAYER byte[] bytes = atlas.EncodeToPNG(); File.WriteAllBytes(Application.dataPath + "/_Experiment/red.png", bytes); #endif } }
public override void CreateAtlases( TextureCombinePipelineData data, TextureCombineHandler combiner, AtlasPackingResult packedAtlasRects, Texture2D[] atlases, EditorMethodsInterface textureEditorMethods) { Rect[] uvRects = packedAtlasRects.rects; int atlasSizeX = packedAtlasRects.atlasX; int atlasSizeY = packedAtlasRects.atlasY; 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 (!TextureCombinePipeline.ShouldWeCreateAtlasForThisProperty(propIdx, data.considerNonTextureProperties, data.allTexturesAreNullAndSameColor)) { atlas = null; Debug.Log("=== Not creating atlas for " + property.name + " because textures are null and default value parameters are the same."); } else { 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++) { MaterialPropTexturesSet texSet = data.distinctMaterialTextures[texSetIdx]; MaterialPropTexture matTex = texSet.ts[propIdx]; string s = "Creating Atlas '" + property.name + "' texture " + matTex.GetTexName(); 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 (textureEditorMethods != null) { textureEditorMethods.SetReadWriteFlag(t, true, true); } DRect samplingRect = texSet.ts[propIdx].GetEncapsulatingSamplingRect(); CopyScaledAndTiledToAtlas(texSet.ts[propIdx], texSet, property, samplingRect, x, y, ww, hh, packedAtlasRects.padding[texSetIdx], atlasPixels, isNormalMap, data, combiner); } 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(); Debug.Log("Saving atlas " + property.name + " w=" + atlas.width + " h=" + atlas.height); } atlases[propIdx] = atlas; 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(data.texPropertyNames[propIdx].name); } }
internal static void CopyScaledAndTiledToAtlas(MaterialPropTexture source, MaterialPropTexturesSet sourceMaterial, ShaderTextureProperty shaderPropertyName, DRect srcSamplingRect, int targX, int targY, int targW, int targH, AtlasPadding padding, Color[][] atlasPixels, bool isNormalMap, TextureCombinePipelineData data, TextureCombineHandler combiner) { //HasFinished = false; Texture2D t = source.GetTexture2D(); 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++) { 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]; } } }
public Texture2D DoRenderAtlas(GameObject gameObject, int width, int height, int padding, Rect[] rss, List <MB3_TextureCombiner.MB_TexSet> textureSetss, int indexOfTexSetToRenders, ShaderTextureProperty texPropertyname, TextureBlender resultMaterialTextureBlender, bool isNormalMap, bool fixOutOfBoundsUVs, bool considerNonTextureProperties, MB3_TextureCombiner texCombiner, MB2_LogLevel LOG_LEV) { LOG_LEVEL = LOG_LEV; textureSets = textureSetss; indexOfTexSetToRender = indexOfTexSetToRenders; _texPropertyName = texPropertyname; _padding = padding; _isNormalMap = isNormalMap; _fixOutOfBoundsUVs = fixOutOfBoundsUVs; //_considerNonTextureProperties = considerNonTextureProperties; _resultMaterialTextureBlender = resultMaterialTextureBlender; 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); }
private void CopyScaledAndTiledToAtlas(MB3_TextureCombiner.MB_TexSet texSet, MB3_TextureCombiner.MeshBakerMaterialTexture source, Vector2 obUVoffset, Vector2 obUVscale, Rect rec, ShaderTextureProperty texturePropertyName, TextureBlender resultMatTexBlender) { Rect r = rec; if (resultMatTexBlender != null) { myCamera.backgroundColor = resultMatTexBlender.GetColorIfNoTexture(texSet.mats[0].mat, texturePropertyName); } else { myCamera.backgroundColor = MB3_TextureCombiner.GetColorIfNoTexture(texturePropertyName); } if (source.t == null) { source.t = combiner._createTemporaryTexture(16, 16, TextureFormat.ARGB32, true); } 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 = source.matTilingRect.GetRect(); Rect targPr = new Rect(); if (_fixOutOfBoundsUVs) { Rect ruv = new Rect(obUVoffset.x, obUVoffset.y, obUVscale.x, obUVscale.y); srcPrTex = MB3_UVTransformUtility.CombineTransforms(ref srcPrTex, ref ruv); if (LOG_LEVEL >= MB2_LogLevel.trace) { Debug.Log("Fixing out of bounds UVs for tex " + source.t); } } Texture2D tex = source.t; /* * if (_considerNonTextureProperties && resultMatTexBlender != null) * { * if (LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log(string.Format("Blending texture {0} mat {1} with non-texture properties using TextureBlender {2}", tex.name, texSet.mats[0].mat, resultMatTexBlender)); * * resultMatTexBlender.OnBeforeTintTexture(texSet.mats[0].mat, texturePropertyName.name); * //combine the tintColor with the texture * tex = combiner._createTextureCopy(tex); * for (int i = 0; i < tex.height; i++) * { * Color[] cs = tex.GetPixels(0, i, tex.width, 1); * for (int j = 0; j < cs.Length; j++) * { * cs[j] = resultMatTexBlender.OnBlendTexturePixel(texturePropertyName.name, cs[j]); * } * tex.SetPixels(0, i, tex.width, 1, cs); * } * tex.Apply(); * } */ //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; }
private void CopyScaledAndTiledToAtlas(MB_TexSet texSet, MeshBakerMaterialTexture source, Vector2 obUVoffset, Vector2 obUVscale, Rect rec, ShaderTextureProperty texturePropertyName, MB3_TextureCombinerNonTextureProperties resultMatTexBlender, bool yIsFlipped) { Rect r = rec; myCamera.backgroundColor = resultMatTexBlender.GetColorForTemporaryTexture(texSet.matsAndGOs.mats[0].mat, texturePropertyName); //yIsFlipped = true; //if (yIsFlipped) //{ //} 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 targPr = new Rect(); Rect srcPrTex = texSet.ts[indexOfTexSetToRender].GetEncapsulatingSamplingRect().GetRect(); if (!_fixOutOfBoundsUVs) { Debug.Assert(source.matTilingRect.GetRect() == texSet.ts[indexOfTexSetToRender].GetEncapsulatingSamplingRect().GetRect()); } Texture2D tex = source.GetTexture2D(); /* * if (_considerNonTextureProperties && resultMatTexBlender != null) * { * if (LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log(string.Format("Blending texture {0} mat {1} with non-texture properties using TextureBlender {2}", tex.name, texSet.mats[0].mat, resultMatTexBlender)); * * resultMatTexBlender.OnBeforeTintTexture(texSet.mats[0].mat, texturePropertyName.name); * //combine the tintColor with the texture * tex = combiner._createTextureCopy(tex); * for (int i = 0; i < tex.height; i++) * { * Color[] cs = tex.GetPixels(0, i, tex.width, 1); * for (int j = 0; j < cs.Length; j++) * { * cs[j] = resultMatTexBlender.OnBlendTexturePixel(texturePropertyName.name, cs[j]); * } * tex.SetPixels(0, i, tex.width, 1, cs); * } * tex.Apply(); * } */ //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; RenderTexture oldRT = RenderTexture.active; RenderTexture.active = _destinationTexture; 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); RenderTexture.active = oldRT; tex.wrapMode = oldTexWrapMode; }
public static void TestRender(Texture2D input, Texture2D output) { int num = 1; ShaderTextureProperty[] array = new ShaderTextureProperty[] { new ShaderTextureProperty("_BumpMap", false) }; int width = input.width; int height = input.height; int padding = 0; Rect[] rects = new Rect[] { new Rect(0f, 0f, 1f, 1f) }; List <MB3_TextureCombiner.MB_TexSet> list = new List <MB3_TextureCombiner.MB_TexSet>(); MB3_TextureCombiner.MeshBakerMaterialTexture[] tss = new MB3_TextureCombiner.MeshBakerMaterialTexture[] { new MB3_TextureCombiner.MeshBakerMaterialTexture(input) }; MB3_TextureCombiner.MB_TexSet item = new MB3_TextureCombiner.MB_TexSet(tss); list.Add(item); GameObject gameObject = new GameObject("MBrenderAtlasesGO"); MB3_AtlasPackerRenderTexture mb3_AtlasPackerRenderTexture = gameObject.AddComponent <MB3_AtlasPackerRenderTexture>(); gameObject.AddComponent <Camera>(); for (int i = 0; i < num; i++) { Debug.Log(string.Concat(new object[] { "About to render ", array[i].name, " isNormal=", array[i].isNormalMap })); mb3_AtlasPackerRenderTexture.LOG_LEVEL = MB2_LogLevel.trace; mb3_AtlasPackerRenderTexture.width = width; mb3_AtlasPackerRenderTexture.height = height; mb3_AtlasPackerRenderTexture.padding = padding; mb3_AtlasPackerRenderTexture.rects = rects; mb3_AtlasPackerRenderTexture.textureSets = list; mb3_AtlasPackerRenderTexture.indexOfTexSetToRender = i; mb3_AtlasPackerRenderTexture.isNormalMap = array[i].isNormalMap; Texture2D texture2D = mb3_AtlasPackerRenderTexture.OnRenderAtlas(null); Debug.Log(string.Concat(new object[] { "Created atlas ", array[i].name, " w=", texture2D.width, " h=", texture2D.height, " id=", texture2D.GetInstanceID() })); Debug.Log(string.Concat(new object[] { "Color ", texture2D.GetPixel(5, 5), " ", Color.red })); byte[] bytes = texture2D.EncodeToPNG(); File.WriteAllBytes(Application.dataPath + "/_Experiment/red.png", bytes); } }
//public static bool TextureCombineEntrance(TextureCombinePipelineData combineData, // AtlasesAndRects resultAtlasesAndRectsData, // Material resultMaterial) //{ // bool isCombineSuccess = false; // MaterialPropTexture.readyToBuildAtlases = false; // return isCombineSuccess; //} /// <summary> /// 收集材质参数名称 /// </summary> /// <param name="data"></param> /// <returns></returns> internal static bool CollectPropertyNames(TextureCombinePipelineData data) { //try custom properties remove duplicates //尝试删除自定义属性的重复项 for (int i = 0; i < data.texPropertyNames.Count; i++) { ShaderTextureProperty s = data.customShaderPropNames.Find(x => x.name.Equals(data.texPropertyNames[i].name)); if (s != null) { data.customShaderPropNames.Remove(s); } } Material m = data.ResultMaterial; if (m == null) { Debug.LogError("合并材质为空。"); return(false); } //Collect the property names for the textures for (int i = 0; i < shaderTexPropertyNames.Length; i++) { if (m.HasProperty(shaderTexPropertyNames[i].name)) { if (!data.texPropertyNames.Contains(shaderTexPropertyNames[i])) { data.texPropertyNames.Add(shaderTexPropertyNames[i]); } if (m.GetTextureOffset(shaderTexPropertyNames[i].name) != new Vector2(0f, 0f)) { Debug.LogWarning("Result material has non-zero offset. This is may be incorrect."); } if (m.GetTextureScale(shaderTexPropertyNames[i].name) != new Vector2(1f, 1f)) { Debug.LogWarning("Result material should have tiling of 1,1"); } } } for (int i = 0; i < data.customShaderPropNames.Count; i++) { if (m.HasProperty(data.customShaderPropNames[i].name)) { data.texPropertyNames.Add(data.customShaderPropNames[i]); if (m.GetTextureOffset(data.customShaderPropNames[i].name) != new Vector2(0f, 0f)) { Debug.LogWarning("Result material has non-zero offset. This is probably incorrect."); } if (m.GetTextureScale(data.customShaderPropNames[i].name) != new Vector2(1f, 1f)) { Debug.LogWarning("Result material should probably have tiling of 1,1."); } } else { Debug.LogWarning("Result material shader does not use property " + data.customShaderPropNames[i].name + " in the list of custom shader property names"); } } return(true); }