Matcap Shader 详解【2】 - Matcap的固有色贴图与法线贴图

前言

上篇文章《Matcap Shader 详解【1】 - 基础思想与Unity中实现》中提到 基础Matcap 有很多“缺陷”,其中第一个缺陷是:

  • 只适用于单一材质、单一固有色且没有法线贴图细节的模型

本文目的便是讲解一下如何在保留Matcap特性的情况下解决这个缺陷。

固有色贴图与法线贴图

基础Matcap只有光照模型,但没有固有色(Albedo)贴图,这个问题很容易解决,只要把固有色贴图通过“正片叠底”的算法——乘法,与光照信息融合,便可得到“上色”的结果——就像用水彩笔在石膏像上涂鸦一样简单。

如下图所示:



这里还有一点小问题——渲染的结果好像有点暗,其实根本原因在于缺乏高光信息,这个问题我们在下一章节解决。

相比传统光照模型,我们的Matcap目前还少了一个次时代利器——法线贴图。法线贴图的添加相比固有色贴图要复杂一些。

在上一章节的 基础Matcap 中,物体法线是在顶点着色器里计算的,但法线贴图只能在片元着色器里计算,所以算法上有一些改动。

先上源码:

Shader "TJia/Matcap_Albedo_Normal" {
	Properties {
		_Color ("Main Color", Color) = (1,1,1,1)
		_MainTex("Albedo Tex", 2D) = "white" {}
		_BumpMap ("Normal Tex", 2D) = "bump" {}
		_BumpValue ("Normal Value", Range(0,10)) = 1
		_MatCapDiffuse ("MatCapDiffuse (RGB)", 2D) = "white" {}
	}
	
	Subshader {
		Tags { "RenderType"="Opaque" }
		
		Pass {
			Tags { "LightMode" = "Always" }
			
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#include "UnityCG.cginc"
				
				struct v2f { 
					float4 pos : SV_POSITION;
					float4	uv : TEXCOORD0;
					float3	TtoV0 : TEXCOORD1;
					float3	TtoV1 : TEXCOORD2;
				};

				uniform float4 _BumpMap_ST;
				uniform float4 _MainTex_ST;
				
				v2f vert (appdata_tan v)
				{
					v2f o;
					o.pos = UnityObjectToClipPos (v.vertex);
					o.uv.xy = TRANSFORM_TEX(v.texcoord,_MainTex);
					o.uv.zw = TRANSFORM_TEX(v.texcoord,_BumpMap);
					
					
					TANGENT_SPACE_ROTATION;
					o.TtoV0 = normalize(mul(rotation, UNITY_MATRIX_IT_MV[0].xyz));
					o.TtoV1 = normalize(mul(rotation, UNITY_MATRIX_IT_MV[1].xyz));
					return o;
				}
				
				uniform fixed4 _Color;
				uniform sampler2D _BumpMap;
				uniform sampler2D _MatCapDiffuse;
				uniform sampler2D _MainTex;
				uniform fixed _BumpValue;
				
				float4 frag (v2f i) : COLOR
				{
					fixed4 c = tex2D(_MainTex, i.uv.xy);
					float3 normal = UnpackNormal(tex2D(_BumpMap, i.uv.zw));
					normal.xy *= _BumpValue;
					normal.z = sqrt(1.0- saturate(dot(normal.xy ,normal.xy)));
					normal = normalize(normal);
					
					half2 vn;
					vn.x = dot(i.TtoV0, normal);
					vn.y = dot(i.TtoV1, normal);

					fixed4 matcapLookup = tex2D(_MatCapDiffuse, vn * 0.5 + 0.5);					
					fixed4 finalColor = matcapLookup * c;
					return finalColor;
				}

			ENDCG
		}
	}
}


左:Matcap_Basic 右:Matcap_Albedo_Normal+法线贴图

说明:

  1. 相比 Matcap_Basic(见上一章),我们去掉了顶点着色中的 NtoV 向量,因为法线贴图是片元级别的。
  2. 由于法线贴图基于切线空间,所以这里增加了 TtoV 矩阵(切线空间转化为视觉空间的矩阵),此处用到了 TANGENT_SPACE_ROTATION 中的 rotation,具体定义可在UnityCG.cginc自行查询。
  3. 在片元着色器中,我们按传统方法对法线贴图进行了解码,然后通过 TtoV 矩阵转化到了视觉空间,此时得到vn(视觉空间中的法线)。

之后的映射上一章中已经讲解,不再赘述,最后得到含有固有色贴图和法线贴图的shader:


系列链接(未完待续):

《Matcap Shader 详解【1】 - 基础思想与Unity中实现》

《Matcap Shader 详解【2】 - Matcap的固有色贴图与法线贴图》

猜你喜欢

转载自blog.csdn.net/weixin_36273312/article/details/80580270