internal static Color GetColorIfNoTexture(ShaderTextureProperty texProperty) { if (texProperty.isNormalMap) { return(new Color(.5f, .5f, 1f)); } else if (texProperty.name.Equals("_MetallicGlossMap")) { return(new Color(0f, 0f, 0f, 1f)); } else if (texProperty.name.Equals("_ParallaxMap")) { return(new Color(0f, 0f, 0f, 0f)); } else if (texProperty.name.Equals("_OcclusionMap")) { return(new Color(1f, 1f, 1f, 1f)); } else if (texProperty.name.Equals("_EmissionMap")) { return(new Color(0f, 0f, 0f, 0f)); } else if (texProperty.name.Equals("_DetailMask")) { return(new Color(0f, 0f, 0f, 0f)); } return(new Color(1f, 1f, 1f, 0f)); }
/** * 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 + ".png"; //need to create a copy because sometimes the packed atlases are not in ARGB32 format Texture2D newTex = MB_Utility.createTextureCopy(atlas); int size = Mathf.Max(newTex.height, newTex.width); byte[] bytes = newTex.EncodeToPNG(); Editor.DestroyImmediate(newTex); System.IO.File.WriteAllBytes(pth, bytes); AssetDatabase.Refresh(); string relativePath = folderPath + baseName + "-" + texPropertyName.name + "-atlas" + atlasNum + ".png"; SetTextureSize((Texture2D)(AssetDatabase.LoadAssetAtPath(relativePath, typeof(Texture2D))), size); SetMaterialTextureProperty(resMat, texPropertyName, relativePath); } }
public static bool ShouldTextureBeLinear(ShaderTextureProperty shaderTextureProperty) { if (shaderTextureProperty.isNormalMap) { return(true); } else { return(false); } }
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)))); } }
// 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(ShaderTextureProperty 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.name, (int)newWidth, (int)newHeight, TextureFormat.ARGB32, true, MB3_TextureCombiner.ShouldTextureBeLinear(propertyName)); 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); }
/** * 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 = MB_Utility.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); } 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 Color GetColorForTemporaryTexture(Material matIfBlender, ShaderTextureProperty texProperty) { Debug.Assert(_textureProperties._considerNonTextureProperties == false); if (texProperty.isNormalMap) { return(NEUTRAL_NORMAL_MAP_COLOR); } else if (_textureProperties.textureProperty2DefaultColorMap.ContainsKey(texProperty.name)) { return(_textureProperties.textureProperty2DefaultColorMap[texProperty.name]); } return(new Color(1f, 1f, 1f, 0f)); }
public Color GetColorIfNoTexture(Material m, ShaderTextureProperty texPropertyName) { if (texPropertyName.name.Equals("_MainTex")) { if (m != null && m.HasProperty("_Color")) { try { //need try because can't garantee _Color is a color return(m.GetColor("_Color")); } catch (Exception) { } } } return(new Color(1, 1, 1, 0)); }
public override bool Equals(object obj) { if (!(obj is ShaderTextureProperty)) { return(false); } ShaderTextureProperty b = (ShaderTextureProperty)obj; if (!name.Equals(b.name)) { return(false); } if (isNormalMap != b.isNormalMap) { return(false); } return(true); }
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<MB3_TextureCombiner.MB_TexSet> distinctMaterialTextures = new List<MB3_TextureCombiner.MB_TexSet>(); MB3_TextureCombiner.MeshBakerMaterialTexture[] dmts = new MB3_TextureCombiner.MeshBakerMaterialTexture[] { new MB3_TextureCombiner.MeshBakerMaterialTexture(input) }; MB3_TextureCombiner.MB_TexSet texSet = new MB3_TextureCombiner.MB_TexSet(dmts); 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 } }
/** 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 + ".png"; //need to create a copy because sometimes the packed atlases are not in ARGB32 format Texture2D newTex = MB_Utility.createTextureCopy(atlas); int size = Mathf.Max(newTex.height,newTex.width); byte[] bytes = newTex.EncodeToPNG(); Editor.DestroyImmediate(newTex); System.IO.File.WriteAllBytes(pth, bytes); AssetDatabase.Refresh(); string relativePath = folderPath + baseName +"-" + texPropertyName.name + "-atlas" + atlasNum + ".png"; SetTextureSize((Texture2D) (AssetDatabase.LoadAssetAtPath(relativePath, typeof(Texture2D))),size); SetMaterialTextureProperty(resMat, texPropertyName, relativePath); } }
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)))); } }
internal Color GetColorIfNoTexture(Material m, ShaderTextureProperty shaderPropertyName) { return(resultMaterialTextureBlender.GetColorIfNoTexture(m, shaderPropertyName)); }
public Texture2D TintTextureWithTextureCombiner(Texture2D t, MB_TexSet sourceMaterial, ShaderTextureProperty shaderPropertyName) { Debug.Assert(_textureProperties._considerNonTextureProperties == false); Debug.LogError("TintTextureWithTextureCombiner should never be called if resultMaterialTextureBlender is null"); return(t); }
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; }
public Color GetColorIfNoTexture(Material mat, ShaderTextureProperty texPropertyName) { if (texPropertyName.name.Equals("_BumpMap")) { return(new Color(.5f, .5f, 1f)); } else if (texPropertyName.name.Equals("_MainTex")) { if (mat != null && mat.HasProperty("_Color")) { try { //need try because can't garantee _Color is a color Color c = mat.GetColor("_Color"); sourceMaterialPropertyCache.CacheMaterialProperty(mat, "_Color", c); return(c); } catch (Exception) { } return(Color.white); } } else if (texPropertyName.name.Equals("_MetallicGlossMap")) { if (mat != null && mat.HasProperty("_Metallic")) { try { //need try because can't garantee _Metallic is a float float v = mat.GetFloat("_Metallic"); Color c = new Color(v, v, v); if (mat.HasProperty("_Glossiness")) { try { c.a = mat.GetFloat("_Glossiness"); } catch (Exception) { } } sourceMaterialPropertyCache.CacheMaterialProperty(mat, "_Metallic", v); sourceMaterialPropertyCache.CacheMaterialProperty(mat, "_Glossiness", c.a); return(c); } catch (Exception) { } return(new Color(0f, 0f, 0f, .5f)); } else { return(new Color(0f, 0f, 0f, .5f)); } } else if (texPropertyName.name.Equals("_ParallaxMap")) { return(new Color(0f, 0f, 0f, 0f)); } else if (texPropertyName.name.Equals("_OcclusionMap")) { return(new Color(1f, 1f, 1f, 1f)); } else if (texPropertyName.name.Equals("_EmissionMap")) { if (mat != null) { if (mat.IsKeywordEnabled("_EMISSION")) { if (mat.HasProperty("_EmissionColor")) { try { Color c = mat.GetColor("_EmissionColor"); sourceMaterialPropertyCache.CacheMaterialProperty(mat, "_EmissionColor", c); return(c); } catch (Exception) { } } else { return(Color.black); } } else { return(Color.black); } } } else if (texPropertyName.name.Equals("_DetailMask")) { return(new Color(0f, 0f, 0f, 0f)); } return(new Color(1f, 1f, 1f, 0f)); }
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 bool CollectPropertyNames(List <ShaderTextureProperty> texPropertyNames, ShaderTextureProperty[] shaderTexPropertyNames, List <ShaderTextureProperty> _customShaderPropNames, Material resultMaterial, MB2_LogLevel LOG_LEVEL) { #if UNITY_2019_3_OR_NEWER // 2018.2 and up // Collect the property names from the shader // Check with the lists of property names to flag which ones are normal maps. if (resultMaterial != null && resultMaterial.shader != null) { Shader s = resultMaterial.shader; for (int i = 0; i < s.GetPropertyCount(); i++) { if (s.GetPropertyType(i) == UnityEngine.Rendering.ShaderPropertyType.Texture) { string matPropName = s.GetPropertyName(i); if (resultMaterial.GetTextureOffset(matPropName) != new Vector2(0f, 0f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material has non-zero offset for property " + matPropName + ". This is probably incorrect."); } } if (resultMaterial.GetTextureScale(matPropName) != new Vector2(1f, 1f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material should probably have tiling of 1,1 for propert " + matPropName); } } ShaderTextureProperty pn = null; // We need to know if the property is a normal map or not. // first check the list of default names for (int defaultIdx = 0; defaultIdx < shaderTexPropertyNames.Length; defaultIdx++) { if (shaderTexPropertyNames[defaultIdx].name == matPropName) { pn = new ShaderTextureProperty(matPropName, shaderTexPropertyNames[defaultIdx].isNormalMap); } } // now check the list of custom property names for (int custPropIdx = 0; custPropIdx < _customShaderPropNames.Count; custPropIdx++) { if (_customShaderPropNames[custPropIdx].name == matPropName) { pn = new ShaderTextureProperty(matPropName, _customShaderPropNames[custPropIdx].isNormalMap); } } if (pn == null) { pn = new ShaderTextureProperty(matPropName, false, true); } texPropertyNames.Add(pn); } } // If using URP or HDRP AND using a default /Lit shader AND both _BaseMap and _MainTex are present, get rid of _MainTex since its essentially a duplicate of _BaseMap MBVersion.PipelineType pipelineType = DetectPipeline(); int _MainTexIndex = texPropertyNames.FindIndex(pn => pn.name.Equals("_MainTex")); bool endsWithLit = s.name.EndsWith("/Lit"); if (pipelineType == MBVersion.PipelineType.URP && endsWithLit && _MainTexIndex != -1 && texPropertyNames.FindIndex(pn => pn.name.Equals("_BaseMap")) != -1) { texPropertyNames.RemoveAt(_MainTexIndex); //Debug.Log("Removed _MainTex"); } // HDRP uses _BaseColorMap instead of _BaseMap but same idea if (pipelineType == MBVersion.PipelineType.HDRP && endsWithLit && _MainTexIndex != -1 && texPropertyNames.FindIndex(pn => pn.name.Equals("_BaseColorMap")) != -1) { texPropertyNames.RemoveAt(_MainTexIndex); //Debug.Log("Removed _MainTex"); } } return(true); #elif UNITY_2018_3_OR_NEWER // 2018.2 and up // Collect the property names from the material // Check with the lists of property names to flag which ones are normal maps. string[] matPropertyNames = resultMaterial.GetTexturePropertyNames(); for (int matIdx = 0; matIdx < matPropertyNames.Length; matIdx++) { string matPropName = matPropertyNames[matIdx]; if (resultMaterial.GetTextureOffset(matPropName) != new Vector2(0f, 0f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material has non-zero offset for property " + matPropName + ". This is probably incorrect."); } } if (resultMaterial.GetTextureScale(matPropName) != new Vector2(1f, 1f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material should probably have tiling of 1,1 for propert " + matPropName); } } ShaderTextureProperty pn = null; // We need to know if the property is a normal map or not. // first check the list of default names for (int defaultIdx = 0; defaultIdx < shaderTexPropertyNames.Length; defaultIdx++) { if (shaderTexPropertyNames[defaultIdx].name == matPropName) { pn = new ShaderTextureProperty(matPropName, shaderTexPropertyNames[defaultIdx].isNormalMap); } } // now check the list of custom property names for (int custPropIdx = 0; custPropIdx < _customShaderPropNames.Count; custPropIdx++) { if (_customShaderPropNames[custPropIdx].name == matPropName) { pn = new ShaderTextureProperty(matPropName, _customShaderPropNames[custPropIdx].isNormalMap); } } if (pn == null) { pn = new ShaderTextureProperty(matPropName, false, true); } texPropertyNames.Add(pn); } return(true); #else { // Pre 2018.2, doesn't have API for querying material for property names. //Collect the property names for the textures string shaderPropStr = ""; for (int i = 0; i < shaderTexPropertyNames.Length; i++) { if (resultMaterial.HasProperty(shaderTexPropertyNames[i].name)) { shaderPropStr += ", " + shaderTexPropertyNames[i].name; if (!texPropertyNames.Contains(shaderTexPropertyNames[i])) { texPropertyNames.Add(shaderTexPropertyNames[i]); } if (resultMaterial.GetTextureOffset(shaderTexPropertyNames[i].name) != new Vector2(0f, 0f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material has non-zero offset. This is may be incorrect."); } } if (resultMaterial.GetTextureScale(shaderTexPropertyNames[i].name) != new Vector2(1f, 1f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material should have tiling of 1,1"); } } } } for (int i = 0; i < _customShaderPropNames.Count; i++) { if (resultMaterial.HasProperty(_customShaderPropNames[i].name)) { shaderPropStr += ", " + _customShaderPropNames[i].name; texPropertyNames.Add(_customShaderPropNames[i]); if (resultMaterial.GetTextureOffset(_customShaderPropNames[i].name) != new Vector2(0f, 0f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material has non-zero offset. This is probably incorrect."); } } if (resultMaterial.GetTextureScale(_customShaderPropNames[i].name) != new Vector2(1f, 1f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material should probably have tiling of 1,1."); } } } else { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material shader does not use property " + _customShaderPropNames[i].name + " in the list of custom shader property names"); } } } } return(true); #endif }
public Color GetColorAsItWouldAppearInAtlasIfNoTexture(Material matIfBlender, ShaderTextureProperty texProperty) { resultMaterialTextureBlender.OnBeforeTintTexture(matIfBlender, texProperty.name); Color c = GetColorForTemporaryTexture(matIfBlender, texProperty); return(resultMaterialTextureBlender.OnBlendTexturePixel(texProperty.name, c)); }
public Color GetColorForTemporaryTexture(Material matIfBlender, ShaderTextureProperty texProperty) { return(resultMaterialTextureBlender.GetColorIfNoTexture(matIfBlender, texProperty)); }
public Texture2D TintTextureWithTextureCombiner(Texture2D t, MB_TexSet sourceMaterial, ShaderTextureProperty shaderPropertyName) { Debug.Assert(resultMaterialTextureBlender != null); resultMaterialTextureBlender.OnBeforeTintTexture(sourceMaterial.matsAndGOs.mats[0].mat, shaderPropertyName.name); if (_textureProperties.LOG_LEVEL >= MB2_LogLevel.trace) { Debug.Log(string.Format("Blending texture {0} mat {1} with non-texture properties using TextureBlender {2}", t.name, sourceMaterial.matsAndGOs.mats[0].mat, resultMaterialTextureBlender)); } for (int i = 0; i < t.height; i++) { Color[] cs = t.GetPixels(0, i, t.width, 1); for (int j = 0; j < cs.Length; j++) { cs[j] = resultMaterialTextureBlender.OnBlendTexturePixel(shaderPropertyName.name, cs[j]); } t.SetPixels(0, i, t.width, 1, cs); } t.Apply(); return(t); }
internal static void SaveAtlasAndConfigureResultMaterial(MB3_TextureCombinerPipeline.TexturePipelineData data, MB2_EditorMethodsInterface textureEditorMethods, Texture2D atlas, ShaderTextureProperty property, int propIdx) { bool doAnySrcMatsHaveProperty = MB3_TextureCombinerPipeline._DoAnySrcMatsHaveProperty(propIdx, data.allTexturesAreNullAndSameColor); if (data._saveAtlasesAsAssets && textureEditorMethods != null) { textureEditorMethods.SaveAtlasToAssetDatabase(atlas, property, propIdx, doAnySrcMatsHaveProperty, data.resultMaterial); } else { if (doAnySrcMatsHaveProperty) { data.resultMaterial.SetTexture(property.name, atlas); } } if (doAnySrcMatsHaveProperty) { data.resultMaterial.SetTextureOffset(property.name, Vector2.zero); data.resultMaterial.SetTextureScale(property.name, Vector2.one); } }
public Color GetColorAsItWouldAppearInAtlasIfNoTexture(Material matIfBlender, ShaderTextureProperty texProperty) { Debug.Assert(false, "Should never be called"); return(Color.white); }
public Color GetColorIfNoTexture(Material mat, ShaderTextureProperty texPropertyName) { if (texPropertyName.name.Equals("_BumpMap")) { return(new Color(.5f, .5f, 1f)); } else if (texPropertyName.name.Equals("_MainTex")) { if (mat != null && mat.HasProperty("_Color")) { try { //need try because can't garantee _Color is a color return(mat.GetColor("_Color")); } catch (Exception) { } } } else if (texPropertyName.name.Equals("_MetallicGlossMap")) { if (mat != null && mat.HasProperty("_Metallic")) { try { //need try because can't garantee _Metallic is a float float v = mat.GetFloat("_Metallic"); Color c = new Color(v, v, v); if (mat.HasProperty("_GlossMapScale")) { try { c.a = mat.GetFloat("_GlossMapScale"); } catch (Exception) { } } return(c); } catch (Exception) { } } else { return(new Color(0f, 0f, 0f, .5f)); } } else if (texPropertyName.name.Equals("_ParallaxMap")) { return(new Color(0f, 0f, 0f, 0f)); } else if (texPropertyName.name.Equals("_OcclusionMap")) { return(new Color(1f, 1f, 1f, 1f)); } else if (texPropertyName.name.Equals("_EmissionMap")) { if (mat != null) { if (mat.HasProperty("_EmissionColor")) { try { return(mat.GetColor("_EmissionColor")); } catch (Exception) { } } else { return(Color.black); } } } else if (texPropertyName.name.Equals("_DetailMask")) { return(new Color(0f, 0f, 0f, 0f)); } return(new Color(1f, 1f, 1f, 0f)); }
internal Color GetColorForTemporaryTexture(Material matIfBlender, ShaderTextureProperty texProperty) { return(_nonTexturePropertiesBlender.GetColorForTemporaryTexture(matIfBlender, texProperty)); }
internal Texture2D DoRenderAtlas(GameObject go, int width, int height, bool isNormalMap, ShaderTextureProperty propertyName) { System.Diagnostics.Stopwatch db_time_DoRenderAtlas = new System.Diagnostics.Stopwatch(); db_time_DoRenderAtlas.Start(); Debug.Assert(_initialized && _camSetup); RenderTexture _destinationTexture; if (isNormalMap) { _destinationTexture = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear); } else { _destinationTexture = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB); } _destinationTexture.filterMode = FilterMode.Point; Camera myCamera = go.GetComponent <Camera>(); myCamera.targetTexture = _destinationTexture; if (LOG_LEVEL >= MB2_LogLevel.debug) { Debug.Log(string.Format("Begin Camera.Render destTex w={0} h={1} camPos={2} camSize={3} camAspect={4}", width, height, go.transform.localPosition, myCamera.orthographicSize, myCamera.aspect.ToString("f5"))); } myCamera.Render(); System.Diagnostics.Stopwatch db_ConvertRenderTextureToTexture2D = new System.Diagnostics.Stopwatch(); db_ConvertRenderTextureToTexture2D.Start(); Texture2D tempTexture = new Texture2D(_destinationTexture.width, _destinationTexture.height, TextureFormat.ARGB32, true, false); MB_TextureCombinerRenderTexture.ConvertRenderTextureToTexture2D(_destinationTexture, MB_TextureCombinerRenderTexture.YisFlipped(LOG_LEVEL), isNormalMap, LOG_LEVEL, tempTexture); if (LOG_LEVEL >= MB2_LogLevel.trace) { Debug.Log("Finished rendering atlas " + propertyName.name + " db_time_DoRenderAtlas:" + (db_time_DoRenderAtlas.ElapsedMilliseconds * .001f) + " db_ConvertRenderTextureToTexture2D:" + (db_ConvertRenderTextureToTexture2D.ElapsedMilliseconds * .001f)); } MB_Utility.Destroy(_destinationTexture); return(tempTexture); }
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 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; }
Color GetColorIfNoTexture(Material mat, ShaderTextureProperty texProperty) { if (texProperty.isNormalMap){ return new Color(.5f,.5f,1f); } else if (texProperty.name.Equals("_MainTex")){ if (mat != null && mat.HasProperty("_Color")){ try{ //need try because can't garantee _Color is a color return mat.GetColor("_Color"); } catch (Exception){} } } else if (texProperty.name.Equals ("_SpecGlossMap")){ if (mat != null && mat.HasProperty("_SpecColor")){ try{ //need try because can't garantee _Color is a color Color c = mat.GetColor("_SpecColor"); if (mat.HasProperty("_Glossiness")){ try{ c.a = mat.GetFloat("_Glossiness"); } catch (Exception){} } Debug.LogWarning(c); return c; } catch (Exception){} } } else if (texProperty.name.Equals("_MetallicGlossMap")){ if (mat != null && mat.HasProperty("_Metallic")){ try{ //need try because can't garantee _Metallic is a float float v = mat.GetFloat("_Metallic"); Color c = new Color(v,v,v); if (mat.HasProperty("_Glossiness")){ try{ c.a = mat.GetFloat("_Glossiness"); } catch (Exception){} } return c; } catch (Exception){} } } else if (texProperty.name.Equals("_ParallaxMap")){ return new Color(0f,0f,0f,0f); } else if (texProperty.name.Equals("_OcclusionMap")){ return new Color(1f,1f,1f,1f); } else if (texProperty.name.Equals("_EmissionMap")){ if (mat != null){ if (mat.HasProperty("_EmissionScaleUI")){ //Standard shader has weird behavior if EmissionMap has never //been set then no EmissionColorUI color picker. If has ever //been set then is EmissionColorUI color picker. if (mat.HasProperty("_EmissionColor") && mat.HasProperty ("_EmissionColorUI")){ try{ Color c1 = mat.GetColor("_EmissionColor"); Color c2 = mat.GetColor("_EmissionColorUI"); float f = mat.GetFloat("_EmissionScaleUI"); if (c1 == new Color(0f,0f,0f,0f) && c2 == new Color(1f,1f,1f,1f)){ //is virgin Emission values return new Color(f,f,f,f); } else { //non virgin Emission values return c2; } } catch(Exception){} } else { try{ //need try because can't garantee _Color is a color float f = mat.GetFloat("_EmissionScaleUI"); return new Color(f,f,f,f); } catch (Exception){} } } } } else if (texProperty.name.Equals("_DetailMask")){ return new Color(0f,0f,0f,0f); } return new Color(1f,1f,1f,0f); }
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._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); } yield break; }
internal Texture2D TintTextureWithTextureCombiner(Texture2D t, MB_TexSet sourceMaterial, ShaderTextureProperty shaderPropertyName) { return(_nonTexturePropertiesBlender.TintTextureWithTextureCombiner(t, sourceMaterial, shaderPropertyName)); }
public Color GetColorIfNoTexture(Material mat, ShaderTextureProperty texProperty) { if (texProperty.isNormalMap) { return(new Color(.5f, .5f, 1f)); } else if (texProperty.name.Equals("_MainTex")) { if (mat != null && mat.HasProperty("_Color")) { try { //need try because can't garantee _Color is a color return(mat.GetColor("_Color")); } catch (Exception) { } } else if (mat != null && mat.HasProperty("_TintColor")) { try { //need try because can't garantee _TintColor is a color return(mat.GetColor("_TintColor")); } catch (Exception) { } } } else if (texProperty.name.Equals("_SpecGlossMap")) { if (mat != null && mat.HasProperty("_SpecColor")) { try { //need try because can't garantee _Color is a color Color c = mat.GetColor("_SpecColor"); if (mat.HasProperty("_Glossiness")) { try { c.a = mat.GetFloat("_Glossiness"); } catch (Exception) { } } Debug.LogWarning(c); return(c); } catch (Exception) { } } } else if (texProperty.name.Equals("_MetallicGlossMap")) { if (mat != null && mat.HasProperty("_Metallic")) { try { //need try because can't garantee _Metallic is a float float v = mat.GetFloat("_Metallic"); Color c = new Color(v, v, v); if (mat.HasProperty("_Glossiness")) { try { c.a = mat.GetFloat("_Glossiness"); } catch (Exception) { } } return(c); } catch (Exception) { } } } else if (texProperty.name.Equals("_ParallaxMap")) { return(new Color(0f, 0f, 0f, 0f)); } else if (texProperty.name.Equals("_OcclusionMap")) { return(new Color(1f, 1f, 1f, 1f)); } else if (texProperty.name.Equals("_EmissionMap")) { if (mat != null) { if (mat.HasProperty("_EmissionScaleUI")) { //Standard shader has weird behavior if EmissionMap has never //been set then no EmissionColorUI color picker. If has ever //been set then is EmissionColorUI color picker. if (mat.HasProperty("_EmissionColor") && mat.HasProperty("_EmissionColorUI")) { try { Color c1 = mat.GetColor("_EmissionColor"); Color c2 = mat.GetColor("_EmissionColorUI"); float f = mat.GetFloat("_EmissionScaleUI"); if (c1 == new Color(0f, 0f, 0f, 0f) && c2 == new Color(1f, 1f, 1f, 1f)) { //is virgin Emission values return(new Color(f, f, f, f)); } else //non virgin Emission values { return(c2); } } catch (Exception) { } } else { try { //need try because can't garantee _Color is a color float f = mat.GetFloat("_EmissionScaleUI"); return(new Color(f, f, f, f)); } catch (Exception) { } } } } } else if (texProperty.name.Equals("_DetailMask")) { return(new Color(0f, 0f, 0f, 0f)); } return(new Color(1f, 1f, 1f, 0f)); }
internal Color GetColorAsItWouldAppearInAtlasIfNoTexture(Material matIfBlender, ShaderTextureProperty texProperty) { return(_nonTexturePropertiesBlender.GetColorAsItWouldAppearInAtlasIfNoTexture(matIfBlender, texProperty)); }
public bool CollectPropertyNames(List <ShaderTextureProperty> texPropertyNames, ShaderTextureProperty[] shaderTexPropertyNames, List <ShaderTextureProperty> _customShaderPropNames, Material resultMaterial, MB2_LogLevel LOG_LEVEL) { #if UNITY_2019_3_OR_NEWER // 2018.2 and up // Collect the property names from the shader // Check with the lists of property names to flag which ones are normal maps. if (resultMaterial != null && resultMaterial.shader != null) { Shader s = resultMaterial.shader; for (int i = 0; i < s.GetPropertyCount(); i++) { if (s.GetPropertyType(i) == UnityEngine.Rendering.ShaderPropertyType.Texture) { string matPropName = s.GetPropertyName(i); if (resultMaterial.GetTextureOffset(matPropName) != new Vector2(0f, 0f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material has non-zero offset for property " + matPropName + ". This is probably incorrect."); } } if (resultMaterial.GetTextureScale(matPropName) != new Vector2(1f, 1f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material should probably have tiling of 1,1 for propert " + matPropName); } } ShaderTextureProperty pn = null; // We need to know if the property is a normal map or not. // first check the list of default names for (int defaultIdx = 0; defaultIdx < shaderTexPropertyNames.Length; defaultIdx++) { if (shaderTexPropertyNames[defaultIdx].name == matPropName) { pn = new ShaderTextureProperty(matPropName, shaderTexPropertyNames[defaultIdx].isNormalMap); } } // now check the list of custom property names for (int custPropIdx = 0; custPropIdx < _customShaderPropNames.Count; custPropIdx++) { if (_customShaderPropNames[custPropIdx].name == matPropName) { pn = new ShaderTextureProperty(matPropName, _customShaderPropNames[custPropIdx].isNormalMap); } } if (pn == null) { pn = new ShaderTextureProperty(matPropName, false, true); } texPropertyNames.Add(pn); } } } return(true); #elif UNITY_2018_3_OR_NEWER // 2018.2 and up // Collect the property names from the material // Check with the lists of property names to flag which ones are normal maps. string[] matPropertyNames = resultMaterial.GetTexturePropertyNames(); for (int matIdx = 0; matIdx < matPropertyNames.Length; matIdx++) { string matPropName = matPropertyNames[matIdx]; if (resultMaterial.GetTextureOffset(matPropName) != new Vector2(0f, 0f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material has non-zero offset for property " + matPropName + ". This is probably incorrect."); } } if (resultMaterial.GetTextureScale(matPropName) != new Vector2(1f, 1f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material should probably have tiling of 1,1 for propert " + matPropName); } } ShaderTextureProperty pn = null; // We need to know if the property is a normal map or not. // first check the list of default names for (int defaultIdx = 0; defaultIdx < shaderTexPropertyNames.Length; defaultIdx++) { if (shaderTexPropertyNames[defaultIdx].name == matPropName) { pn = new ShaderTextureProperty(matPropName, shaderTexPropertyNames[defaultIdx].isNormalMap); } } // now check the list of custom property names for (int custPropIdx = 0; custPropIdx < _customShaderPropNames.Count; custPropIdx++) { if (_customShaderPropNames[custPropIdx].name == matPropName) { pn = new ShaderTextureProperty(matPropName, _customShaderPropNames[custPropIdx].isNormalMap); } } if (pn == null) { pn = new ShaderTextureProperty(matPropName, false, true); } texPropertyNames.Add(pn); } return(true); #else { // Pre 2018.2, doesn't have API for querying material for property names. //Collect the property names for the textures string shaderPropStr = ""; for (int i = 0; i < shaderTexPropertyNames.Length; i++) { if (resultMaterial.HasProperty(shaderTexPropertyNames[i].name)) { shaderPropStr += ", " + shaderTexPropertyNames[i].name; if (!texPropertyNames.Contains(shaderTexPropertyNames[i])) { texPropertyNames.Add(shaderTexPropertyNames[i]); } if (resultMaterial.GetTextureOffset(shaderTexPropertyNames[i].name) != new Vector2(0f, 0f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material has non-zero offset. This is may be incorrect."); } } if (resultMaterial.GetTextureScale(shaderTexPropertyNames[i].name) != new Vector2(1f, 1f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material should have tiling of 1,1"); } } } } for (int i = 0; i < _customShaderPropNames.Count; i++) { if (resultMaterial.HasProperty(_customShaderPropNames[i].name)) { shaderPropStr += ", " + _customShaderPropNames[i].name; texPropertyNames.Add(_customShaderPropNames[i]); if (resultMaterial.GetTextureOffset(_customShaderPropNames[i].name) != new Vector2(0f, 0f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material has non-zero offset. This is probably incorrect."); } } if (resultMaterial.GetTextureScale(_customShaderPropNames[i].name) != new Vector2(1f, 1f)) { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material should probably have tiling of 1,1."); } } } else { if (LOG_LEVEL >= MB2_LogLevel.warn) { Debug.LogWarning("Result material shader does not use property " + _customShaderPropNames[i].name + " in the list of custom shader property names"); } } } } return(true); #endif }