這篇文章給大家分享的是有關Unity如何實現(xiàn)人物半透明處理的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
為南海等地區(qū)用戶提供了全套網頁設計制作服務,及南海網站建設行業(yè)解決方案。主營業(yè)務為做網站、網站制作、南海網站設計,以傳統(tǒng)方式定制建設網站,并提供域名空間備案等一條龍服務,秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務。我們深信只要達到每一位用戶的要求,就會得到認可,從而選擇與我們長期合作。這樣,我們也可以走得更遠!
需要同時處理圖片的透明和剔除,shader中一個pass是處理不了的。常規(guī)做法是進行兩次渲染,一次渲染半透明效果,一次進行透明剔除。
首先,利用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游戲中,模型的換裝是很常見的功能,沒有換裝也會有簡單的武器,飾品類部件的綁定。這種情況下實現(xiàn)半透明隱身效果,就會出現(xiàn)模型間相互穿插的問題。
模型中支持換發(fā)功能,身體和頭發(fā)屬于兩個部件,透明后相互穿插,效果十分不好
出現(xiàn)這種情況是因為兩個部件之間的半透明后,并不知道彼此的深度關系(半透明效果在關閉ZWrite模式下渲染),只有將其合并到同一個Mesh(網格)中才能實現(xiàn)比較完美的透明效果。
unity官方mesh合并文檔
當然只靠官方文檔并沒有什么卵用,unity官方文檔的一貫風格,你們懂得~~我們還是要自己寫代碼,或者也可以使用像Mesh Baker這樣的現(xiàn)成工具實現(xiàn),對于Mesh Baker的使用這里就不累述了,有很詳細的文檔和例子。網格合并的同時還進行了材質合并,代碼在下一部分以前給出。
多個部件一般都是在不同的材質中,這樣在渲染一個3D模型的時候就需要同時處理多個材質球,打開Unity我們就會發(fā)現(xiàn)每使用一個材質球就會產生一個drawcall。合并多材質也是unity性能優(yōu)化的一種方式。
未材質合并下的batches為4
材質合并后的batches為2
在模型的最外層,我掛載了一個Model3D.cs的腳本,用于處理模型和材質的合并,材質合并還需要對UV處理,代碼中也已經包含。
void Combine() { ListcombineInstances = new List (); List materials = new List (); List bones = new List (); Transform[] transforms = GetComponentsInChildren (); List textures = new List (); int width = 0; int height = 0; int uvCount = 0; List uvList = new List (); //蒙皮模型 foreach (SkinnedMeshRenderer smr in GetComponentsInChildren ()) { 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 ().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 (); if (!r) r = gameObject.AddComponent (); 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中,就會默認統(tǒng)一導入為SkinnedMeshRenderer類型,也就不存在不同類型網格合并問題。
2、實際上SkinnedMeshRenderer和Mesh類型是可以進行合并的,如Mesh Baker中就可以實現(xiàn),具體的方法我沒有具體研究,有興趣的朋友可以自己看看。
合并后的運行效果,沒有穿幫現(xiàn)象
1、使用該shader渲染的時候,如果是非透明情況,需要將_cutoff的數值調整為接近1,且小于1的數值,如0.95,這樣的顯示效果才正確。
2、修改透明度調低顏色的Alpha值時需要同步調低_cutoff,Alpha值略大于_cutoff值即可,否則會出現(xiàn)模型層級不對問題(渲染先后順序)。
感謝各位的閱讀!關于“Unity如何實現(xiàn)人物半透明處理”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!