模型烘焙後保存mesh數據生成新的預製體

模型烘焙後保存mesh數據生成新的預製體

 

unity版本5.4.1

1、C#代碼控制模型烘焙後生成新的材質球保存mesh數據,並關聯到新生成的預製體。

SetUVData.cs用於掛在遊戲物體上,設置你要賦值的數據,代碼如下:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

[ExecuteInEditMode]
public class SetUVData : MonoBehaviour {
    
    public bool preservePrefab = false;

    //下面的是另一種加載預製體的方法-----------------------------------------------
    //    MeshRenderer[] renderers ;
//    Transform[] renderers ;

//    public List <RendererInfo>  m_RendererInfo;
//    [System.Serializable]
//    public struct RendererInfo
//    {
//        public Renderer renderer;
//        public int  lightmapIndex;
//        public Vector4 lightmapOffsetScale;
//    }



//    void Awake()
//    {
//        Debug.Log ("--------Awake----------");
////        LoadLightmap ();
//        renderers = GetComponentsInChildren<Transform> ();
//
//        for (int i = 0; i < renderers.Length; i++) 
//        {
//            Debug.Log ("renders [i].lightmapIndex  "+i);
////            Debug.Log ("renders [i].lightmapIndex  "+i+"   " + renderers [i].lightmapIndex);
//        }
//    }

//    void Start()
//    {
//        RaycastHit hit;
//        Vector3 pos = transform.position + new Vector3 (0, 0.1f,0);
//        Debug.Log ("pos " + pos);
//
//        if (Physics.Raycast (pos, -Vector3.up, out hit, 100f,LayerMask.GetMask ("Lighting"))) {   //LayerMask..GetMask ("Lighting") 
//            Debug.DrawLine (transform.position, hit.point, Color.red);
//            Debug.Log ("???????????"+ hit.collider.gameObject);
//        }
//    }


    /// <summary>
    /// Saves the lightmap.保存光照貼圖信息到預製體
    /// </summary>
//    public void SaveLightmap() {
//        Debug.Log ("----------SaveLightmap-----------");
//        m_RendererInfo.Clear ();
//
//        for (int i = 0; i < renderers.Length; i++) 
//        {
//            if(renderers[i].lightmapIndex != -1)
//            {
//                RendererInfo info = new RendererInfo ();
//                info.renderer = renderers[i];
//                info.lightmapOffsetScale = renderers [i].lightmapScaleOffset;
//                info.lightmapIndex  = renderers [i].lightmapIndex;
//
//                m_RendererInfo.Add (info);
//            }
//        }

//    }

    /// <summary>
    /// Loads the lightmap.加載光照貼圖信息到預製體
    /// </summary>
//    public void LoadLightmap() {
//        Debug.Log ("----------LoadLightmap-----------");
//        if (m_RendererInfo.Count <= 0)
//            return;
//        
//        for (int i = 0; i < m_RendererInfo.Count; i++) 
//        {
//            m_RendererInfo [i].renderer.lightmapIndex = m_RendererInfo [i].lightmapIndex;                //將結構體中第二三的參數設置到1中
//            m_RendererInfo [i].renderer.lightmapScaleOffset = m_RendererInfo [i].lightmapOffsetScale;
//        }
//    }
//
}

 

 

CreatUV3.cs用於自定義inspector界面及將型烘焙後生成新的材質球保存mesh數據,生成新的預製體。將這個文件放Editor文件夾下,代碼如下:

using UnityEngine;
using System.Collections;
using UnityEditor;

[CustomEditor(typeof(SetUVData))]
public class CreatUV3 : Editor {
    SetUVData originalObj;
    Mesh mesh;
    MeshFilter [] meshFilters;

    LightmapData lightmapData;
    Texture2D lightmapTex2d;
    Vector2 texSize;
    Renderer renderer;

    //inspector自定義界面編輯, custom inspector
    public override void OnInspectorGUI()            
    {
        DrawDefaultInspector();
        originalObj = (SetUVData)target;

        if (GUILayout.Button ("Write UV Data", GUILayout.Height (20))) {

            GameObject prefab = originalObj.gameObject;

            WriteDataAll (originalObj.gameObject);
            if(originalObj.preservePrefab)
            {
                prefab = BuildPrefab () as GameObject;
                EditorUtility.SetDirty (prefab);            
            }
        }
    }


    /// <summary>
    /// Getoriginals the name of the object.獲取當前物體的名字
    /// </summary>
    /// <returns>The object name.</returns>
    string GetoriginalObjName()
    {
        string originalObjName = originalObj.gameObject.name;
        return originalObjName;
    }

    //創建預製體
    public  object BuildPrefab()
    {
        Debug.Log ("==========BuildPrefab  =============");
        object    temPrefab = PrefabUtility.CreateEmptyPrefab ("Assets/"+"newPfb/"+GetoriginalObjName() + ".prefab");  

        temPrefab = PrefabUtility.ReplacePrefab (originalObj.gameObject, temPrefab as UnityEngine.Object);
        return temPrefab;
    }

