轻松愉快学Shader(2)——Phong着色

Phong着色法简介:

  上一讲我们通过基本的光照计算,渲染出了一个球体。这个球体已经能基本体现出漫反射光、镜面光的效果。但是凡事就怕比较,如果对比一下下面两幅图,你还会觉得左边的好看吗?(左边的是我们上一讲画的)。


  哈哈,现在各位一定会觉得上一讲我们画的球体,简直是弱爆了。问题在哪里?两个球体蓝色的部分似乎差不了太多,但是白色的镜面光部分,右边的球体明显要逼真很多,而左边球体的镜面光部分就显得很挫。

  造成这种现象的原因,是因为我们只是计算了每个顶点的光照颜色(在顶点着色器里),而对于球体上的每个像素,我们只是简单的通过差值计算颜色的近似值。我们没有对每个像素进行光照计算。对于漫反射光,差值算法可以相对准确的近似每个像素颜色,但是对于较为锐利的镜面光,这种差值算法就力不从心了。所以左边球体看起来就不是很逼真。如果我们能针对球体上的每个像素,分别带入光照模型的公式,计算其光照颜色。则我们的球体就会像右边的一样逼真。这就是我们这一讲要学习的Phong着色算法。

Shader算法实现:

  上一讲中,我们主要的工作都是在顶点着色器中实现的。而Phong算法既然是一种Per-Pixel Lighting(针对每个像素的光照计算),它的很大一部分代码都需要在像素着色器中完成。首先,既然要在像素着色器中应用上一讲的光照模型,有几个向量我们必须要拿到,包括Normal、LightDir、HalfVect三个向量(三个向量的含义请参看上一讲)。但是在像素着色器里想要拿到法线等向量,似乎是办不到的。不过我们可以用一些技巧,在顶点着色器里返回这三个向量,通过顶点着色器向像素着色器传入这三个向量。这样说读者未必理解,我们先看看代码,首先把VS_OUTPUT结构体的定义改成:

struct VS_OUTPUT
{
	float4 Position : POSITION0;
	float4 LightDir : TEXCOORD0;
	float3 Normal : TEXCOORD1;
	float3 HalfVect : TEXCOORD2;
};

  这个结构体定义的就是顶点着色器的返回类型。其中LightDir、Normal、HalfVect成员分别用来存储三个向量。注意,这里的用途标记TEXCOOR0、TEXCOOR1、TEXCOOR2并不是真的表示他们是纹理坐标,而只是用来告诉DX9,我们借用GPU里用来存储纹理坐标的寄存器来存储各种向量。

  下面我们再看一下顶点着色器的算法:

VS_OUTPUT vs_main(float4 Pos : POSITION0, float3 Normal : NORMAL)
{
	VS_OUTPUT output = (VS_OUTPUT)0;
	output.Position = mul(Pos, MatWVP);
	output.Normal = Normal;

	//计算光线入射方向
	float3 LightDir = LightPos - Pos;
	float Dist = length(LightDir);
	
	//将光线入射向量存储在VS_OUTPUT的LightDir的成员的前三个分量中
	//而用w分量存储距离衰减系数DistAtten
	output.LightDir.xyz = LightDir / Dist;
	output.LightDi
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值