您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關Unity如何實現人物半透明處理的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
需要同時處理圖片的透明和剔除,shader中一個pass是處理不了的。常規做法是進行兩次渲染,一次渲染半透明效果,一次進行透明剔除。
首先,利用AlphaTest進行剔除處理,需要開啟ZWrite選項,渲染一遍。
Pass { AlphaTest Greater [_CutOff] ZWrite On ColorMask 0 SetTexture [_MainTex] { ConstantColor [_Color] Combine Texture * constant } }
其次,半透明渲染的時候需要關閉ZWrite選項
Pass { ZWrite Off Blend SrcAlpha OneMinusSrcAlpha ZTest LEqual SetTexture[_MainTex] { ConstantColor[_Color] Combine Texture * constant } }
最終效果,飄帶為半透明,裙邊為剔除效果
模型有些糙,大家湊合看
在一個3D游戲中,模型的換裝是很常見的功能,沒有換裝也會有簡單的武器,飾品類部件的綁定。這種情況下實現半透明隱身效果,就會出現模型間相互穿插的問題。
模型中支持換發功能,身體和頭發屬于兩個部件,透明后相互穿插,效果十分不好
出現這種情況是因為兩個部件之間的半透明后,并不知道彼此的深度關系(半透明效果在關閉ZWrite模式下渲染),只有將其合并到同一個Mesh(網格)中才能實現比較完美的透明效果。
unity官方mesh合并文檔
當然只靠官方文檔并沒有什么卵用,unity官方文檔的一貫風格,你們懂得~~我們還是要自己寫代碼,或者也可以使用像Mesh Baker這樣的現成工具實現,對于Mesh Baker的使用這里就不累述了,有很詳細的文檔和例子。網格合并的同時還進行了材質合并,代碼在下一部分以前給出。
多個部件一般都是在不同的材質中,這樣在渲染一個3D模型的時候就需要同時處理多個材質球,打開Unity我們就會發現每使用一個材質球就會產生一個drawcall。合并多材質也是unity性能優化的一種方式。
未材質合并下的batches為4
材質合并后的batches為2
在模型的最外層,我掛載了一個Model3D.cs的腳本,用于處理模型和材質的合并,材質合并還需要對UV處理,代碼中也已經包含。
void Combine() { List<CombineInstance> combineInstances = new List<CombineInstance>(); List<Material> materials = new List<Material>(); List<Transform> bones = new List<Transform>(); Transform[] transforms = GetComponentsInChildren<Transform>(); List<Texture2D> textures = new List<Texture2D>(); int width = 0; int height = 0; int uvCount = 0; List<Vector2[]> uvList = new List<Vector2[]>(); //蒙皮模型 foreach (SkinnedMeshRenderer smr in GetComponentsInChildren<SkinnedMeshRenderer>()) { if (_material == null) _material = Instantiate(smr.sharedMaterial) as Material; for (int sub = 0; sub < smr.sharedMesh.subMeshCount; sub++) { CombineInstance ci = new CombineInstance(); ci.mesh = smr.sharedMesh; ci.subMeshIndex = sub; ci.transform = smr.transform.localToWorldMatrix; combineInstances.Add(ci); } uvList.Add(smr.sharedMesh.uv); uvCount += smr.sharedMesh.uv.Length; if (smr.material.mainTexture != null) { //保存材質 materials.AddRange(smr.GetComponent<Renderer>().materials); //保存貼圖 foreach (var mat in materials) { textures.Add(mat.mainTexture as Texture2D); } } //保存骨骼信息 foreach (Transform bone in smr.bones) { bones.Add(bone); } Destroy(smr.gameObject); } SkinnedMeshRenderer r = GetComponent<SkinnedMeshRenderer>(); if (!r) r = gameObject.AddComponent<SkinnedMeshRenderer>(); r.sharedMesh = new Mesh(); //合并子網格 r.sharedMesh.CombineMeshes(combineInstances.ToArray(), true, false); r.bones = bones.ToArray(); r.material = _material; Texture2D skinnedMeshAtlas = new Texture2D(width, height); Rect[] packingResult = skinnedMeshAtlas.PackTextures(textures.ToArray(), 0); Vector2[] atlasUVs = new Vector2[uvCount]; //合并材質,處理uv int j = 0; for (int i = 0; i < uvList.Count; i++) { foreach (Vector2 uv in uvList[i]) { atlasUVs[j].x = Mathf.Lerp(packingResult[i].xMin, packingResult[i].xMax, uv.x); atlasUVs[j].y = Mathf.Lerp(packingResult[i].yMin, packingResult[i].yMax, uv.y); j++; } } r.material.mainTexture = skinnedMeshAtlas; r.sharedMesh.uv = atlasUVs; }
上述代碼中還存在一個問題,就是只合并了SkinnedMeshRenderer類型的網格,在unity中,帶動作的模型FBX檔案導入到項目中的時候,unity會默認導入為SkinnedMeshRenderer類型。但是如果當前的FBX不帶動作(很多的武器是不需要動作,直接依靠綁點動作的),unity會默認導入為MeshRenderer類型,這時候這段代碼就無法將該模型的網格進行合并。
SkinnedMeshRenderer(帶動作包含骨骼信息)
MeshRenderer(不帶動作不包含骨骼信息)
1、浪費一根骨骼的資源,在所有不含動作的部件中加入一根骨骼,這樣導入到unity中,就會默認統一導入為SkinnedMeshRenderer類型,也就不存在不同類型網格合并問題。
2、實際上SkinnedMeshRenderer和Mesh類型是可以進行合并的,如Mesh Baker中就可以實現,具體的方法我沒有具體研究,有興趣的朋友可以自己看看。
合并后的運行效果,沒有穿幫現象
1、使用該shader渲染的時候,如果是非透明情況,需要將_cutoff的數值調整為接近1,且小于1的數值,如0.95,這樣的顯示效果才正確。
2、修改透明度調低顏色的Alpha值時需要同步調低_cutoff,Alpha值略大于_cutoff值即可,否則會出現模型層級不對問題(渲染先后順序)。
感謝各位的閱讀!關于“Unity如何實現人物半透明處理”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。