逐顶点高光反射

///逐顶点高光反射
shader"Unity Shader Book/Chapter 6/Specular Vertex_Leve1"{
	//设置了三个属性,漫反射颜色,高光反射颜色,高光区域的大小
	properties{
		_Diffuse("Diffuse",Color) = (1,1,1,1)
		_Specular("Specular",Color) = (1,1,1,1)
		_Gloss("Gloss",Range(8.0,256)) = 20
	}
		SubShader{
		//顶点/片元着色器的代码需要写在pass语义块内
		Pass{
		//指明光照模式
		Tags{ "LightMode" = "ForwardBase" }

		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
		//引用内置的变量
#include "Lighting.cginc"
		//定义和属性相匹配变量
	fixed4 _Diffuse;
	fixed4 _Specular;
	float _Gloss;
	//顶点着色器的输入结构体
	struct a2v {
		float4 vertex :POSITION;
		float3 normal :NORMAL;
	};
	//顶点着色器的输出结构体,同时也是片元着色器的输入结构体
	struct v2f {
		float4 pos : SV_POSITION;
		fixed3 color : COLOR;
	};
	//顶点着色器
	v2f vert(a2v v) {
		//定义返回值o;
		v2f o;
		// Transform the  vertex from object space to projection space 顶点位置从模型空间转化到裁剪空间
		o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
		//get ambient term 得到环境光部分
		fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
		//transform the normal fram object space to world space 转换法线从模型到世界坐标
		fixed3 worldNormal = normalize(mul(v.normal, (float3x3)_World2Object));
		//get the light direction in world space 获得世界空间中的光照方向
		fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
		//compute diffuse term 计算漫反射项
		fixed3 diffuse = _LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal, worldLightDir));


		//get the reflect direction in world space 获得世界空间中的反射方向 
		fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
		//get the view direction in world space 获得世界空间中的观察方向(相机位置)
		fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(_Object2World, v.vertex).xyz);
		//computer specular term 计算高光反射项
		fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(saturate(dot(reflectDir, viewDir)), _Gloss);
		//环境光+漫反射+高光反射  得到最终光照
		o.color = ambient + diffuse + specular;
		return o;
	}

	fixed4 frag(v2f i) :SV_Target{
		return fixed4(i.color,1.0);
	}
		ENDCG
	}
	}
		Fallback"Specular"
}

对于高光反射部分:

先计算入射光线关于表面法线的反射方向【reflectDir】。由于CG的reflect函数的入射方向要求是由光源指向交点处的,因此我们需要对【worldLightDir】取反再传给reflect函数。

然后通过【_WorldSpaceCameraPos】得到世界空间中的摄像机位置,再把顶点从 模型空间变换到世界空间下,再通过和_WorldSpaceCameraPos相减得到世界空间下的视角方向


逐顶点高光反射部分很不光滑,因为高光反射部分的计算是非线性的,而在顶点着色器中计算光照再进行插值的过程是线性的,破坏了原计算的非线性关系。(有待理解)


高光反射计算公式:

                                                                 c_{specular} = (c_{light}\cdot m_{specular})max(0,\hat{v}\cdot \hat{r})^{m_{gloss}}

c_{light}:入射光线的颜色和强度

m_{specular}:材质的高光反射系数

\hat{}\hat{v}:视角方向

\hat{r}:反射方向                                            \hat{r} = \hat{l}-2(\hat{n}\cdot \hat{l})

 \hat{l}:光源方向

reflect(i,n):函数,由CG提供,通过  入射方向 和  法线方向  计算  反射方向

pow(x,y):函数  用来求 x 的 y 次幂(次方)

猜你喜欢

转载自blog.csdn.net/ABigDeal/article/details/81504881