Unity实现玉石效果学习笔记

效果展示

最终效果

学习文章地址:http://walkingfat.com/simple-subsurface-scatterting-for-mobile-%ef%bc%88%e4%b8%80%ef%bc%89%e9%80%9a%e9%80%8f%e6%9d%90%e8%b4%a8%e7%9a%84%e6%ac%a1%e8%a1%a8%e9%9d%a2%e6%95%a3%e5%b0%84/

这个博主真的太强了!!!就是存在的问题是你的调参能力要非常强,不然就算代码完全一摸一样可能都达不到博主的效果…..

制作思路

将平行光源的方向反转,相当于背对光源的那一面的光照由反转的虚拟光源提供,达到了一种次表面散射的效果。同时利用表面法线对反向光源进行一定偏移代表不同散射强度。

img

然后添加漫反射,高光,边缘光,调成参数达到一个比较好的效果。

image-20201217211954161

因为模型不同的厚薄程度会影响次表面散射的效果,所以我把模型导入substancePainter中烘焙出thickess贴图来代表模型的厚度。左边为没有厚度图效果,右边厚度图效果。

image-20201217211721182image-20201217211818301

最后,我添加了Bloom和AO的后处理效果。

image-20201217211752569

完整代码

Shader "Unlit/SSS_Shader"
{
    Properties
    {
        _AOTex("AO贴图",2D) = "white" {}
        _subsurfaceParam("散射偏移",float) = 1
        [HDR]_scatteringColor("散射颜色",Color) = (1,1,1,1)
        _diffuse("漫反射颜色",color) = (1,1,1,1)
        _specular("高光颜色",color) = (1,1,1,1)
        _specularPower("高光区域范围",float) = 1
        _rimPower("边缘光区域范围",float) = 1
        _rimIntensity("边缘光强度",float) = 1
        _thickness("厚度修改值",float) = 0.2
        _power("power",float) = 1
        _scale("scale",float) = 1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            Tags{"LightMode" = "ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityLightingCommon.cginc"
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normalDir : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float3 worldNormalDir : TEXCOORD1;
                float3 worldViewDir : TEXCOORD2;
                float3 worldLightDir : TEXCOORD3;
                float4 worldPos : TEXCOORD4;
                UNITY_FOG_COORDS(5)
                float4 vertex : SV_POSITION;
            };

            sampler2D _AOTex;
            float _subsurfaceParam;
            float4 _scatteringColor;
            float4 _diffuse;
            float4 _specular;
            float _thickness;
            float _specularPower;
            float _rimPower;
            float _rimIntensity;
            float _power;
            float _scale;


            //次表面散射计算函数
            float SubsurfaceScattering(float3 viewDir,float3 lightDir, float3 normalDir,float subsurfaceParam)
            {
                //背面次表面反射
                float3 backLightDir = normalDir * subsurfaceParam + lightDir;
                //正面次表面反射
                float3 frontLightDir = normalDir * subsurfaceParam - lightDir;
                float result = pow(saturate(dot(viewDir,-backLightDir))+saturate(dot(viewDir,-frontLightDir))*0.5,_power)*_scale;
                return result;
            }

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                //计算worldPos
                o.worldPos = mul(unity_ObjectToWorld,v.vertex);
                //计算normal,view,light等方向
                o.worldNormalDir = UnityObjectToWorldNormal(v.normalDir);
                o.worldViewDir = normalize(UnityWorldSpaceViewDir(o.worldPos));
                o.worldLightDir = normalize(UnityWorldSpaceLightDir(o.worldPos));
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_AOTex, i.uv);

                float sssValue = SubsurfaceScattering(i.worldViewDir,i.worldLightDir,i.worldNormalDir,_subsurfaceParam);
                //获得次表面散射颜色
                fixed3 sssColor = lerp(_scatteringColor,_LightColor0,sssValue)*sssValue;

                //计算diffuse颜色
                float diff = max(0,dot(i.worldNormalDir,i.worldLightDir));
                float3 unlitCol = _diffuse * _scatteringColor * 0.5;//暗部颜色
                float3 diffuse_color = lerp(unlitCol,_diffuse,diff);

                //计算高光
                float3 H = normalize(i.worldLightDir+i.worldViewDir);
                float3 specular_color = _LightColor0*_specular*pow(max(0,dot(normalize(i.worldNormalDir),H)),_specularPower);

                //计算边缘光
                float rim = 1.0 - max(0,dot(i.worldNormalDir,i.worldViewDir));
                float rimValue = lerp(rim,0,sssValue);
                float3 rimColor =max(0, lerp(_scatteringColor,_LightColor0,rimValue)*pow(rimValue,_rimPower)*_rimIntensity);
                //将sssColor和diffuse_color相加
                float3 finalColor = sssColor*(saturate((1-col.r)+_thickness))+diffuse_color+specular_color+rimColor;
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return fixed4(finalColor,1);
            }
            ENDCG
        }
    }
    Fallback "Specular"
}
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2015-2021 Opda
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信