原帖地址:http://ogldev.atspace.co.uk/www/tutorial09/tutorial09.html
本章我们了解3D管线的一个重要特性,在光栅化阶段的顶点属性插值。从前面的教程我们知道,为了在屏幕上输出渲染的物体,我们在顶点shader中输出gl_Position,这是一个四维向量,表示齐次空间的顶点坐标,x,y,z都经过了透视除法,除以了w值,x、y的范围是[-1,1],而z的范围是[0,1],而w则成为了1.0(因为w/w的缘故),接着会进行视口变化,转化到屏幕空间,然后进行光栅化操作。
光栅化阶段会执行顶点属性插值操作,而三角形内部光栅化后的片元(或者像素)会执行片元shader,片元shader会返回该片元的颜色,然后会进行深度测试、模版测试等操作,如果通过这些测试,那么该片元的颜色将会更新framebuffer中对应像素的颜色。
顶点shader中的变量如果没有经过上述步骤,可能会被driver优化掉,从而提高程序性能,比如一个顶点属性在顶点shader中存在,但没有被传输到片元shader,就有可能被优化掉,而传到片元shader的顶点属性则会执行插值操作。主要根据三个顶点的属性,比如颜色,执行双线性插值,得到片元(或像素)的颜色, 插值后的三角形通常都是渐变颜色的。
可以参考一下我的另外一篇文章,专门接受顶点属性插值的:http://www.cnblogs.com/mikewolf2002/archive/2012/11/25/2787480.html
两个常依赖于插值的顶点属性是顶点法向和纹理坐标。对一个三角形来说,常用三个顶点法向平均值做为三角形面的法向值,但当三角形面不是平(flat,意思是说三角形面上的颜色是一样的,没有渐变之类的效果)的时候,我们一般通过插值方法得到三角形上每个像素的法向值。得到插值后的法向值经常在片元shader中用来计算光照颜色,而纹理坐标插值主要是用来采样纹理,得到该纹理上相应的颜色值,然后和光照计算得到的颜色混合,得到像素最终的颜色。
在这片教程中,我们将会看到颜色插值的效果。
主要代码:
out vec4 Color;
在管线之间传输的变量,都要被声明为out,out是一个shader保留关键字。颜色变量用了vec4,xyz的值分别表示RGB,w的值为颜色的alpha值。
Color = vec4(clamp(Position, 0.0, 1.0), 1.0);
图形管线中的颜色值,通常用范围在[0.0,1.0]之间的浮点数表示,这个值能够被映射到[0,255]。我们根据顶点位置设定顶点的颜色,并用内建函数clamp把颜色值限定在[0.0,1.0]之间,因为顶点坐标xy值在[-1.0,1.0]之间变化,如果不做clamp操作,颜色可能出现负值,这时就成了为黑色,并不是我们所要的效果。
在glsl中,clamp函数并没有vec4的版本,所以我们扩展成四维坐标,并设置w=1.0,表示alpha=1.0,即颜色混合操作时,该颜色是透明的。
in vec4 Color;
在片元shader中,定义输入颜色,该输入颜色是顶点属性插值后像素的颜色。我们用该插值颜色,做为片元shader最终的输出颜色。
FragColor = Color;
程序执行后效果如下,注意左边的图是使用没有clamp函数的颜色,此时部分区域是黑色: