GLSL实现Glow效果 [转]
http://blog.csdn.net/a3070173/archive/2008/11/04/3220940.aspx
Glow即辉光效果现在已成为3D图形中一个引人注目的特效.本文主要介绍如何使用GLSL实现一个典型的GLow效果.
实现步骤:1.渲染整个场景到一个祯缓冲区中
2.将场景中需要进行GLow处理的物体绘制第二个FBO纹理A中
3.在FBO纹理A和B之间进行横和纵"高斯"过滤
4.将进行过GLow处理后的FBO纹理A与祯缓冲区中的场景图像以glBlendFunc(GL_ONE, GL_ONE)方式进行混合处理
GLSL文件功能简介:
FullScreen.vert - 用于绘制覆盖整个视口的四边形以进行Glow效果的高斯过滤
Filter.frag - 用于横和纵的高斯过滤
Blend.frag - 用于处理过的GLowFBO纹理与原始场景图像进行混合
为了直接进行生成Glow效果的介绍,这里假设程序已正确处理了OpenGL和GLSL的初始化.
void RenderOrigionalScene()
{
if (g_bUseFillRender)
{
glPolygonMode(GL_FRONT, GL_FILL);
}
else
{
glPolygonMode(GL_FRONT, GL_LINE);
}
RenderObject();
}
首先让我们绘制原始场景,由于本Demo未绘制除辉光物体外的其它事物,所以此处就直接绘制为进行具有辉光效果的物体.
void RenderGlowObject()
{
// 设置视口
glViewport(0, 0, g_uiTextureWidth, g_uiTextureHeight);
// 将原始场景绘制到第二个FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_uiFboColorOne);
// 清除第一个FBO颜色和深度缓存
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 绘制辉光物体
RenderObject();
}
然后设置绘制目标到FBO纹理A并将欲进行Glow处理的物体绘制到上面来,这里需要注意的是必须根据FBO纹理的尺寸设置一个
视口使其跟FBO纹理一样大,以使物体能够准确地映射到整个FBO纹理上.清除FBO颜色缓冲区和绘制深度缓冲区是必要的,因为
每次绘制到FBO纹理中的图像都不一样.
void FilterGlowObject()
{
glPolygonMode(GL_FRONT, GL_FILL);
// 将水平过滤后的图像绘制第二个FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_uiFboColorTwo);
// 清除第二个FBO颜色
glClear(GL_COLOR_BUFFER_BIT);
// 重新设置片元着色器
glUseProgram(g_ProgramObjectOne);
// 设置水平过滤标志
GLint iUniformIndex = glGetUniformLocation(g_ProgramObjectOne, "g_bFiterMode");
glUniform1i(iUniformIndex, 1);
// 设置纹理
glBindTexture(GL_TEXTURE_2D, g_uiIDOne);
// 绘制
RenderFullScreen();
// 将竖直过滤后的图像绘制第一个FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_uiFboColorOne);
// 清除第一个FBO颜色和深度缓存
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 设置竖直过滤标志
iUniformIndex = glGetUniformLocation(g_ProgramObjectOne, "g_bFiterMode");
glUniform1i(iUniformIndex, 0);
// 设置纹理
glBindTexture(GL_TEXTURE_2D, g_uiIDTwo);
// 绘制
RenderFullScreen();
}
下面到Glow效果处理的重头戏,是否能生成完美的辉光效果关键就在于此步的处理.但其实也很简单,主要就是为Filter着色器设
置进行合适横,纵两次过滤的标志和绘制目标,然后绘制全视口四边形,剩下的过滤工作则由GLSL的高斯过滤着色器全权负责.
void RenderToScreen()
{
// 恢复视口
glViewport(0, 0, g_uiCurrentWindowWidth, g_uiCurrentWindowHeight);
// 恢复绘制目标为祯缓冲区
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, NULL);
// 启动混合
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
// 绑定纹理
glBindTexture(GL_TEXTURE_2D, g_uiIDOne);
// 重新设置片元着色器
glUseProgram(g_ProgramObjectTwo);
// 绘制
RenderFullScreen();
// 恢复固定功能管线
glUseProgram(0);
// 关闭混合
glDisable(GL_BLEND);
}
最后一步无非就是将过滤好的Glow纹理与原始场景图像进行混合,当然使用OpenGL固定功能管线或GLSL都可以轻易实现,但首先必
须把视口设置回原来的状态.
以下是高斯过滤的GLSL着色器代码,粘贴于此以方便读者查阅.
顶点着色器:
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = gl_Vertex;
}
高斯过滤着色器:
const int g_iFilterTime = 9; // 过滤次数
const float g_fGene = (1.0/(1.0 + 2.0*(0.93 + 0.8 + 0.7 + 0.6 + 0.5 + 0.4 + 0.3 + 0.2 + 0.1))); // 衰减因子
uniform sampler2D g_Decal;
uniform bool g_bFiterMode;
uniform float g_fGlowGene;
uniform vec2 g_vec2HorizontalDir; // 水平过滤方向
uniform vec2 g_vec2VerticalDir; // 竖直过滤方向
uniform float g_fFilterOffset; // 过滤偏移
void main()
{
float aryAttenuation[g_iFilterTime];
aryAttenuation[0] = 0.93;
aryAttenuation[1] = 0.8;
aryAttenuation[2] = 0.7;
aryAttenuation[3] = 0.6;
aryAttenuation[4] = 0.5;
aryAttenuation[5] = 0.4;
aryAttenuation[6] = 0.3;
aryAttenuation[7] = 0.2;
aryAttenuation[8] = 0.1;
// 采样原始颜色
vec2 vec2Tex0 = gl_TexCoord[0].st;
vec4 vec4Color = texture2D(g_Decal, vec2Tex0)*g_fGene;
// 计算过滤方向
vec2 vec2FilterDir = g_vec2HorizontalDir + vec2(g_fFilterOffset, 0.0); // 水平过滤
if (!g_bFiterMode)
{
vec2FilterDir = g_vec2VerticalDir + vec2(0.0, g_fFilterOffset); // 竖直过滤
}
// 进行过滤
vec2 vec2Step = vec2FilterDir;
for(int i = 0; i< g_iFilterTime; ++i)
{
vec4Color += texture2D(g_Decal, vec2Tex0 + vec2Step)*aryAttenuation[i]*g_fGene;
vec4Color += texture2D(g_Decal, vec2Tex0 - vec2Step)*aryAttenuation[i]*g_fGene;
vec2Step += vec2FilterDir;
}
if (g_bFiterMode)
{
gl_FragColor = vec4Color*g_fGlowGene;
}
else
{
gl_FragColor = vec4Color;
}
}
混合着色器:
uniform sampler2D g_Decal;
void main()
{
gl_FragColor = texture2D(g_Decal, gl_TexCoord[0].st);
}
Demo效果图:

参考资料:Nvidia OpenGL SDK 10.5 Simple Glow
exe文件:http://www.fileupyours.com/view/219112/GLSL/Glow%20Demo.rar
GLSL实现Glow效果 [转]的更多相关文章
- GLSL实现Glow效果 【转】
http://blog.csdn.net/a3070173/article/details/3220940 Glow即辉光效果现在已成为3D图形中一个引人注目的特效.本文主要介绍如何使用GLSL实现一 ...
- Glow 效果材质
转自:http://blog.csdn.net/panda1234lee/article/details/60960846 算法较简单,首先来看 Base color 部分: 就是将对事先准备好的三张 ...
- GraphicsLab Project之辉光(Glare,Glow)效果 【转】
作者:i_dovelemon 日期:2016 / 07 / 02 来源:CSDN 主题:Render to Texture, Post process, Glare, Glow, Multi-pass ...
- Bump mapping的GLSL实现 [转]
原文 http://www.cnblogs.com/CGDeveloper/archive/2008/07/03/1234206.html 如果物体表面细节很多,我们可以不断的精细化物体的几何数据,但 ...
- Cesium官方教程8-- 几何体和外观效果
原文地址:https://cesiumjs.org/tutorials/Geometry-and-Appearances/ 几何体和外观效果(Geometry and Appearances) 这篇教 ...
- Unity3D使用过程中常见的20个问题
1:天空盒有接缝怎么解决?答:在贴图导入设置里设置Wrap Mode为"Clamp". 2:DDS格式怎么不显示?答:Unity不支持DDS格式,Unity会将除DDS外的其他格式 ...
- Flex里的特效
Flex中提供了丰富的效果组件.因为效果是一种依据时间渐变的过程,因此全部效果都具有duration属性,用来设置播放时间(以毫秒为单位).也能够通过设置repeatCount属性和repeatD ...
- div使用
div style常用属性 一.常用属性: 1.Height:设置DIV的高度. 2.Width:设置DIV的宽度. 例: <div style="width:200px;height ...
- Unity Shader-后处理:Bloom全屏泛光
一.简介 今天来学习一下全屏Bloom效果,有时候也叫Glow效果,中文一般叫做“全屏泛光”,这是一种可以模拟出HDR的全屏后处理效果,但是实现原理与HDR相差很远,效果比HDR差一些,但是比HD ...
随机推荐
- JS调试必备的5个debug技巧
我一直使用printf调试程序,一般来说都是比较顺利,但有时候,你会发现需要更好的方法.下面几个JavaScript技巧相信你一定会觉得十分有用 1. debugger; 我以前也说过,你可以在J ...
- 解决WCF大数据量传输 ,System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接
开发中所用的数据需要通过WCF进行数据传输,结果就遇到了WCF大量传输问题 也就是提示System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接 网上解决 ...
- POJ 1423 Big Number
题意:求n阶乘的位数. 解法:斯特林公式,,然后取log10就是位数了,因为精度问题需要化简这个式子,特判1. 代码: #include<stdio.h> #include<iost ...
- 【LeetCode 229】Majority Element II
Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorit ...
- 【LR】关于宽带与比特之间的关系
1.比特=bps 2M比特的意思是2宽带 1M宽带=12M比特=1*1024K比特=1*1024*1024比特=1057648比特 2M宽带=2*1024*1024比特=2097152比特 4M宽带= ...
- 关于java异常的一点思考
关于异常的一点思考 异常生命周期 异常的来源 所有的异常都是抛出来的 有底层api抛出的 有自定义抛出的 异常的处理 1, 运行时异常 不做任何处理仍可编译通过 不建议捕获(不建议用异常来做流程控制, ...
- MFC图形图像
一.CDC类 CDC类简介 CDC类是一个设备上下文类. CDC类提供了用来处理显示器或打印机等设备上下文的成员函数,还有处理与窗口客户区关联的显示上下文的成员函数.使用CDC的成员函数可以进行所有的 ...
- 一个鼠标键盘控制两台甚至多台主机的方法--Synergy
在多台主机,不同系统中操作.避免了更换键鼠的麻烦.即使下面图中的功能. 鼠标同时在三台或者多台主机之间进行移动,而且是无缝滑动,鼠标直接从左滑倒右,而且支持,这台电脑复制,另一台黏贴.非常的方便实用. ...
- adb常用命令介绍
adb connect 命令格式:adb connect <host>[:<port>] 作用:connect to a device via TCP/IP,Port 5555 ...
- 关于python的import
在软件包里,必须添加__init__.py文件. 想要对外公开的module必须在__init__.py内import一次,这样这些module才能被外部代码import并调用.