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效果 [转]

时间: 2024-10-09 01:07:35

GLSL实现Glow效果 [转]的相关文章

材质 “Glow 效果” 的实现【UE4】

效果如下:(由于对上传图片大小有限制,所以GIF截图质量下降严重) 算法较简单,首先来看 Base color 部分: 就是将对实现准备好的三张纹理进行线性插值,其中 Mask 为遮罩纹理 接着再来看 Emissive Color 部分: 算法也很简单,即随着时间的变化,经过变化的常量颜色和遮罩纹理进行线性插值,然后结果传入 Emissive Color 总览图 最后,附上 UE4 自动生成 HLSL 代码,有兴趣的朋友可以研究一下: // Copyright 1998-2016 Epic Ga

Bump mapping的GLSL实现 [转]

原文 http://www.cnblogs.com/CGDeveloper/archive/2008/07/03/1234206.html 如果物体表面细节很多,我们可以不断的精细化物体的几何数据,但是这样会产生大量的Lighting & Transformation等计算,为了实现丰富真实的物体表面,除了贴上一般纹理之外,往往还使用Bump mapping(凹凸纹理)技术.Bump mapping并没有增加物体的几何复杂度,它只是在计算物体的光照效果时作了“弊”,不使用物体本身的法向量,而是使

Cesium官方教程8-- 几何体和外观效果

原文地址:https://cesiumjs.org/tutorials/Geometry-and-Appearances/几何体和外观效果(Geometry and Appearances)这篇教程会教大家学习Primitive API中支持的几何体和外观效果.这篇教程并不是面向Cesium的普通用户,主要讨论Cesium的高级知识,包括自定义三角网(mesh),形状(shape),体(volume)以及他们的外观.如果你是初学者,建议先学下这篇教程.Cesium可以使用Entity创建不同的几

DIV样式汇总

DIV样式汇总 最近在学习JavaScript,在做到个要控制控件样式的例子时,突然有了把常用样式汇总一下的想法,于是乎就写了以下内容,以下是以div为例来汇总的,希望对大家有些帮助. 一.常用属性: 1.Height:设置DIV的高度. 2.Width:设置DIV的宽度. 例: <div style="width:200px;height:200px;"></div> 3.margin:用于设置DIV的外延边距,也就是到父容器的距离. 例: Code 说明:m

unity常见问题之20题

1:天空盒有接缝怎么解决? 答:在贴图导入设置里设置Wrap Mode为"Clamp". 2: DDS格式怎么不显示? 答:Unity不支持DDS格式,Unity会将除DDS外的其它格式图片具有为DDS相同的优化. 3:Unity怎样动态加载外部模型等文件? 答:能够使用AssetBundle:http://unity3d.com/support/docum ... ce/AssetBundle.html 4:脚本编辑器有语法提示吗? 答:有的,Win版使用Ctrl+I,Mac版使用C

cocos2dx[3.2](14)——新字体标签Label

[唠叨] 在3.x中,废弃了2.x里的LabelTTF.LabelAtlas.LabelBMFont三个字体类,取而代之的是全新的字体标签Label. 实际上Label是将三个字体类进行了融合,进行统一的管理与渲染,这使得创建字体标签Label的方式更加统一,更加方便. 本节来学习一下3.x中新的标签类Label,如果对2.x中的三个字体类不了解的话,建议先去看看那三个类的用法,再来学习本节内容,能够更好的理解. 2.x中的旧标签类,请移步:http://shahdza.blog.51cto.c

Unity Shader-后处理:Bloom全屏泛光

一.简介 今天来学习一下Bloom效果,Bloom效果有时候也叫Glow效果,中文一般叫做"全屏泛光",这是一种可以模拟出HDR的全屏后处理效果,但是实现原理与HDR相差很远,效果比HDR差一些,但是比HDR的性能要节省很多. 二.原理介绍 这里不得不提一下传说中的HDR,从接触引擎开始,就一群大牛们经常讨论到这个词,然而作为一个新手,一直对这个传说中的技术抱着"敬畏"的态度,不过如今逐渐熟悉了一些渲染相关的东西,贱贱地,也没有那么害怕这个技术了.今天就来学习一下H

TextView 高级教程

前言 光看题目,估计有人已经忍不住吐槽了:尼玛,TextView 这么简单的控件,还有什么高级用法吗?放在以前,我也会这么想,但是随着开发经验的积累,我愈发觉得 TextView 简直就是一座宝藏,里面有很多宝贝值得研究. 本文基于 @Chiuki 的讲座,并结合我自己的经验整理而成. 视频地址:Youtube 讲稿地址:Github 部分 demo 对应的代码地址:Github 文章中的大部分图片和代码均摘自讲稿,感谢原作者的分享. Compound Drawable 如下图1中的效果,我们可

使用GLSL实现的海洋效果 【转】

http://bbs.osgchina.org/viewthread.php?tid=342&extra=page%3D3 虽说自己原创的部分并不算多,不过总算是调试通过了,中间有多次严重的死机……估计该换新显卡了~~不过最后的效果还蛮不错? 实现海洋平面的GLSL源代码来自:http://emiug.alanabram.co.uk,感觉他的代码比Bonzai公司的要简单些(后者需要水面纹理的反射/散射/法线/深度/Dudv贴图,3DVRI实现的水面效果好像也与之类似).不过我个人还是GLSL的