GLSL实现Glow效果
来源:互联网 发布:淘宝店标在线制作免费 编辑:程序博客网 时间:2024/05/21 09:34
引言
从GraphicsLab Project项目立项以来,一直都在忙着搭建Shader的实验环境,现在基本的实验环境已经搭建完毕,所以就试着使用它来编写一些效果。本篇文章就将向大家讲述,如何在OpenGL中,使用GLSL编写出辉光效果。
辉光(Glare,Glow)
辉光效果,也就是Glare,Glow效果。它的主要作用是模拟一些场景中发光物体周边的朦胧模糊的发光效果,有点类似于PS中的外发光。先来看一看这种效果的实际图片,给大家一个感性的认识。
图1
图2
图3
上面图片给大家展示了辉光效果能够带来的视觉体验。为场景中的发光物体添加辉光效果,能够实现灯光的朦胧感觉。当然,为了整体画面的和谐也不能乱用此效果,否则就给人一种很俗气的感觉。
原理
下面给大家讲述下这种效果的实现方式。其实说白了它的实现原理很简单,我们只要对要添加辉光效果的物体进行一次模糊操作,然后将模糊过后的图片与原先的图片进行Alpha Blend,就能够得到上面所示的效果。操作如图所展示的那样(这里为了简便,只在场景中绘制Glare物体,并且只添加了些许光照,没有添加其他效果):
图4 未进行模糊的原场景
图5 对原场景进行模糊之后的图像
图6 将模糊之后的场景与原场景进行Alpha blend之后的最终效果
上面三张图片展示了绘制一个简单辉光效果的整体步骤。原理是不是十分的简单???大家可以自己在PS等图像处理软件中,直接模拟看看是否能够得出这种效果来。
OpenGL实现
在讲述具体的实现之前,我们需要先了解一些基本的知识点。在了解了这些知识点的基础之上,我们才能够实现这种效果。
渲染到纹理(Render to Texture, RTT)
在图形学处理中,我们经常需要对渲染好的场景进行一些处理。也就是说,我们需要一种方式,能够让我们通过图形API(OpenGL, DirectX)绘制的场景保存到我们指定的内存(显存)中去,以便于我们后期对他进行一些处理。而在OpenGL中,我们能够很容易的实现这一点。这种技术在我的博客中也有讲到。大家可以根据博客中的描述和代码对此进行了解。
后处理(Post-processing)
后处理在图形学中经常被用到。我们在游戏中绘制的场景,往往是没有办法仅仅依靠光照模型计算就能够实现出来的。很多的特殊效果,都是通过对渲染好的场景进行图像空间的后期出理来得到。比如本篇文章中实现的辉光效果,就使用了这种技术。还有很多其他在图像空间进行后处理的特效,感兴趣的同学可以阅读Real-time Rendering中关于此技术的章节。
图像模糊(Blur)
在前面讲述辉光效果整体绘制流程的时候,讲到了我们需要对原场景图像进行模糊操作。那么怎么样才能够实现对图像的模糊操作了?
在图像处理中,我们经常使用的模糊是基于高斯分布函数的高斯模糊。这篇文章详细的讲述了图像模糊的一些技术细节,大家可以据此了解如何进行高斯模糊。
高斯模糊在图像处理的时候,是使用2维的高斯分布函数对一个像素的上下左右包围的像素进行采样来实现的。我们假设模糊的半径为20个像素,按照高斯模糊的原始计算方式,每一个像素都需要计算(2 * 20) ^ 2次采样。这在图像处理上面可以接受,但是对于实时性的游戏来说,计算量就有点大了。
为此,人们想出了一种优化的方法来实现高斯模糊。对于一个像素,它的模糊半径为20,那么我们可以分两次进行模糊,一次是横向的模糊计算,一次是纵向的模糊计算。也就是将模糊操作从O(N^2)降低到了2 * O(N)。下图展示了如何进行这样的操作:
图7
从图中,我们可以看到,我们先对原场景图进行一次横向的模糊计算,此次计算我们只需要采用一维的高斯分布进行计算即可。然后对横向模糊之后的图像进行纵向模糊,与横向模糊一样,使用一维的高斯分布函数进行。这样就能够得到一张高斯模糊之后的图像,它的模糊效果不比二维高斯模糊效果来的差。
OpenGL绘制流程
下面就以我的代码中的绘制流程来向大家展示如何在OpenGL中绘制一个辉光效果:
上面的代码给出了我绘制的流程:
(1).绘制正常场景 -- 此处绘制的场景保存到一张纹理A中,并且复制A纹理到B纹理中
(2)绘制一个和屏幕一样大小的矩形,将纹理A作为该矩形的贴图,施加横向模糊的Shader计算,最后的结果保存到另外一张贴图C中
(3)绘制一个和屏幕一样大小的矩形,将纹理C作为该矩形的贴图,施加纵向模糊的Shader计算,最后的结果保存到纹理A中(A已经被复制到B中去,所以可以被覆盖)
(4)经过前三步之后,A纹理保存了模糊之后的图像,B纹理保存了原图像,然后画一个矩形,把这两张贴图都传递进入,进行Alpha混合计算。
Shader计算
对于(1)步骤,使用如下的两个Shader:
这两个Shader只是为了实现Phong式光照计算,给场景一点光亮,对于绘制辉光效果并不是必须的,但你总得有东西才能绘制辉光效果吧!
对于步骤(2)和步骤(3),使用如下的三个Shader:
上面三个Shader组合完成了高斯模糊的计算。这里有几点需要注意。
(1)进行模糊计算的时候,逻辑上是以一个像素单位为步进值,但是由于纹理坐标是从[0,1],所以我们需要将一个像素的步进值计算为对应的纹理坐标步进。这个操作可以在Application阶段计算完成,然后传递到Shader中,这里博主偷懒了,直接在Shader里面计算了。
(2)Shader中的gauss_num[21]保存了模糊半径为20的高斯分布的各个数值。这个数值的计算是在Application阶段完成,然后提交到Shader中去的,如下是计算Gauss_num的函数,使用的是一维的高斯分布函数完成:
对于步骤(4),使用了如下的两个Shader:
最后的混合计算,我选取了模糊贴图的一半加上场景贴图的一半来进行混合操作。最终的效果如下图所示:
图8
总结
上面文章为了简化操作,做了很多在实际项目中不可以的操作。比如在Shader中计算纹理步进值。而在实际的情况下,实现辉光效果远远要比这里展示的复杂的多,比如场景中有不发光的物体,和发光的物体,此时需要通过Alpha贴图来标识出场景图中哪些是需要进行模糊的,而哪些是不需要进行。又比如说,发光物体在某个不发光物体的后面,那么进行模糊计算的时候,必然会让发光物体渗透到不发光物体中,会产生比较粗糙的感觉。
所以,本片文章仅仅是为了向大家讲述辉光算法的基本原理,至于如何整合到你们自己的项目中去,需要大家自己来思考!希望本篇文章能够帮助到你们!
参考文献
http://http.developer.nvidia.com/GPUGems/gpugems_ch21.html GPU Gems - Chapter 21.Real-time Glow
http://www.nutty.ca/?page_id=352&link=glow Nutty-Software-Glow(aka Bloom)
http://blog.csdn.net/a3070173/article/details/3220940 GLSL实现Glow效果
http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html 高斯模糊的算法-阮一峰的网络日志
http://baike.baidu.com/link?url=bWuVG4Lbr7DM-UReJNKUDOqrNcA788yhwpgl7Ln1IE-TRqiBkEYJrRP1tJEZ2sHOa0MAat21_iVRSs2dS6R4_a 正态分布-高斯分布-百度百科
阅读全文
1 0
- GLSL实现Glow效果
- GLSL实现Glow效果
- GLSL实现Glow效果
- 材质 “Glow 效果” 的实现【UE4】
- GLSL实现滤镜效果
- GLSL/C++ 实现滤镜效果
- 辉光效果(Glow Effect)
- 使用GLSL实现的海洋效果
- 使用GLSL实现雾化的效果
- 用hlsl/glsl实现内发光效果
- CSS通过滤镜shadow,glow等实现四个面阴影,效果算不上完美
- 使用CADisplayLink实现果冻效果动画(学习于Glow 技术团队)
- glow
- 使用glsl实现cocos2dx平台下的随机光晕效果
- Shader特效——实现“HDR”效果【GLSL】
- Shader特效——“Sephia等效果”的实现 【GLSL】
- Shader特效——“帧动画效果”的实现 【GLSL】
- Shader特效——“Median Filter效果”的实现 【GLSL】
- 各版本MyEclipse8.5安装Git插件
- 独木舟上的旅行
- maven 部署war包到tomcat 报错 Cannot invoke Tomcat manager: xxxxxx
- 机器学习技法课程学习笔记12-- Neural Network
- ffprobe使用配置
- GLSL实现Glow效果
- 通过代码设置改变radiobutton图片大小
- 人群分析综述--Crowd Scene Understanding from Video: A Survey
- 云栖大会第二天高性能计算,打call送礼
- 运维架构服务监控Open-Falcon
- 如何选择web前端培训机构?
- bootstrap实现标签页,鼠标滑过激活当前选项卡。
- 请手动释放你的资源
- 深入理解python中的元类