    /// <summary>
    /// Writes the data all.寫入所有的子對象中
    /// </summary>
    /// <param name="obj">Object.</param>
    void WriteDataAll(GameObject obj)
    {
        Debug.Log ("originalObj.transform.childCount  "+obj.transform.childCount);


        meshFilters = obj.GetComponentsInChildren<MeshFilter> ();
        for(int i = 0;i<meshFilters.Length;i++)
        {
            Debug.Log (string.Format("i{0},  meshFilters [i]: {1}  ",i,meshFilters [i]) );
            //            GameObject target = meshFilters [i].gameObject; 
            if(meshFilters[i].sharedMesh == null)
            {
                Debug.Log (obj.name+"???meshFilters lost");
            }
            WriteData (meshFilters [i]);
        }

    } 

    /// <summary>
    /// Writes the data.將originalObj數據寫入到mesh中,WriteData in mesh
    /// </summary>
    /// <param name="originalObjChuild">Original object chuild.</param>
    public void WriteData (MeshFilter mf) {
        mesh = GameObject.Instantiate (mf.sharedMesh) as Mesh;
        //        renderer = originalObjChuild.GetComponent<Renderer> ();
        if (!mf.transform.GetComponent<Renderer>()) {
            Debug.Log("???? no render ???");
            return;
        }

        renderer = mf.transform.GetComponent<Renderer> ();

        Vector3[] vertices = mesh.vertices;
        Vector2[] newUV = new Vector2[vertices.Length];

        lightmapData = LightmapSettings.lightmaps [0];      //獲取當前的光照貼圖序號.烘焙一張光照貼圖
        lightmapTex2d = lightmapData.lightmapFar;            //光照圖儲存所有入射光線。 


        string texPath = AssetDatabase.GetAssetPath (lightmapTex2d);            
        TextureImporter importer = TextureImporter.GetAtPath (texPath) as TextureImporter;
        if (!importer.isReadable) {
            importer.isReadable = true;
            AssetDatabase.ImportAsset (texPath, ImportAssetOptions.ForceUpdate);  //用戶啓動資源導入ImportAssetOptions.ForceUpdate
        }


        //UV賦值
        for (int i = 0; i < vertices.Length; i++) {
            //            pos = originalObjChuild.TransformPoint (vertices[i]);
            newUV [i] = new Vector2 (mesh.uv2 [i].x * renderer.lightmapScaleOffset.x + renderer.lightmapScaleOffset.z,  
                mesh.uv2 [i].y * renderer.lightmapScaleOffset.y + renderer.lightmapScaleOffset.w);
        }
        mesh.uv3 = newUV;            //數組的形式賦值,一定要給UV3賦值這個
//        mesh.colors = newColors;            //數組的形式賦值
//        mf.sharedMesh = mesh;                //烘焙後mesh存儲了Lightmap的UV2偏移信息

        if (EditorUtility.IsPersistent (mf.sharedMesh)) {
            //            string vpDataPath = AssetDatabase.GetAssetPath (mf.sharedMesh);

            //            Debug.Log ("vpDataPath " + vpDataPath);
            //            vpDataPath = vpDataPath.Substring (0, vpDataPath.LastIndexOf ("."));
            //            vpDataPath += "1.asset";                                 //保存地址爲原地址的位置,名字+1
            AssetDatabase.CreateAsset (mesh, "Assets/" + "newMesh/" + mf.gameObject.name + ".asset");
            mf.sharedMesh = mesh;
        } else {
            //            string vpDataPath = EditorUtility.SaveFilePanelInProject ("save Mesh", "mesh", "asset", "Pick a location to save your mesh.");  //打開電腦的文件保存窗口
            AssetDatabase.CreateAsset (mesh, "Assets/" + "newMesh/" + mf.gameObject.name + ".asset"); //mf.sharedMesh會加上clone
            mf.sharedMesh = mesh;
        }
    }
}

 

 

 

2、shader讀取當前場景的烘焙貼圖,並解碼烘焙貼圖。

//unity版本5.4.1,其他unity版本可能寫法什麼的不一樣一些。

Shader "LT/LightmapTest"
{
    Properties
    {
        _MainTex ("Texture"2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON  

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float2 uv2 : TEXCOORD2;
//                float2 uv3 : TEXCOORD3;
                float4 color:COLOR;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float4 col : TEXCOORD1;
                float2 uv2 : TEXCOORD2;
//                float2 uv3 : TEXCOORD3;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
    half4 unity_LightmapST;
    sampler2D unity_Lightmap;


            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.col = v.color;
//                o.uv3 = v.uv3;

                #ifndef LIGHTMAP_OFF
                o.uv2 = v.uv2.xy * unity_LightmapST.xy + unity_LightmapST.zw;  //模型自帶的UV2,烘焙後unity會根據模型的UV2來排列光照貼圖,據說。。。
                #endif

                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);

                #ifndef LIGHTMAP_OFF
                fixed3 lm = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap,i.uv2));    //解碼光照貼圖
                #endif
                
                col.rgb *= lm;
                return col;
//                return fixed4(i.uv2,0,1);    //發現UV2烘焙前後不一樣了,是因爲網格合併了嗎
            }
            ENDCG
        }
    }
    fallback "Diffuse"
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章