Iron Man material production - 3. Realization of basic lighting model

Iron Man Unlit lighting Shader, three effect changes


Back to Contents

Hello everyone, I'm Ah Zhao, here is the third part of Iron Man's material production, the realization of the basic lighting model.

I don't want to talk too much about this process, because it is just applying the previous lighting model, but this time there is a specific model, and you can also take a look at the impact of each process on the actual display effect of the model.
The lighting model used here can be chosen by yourself. For example, I chose HalfLambert for the diffuse reflection model, and BlinnPhong for the specular model. This is not fixed, and you can also replace it with other lighting models you like.
The final calculation result is still ambient light color + diffuse reflection color + highlight color.

1. Diffuse map

insert image description here

This pass simply samples the model's diffuse map and displays it.

2. Use the HalfLambert diffuse lighting model

insert image description here

It can be seen that this process model has produced some differences between the bright side and the dark side, and the model has some three-dimensional effect.

3. Use the BlinnPhong highlight model

insert image description here

After adding highlights, the model is more three-dimensional, but a bit greasy

4. Add a highlight mask map:

insert image description here
insert image description here

After adding the highlight mask map, you can control the intensity of the highlights produced by different positions of the model, so that the model does not look so greasy. However, this specular map came with me when I downloaded the model. Personally, I feel that it seems to be transferred directly from the diffuse reflection map. The change of the specular light is too uniform, and the effect is not very ideal. Here I just demonstrate how to use the mask map, so I didn't retouch the image.

5. Add normal map

insert image description here

After adding the normal map, you can add a lot of details to the lighting effect, which looks more delicate.

It should be noted that I did the UnpackScaleNormal operation in the Shader, so in the import option of the normal map, there is no need to select Normal, and the normal texture format is fine. Otherwise, the repeated Unpack will have the wrong effect.

6. Complete Shader:

Shader "azhao/IronManBodyCode"
{
    Properties
    {
		_RimBias("RimBias", Float) = 1
		_RimPow("RimlPow", Float) = 2
		_RimlCol("RimCol", Color) = (0,0,0,0)
		_NoiseMap("NoiseMap",2D) = "black"{}
		_NoiseTiling("NoiseTiling",Vector) = (1,1,0,0)
		_NoiseSpeed("NoiseSpeed",float) = 0

		_AmbientStength("AmbientStength",float) = 1
		_MainTex("BaseCol",2D) = "white"{}
		_NormalMap("NormalMap",2D) = "black"{}
		_NormalScale("NormalScale",float) = 1
		_SpecCol("SpecCol",Color) = (1,1,1,1)
		_Shininess("_Shininess",float) = 1
		_SpecStength("SpecStength",float) = 1
		_SpecMask("SpecMask",2D) = "white"{}


    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag


            #include "UnityCG.cginc"

			//简化版的转换法线并缩放的方法
			half3 UnpackScaleNormal(half4 packednormal, half bumpScale)
			{
				half3 normal;
				//由于法线贴图代表的颜色是0到1,而法线向量的范围是-1到1
				//所以通过*2-1,把色值范围转换到-1到1
				normal = packednormal * 2 - 1;
				//对法线进行缩放
				normal.xy *= bumpScale;
				//向量标准化
				normal = normalize(normal);
				return normal;
			}


			//获取HalfLambert漫反射值
			float GetHalfLambertDiffuse(float3 worldPos, float3 worldNormal)
			{
				float3 lightDir = UnityWorldSpaceLightDir(worldPos);
				float NDotL = saturate(dot(worldNormal, lightDir));
				float halfVal = NDotL * 0.5 + 0.5;
				return halfVal;
			}

			//获取BlinnPhong高光
			float GetBlinnPhongSpec(float3 worldPos, float3 worldNormal,float shininess)
			{
				float3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
				float3 halfDir = normalize((viewDir + _WorldSpaceLightPos0.xyz));
				float specDir = max(dot(normalize(worldNormal), halfDir),0);
				float specVal = pow(specDir, shininess);
				return specVal;
			}


            struct appdata
            {
                float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
				float4 tangent : TANGENT;

            };

            struct v2f
            {
                float4 pos : SV_POSITION;
				float2 uv : TEXCOORD0;
				float3 worldPos :TEXCOORD1;
				float3 worldNormal : TEXCOORD2;
				float3 worldTangent :TEXCOORD3;
				float3 worldBitangent : TEXCOORD4;
				
            };

			float _RimBias;
			float _RimPow;
			float4 _RimlCol;
			sampler2D _NoiseMap;
			float4 _NoiseTiling;
			float _NoiseSpeed;

			sampler2D _MainTex;
			sampler2D _NormalMap;
			float _NormalScale;
			float _AmbientStength;
			float4 _SpecCol;
			float _Shininess;
			float _SpecStength;
			sampler2D _SpecMask;


            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = v.uv;
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
				o.worldTangent = UnityObjectToWorldDir(v.tangent);
				o.worldBitangent = cross(o.worldNormal, o.worldTangent);
                return o;
            }

            half4 frag (v2f i) : SV_Target
            {
				/*
				光线轮廓暂时先屏蔽掉
				float3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
				float NdotV = dot(i.worldNormal, worldViewDir);
				float fresnelVal = pow((1 - NdotV)*_RimBias, _RimPow);
				

				float2 noiseUV = i.worldPos.xy *_NoiseTiling.xy + _NoiseTiling.zw;
				noiseUV.y += frac(_Time.y)*_NoiseSpeed;
				float4 noiseCol = tex2D(_NoiseMap, noiseUV);

				half4 RimRGBA = _RimlCol * (fresnelVal+noiseCol.r);
				*/
				half4 baseCol = tex2D(_MainTex,i.uv);

				half4 normalCol = tex2D(_NormalMap, i.uv);
				//得到切线空间的法线方向
				half3 normalVal = UnpackScaleNormal(normalCol, _NormalScale).rgb;

				//构建TBN矩阵
				float3 tanToWorld0 = float3(i.worldTangent.x, i.worldBitangent.x, i.worldNormal.x);
				float3 tanToWorld1 = float3(i.worldTangent.y, i.worldBitangent.y, i.worldNormal.y);
				float3 tanToWorld2 = float3(i.worldTangent.z, i.worldBitangent.z, i.worldNormal.z);

				//通过切线空间的法线方向和TBN矩阵,得出法线贴图代表的物体世界空间的法线方向
				float3 worldNormal = float3(dot(tanToWorld0, normalVal), dot(tanToWorld1, normalVal), dot(tanToWorld2, normalVal));

				float diffuseVal = GetHalfLambertDiffuse(i.worldPos, worldNormal);
				float4 specMaskVal = tex2D(_SpecMask, i.uv).r;
				float specVal = GetBlinnPhongSpec(i.worldPos, worldNormal, _Shininess)*specMaskVal*_SpecStength;
				half3 finalRGB = UNITY_LIGHTMODEL_AMBIENT * _AmbientStength + baseCol.rgb*diffuseVal+ _SpecCol.rgb*specVal;
				return half4(finalRGB,1);
            }
            ENDCG
        }
    }
}

Guess you like

Origin blog.csdn.net/liweizhao/article/details/130031817