实现BlinnPhong 光照的原理

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xiaoge132/article/details/50576346
引言:

在Shader中实现BlinnPhong光照时,会用到一些代码,这些代码令人费解,下面是BlinnPhong 在Unity里内置的函数:

 在文件Lighting.cginc里面

windows系统下位于:

…Unity\Editor\Data\CGIncludes\


这个是实现BlinnPhong  的函数


inline fixed4 LightingBlinnPhong (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
{
	half3 h = normalize (lightDir + viewDir);
	
	fixed diff = max (0, dot (s.Normal, lightDir));
	
	float nh = max (0, dot (s.Normal, h));

	float spec = pow (nh, s.Specular*128.0) * s.Gloss;
	
	fixed4 c;
	c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2); 
	c.a = s.Alpha + _LightColor0.a * _SpecColor.a * spec * atten;
	return c;
}

忽然给了这么一段代码,学过CG 的人也会感到一些迷惑,下面我们从图形学的角度来看这些代码的含义.

我们先来了解一下光照的计算。

光照是由发射光,环境光,漫反射光以及镜面高光组成的,这四个部分先单独运算,然后再累积起来组成最终的效果。


一    发射光:

openGL 中物体材质设置发射颜色来模拟发射光的

发射颜色 = 物体发射材质颜色


二   漫反射:

漫反射颜色 = 光源的漫反射光颜色x物体的漫反射材质颜色x diff

其中漫反射因子diff是光线与定点法线向量的点积:

diff = max(0,dot(N,L))


PS:   dot() 为两个向量之间的的cos值.很直观的展示的漫反射的规律.在正对着入射光线时光照最强,在大于等于90度时候,没有反射的效果.


三 环境光:

环境颜色 = 光源的环境光颜色 x 物体的环境材质颜色



四 镜面反射:

镜面反射颜色 = 光源的镜面光颜色x物体的镜面材质颜色 x spec

spec =power(max(0,dot(s.Normal, h)),shininess)

这里的shininess是128

h = normalize (lightDir + viewDir)

h向量是视线向量viewDir 与光线向量lightDir的半向量,几何意义就是视线与光线夹角的平分线.


这里的normalize()函数用于获取lightDir + viewDir 坐标转化为单位向量,且方向不变.



光照的终极公式:

光照颜色 = 反射颜色 +全局环境颜色 +(环境颜色 + 漫反射颜色 +镜面反射颜色) x 聚光灯效果 x 衰弱因子

这里给的物体是不发光的,没有反射颜色这的部分.

	half3 h = normalize (lightDir + viewDir);	//h向量是视线向量viewDir 与光线向量lightDir的半向量,几何意义就是视线与光线夹角的平分线.
	
	fixed diff = max (0, dot (s.Normal, lightDir));	//漫反射因子diff是光线与定点法线向量的点积,大于等于90度,没有反射的效果.
	
	float nh = max (0, dot (s.Normal, h))	//nh 是h向量与定点法线向量的点积

	float spec = pow (nh, s.Specular*128.0) * s.Gloss; //得到nh 向量进行s.Specular*128.0 次乘方计算

	
	fixed4 c;
	// 光照颜色 = 反射颜色 +全局环境颜色 +(环境颜色 + 漫反射颜色 +镜面反射颜色) x 聚光灯效果 x 衰弱因子

	c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2);//漫反射 + 镜面反射
	c.a = s.Alpha + _LightColor0.a * _SpecColor.a * spec * atten;










展开阅读全文

没有更多推荐了,返回首页