Chicken shader: code implementation of L7 character model material (Dota2 ogre)

This class feels that there are many details of the code. Some things still need to be combined with the intuitive experience of art to write code. I still have to sigh that it is really natural to transfer from art to technical art.

Let me briefly put my code below. I feel that there is nothing to say. Some important things are also commented in the code. The most important ones are the following pictures:

    1. texture composition
      insert image description here
      insert image description here
    1. PS treatment
      insert image description here
    • It should be noted that some pictures are crooked. For example, the four pictures of SpecularMask, RimMask, TintByBaseMask and SpecularExponent of weapons are all crooked. It needs to be flipped vertically in ps, and then synthesized into a picture.
    • The last three fresnel images are directly stretched into length and width images, because they only have different u coordinates and the v coordinates are the same. The original length and width should be like this:
      insert image description here
    1. Material shader implementation idea diagram
    • OldSchoolPro model. In order to prevent confusion with the previous class, let's put the previous shader idea diagram first. It's different from the previous ones. The previous shader divided the model into two main parts, direct lighting and ambient light, and subdivided it into diffuse reflection and specular reflection for rendering under lighting and ambient light.
      insert image description here
    • Dota2 model. In the Dota2 material, the model is divided into two main parts of diffuse reflection and specular reflection for rendering, and then under specular reflection and diffuse reflection, it is divided into direct lighting and ambient light for rendering, and then some other details are added, such as contour light self-illumination and so on.
      insert image description here

Put the code directly below:

