zoukankan      html  css  js  c++  java
  • 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对最后的向量进行归一化,这样可以避免法线贴图看起来杂乱。

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

  • 相关阅读:
    更好的抽屉效果(ios)
    系统拍照动画
    UITabBarController详解
    touch事件分发
    iOS UWebView详解
    iOS 监听声音按键
    webservice偶尔报黄页,解决方案
    FastReport脚本把数据绑定到文本控件上
    [转]js版的md5()
    JQuery中$.ajax()方法参数详解
  • 原文地址:https://www.cnblogs.com/2Yous/p/4254672.html
Copyright © 2011-2022 走看看