Unity3D 双面渲染Shader实现 |
您所在的位置:网站首页 › 决战羽毛球游戏技巧教学 › Unity3D 双面渲染Shader实现 |
概述
在建模软件中可以为每个顶点设置法线,三个顶点可以组成一个三角面,三角面的法线是根据其顶点的法线插值而来,这个法线朝向就代表了这个平面的正面。 而在现代大部分引擎和游戏中,会默认只显示平面的正面,即对每个三角面进行一次面法线和摄像机出射向量的点积,判断正负,如果当前平面是背面朝向摄像机,则不渲染该面片。 Unity 的standard shader就是这样,我们只要创建一个平面就能看出这种效果。 创建一个平面,默认此平面正面朝上。 这种作法主要是为了提高性能,因为除了极个别图形例如上面的单纯平面之外,很多模型的面片背面是完全看不见的。 想象一下正方形就可以得知,正方形六个面每个的背面,都完全被包裹起来隐藏在正方形内部,正常情况是完全看不见的,那么此时直接不渲染背面也完全没有影响,还能足足减少一半需要渲染的面片。 但是总有时候是会需要渲染背面面片的,常见情况有渲染一些破损的模型,可以从模型外部看到内部,或者是半透明的效果,也需要能看到一个模型的内部。 这种效果俗称为双面渲染,意思就是同时渲染模型正面和背面,在unity3d里实现双面渲染相当简单,第一种做法是用两个pass,第一个渲染正面第二个渲染背面。 第一个pass如下,因为破损的模型不太好找,我们直接用一张贴图加上clip函数来实现可以看到一个模型内部的效果。 首先开启 Cull Back来只渲染正面 Cull Back void surf(Input IN, inout SurfaceOutputStandard o) { clip(tex2D(_Mask, IN.uv_Mask).a - _MaskClipValue); fixed4 c = tex2D(_BackTex, IN.uv_BackTex) * _Color; o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; }此时的效果很怪,因为只渲染了正面,但是此时是可以看到背面的。 除了直接渲染两个pass之外,还可以使用VFACE这个语义来直接获取顶点朝向,大于0则为朝向摄像机,小于0为背向摄像机。但是该语义需要支持shader model 3.0。 使用vface语义的话就不可避免的需要写if语句,虽然在shader里做if判断会影响性能 但是比跑两个pass还是要好,而且两个pass要跑两次clip 主要修改就是两个pass变成一个pass,还有要使用Cull Off关闭背面裁剪。 void surf(Input IN, inout SurfaceOutputStandard o) { clip(tex2D(_Mask, IN.uv_Mask).a - _MaskClipValue); fixed4 frontC = tex2D(_FrontTex, IN.uv_FrontTex) * _Color; fixed4 backC = tex2D(_BackTex, IN.uv_FrontTex) * _Color; //虽然要做if判断会影响性能 但是比跑两个pass还是要好,而且两个pass如果里面有clip操作的话要跑两次clip if (IN.face > 0) { o.Albedo = frontC.rgb; o.Alpha = frontC.a; } else { o.Albedo = backC.rgb; o.Alpha = backC.a; } o.Metallic = _Metallic; o.Smoothness = _Glossiness; }参数面板 完整代码如下 两个pass的方法 Shader "Custom/twoSide2" { Properties { _Color ("Color", Color) = (1,1,1,1) _FrontTex ("FrontTex", 2D) = "white" {} _BackTex ("BackTex", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Mask ("Mask", 2D) = "white" {} _Metallic ("Metallic", Range(0,1)) = 0.0 _MaskClipValue ("MaskClipValue", range(0,1)) = 0 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 Cull Back CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 sampler2D _FrontTex; sampler2D _Mask; struct Input { float2 uv_FrontTex; float2 uv_Mask; }; half _Glossiness; half _Metallic; fixed4 _Color; float _MaskClipValue; void surf(Input IN, inout SurfaceOutputStandard o) { clip(tex2D(_Mask, IN.uv_Mask).a - _MaskClipValue); fixed4 c = tex2D(_FrontTex, IN.uv_FrontTex) * _Color; o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG Cull Front CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 sampler2D _BackTex; sampler2D _Mask; struct Input { float2 uv_BackTex; float2 uv_Mask; }; half _Glossiness; half _Metallic; fixed4 _Color; float _MaskClipValue; void surf(Input IN, inout SurfaceOutputStandard o) { clip(tex2D(_Mask, IN.uv_Mask).a - _MaskClipValue); fixed4 c = tex2D(_BackTex, IN.uv_BackTex) * _Color; o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }完整代码2 使用vface语义的代码 Shader "LX/twoSide1" { Properties { _Color ("Color", Color) = (1,1,1,1) _FrontTex ("FrontTex", 2D) = "white" {} _BackTex ("BackTex", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 _Mask ("Mask", 2D) = "white" {} _MaskClipValue ("MaskClipValue", range(0,1)) = 0 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 Cull Off CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 sampler2D _FrontTex; sampler2D _BackTex; sampler2D _Mask; struct Input { float2 uv_FrontTex; float2 uv_BackTex; float2 uv_Mask; fixed face : VFACE; }; half _Glossiness; half _Metallic; fixed4 _Color; float _MaskClipValue; void surf(Input IN, inout SurfaceOutputStandard o) { clip(tex2D(_Mask, IN.uv_Mask).a - _MaskClipValue); fixed4 frontC = tex2D(_FrontTex, IN.uv_FrontTex) * _Color; fixed4 backC = tex2D(_BackTex, IN.uv_FrontTex) * _Color; //虽然要做if判断会影响性能 但是比跑两个pass还是要好,而且两个pass如果里面有clip操作的话要跑两次clip if (IN.face > 0) { o.Albedo = frontC.rgb; o.Alpha = frontC.a; } else { o.Albedo = backC.rgb; o.Alpha = backC.a; } o.Metallic = _Metallic; o.Smoothness = _Glossiness; } ENDCG } FallBack "Diffuse" }另外代码也传到github仓库里了,大家也可以关注一下哦~ 我的github 注:此shader只是演示了如何实现一个最简单的双面渲染效果,实际项目中肯定是要对以前使用的shader进行改造使其支持双面渲染的,所以肯定还有其他地方要修改。 |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |