zoukankan      html  css  js  c++  java
  • GLSL实现Glow效果 【转】

    http://blog.csdn.net/a3070173/article/details/3220940

      1.  Glow即辉光效果现在已成为3D图形中一个引人注目的特效.本文主要介绍如何使用GLSL实现一个典型的GLow效果.
      2.  实现步骤:1.渲染整个场景到一个祯缓冲区中
      3.     2.将场景中需要进行GLow处理的物体绘制第二个FBO纹理A中
      4.     3.在FBO纹理A和B之间进行横和纵"高斯"过滤
      5.     4.将进行过GLow处理后的FBO纹理A与祯缓冲区中的场景图像以glBlendFunc(GL_ONE, GL_ONE)方式进行混合处理
      6.    
      7.  GLSL文件功能简介:
      8.  FullScreen.vert - 用于绘制覆盖整个视口的四边形以进行Glow效果的高斯过滤
      9.  Filter.frag - 用于横和纵的高斯过滤
      10.  Blend.frag - 用于处理过的GLowFBO纹理与原始场景图像进行混合
      11.  为了直接进行生成Glow效果的介绍,这里假设程序已正确处理了OpenGL和GLSL的初始化.
      12. void RenderOrigionalScene()
      13. {
      14.  if (g_bUseFillRender)
      15.  {
      16.   glPolygonMode(GL_FRONT, GL_FILL);
      17.  }
      18.  else
      19.  {
      20.   glPolygonMode(GL_FRONT, GL_LINE);
      21.  }
      22.  RenderObject();
      23. }
      24.  首先让我们绘制原始场景,由于本Demo未绘制除辉光物体外的其它事物,所以此处就直接绘制为进行具有辉光效果的物体.
      25. void RenderGlowObject()
      26. {
      27.  // 设置视口
      28.  glViewport(0, 0, g_uiTextureWidth, g_uiTextureHeight);
      29.  // 将原始场景绘制到第二个FBO
      30.  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_uiFboColorOne);
      31.  // 清除第一个FBO颜色和深度缓存
      32.  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      33.  // 绘制辉光物体
      34.  RenderObject();
      35. }
      36.  然后设置绘制目标到FBO纹理A并将欲进行Glow处理的物体绘制到上面来,这里需要注意的是必须根据FBO纹理的尺寸设置一个
      37.  视口使其跟FBO纹理一样大,以使物体能够准确地映射到整个FBO纹理上.清除FBO颜色缓冲区和绘制深度缓冲区是必要的,因为
      38.  每次绘制到FBO纹理中的图像都不一样.
      39. void FilterGlowObject()
      40. {
      41.  glPolygonMode(GL_FRONT, GL_FILL);
      42.  // 将水平过滤后的图像绘制第二个FBO
      43.  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_uiFboColorTwo);
      44.  // 清除第二个FBO颜色
      45.  glClear(GL_COLOR_BUFFER_BIT);
      46.  // 重新设置片元着色器
      47.  glUseProgram(g_ProgramObjectOne);
      48.  // 设置水平过滤标志
      49.  GLint iUniformIndex = glGetUniformLocation(g_ProgramObjectOne, "g_bFiterMode");
      50.  glUniform1i(iUniformIndex, 1);
      51.  // 设置纹理
      52.  glBindTexture(GL_TEXTURE_2D, g_uiIDOne);
      53.  // 绘制
      54.  RenderFullScreen();
      55.  // 将竖直过滤后的图像绘制第一个FBO
      56.  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_uiFboColorOne);
      57.  // 清除第一个FBO颜色和深度缓存
      58.  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      59.  // 设置竖直过滤标志
      60.  iUniformIndex = glGetUniformLocation(g_ProgramObjectOne, "g_bFiterMode");
      61.  glUniform1i(iUniformIndex, 0);
      62.  // 设置纹理
      63.  glBindTexture(GL_TEXTURE_2D, g_uiIDTwo);
      64.  // 绘制
      65.  RenderFullScreen();
      66. }
      67.  下面到Glow效果处理的重头戏,是否能生成完美的辉光效果关键就在于此步的处理.但其实也很简单,主要就是为Filter着色器设
      68.  置进行合适横,纵两次过滤的标志和绘制目标,然后绘制全视口四边形,剩下的过滤工作则由GLSL的高斯过滤着色器全权负责.
      69. void RenderToScreen()
      70. {
      71.  // 恢复视口
      72.  glViewport(0, 0, g_uiCurrentWindowWidth, g_uiCurrentWindowHeight);
      73.  // 恢复绘制目标为祯缓冲区
      74.  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, NULL);
      75.  // 启动混合
      76.  glEnable(GL_BLEND);
      77.  glBlendFunc(GL_ONE, GL_ONE);
      78.  // 绑定纹理
      79.  glBindTexture(GL_TEXTURE_2D, g_uiIDOne);
      80.  // 重新设置片元着色器
      81.  glUseProgram(g_ProgramObjectTwo);
      82.  // 绘制
      83.  RenderFullScreen();
      84.  // 恢复固定功能管线
      85.  glUseProgram(0);
      86.  // 关闭混合
      87.  glDisable(GL_BLEND);
      88. }
      89.  最后一步无非就是将过滤好的Glow纹理与原始场景图像进行混合,当然使用OpenGL固定功能管线或GLSL都可以轻易实现,但首先必
      90.  须把视口设置回原来的状态.
      91.  以下是高斯过滤的GLSL着色器代码,粘贴于此以方便读者查阅.
      92.  顶点着色器:
      93. void main()
      94. {
      95.  gl_TexCoord[0] = gl_MultiTexCoord0;
      96.     gl_Position = gl_Vertex;
      97. }
      98.  高斯过滤着色器:
      99. const int g_iFilterTime = 9; // 过滤次数
      100. 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))); // 衰减因子
      101. uniform sampler2D g_Decal;
      102. uniform bool g_bFiterMode;
      103. uniform float g_fGlowGene;
      104. uniform vec2 g_vec2HorizontalDir; // 水平过滤方向
      105. uniform vec2 g_vec2VerticalDir;  // 竖直过滤方向
      106. uniform float g_fFilterOffset; // 过滤偏移
      107. void main()
      108. {
      109.  float aryAttenuation[g_iFilterTime];
      110.  aryAttenuation[0] = 0.93;
      111.  aryAttenuation[1] = 0.8;
      112.  aryAttenuation[2] = 0.7;
      113.  aryAttenuation[3] = 0.6;
      114.  aryAttenuation[4] = 0.5;
      115.  aryAttenuation[5] = 0.4;
      116.  aryAttenuation[6] = 0.3;
      117.  aryAttenuation[7] = 0.2;
      118.  aryAttenuation[8] = 0.1;
      119.  // 采样原始颜色
      120.  vec2 vec2Tex0 = gl_TexCoord[0].st;
      121.  vec4 vec4Color = texture2D(g_Decal, vec2Tex0)*g_fGene;
      122.  // 计算过滤方向
      123.  vec2 vec2FilterDir = g_vec2HorizontalDir + vec2(g_fFilterOffset, 0.0); // 水平过滤
      124.  if (!g_bFiterMode)
      125.  {
      126.   vec2FilterDir = g_vec2VerticalDir + vec2(0.0, g_fFilterOffset); // 竖直过滤
      127.  }
      128.  // 进行过滤
      129.  vec2 vec2Step = vec2FilterDir;
      130.  for(int i = 0; i< g_iFilterTime; ++i)
      131.  {
      132.   vec4Color += texture2D(g_Decal, vec2Tex0 + vec2Step)*aryAttenuation[i]*g_fGene;
      133.   vec4Color += texture2D(g_Decal, vec2Tex0 - vec2Step)*aryAttenuation[i]*g_fGene;
      134.   vec2Step += vec2FilterDir;
      135.  }
      136.  if (g_bFiterMode)
      137.  {
      138.   gl_FragColor = vec4Color*g_fGlowGene;
      139.  }
      140.  else
      141.  {
      142.   gl_FragColor = vec4Color;
      143.  }
      144. }
      145.  混合着色器:
      146. uniform sampler2D g_Decal;
      147. void main()
      148. {
      149.  gl_FragColor = texture2D(g_Decal, gl_TexCoord[0].st);
      150. }
      151. Demo效果图:

    1. 参考资料:Nvidia OpenGL SDK 10.5 Simple Glow
    2. exe文件:http://www.fileupyours.com/view/219112/GLSL/Glow%20Demo.rar
  • 相关阅读:
    POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)
    UVaLive 5031 Graph and Queries (Treap)
    Uva 11996 Jewel Magic (Splay)
    HYSBZ
    POJ 3580 SuperMemo (Splay 区间更新、翻转、循环右移,插入,删除,查询)
    HDU 1890 Robotic Sort (Splay 区间翻转)
    【转】ACM中java的使用
    HDU 4267 A Simple Problem with Integers (树状数组)
    POJ 1195 Mobile phones (二维树状数组)
    HDU 4417 Super Mario (树状数组/线段树)
  • 原文地址:https://www.cnblogs.com/mazhenyu/p/6472111.html
Copyright © 2011-2022 走看看