首页 > 代码库 > Unity3D ShaderLab 布料着色器

Unity3D ShaderLab 布料着色器

Unity3D ShaderLab布料着色器

布料着色器是我们在虚拟现实中经常使用的着色器。本篇就来完成一个较为简单的布料着色器。

新建Shader,Material,InteractiveCloth【布料】。完成的代码如下

 

Shader "91YGame/ClothShader" {    Properties {        //参数;        _MainTint("Base Color",Color)=(1,1,1,1)        _BumpMap ("Normal Map", 2D) = "bump" {}        _DetailBump("Detail Normal",2D)=""{}        _DetailTex("Fabric Weave",2D)=""{}        _FresnelColor("Fresnel Color",Color)=(1,1,1,1)        _FresnelPower("Fresnel Power",Range(0.01,10))=3        _RimPower("Rim Falloff",Range(0.01,10))=3        _SpecIntesity("Specular Intensity",Range(0.01,1))=0.3        _SpecWidth("Specular Width",Range(0.01,1))=0.2    }    SubShader {        Tags { "RenderType"="Opaque" }        LOD 200                CGPROGRAM        #pragma surface surf VelvetCloth        #pragma target 3.0        //变量;        sampler2D _BumpMap;        sampler2D _DetailBump;        sampler2D _DetailTex;        float4 _MainTint;        float4 _FresnelColor;        float _FresnelPower;        float _RimPower;        float _SpecIntesity;        float _SpecWidth;        //输入结构体;        struct Input {            float2 uv_BumpMap;            float2 uv_DetailBump;            float2 uv_DetailTex;        };        inline fixed4 LightingVelvetCloth(SurfaceOutput s,fixed3 lightDir, fixed3 viewDir, fixed atten){            //光照向量;            viewDir =normalize(viewDir);            lightDir = normalize(lightDir);            half3 halfVec = normalize(lightDir+viewDir);            fixed NdotL = max(0.01,dot(s.Normal,lightDir));            //计算高光;            float NdotH = max(0.01,dot(s.Normal,halfVec));            float spec = pow(NdotH,s.Specular*128)*s.Gloss;            //视线越贴近布料表面,纤维吸收的背面光就越多,高光也就越强;            float HdotV = pow(1-max(0,dot(halfVec,viewDir)),_FresnelPower);            float NdotE = pow(1-max(0,dot(s.Normal,viewDir)),_RimPower);            float finalSpecMask = NdotE*HdotV;            //最终颜色;            fixed4 c;            c.rgb = (s.Albedo*NdotL*_LightColor0.rgb)+(spec*(finalSpecMask*_FresnelColor))*(atten*2);            c.a =1;            return c;        }        void surf (Input IN, inout SurfaceOutput o) {            half4 c = tex2D (_DetailTex, IN.uv_DetailTex);            //提取法线;            fixed3 normals = UnpackNormal(tex2D(_BumpMap,IN.uv_BumpMap)).rgb;            fixed3 detailNormals = UnpackNormal(tex2D(_DetailBump,IN.uv_DetailBump)).rgb;            fixed3 finalNormals = float3(normals.x+detailNormals.x,normals.y+detailNormals.y,normals.z+detailNormals.z);            o.Normal = normalize(finalNormals);            o.Specular = _SpecWidth;            o.Gloss = _SpecIntesity;            o.Albedo = c.rgb*_MainTint;            o.Alpha = c.a;        }        ENDCG    }     FallBack "Diffuse"}

 

 

返回Unity,设置变量。最终效果如下:

技术分享

技术分享

在上面的实现过程中,我们将两张不同平铺率的法线贴图结合到一起。计算出新的法线向量。

所以使用UnpackNormal从变化法线贴图中提取出法线向量在产生新的法线贴图。然后使用normalize对最后的向量进行归一化,这样可以避免法线贴图看起来杂乱。

最后 将菲涅尔计算和高光计算的结果进行合并,创建出布料的纤维效果。

Unity3D ShaderLab 布料着色器