Shader "shader forge/Dota_weapon"
{
    
    
    Properties
    {
    
    
        [Header(Texture)]   [Space]
        _MainTex ("RGB With A(A:Cutout)", 2D) = "white" {
    
    }
        _MaskTex("R:SpecInt G:RimInt B:TintMask A:SpecPow",2D) = "black"{
    
    }
        _NormTex("RGB:Normal",2D) = "bump"{
    
    }
        _MetalnessMask("Metalness Mask",2D) = "black"{
    
    }
        _EmissionMask("Emission Mask",2D) = "black"{
    
    }
        _DiffWrapTex("Diffuse Color Wrap Tex",2D) = "gray"{
    
    }
        _FresWrapTex("Fresnel Wrap Tex",2D) = "gray"{
    
    }
        _Cubemap("Cube Map",Cube) = "_Skybox"{
    
    }

        [Header(Diffuse_Dir)] [Space]
        _Light_Color("Light Color",Color) = (1.0,1.0,1.0,1.0)

        [Header(Diffuse_Env)] [Space]
        _EnvDiffCol ("Env Color",COLOR) = (1.0,1.0,1.0,1.0)
        _EnvDiffInt ("Env Color Intensity", Range(0.0,10.0)) = 1.0

        [Header(Specular_Dir)] [Space]
        _mySpecInt ("Specular Intensity", Range(0.0,10.0)) = 5
        _mySpecPow("Specular Power", Range(0.0,30.0)) = 5

        [Header(Specular_Env)] [Space]
        _EnvSpecInt ("Env Specular Intensity",Range(0.0,30.0)) = 1.0

        [Header(RimLight)] [Space]
        _RimCol ("Rim Color", Color) = (1.0,1.0,1.0,1.0)
        _RimInt ("Rim Intensity", Range(0.0,20.0)) = 1.0

        [Header(Emission)] [Space]
        _EmitInt ("Emission Intensity",Range(0.0,20.0)) = 1.0

        [HideInInspector]
        _Cutoff ("Cutoff", Range(0.0,1.0)) = 0.05
        [HideInInspector]
        _Color  ("Main Color",color)=(1,1,1,1)
    }
    SubShader
    {
    
    
        Tags {
    
     "RenderType"="Opaque" }       
        LOD 100

        Pass
        {
    
    
            Name "FORWARD"
            Tags{
    
    
                "RenderType" = "ForwardBase"
            }
            Cull Off

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #include "Lighting.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma target 3.0
            struct appdata
            {
    
    
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
                float4 tangent : TANGENT;
            };

            struct v2f
            {
    
    
                float2 uv : TEXCOORD0;
                float4 pos : SV_POSITION;
                float4 posWorld : TEXCOORD1;
                float3 nDirWS : TEXCOORD2;
                float3 tDirWS : TEXCOORD3;
                float3 bDirWS : TEXCOORD4;
                LIGHTING_COORDS(5,6)
            };

            //Texture
            uniform sampler2D _MainTex;
            uniform float4 _MainTex_ST;
            uniform sampler2D _MaskTex;
            uniform sampler2D _NormTex;
            uniform sampler2D _MetalnessMask;
            uniform sampler2D _EmissionMask;
            uniform sampler2D _DiffWrapTex;
            uniform sampler2D _FresWrapTex;
            uniform samplerCUBE _Cubemap;

            //Diffuse_Dir
            uniform float4 _Light_Color;

            //Diffuse_Env
            uniform float4 _EnvDiffCol;
            uniform float _EnvDiffInt;

            //Specular_Dir
            uniform half _mySpecInt;
            uniform half _mySpecPow;

            //Specular_Env
            uniform half _EnvSpecInt;

            //Rim 
            uniform half4 _RimCol;
            uniform half _RimInt;

            //Emission
            uniform half _EmitInt;

            //透切
            uniform half _Cutoff;

            v2f vert (appdata v)
            {
    
    
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.posWorld = mul(unity_ObjectToWorld, v.vertex);
                o.nDirWS = UnityObjectToWorldNormal(v.normal);
                o.tDirWS = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz,0.0)).xyz);
                o.bDirWS = normalize(cross(o.nDirWS,o.tDirWS) * v.tangent.w);
                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
    
                    
                float3 nDirTS = UnpackNormal(tex2D(_NormTex,i.uv)).rgb;

                //向量准备
                float3x3 TBN_Matrix = float3x3(i.tDirWS,i.bDirWS,i.nDirWS);
                //unity shader里的是列向量,列向量右乘矩阵时,结果是列向量
                //但是法线本身有特殊性,这里反过来乘是为了乘以矩阵的逆转置矩阵
                float3 nDirWS_FT = normalize(mul(nDirTS, TBN_Matrix));    
                float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
                float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
                float3 halfDir = normalize(lightDir + viewDir);
                float3 vrDirWS = normalize(reflect(-viewDir,nDirWS_FT));             

                //中间量准备
                half NoL = clamp(dot(nDirWS_FT,lightDir),0.0,1.0);
                half NoV = clamp(dot(nDirWS_FT,viewDir),0.0,1.0);                
                half NoH = clamp(dot(nDirWS_FT,halfDir),0.0,1.0);
                half VoR = clamp(dot(viewDir, vrDirWS),0.0,1.0);

                //贴图采样
                half4 var_MainTex = tex2D(_MainTex,i.uv);
                half4 var_MaskTex = tex2D(_MaskTex,i.uv);
                half var_Metalness = tex2D(_MetalnessMask,i.uv).r;
                half var_Emission = tex2D(_EmissionMask,i.uv).r;         
                half3 var_Fresnel = tex2D(_FresWrapTex,half2(NoV,0.3)).rgb;
                half3 var_Cubemap = texCUBElod(_Cubemap,float4(vrDirWS,lerp(8.0,0.0,var_MaskTex.a))).rgb;

                //提取信息
                half3 baseCol = var_MainTex.rgb;
                half opacity = var_MainTex.a;   //不透明度
                half specInt = var_MaskTex.r;
                half rimInt = var_MaskTex.g;
                half specTint = var_MaskTex.b;
                half specPow = var_MaskTex.a;
                half metalness = var_Metalness;
                half emitInt = var_Emission;
                half3 envCube = var_Cubemap;
                half3 shadow = LIGHT_ATTENUATION(i);                

                //光照模型
                    //漫反射和镜面反射,两个被不同的变量控制染色程度
                    half3 diff_col = lerp(baseCol,float3(0.0,0.0,0.0),metalness);
                    half3 spec_col = lerp(baseCol,float3(0.3,0.3,0.3),specTint);    //0.3是经验值
                    //Fresnel
                    half3 fresnel = lerp(var_Fresnel,0.0,metalness);
                    half fres_col = fresnel.r;  //罕见,这里不使用
                    half fres_rim = fresnel.g;  //轮廓光用的Fresnel
                    half fres_spec = fresnel.b; //镜面反射光用的fresnel
                    //漫反射和镜面反射下都分为主光和环境光
                        // 1.0 漫反射的主光
                        half halfLambert = NoH * 0.5 + 0.5;     //半兰伯特
                        half3 diffuseWrapTex = tex2D(_DiffWrapTex,half2(halfLambert,0.2)).rgb;
                        half3 dir_diffuseCol = diff_col * diffuseWrapTex * _Light_Color;
                        // 1.1 漫反射的环境光
                        half3 env_diffuseCol = diff_col * _EnvDiffCol * _EnvDiffInt;
                        // 2.0 镜面反射的主光
                        half phong = pow(max(VoR,0.0),specPow * _mySpecPow);
                        half spec = phong * max(0.0, NoL);     //phong和lambert相乘,意思是在漫反射比较黑的地方,镜面反射也弱一些
                        spec = max(spec, fres_spec);    //跟菲尼尔的高光进行混合,这里是使用取最大值
                        spec = spec * _mySpecInt;
                        half3 dir_specularCol = spec * spec_col * _Light_Color;
                        // 2.1 镜面反射的环境光
                        half envSpecInt = max(fres_spec,metalness) * specInt;
                        half3 env_specularCol = spec_col * envSpecInt * envCube * _EnvSpecInt;
                    //轮廓光rim 
                    half3 rimCol = _RimCol * fres_rim * rimInt * max(0.0,nDirWS_FT.g) * _RimInt;
                    //half3 test = _RimCol * _RimInt * rimInt * max(0.0,nDirWS_FT.g);
                    //自发光Emission
                    half3 emitColor = diff_col * emitInt * _EmitInt;

                //返回值
                half3 finalColor = (dir_diffuseCol + dir_specularCol) * shadow + (env_diffuseCol + env_specularCol) + rimCol + emitColor;
                //clip(opacity - _Cutoff);    //透切,没大过阈值的都抛弃掉
                return float4(finalColor,1.0);
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
    //FallBack "Legacy Shaders/Transparent/Cutout/VertexLit"
}

Let’s take a look at the effect picture. I commented out the line of the clip above, because the Translucency map of this weapon is completely black, and there is only a white dot in the middle. After using the line of code, there will be nothing. I don't understand what's going on with the teacher, I should have drawn the stickers myself.
insert image description here
shader effect:
insert image description here

Then I tried the main body of the model, which is the ogre model, and the effect is as follows:
insert image description here

  • It should be noted here that we have to observe from the Game window, because this is to observe the world from the perspective of the camera. The Fresnel sampling in our shader is also sampled according to the observation direction of the camera, and the normal effect is seen from the Game window.
  • If you look directly from the Scene window instead of the Game, you will get a glossy result. This made me puzzled for a long time. After thinking about it, it turned out to be a problem with the viewing angle. Glossy water looks like this:
    insert image description here
    insert image description here

imperfections

There is a disadvantage, just like the FallBack written at the end of my code, the projection is normal only when Diffuse is used. The assignments in the previous classes were all projection problems. I checked around and felt that it might be a version problem.

Guess you like

Origin blog.csdn.net/weixin_43789369/article/details/131502089