中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Unity如何實現人物半透明處理

發布時間:2022-01-05 14:41:30 來源:億速云 閱讀:329 作者:小新 欄目:大數據

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

1 透明Shader的處理

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

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

Unity如何實現人物半透明處理

模型有些糙,大家湊合看

2 模型多部件的網格合并

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

Unity如何實現人物半透明處理

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


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

unity官方mesh合并文檔

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

3 模型多材質合并

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

Unity如何實現人物半透明處理

未材質合并下的batches為4

Unity如何實現人物半透明處理

材質合并后的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類型,這時候這段代碼就無法將該模型的網格進行合并。

Unity如何實現人物半透明處理

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

Unity如何實現人物半透明處理

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

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

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

Unity如何實現人物半透明處理

合并后的運行效果,沒有穿幫現象

注意

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

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

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

鹤壁市| 红河县| 丰都县| 都安| 杂多县| 雷山县| 安远县| 静安区| 罗源县| 黔东| 龙南县| 江北区| 宁化县| 北川| 怀来县| 扶风县| 嫩江县| 离岛区| 宜章县| 嘉义县| 育儿| 大兴区| 东丽区| 康保县| 巴马| 吴忠市| 合川市| 海宁市| 潞城市| 富平县| 大邑县| 二连浩特市| 汤阴县| 中江县| 铁岭市| 呼伦贝尔市| 老河口市| 黑山县| 三穗县| 涞水县| 长治县|