Unity如何实现人物半透明处理
Unity如何实现人物半透明处理
这篇文章给大家分享的是有关Unity如何实现人物半透明处理的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
1 透明Shader的处理
需要同时处理图片的透明和剔除,shader中一个pass是处理不了的。常规做法是进行两次渲染,一次渲染半透明效果,一次进行透明剔除。
首先,利用AlphaTest进行剔除处理,需要开启ZWrite选项,渲染一遍。
Pass{AlphaTestGreater[_CutOff]ZWriteOnColorMask0SetTexture[_MainTex]{ConstantColor[_Color]CombineTexture*constant}}
其次,半透明渲染的时候需要关闭ZWrite选项
Pass{ZWriteOffBlendSrcAlphaOneMinusSrcAlphaZTestLEqualSetTexture[_MainTex]{ConstantColor[_Color]CombineTexture*constant}}
最终效果,飘带为半透明,裙边为剔除效果
模型有些糙,大家凑合看
2 模型多部件的网格合并
在一个3D游戏中,模型的换装是很常见的功能,没有换装也会有简单的武器,饰品类部件的绑定。这种情况下实现半透明隐身效果,就会出现模型间相互穿插的问题。
模型中支持换发功能,身体和头发属于两个部件,透明后相互穿插,效果十分不好
出现这种情况是因为两个部件之间的半透明后,并不知道彼此的深度关系(半透明效果在关闭ZWrite模式下渲染),只有将其合并到同一个Mesh(网格)中才能实现比较完美的透明效果。
unity官方mesh合并文档
当然只靠官方文档并没有什么卵用,unity官方文档的一贯风格,你们懂得~~我们还是要自己写代码,或者也可以使用像Mesh Baker这样的现成工具实现,对于Mesh Baker的使用这里就不累述了,有很详细的文档和例子。网格合并的同时还进行了材质合并,代码在下一部分以前给出。
3 模型多材质合并
多个部件一般都是在不同的材质中,这样在渲染一个3D模型的时候就需要同时处理多个材质球,打开Unity我们就会发现每使用一个材质球就会产生一个drawcall。合并多材质也是unity性能优化的一种方式。
未材质合并下的batches为4
材质合并后的batches为2
在模型的最外层,我挂载了一个Model3D.cs的脚本,用于处理模型和材质的合并,材质合并还需要对UV处理,代码中也已经包含。
voidCombine(){List<CombineInstance>combineInstances=newList<CombineInstance>();List<Material>materials=newList<Material>();List<Transform>bones=newList<Transform>();Transform[]transforms=GetComponentsInChildren<Transform>();List<Texture2D>textures=newList<Texture2D>();intwidth=0;intheight=0;intuvCount=0;List<Vector2[]>uvList=newList<Vector2[]>();//蒙皮模型foreach(SkinnedMeshRenderersmrinGetComponentsInChildren<SkinnedMeshRenderer>()){if(_material==null)_material=Instantiate(smr.sharedMaterial)asMaterial;for(intsub=0;sub<smr.sharedMesh.subMeshCount;sub++){CombineInstanceci=newCombineInstance();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(varmatinmaterials){textures.Add(mat.mainTextureasTexture2D);}}//保存骨骼信息foreach(Transformboneinsmr.bones){bones.Add(bone);}Destroy(smr.gameObject);}SkinnedMeshRendererr=GetComponent<SkinnedMeshRenderer>();if(!r)r=gameObject.AddComponent<SkinnedMeshRenderer>();r.sharedMesh=newMesh();//合并子网格r.sharedMesh.CombineMeshes(combineInstances.ToArray(),true,false);r.bones=bones.ToArray();r.material=_material;Texture2DskinnedMeshAtlas=newTexture2D(width,height);Rect[]packingResult=skinnedMeshAtlas.PackTextures(textures.ToArray(),0);Vector2[]atlasUVs=newVector2[uvCount];//合并材质,处理uvintj=0;for(inti=0;i<uvList.Count;i++){foreach(Vector2uvinuvList[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如何实现人物半透明处理”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
推荐阅读
-
如何将三个变量放在一个表格中(unity pro xl 如何在硬件中添加变量标签)
unityproxl如何在硬件中添加变量标签?不知道你的变量标签是咋系统设置的,我这边打印出来可变数据标签的话,是会先将标签内...
-
VS Code里如何使用Debugger for Unity插件调试
-
Unity如何实现射击小游戏
-
Unity如何实现炸弹人游戏
-
Unity中怎么通过LitJson对JSON数据创建与使用
Unity中怎么通过LitJson对JSON数据创建与使用这篇文章...
-
Unity实现动物识别的代码怎么写
-
怎么用Unity命令行打包WebGL
怎么用Unity命令行打包WebGL本文小编为大家详细介绍“怎么用...
-
如何教训unity与3dmax美工部分的总结
如何教训unity与3dmax美工部分的总结今天给大家介绍一下如何...
-
Unity图形学中的ShaderLab怎么入门
-
Unity怎么实现植物识别