设为首页 加入收藏

TOP

OpenGL超级宝典学习笔记——片段着色器(二)
2015-02-25 22:42:45 来源: 作者: 【 】 浏览:30
Tags:OpenGL 超级 宝典 学习 笔记 片段 着色

图像处理是一种独立于顶点着色器的特殊处理程序。在不使用片段着色器的情况下绘制场景之后,可以按照各种方式应用卷积核。


为了保持着色器的简洁,使用硬件加速,我们限制总卷积的大小为3X3.


在示例程序中,调用glCopyTexIamge2D把帧缓冲区拷贝到纹理中。纹理的大下为小于窗口的2的最大N次方值(在2.0中则没有这个限制)。然后在窗口的中间绘制一个片段着色的四边形,大小与这个纹理相同,其纹理坐标从左下角(0,0)到右上角(1,1)。


片段着色器基于纹理坐标,在以其为核心的相邻的3X3纹理中进行采样,然后进行过滤,得到这个中心点的颜色。


模糊可能是最常见的过滤器。它能够平滑一些高频率的特性,例如物体边缘的锯齿。它也叫做低通滤波器。它允许低频率的特性通过,而截留高频率的特性。


如果我们只用3X3的卷积核,那么在单次采样时不会有太明显的变化。我们可以进行多次采样。


下面是着色器代码:


在这个过程中,首先我们先不使用着色器绘制好图形,然后启用着色器程序,设置好sampler0和tc_offse,把帧缓冲拷贝到纹理中。再设置好纹理坐标,绘制一个正方形,使用着色器处理纹理。下面是部分关建代码:


只进行一次采样:


image


5次采样:


image


锐化与模糊相反,它是使得物体的边缘更加明显和文字容易阅读。


锐化的着色器代码:


注意这个卷积核相加的结果为1,这和模糊过滤器相同。这个操作保证了这种过滤器不会增强或减弱亮度。


锐化效果图


image


膨胀只是简单的找到相邻的最大值。


腐蚀取周围相邻的最小值。


image


比较有价值的过滤器是边缘检测。图像的边缘是颜色变化快的地方,而边缘检测则是选取这部分颜色急剧变化的地方并高亮它们。


有三种边缘检测器Laplacian,Sobel和Prewitt. Sobel和Prewitt梯度过滤器,它们检测每个通道强度的一阶导数的变化,只是在单个方向上进行。Laplacian则检测二阶导数的零值,也就是颜色的强度梯度从暗变亮的地方(或相反)。它可以用于所有的边缘。


下面的代码使用Laplacian过滤器。


image


它和锐化过滤器的区别就是中间的那个值是8不是9,这样系数之和就是0。这也说明了为何图形中间是黑的。因为图元中间的颜色相近,通过卷积核过滤之后就接近于0了。只有在图元边缘颜色变化剧烈的地方,才有较大的颜色值。


在此之前,我们讨论过逐顶点的光照。还讨论了通过分离镜面光和使用纹理查找的方式来提升光照效果。在这里我们使用片段着色器的方式来处理光照。算法是一样的。


在这里我们结合顶点着色器和片段着色器来实现。顶点着色器对法线、光照向量沿着线和三角形进行插值。然后,片段着色器处理顶点着色器产生的值得到最终的结果。


公式:


Cdiff = max{N ? L, 0} * Cmat * Cli


这与之前只用顶点着色器不同的是,这里用varyings修饰的标识符N和L作为输出,在片段着色器中用一样的名称就可以访问到N,L。这种方式比之前使用纹理坐标作为输出的方式更容易理解,也不容易出错(试想不小心把L输出到textureCoord[1]中,但实际使用的是textureCoord[0], 不会产生编译错误,但得不到想要的结果)。


下面是片段着色器代码:


镜面光公式:


Cspec = max{N ? H, 0}Sexp * Cmat * Cli


VS有多个L的输出


image


?


源码:https://github.com/sweetdark/openglex


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇OpenGL超级宝典学习笔记——顶点.. 下一篇Python pickle模块的简单使用笔记

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: