真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網站制作重慶分公司

Unity如何實現(xiàn)人物半透明處理

這篇文章給大家分享的是有關Unity如何實現(xiàn)人物半透明處理的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

為南海等地區(qū)用戶提供了全套網頁設計制作服務,及南海網站建設行業(yè)解決方案。主營業(yè)務為做網站、網站制作、南海網站設計,以傳統(tǒng)方式定制建設網站,并提供域名空間備案等一條龍服務,秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務。我們深信只要達到每一位用戶的要求,就會得到認可,從而選擇與我們長期合作。這樣,我們也可以走得更遠!

1 透明Shader的處理

需要同時處理圖片的透明和剔除,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
    }
}

最終效果,飄帶為半透明,裙邊為剔除效果

Unity如何實現(xiàn)人物半透明處理

模型有些糙,大家湊合看

2 模型多部件的網格合并

在一個3D游戲中,模型的換裝是很常見的功能,沒有換裝也會有簡單的武器,飾品類部件的綁定。這種情況下實現(xiàn)半透明隱身效果,就會出現(xiàn)模型間相互穿插的問題。

Unity如何實現(xiàn)人物半透明處理

模型中支持換發(fā)功能,身體和頭發(fā)屬于兩個部件,透明后相互穿插,效果十分不好


出現(xiàn)這種情況是因為兩個部件之間的半透明后,并不知道彼此的深度關系(半透明效果在關閉ZWrite模式下渲染),只有將其合并到同一個Mesh(網格)中才能實現(xiàn)比較完美的透明效果。

unity官方mesh合并文檔

當然只靠官方文檔并沒有什么卵用,unity官方文檔的一貫風格,你們懂得~~我們還是要自己寫代碼,或者也可以使用像Mesh Baker這樣的現(xiàn)成工具實現(xiàn),對于Mesh Baker的使用這里就不累述了,有很詳細的文檔和例子。網格合并的同時還進行了材質合并,代碼在下一部分以前給出。

3 模型多材質合并

多個部件一般都是在不同的材質中,這樣在渲染一個3D模型的時候就需要同時處理多個材質球,打開Unity我們就會發(fā)現(xiàn)每使用一個材質球就會產生一個drawcall。合并多材質也是unity性能優(yōu)化的一種方式。

Unity如何實現(xiàn)人物半透明處理

未材質合并下的batches為4

Unity如何實現(xiàn)人物半透明處理

材質合并后的batches為2

在模型的最外層,我掛載了一個Model3D.cs的腳本,用于處理模型和材質的合并,材質合并還需要對UV處理,代碼中也已經包含。

void Combine()
    {
        List combineInstances = 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類型,這時候這段代碼就無法將該模型的網格進行合并。

Unity如何實現(xiàn)人物半透明處理

SkinnedMeshRenderer(帶動作包含骨骼信息)

Unity如何實現(xiàn)人物半透明處理

MeshRenderer(不帶動作不包含骨骼信息)

這種情況有兩種解決辦法:

1、浪費一根骨骼的資源,在所有不含動作的部件中加入一根骨骼,這樣導入到unity中,就會默認統(tǒng)一導入為SkinnedMeshRenderer類型,也就不存在不同類型網格合并問題。
2、實際上SkinnedMeshRenderer和Mesh類型是可以進行合并的,如Mesh Baker中就可以實現(xiàn),具體的方法我沒有具體研究,有興趣的朋友可以自己看看。

Unity如何實現(xiàn)人物半透明處理

合并后的運行效果,沒有穿幫現(xiàn)象

注意

1、使用該shader渲染的時候,如果是非透明情況,需要將_cutoff的數值調整為接近1,且小于1的數值,如0.95,這樣的顯示效果才正確。
2、修改透明度調低顏色的Alpha值時需要同步調低_cutoff,Alpha值略大于_cutoff值即可,否則會出現(xiàn)模型層級不對問題(渲染先后順序)。

感謝各位的閱讀!關于“Unity如何實現(xiàn)人物半透明處理”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!


新聞名稱:Unity如何實現(xiàn)人物半透明處理
文章地址:http://weahome.cn/article/psphgg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部