翻译:GLSL的顶点位移贴图

翻译自: Vertex Displacement Mapping using GLSL

  • 译者: FreeBlues

说明: 之所以选择这篇文档, 是因为现在但凡提到位移贴图(Displacement Mapping), 都要求设备支持镶嵌细分(tessellates), 但是目前大多数的移动设备都不支持这个特性, 而本文的年代比较久远(2006~2008), 那时的设备更不可能支持镶嵌细分了, 说明位移贴图并非必需镶嵌细分这个特性, 也意味着本文的实现方法可以在大多数设备上运行.

介绍

顶点位移贴图(Vertex Displacement Mapping)或者简单点儿位移贴图(Displacement Mapping) 是一种技术, 它允许用一个纹理贴图(位移图-displacement map)对一个多边形网格(mesh)进行变形, 以便增加表面细节. 它的原理并不新鲜. 它甚至是一些地形生成算法的基础(请参考 Terrain Generator GLUT 项目). 新鲜的是使用 GPU 来实现实时网格变形.

  • 2006.11.5 更新

位移贴图需要显卡允许在顶点着色器中访问至少一个纹理贴图单元. 在顶点着色器中访问纹理贴图被称为 顶点纹理存取(Vertex Texture Fetching). 着色器模型 3.0 强制实现在顶点着色器内至少有 4 个纹理单元能被访问. 现在, 只有基于 nVidiaGeforce 6, Geforce 7 以及更高版本支持 顶点纹理存取. ATI 显卡不支持 顶点纹理存取, 甚至连最新的高端型号比如 X1950XTX 也不支持(更多解释请看这里 ATI X1900XTX and VTF)

  • 2006.11.22 更新

看起来 Forceware 显卡驱动 91.xx91.xx 有点问题. 老一点的驱动 (84.xx) 或者最新的 (96.xx) 都能正确地工作(这篇文章中有更多细节)

  • 2008.9.30 更新

顶点纹理存取 现在在 radeon 也可用了: ATI Catalyst 8.10 Fixes the Displacement Mapping Bug in OpenGL @ Geeks3D.

GPU Caps Viewer 工具允许你快速知道在顶点着色器中可访问纹理单元数:

截图:

这个信息能通过 OpenGL 的常量 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 获得.

下面的截图展示了对本教程使用项目的渲染. 我们将会使用 Demoniak3D 平台以便快速编写位移贴图示例.

例程截图:

不同的例程使用了 GLSL (OpenGL Shading Language) 进行着色器编程.

位移原理

用于变形的基本元素是从位移图中查询到的向量. 这个向量通常要么保存一个 RGBA 的颜色, 要么保存一个标量颜色(用灰度表示的高度图). 我们将会使用这个向量以及更精确的它的一些部件的总额, 作为一个因子, 用来改变顶点的位置. 最常见的一种方法是按前一个因子的比例沿着顶点的法线移动顶点的位置.

截图:

上图可以总结为如下的关系:

  1. P1 = P0 + (N * df * uf)
  • P0 是顶点原始的位置
  • P1 是位移之后的顶点位置
  • N 是顶点的法线向量
  • df 是被规范化的位移因子(如 [0.0; 1.0])
  • uf 是一个用户选择的缩放因子

df 能从下面的关系中获得, 它把一个 RGB 值转换成一个灰度值:

  1. df = 0.30*dv.x + 0.59*dv.y + 0.11*dv.z

dv 就是当前被处理的顶点从位移图中获取的向量.

现在理论已经齐备, 只欠实践了...

位移顶点着色器

一旦所需的良好的工作条件准备妥当, 顶点着色器是相当简单的. 就像任何一种世界上的 3D 显卡的技术发展一样, 顶点位移贴图 有一些少许的限制, 如果它们不在考虑在内,将会把你的 Ultra-Boosted 7800 GTX 变成一个古老的 S3 trio (你还记得......).

为了完成 顶点位移贴图, 这里有两个主要限制:

  • 位移图必须是浮点格式. 在 OpenGL 的条款中, 它意味着内部像素格式被设置为GL_RGBA_FLOAT32_ATI (ATInVidia 都能用).
  • 位移图必须不能被过滤: 没有线性(linear)或三线性(trilinear)过滤, Nearest 模式是唯一被接受的.

因此一旦位移图被以 nearest 模式过滤的浮点格式加载, 位移贴图实际上变得简单了, 如下面的顶点/像素着色器:

  1. [Vertex_Shader]
  2. uniform sampler2D displacementMap;
  3. void main(void)
  4. {
  5. vec4 newVertexPos;
  6. vec4 dv;
  7. float df;
  8. gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
  9. dv = texture2D( displacementMap, gl_MultiTexCoord0.xy );
  10. df = 0.30*dv.x + 0.59*dv.y + 0.11*dv.z;
  11. newVertexPos = vec4(gl_Normal * df * 100.0, 0.0) + gl_Vertex;
  12. gl_Position = gl_ModelViewProjectionMatrix * newVertexPos;
  13. }
  14. [Pixel_Shader]
  15. uniform sampler2D colorMap;
  16. void main(void)
  17. {
  18. gl_FragColor = texture2D(colorMap, gl_TexCoord[0].xy);
  19. }

在顶点着色器中获取位移图跟我们在像素着色器中获取纹理贴图一样: 使用 GLSLtexture2D() 函数.

Demoniak3D 的示例展示了一个 80000 个多边形网格用一个简单 BMP 图像的变形:

截图:

nearest 过滤模式是今天硬件的顶点着色器里唯一可用的模式. 但是没有什么能够阻止我们实现我们自己的 bilinear 过滤模式. 这里是这个函数(改编自 nVidiaCg 代码)做了这个工作:

  1. #define textureSize 256.0
  2. #define texelSize 1.0 / 256.0
  3. vec4 texture2D_bilinear( uniform sampler2D tex, vec2 uv )
  4. {
  5. vec2 f = fract( uv.xy * textureSize );
  6. vec4 t00 = texture2D( tex, uv );
  7. vec4 t10 = texture2D( tex, uv + vec2( texelSize, 0.0 ));
  8. vec4 tA = mix( t00, t10, f.x );
  9. vec4 t01 = texture2D( tex, uv + vec2( 0.0, texelSize ) );
  10. vec4 t11 = texture2D( tex, uv + vec2( texelSize, texelSize ) );
  11. vec4 tB = mix( t01, t11, f.x );
  12. return mix( tA, tB, f.y );
  13. }

这个函数的使用很简单, 只要把 texture2D() 替换成 texture2D_bilinear() 就行了:

  1. dv = texture2D_bilinear( displacementMap, gl_MultiTexCoord0.xy );

这段代码在顶点着色器和像素着色器里都运行得很好.

法线的问题

顶点位移贴图 最大的一个缺点是面对法线的顶点被破坏了因为对于未变形网格来说它们是有效的. 因为我们在一个顶点着色器中, 我们不能访问其他两个来自当前被处理的面的顶点, 然后我们无法重新计算法线.

不过有两种方式来解决这个棘手的问题: 第一个就是简单地不使用......法线! 使用静态光线(就像光线贴图-lightmapping), 法线就没用了, 因为光线来自光线图-light-map.

第二个方法是为像素着色器提供法线. 一个简单的方法是从位移图创建一个法线图. 法线图保存法线向量, 被指向模拟位移图的起伏. 这个技巧工作得非常好, 如果我们忘掉一些小缺点, 比如一些区域不应该被照亮.

下面这幅图展示了一个 凹凸位移贴图(BumpDisplacementMapping) 着色器的结果. 位移图和法线图都被根据基本图(石头的纹理贴图)创建了. 这个项目也可以在下载存档中可用.

截图:

结论

顶点位移贴图 能被用于创造很酷的效果并且允许发挥顶点处理器的威力, 它常常被遗忘于像素处理器的好处. 然而, 我们必须考虑到一些限制, 比如完成顶点纹理存取的硬件能力(ATI/RadeonGPU 不支持 顶点位移映射 ),法线的问题变成错误, 甚至不可能像 shadow-volumes 一样使用一些算法 (或者是你的 3D 引擎的一部分),因为这些算法处理的顶点存储在系统内存中, 而不是存储在 GPU 的图形内存中......

记着这些约束, 顶点位移贴图 允许实现, 例如,极其逼真的水呈现模拟(见更多资源部分中的链接)或甚至互动顶点位移, 如下示例所示: 顶点位移是由一个 AVI 视频控制 (视频来源于 K-Meleon web 浏览器目录)

截图:

更多资源

nVidia - Vertex Texture Fetch

Using Vertex Texture Displacement for Realistic Water Rendering

OpenGL Setup for GLSL

例程下载

例程下载: 例程

例程代码需要 Demoniak3D 才能正常运行.

Demoniak3D 可以从这里下载: Demoniak3D Demo-System.

附录:教程提供的完整例程代码

完整例程中给出了详细的参数设置和如何使用那些图像资源作为纹理, 只要稍微修改一下就可以在我们自己的 OpenGL ES 框架下直接使用.

顶点位移贴图例程

  1. <?xml version="1.0" encoding="Windows-1252" standalone="yes"?>
  2. <!--
  3. ==============================================================================
  4. AUTHOR: JeGX - jegx@ozone3d.net
  5. DATE: 10.03.2006
  6. PURPOSE: Vertex Displacement Mapping Demo.
  7. TUTORIAL: http://www.ozone3d.net/tutorials/vertex_displacement_mapping.php
  8. ====================================
  9. \==:: http://www.oZone3D.Net ::==/
  10. ===============================
  11. ==============================================================================
  12. -->
  13. <hyperion version_major="1" version_minor="2" >
  14. <!--
  15. The Scene!
  16. -->
  17. <scene name="displacement_mapping_demo"
  18. display_fps="TRUE"
  19. show_ref_grid="TRUE"
  20. vsync="TRUE" >
  21. <infos_color r="1.0" g="1.0" b="1.0" />
  22. <window_size width="1024" height="768" />
  23. <background_color r="0.3" g="0.0" b="0.0" />
  24. <background_image image="data/stars.gif" />
  25. <!--
  26. Check the GLSL support and the number of vertex shader texture units we need in this demo.
  27. -->
  28. <check_hardware_caps glsl="TRUE" vs_tex_samplers="1"
  29. error_message="Sorry, this demo requires a Shader Model 3.0 (for vertex texture fetching) complient graphics controller. Demo startup failed. Bye..." />
  30. </scene>
  31. <!--
  32. Setup an EXAMINE camera.
  33. -->
  34. <camera name="myCamera" fov="60.0" navigation_mode="EXAMINE" >
  35. <position x="-143.41" y="218.55" z="241.49" />
  36. <orientation pitch="30.0" yaw="120.0" />
  37. </camera>
  38. <!--
  39. The base map (or color map)
  40. -->
  41. <texture name="colorMap" filename="data/supernova.bmp" pixel_format="RGB" />
  42. <!--
  43. The displacement map.
  44. Note the RGBA_32F pixel format and the filtering mode (NONE==nearest).
  45. This is mandatory for vertex texture fetching on today's hardware.
  46. -->
  47. <texture name="displacementMap"
  48. filename="data/supernova.bmp"
  49. pixel_format="RGBA_32F" filtering_mode="NONE"
  50. num_mipmaps="0" />
  51. <!--
  52. The mesh plane's material. We have to create it in order to attach the displacement shader.
  53. -->
  54. <material name="plane_mat" shader_program_name="displacementShader" />
  55. <!--
  56. The mesh plane: 200*200*2 = 80000 polys.
  57. In order to get decent frame rate, do not forget to set the VBO state...
  58. -->
  59. <mesh render="TRUE" name="mesh_plane" shape_type="PLANE" texturing="TRUE" lighting="FALSE"
  60. polygon_mode="SOLID" use_vbo="TRUE" back_face_culling="FALSE" >
  61. <plane x_size="400.0" z_size="400.0" num_segs_x="200" num_segs_z="200" />
  62. <position x="0.0" y="0.0" z="0.0" />
  63. <orientation pitch="0.0" />
  64. <attach_material name="plane_mat" />
  65. <!--
  66. The displacement map on texture unit 0.
  67. -->
  68. <texture texture_name="displacementMap"
  69. material_name="plane_mat"
  70. texture_unit="0"
  71. u_tile="1.0" v_tile="1.0" />
  72. <!--
  73. The color map on texture unit 1.
  74. -->
  75. <texture texture_name="colorMap"
  76. material_name="plane_mat"
  77. texture_unit="1"
  78. u_tile="1.0" v_tile="1.0" />
  79. </mesh>
  80. <!--
  81. The displacement shader.
  82. -->
  83. <shader_program name="displacementShader" >
  84. <constant_1i name="displacementMap" value="0" />
  85. <constant_1i name="colorMap" value="1" />
  86. <raw_data><![CDATA[
  87. [Vertex_Shader]
  88. uniform float time;
  89. uniform sampler2D displacementMap;
  90. #define textureSize 256.0
  91. #define texelSize 1.0 / 256.0
  92. vec4 tex2D_bilinear( uniform sampler2D tex, vec2 t )
  93. {
  94. vec2 f = fract( t.xy * textureSize );
  95. vec4 t00 = texture2D( tex, t );
  96. vec4 t10 = texture2D( tex, t + vec2( texelSize, 0.0 ));
  97. vec4 tA = mix( t00, t10, f.x );
  98. vec4 t01 = texture2D( tex, t + vec2( 0.0, texelSize ) );
  99. vec4 t11 = texture2D( tex, t + vec2( texelSize, texelSize ) );
  100. vec4 tB = mix( t01, t11, f.x );
  101. return mix( tA, tB, f.y );
  102. }
  103. void main(void)
  104. {
  105. vec4 newVertexPos;
  106. vec4 dv;
  107. float df;
  108. gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
  109. dv = tex2D_bilinear( displacementMap, gl_MultiTexCoord0.xy );
  110. //dv = texture2D( displacementMap, gl_MultiTexCoord0.xy );
  111. df = 0.30*dv.x + 0.59*dv.y + 0.11*dv.z;
  112. newVertexPos = vec4(gl_Normal * df * 100.0, 0.0) + gl_Vertex;
  113. gl_Position = gl_ModelViewProjectionMatrix * newVertexPos;
  114. }
  115. [Pixel_Shader]
  116. uniform sampler2D colorMap;
  117. void main(void)
  118. {
  119. gl_FragColor = texture2D(colorMap, gl_TexCoord[0].xy);
  120. }
  121. ]]></raw_data>
  122. </shader_program>
  123. <!--
  124. A little bit of interactivity: swap the mesh plane polygon rendering mode.
  125. -->
  126. <script name="switch_polygon_mode" run_mode="ASYNCHRONOUS" >
  127. <raw_data><![CDATA[
  128. if( g_mode==NIL ) then
  129. g_mode=0;
  130. end
  131. WIREFRAME = 1;
  132. SOLID = 2;
  133. if( g_mode==1 ) then
  134. HYP_Object.SetPolygonMode( "mesh_plane", SOLID );
  135. g_mode=0;
  136. else
  137. HYP_Object.SetPolygonMode( "mesh_plane", WIREFRAME );
  138. g_mode=1;
  139. end
  140. ]]></raw_data>
  141. </script>
  142. <hotkey name="space_key" script="switch_polygon_mode" key="KEY_SPACE" />
  143. <!--
  144. The white rectangle under the supernova hud.
  145. -->
  146. <hud name="under_nova" texturing="FALSE" >
  147. <size width="220" height="220" />
  148. <position x="380" y="250" />
  149. </hud>
  150. <!--
  151. The hud that displays the small supernova image.
  152. -->
  153. <hud name="nova" >
  154. <texture texture_name="colorMap" texture_unit="0" />
  155. <size width="200" height="200" />
  156. <position x="380" y="250" />
  157. </hud>
  158. <!--
  159. Display some information / commands
  160. -->
  161. <font name="myFontArial12" render="TRUE" ttf_name="Arial" size="14" >
  162. <text_2d>
  163. <color r="1.0" g="1.0" b="0.0" />
  164. <position x="10" y="30" />
  165. <text text="Vertex Displacement Mapping Demo" />
  166. </text_2d>
  167. <text_2d>
  168. <color r="1.0" g="1.0" b="0.0" />
  169. <position x="10" y="50" />
  170. <text text="Controls:" />
  171. </text_2d>
  172. <text_2d>
  173. <color r="1.0" g="1.0" b="0.0" />
  174. <position x="20" y="70" />
  175. <text text="> SPACE: switch polygon mode (WIREFRAME/SOLID)" />
  176. </text_2d>
  177. </font>
  178. </hyperion>

位移贴图+凹凸贴图

  1. <?xml version="1.0" encoding="Windows-1252" standalone="yes"?>
  2. <!--
  3. ==============================================================================
  4. AUTHOR: JeGX - jegx@ozone3d.net
  5. DATE: 10.03.2006
  6. PURPOSE: Vertex Displacement Mapping Demo.
  7. TUTORIAL: http://www.ozone3d.net/tutorials/vertex_displacement_mapping.php
  8. ====================================
  9. \==:: http://www.oZone3D.Net ::==/
  10. ===============================
  11. ==============================================================================
  12. -->
  13. <hyperion version_major="1" version_minor="2" >
  14. <!--
  15. The Scene!
  16. -->
  17. <scene name="displacement_mapping_demo"
  18. display_fps="TRUE"
  19. show_ref_grid="TRUE"
  20. vsync="TRUE" >
  21. <infos_color r="1.0" g="1.0" b="1.0" />
  22. <window_size width="1024" height="768" />
  23. <background_color r="0.3" g="0.0" b="0.0" />
  24. <!--
  25. Check the GLSL support and the number of vertex shader texture units we need in this demo.
  26. -->
  27. <check_hardware_caps glsl="TRUE" vs_tex_samplers="1"
  28. error_message="Sorry, this demo requires a Shader Model 3.0 (for vertex texture fetching) complient graphics controller. Demo startup failed. Bye..." />
  29. </scene>
  30. <!--
  31. Setup an EXAMINE camera.
  32. -->
  33. <camera name="myCamera" fov="60.0" navigation_mode="EXAMINE" >
  34. <position x="-143.41" y="218.55" z="241.49" />
  35. <orientation pitch="30.0" yaw="120.0" />
  36. </camera>
  37. <light name="myLight" render="TRUE" type="OMNI" >
  38. <position x="10.0" y="100.0" z="45.0" />
  39. <ambient r="0.4" g="0.4" b="0.4" />
  40. <diffuse r="0.9" g="0.9" b="0.9" />
  41. <specular r="0.9" g="0.9" b="0.9" />
  42. </light>
  43. <!--
  44. The base map (or color map)
  45. -->
  46. <texture name="colorMap" filename="data/wall002_512x512.jpg" />
  47. <!--
  48. The displacement map.
  49. Note the RGBA_32F pixel format and the filtering mode (NONE==nearest).
  50. This is mandatory for vertex texture fetching on today's hardware.
  51. -->
  52. <texture name="displacementMap"
  53. filename="data/wall002_hmap2_512x512.jpg"
  54. pixel_format="RGBA_32F" filtering_mode="NONE"
  55. num_mipmaps="0" />
  56. <!--
  57. The normal map (or bump map)
  58. -->
  59. <texture name="normalMap"
  60. filename="data/wall002_nmap2_512x512.jpg" />
  61. <!--
  62. The mesh plane's material. We have to create it in order to attach the displacement shader.
  63. -->
  64. <material name="plane_mat" shader_program_name="displaceBumpMappingShader" >
  65. <ambient r="0.6" g="0.6" b="0.6" />
  66. <diffuse r="0.9" g="0.9" b="0.9" />
  67. <specular r="0.6" g="0.6" b="0.6" />
  68. </material>
  69. <!--
  70. The mesh plane: 200*200*2 = 80000 polys.
  71. In order to get decent frame rate, do not forget to set the VBO state...
  72. -->
  73. <mesh render="TRUE" name="mesh_plane" shape_type="PLANE" texturing="TRUE" lighting="FALSE"
  74. polygon_mode="SOLID" use_vbo="TRUE" back_face_culling="TRUE" >
  75. <plane x_size="400.0" z_size="400.0" num_segs_x="200" num_segs_z="200" />
  76. <position x="0.0" y="10.0" z="0.0" />
  77. <orientation pitch="0.0" />
  78. <attach_material name="plane_mat" />
  79. <!--
  80. The displacement map on texture unit 0.
  81. -->
  82. <texture texture_name="displacementMap"
  83. material_name="plane_mat"
  84. texture_unit="0"
  85. u_tile="1.0" v_tile="1.0" />
  86. <!--
  87. The normal map on texture unit 1.
  88. -->
  89. <texture texture_name="normalMap"
  90. material_name="plane_mat"
  91. texture_unit="1"
  92. u_tile="1.0" v_tile="1.0" />
  93. <!--
  94. The color map on texture unit 2.
  95. -->
  96. <texture texture_name="colorMap"
  97. material_name="plane_mat"
  98. texture_unit="2"
  99. u_tile="1.0" v_tile="1.0" />
  100. </mesh>
  101. <!--
  102. The displacement shader.
  103. -->
  104. <shader_program name="displaceBumpMappingShader" >
  105. <constant_1i name="displacementMap" value="0" />
  106. <constant_1i name="normalMap" value="1" />
  107. <constant_1i name="colorMap" value="2" />
  108. <vertex_attrib name="tangent" value="1" />
  109. <constant_1f name="invRadius" value="0.001" />
  110. <raw_data><![CDATA[
  111. [Vertex_Shader]
  112. varying vec3 lightVec;
  113. varying vec3 eyeVec;
  114. varying vec2 texCoord;
  115. attribute vec3 tangent;
  116. uniform sampler2D displacementMap;
  117. #define textureSize 1024.0
  118. #define texelSize 1.0 / 1024.0
  119. vec4 tex2D_bilinear( uniform sampler2D tex, vec2 t )
  120. {
  121. vec2 f = fract( t.xy * textureSize );
  122. vec4 t00 = texture2D( tex, t );
  123. vec4 t10 = texture2D( tex, t + vec2( texelSize, 0.0 ));
  124. vec4 tA = mix( t00, t10, f.x );
  125. vec4 t01 = texture2D( tex, t + vec2( 0.0, texelSize ) );
  126. vec4 t11 = texture2D( tex, t + vec2( texelSize, texelSize ) );
  127. vec4 tB = mix( t01, t11, f.x );
  128. return mix( tA, tB, f.y );
  129. }
  130. void main(void)
  131. {
  132. vec4 displacedVertexPos;
  133. vec4 displacementVec;
  134. float f;
  135. texCoord = gl_MultiTexCoord0.xy;
  136. displacementVec = tex2D_bilinear(displacementMap, gl_MultiTexCoord0.xy );
  137. //f = (0.30*displacementVec.x + 0.59*displacementVec.y + 0.11*displacementVec.z);
  138. f = displacementVec.x;
  139. displacedVertexPos = vec4(gl_Normal * f * 10.0, 0.0) + gl_Vertex;
  140. gl_Position = gl_ModelViewProjectionMatrix * displacedVertexPos;
  141. vec3 n = normalize(gl_NormalMatrix * gl_Normal);
  142. vec3 t = normalize(gl_NormalMatrix * tangent);
  143. vec3 b = cross(n, t);
  144. vec3 vVertex = vec3(gl_ModelViewMatrix * displacedVertexPos);
  145. vec3 tmpVec = gl_LightSource[0].position.xyz - vVertex;
  146. lightVec.x = dot(tmpVec, t);
  147. lightVec.y = dot(tmpVec, b);
  148. lightVec.z = dot(tmpVec, n);
  149. tmpVec = -vVertex;
  150. eyeVec.x = dot(tmpVec, t);
  151. eyeVec.y = dot(tmpVec, b);
  152. eyeVec.z = dot(tmpVec, n);
  153. }
  154. [Pixel_Shader]
  155. varying vec3 lightVec;
  156. varying vec3 eyeVec;
  157. varying vec2 texCoord;
  158. uniform sampler2D colorMap;
  159. uniform sampler2D normalMap;
  160. uniform float invRadius;
  161. void main (void)
  162. {
  163. float distSqr = dot(lightVec, lightVec);
  164. float att = clamp(1.0 - invRadius * sqrt(distSqr), 0.0, 1.0);
  165. vec3 lVec = lightVec * inversesqrt(distSqr);
  166. vec3 vVec = normalize(eyeVec);
  167. vec4 base = texture2D(colorMap, texCoord);
  168. vec3 bump = normalize(texture2D(normalMap, texCoord).xyz * 2.0 - 1.0);
  169. vec4 vAmbient = gl_LightSource[0].ambient * gl_FrontMaterial.ambient;
  170. vec4 final_color = vAmbient*base;
  171. float diffuse = dot(lVec, bump);
  172. if(diffuse>0.0)
  173. {
  174. vec4 vDiffuse = gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse * diffuse;
  175. float specular = pow(clamp(dot(reflect(-lVec, bump), vVec), 0.0, 1.0), gl_FrontMaterial.shininess );
  176. //float specular = 0.0;
  177. vec4 vSpecular = gl_LightSource[0].specular * gl_FrontMaterial.specular *specular;
  178. final_color += (vDiffuse*base + vSpecular) * att;
  179. }
  180. gl_FragColor = final_color;
  181. }
  182. ]]></raw_data>
  183. </shader_program>
  184. <!--
  185. A little bit of interactivity: swap the mesh plane polygon rendering mode.
  186. -->
  187. <script name="switch_polygon_mode" run_mode="ASYNCHRONOUS" >
  188. <raw_data><![CDATA[
  189. if( g_mode==NIL ) then
  190. g_mode=0;
  191. end
  192. WIREFRAME = 1;
  193. SOLID = 2;
  194. if( g_mode==1 ) then
  195. HYP_Object.SetPolygonMode( "mesh_plane", SOLID );
  196. g_mode=0;
  197. else
  198. HYP_Object.SetPolygonMode( "mesh_plane", WIREFRAME );
  199. g_mode=1;
  200. end
  201. ]]></raw_data>
  202. </script>
  203. <hotkey name="space_key" script="switch_polygon_mode" key="KEY_SPACE" />
  204. <!--
  205. Display some information / commands
  206. -->
  207. <font name="myFontArial12" render="TRUE" ttf_name="Arial" size="14" >
  208. <text_2d>
  209. <color r="1.0" g="1.0" b="0.0" />
  210. <position x="10" y="30" />
  211. <text text="Vertex Displacement Mapping Demo" />
  212. </text_2d>
  213. <text_2d>
  214. <color r="1.0" g="1.0" b="0.0" />
  215. <position x="10" y="50" />
  216. <text text="Controls:" />
  217. </text_2d>
  218. <text_2d>
  219. <color r="1.0" g="1.0" b="0.0" />
  220. <position x="20" y="70" />
  221. <text text="> SPACE: switch polygon mode (WIREFRAME/SOLID)" />
  222. </text_2d>
  223. </font>
  224. </hyperion>

位移贴图视频

  • 译者注: 这个功能可能只能在教程提供的 3D 演示平台上使用.
  1. <?xml version="1.0" encoding="Windows-1252" standalone="yes"?>
  2. <!--
  3. ==============================================================================
  4. AUTHOR: JeGX - jegx@ozone3d.net
  5. DATE: 10.03.2006
  6. PURPOSE: Vertex Displacement Mapping Demo.
  7. TUTORIAL: http://www.ozone3d.net/tutorials/vertex_displacement_mapping.php
  8. ====================================
  9. \==:: http://www.oZone3D.Net ::==/
  10. ===============================
  11. ==============================================================================
  12. -->
  13. <hyperion version_major="1" version_minor="2" >
  14. <!--
  15. The Scene!
  16. -->
  17. <scene name="displacement_mapping_demo"
  18. display_fps="TRUE"
  19. show_ref_grid="TRUE"
  20. vsync="TRUE" >
  21. <infos_color r="1.0" g="1.0" b="1.0" />
  22. <window_size width="1024" height="768" />
  23. <background_color r="0.3" g="0.0" b="0.0" />
  24. <background_image image="data/stars.gif" />
  25. <!--
  26. Check the GLSL support and the number of vertex shader texture units we need in this demo.
  27. -->
  28. <check_hardware_caps glsl="TRUE" vs_tex_samplers="1"
  29. error_message="Sorry, this demo requires a Shader Model 3.0 (for vertex texture fetching) complient graphics controller. Demo startup failed. Bye..." />
  30. </scene>
  31. <!--
  32. Setup an EXAMINE camera.
  33. -->
  34. <camera name="myCamera" fov="60.0" navigation_mode="EXAMINE" >
  35. <position x="-143.41" y="218.55" z="241.49" />
  36. <orientation pitch="30.0" yaw="120.0" />
  37. </camera>
  38. <!--
  39. The base map (or color map)
  40. -->
  41. <texture name="colorMap" filename="data/throbber.avi" pixel_format="RGB" >
  42. <size width="256" height="256" />
  43. </texture>
  44. <!--
  45. The displacement map.
  46. Note the RGBA_32F pixel format and the filtering mode (NONE==nearest).
  47. This is mandatory for vertex texture fetching on today's hardware.
  48. -->
  49. <texture name="displacementMap" type="TEXTURE_2D"
  50. filename="data/throbber.avi"
  51. pixel_format="RGBA_32F" filtering_mode="NONE" addressing_mode="CLAMP"
  52. num_mipmaps="0" >
  53. <size width="256" height="256" />
  54. </texture>
  55. <!--
  56. The mesh plane's material. We have to create it in order to attach the displacement shader.
  57. -->
  58. <material name="plane_mat" shader_program_name="displacementShader" />
  59. <!--
  60. The mesh plane: 100*100*2 = 20000 polys.
  61. In order to get decent frame rate, do not forget to set the VBO state...
  62. -->
  63. <mesh render="TRUE" name="mesh_plane" shape_type="PLANE" texturing="TRUE" lighting="FALSE"
  64. polygon_mode="SOLID" use_vbo="TRUE" back_face_culling="FALSE" >
  65. <plane x_size="400.0" z_size="400.0" num_segs_x="100" num_segs_z="100" />
  66. <position x="0.0" y="0.0" z="0.0" />
  67. <orientation pitch="0.0" />
  68. <attach_material name="plane_mat" />
  69. <!--
  70. The displacement map on texture unit 0.
  71. -->
  72. <texture texture_name="displacementMap"
  73. material_name="plane_mat"
  74. texture_unit="0"
  75. u_tile="1.0" v_tile="1.0" />
  76. <!--
  77. The color map on texture unit 1.
  78. -->
  79. <texture texture_name="colorMap"
  80. material_name="plane_mat"
  81. texture_unit="1"
  82. u_tile="1.0" v_tile="1.0" />
  83. </mesh>
  84. <!--
  85. The displacement shader.
  86. -->
  87. <shader_program name="displacementShader" >
  88. <constant_1i name="displacementMap" value="0" />
  89. <constant_1i name="colorMap" value="1" />
  90. <constant_1f name="time" value="0.0" />
  91. <raw_data><![CDATA[
  92. [Vertex_Shader]
  93. uniform sampler2D displacementMap;
  94. #define textureSize 256.0
  95. #define texelSize 1.0 / 256.0
  96. vec4 tex2D_bilinear( uniform sampler2D tex, vec2 t )
  97. {
  98. vec2 f = fract( t.xy * textureSize );
  99. vec4 t00 = texture2D( tex, t );
  100. vec4 t10 = texture2D( tex, t + vec2( texelSize, 0.0 ));
  101. vec4 tA = mix( t00, t10, f.x );
  102. vec4 t01 = texture2D( tex, t + vec2( 0.0, texelSize ) );
  103. vec4 t11 = texture2D( tex, t + vec2( texelSize, texelSize ) );
  104. vec4 tB = mix( t01, t11, f.x );
  105. return mix( tA, tB, f.y );
  106. }
  107. void main(void)
  108. {
  109. vec4 displacedVertexPos;
  110. vec4 displacementVec;
  111. float f;
  112. gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
  113. //displacementVec = texture2D(displacementMap, gl_MultiTexCoord1.xy);
  114. displacementVec = tex2D_bilinear(displacementMap, gl_MultiTexCoord1.xy);
  115. f = (0.30*displacementVec.x + 0.59*displacementVec.y + 0.11*displacementVec.z);
  116. displacedVertexPos = vec4(gl_Normal * f * 100.0, 0.0) + gl_Vertex;
  117. gl_Position = gl_ModelViewProjectionMatrix * displacedVertexPos;
  118. }
  119. [Pixel_Shader]
  120. uniform sampler2D colorMap;
  121. void main(void)
  122. {
  123. gl_FragColor = texture2D(colorMap, gl_TexCoord[0].xy);
  124. }
  125. ]]></raw_data>
  126. </shader_program>
  127. <!--
  128. Update time uniform variable for the displacement shader.
  129. -->
  130. <script name="update_scene" run_mode="EXECUTE_EACH_FRAME" >
  131. <raw_data><![CDATA[
  132. elapsed_time = HYP_GetElapsedTime() * 0.001;
  133. HYP_GPUShader.SetConstant_1f( "displacementShader", "time", elapsed_time );
  134. ]]></raw_data>
  135. </script>
  136. <!--
  137. A little bit of interactivity: swap the mesh plane polygon rendering mode.
  138. -->
  139. <script name="switch_polygon_mode" run_mode="ASYNCHRONOUS" >
  140. <raw_data><![CDATA[
  141. if( g_mode==NIL ) then
  142. g_mode=0;
  143. end
  144. WIREFRAME = 1;
  145. SOLID = 2;
  146. if( g_mode==1 ) then
  147. HYP_Object.SetPolygonMode( "mesh_plane", SOLID );
  148. g_mode=0;
  149. else
  150. HYP_Object.SetPolygonMode( "mesh_plane", WIREFRAME );
  151. g_mode=1;
  152. end
  153. ]]></raw_data>
  154. </script>
  155. <hotkey name="space_key" script="switch_polygon_mode" key="KEY_SPACE" />
  156. <!--
  157. The white rectangle under the hud.
  158. -->
  159. <hud name="under_nova" texturing="FALSE" >
  160. <size width="220" height="220" />
  161. <position x="380" y="250" />
  162. </hud>
  163. <!--
  164. The hud that displays the small image.
  165. -->
  166. <hud name="nova" >
  167. <texture texture_name="colorMap" texture_unit="0" />
  168. <size width="200" height="200" />
  169. <position x="380" y="250" />
  170. </hud>
  171. <!--
  172. Display some information / commands
  173. -->
  174. <font name="myFontArial12" render="TRUE" ttf_name="Arial" size="14" >
  175. <text_2d>
  176. <color r="1.0" g="1.0" b="0.0" />
  177. <position x="10" y="30" />
  178. <text text="Vertex Displacement Mapping Demo" />
  179. </text_2d>
  180. <text_2d>
  181. <color r="1.0" g="1.0" b="0.0" />
  182. <position x="10" y="50" />
  183. <text text="Controls:" />
  184. </text_2d>
  185. <text_2d>
  186. <color r="1.0" g="1.0" b="0.0" />
  187. <position x="20" y="70" />
  188. <text text="> SPACE: switch polygon mode (WIREFRAME/SOLID)" />
  189. </text_2d>
  190. </font>
  191. </hyperion>

翻译:GLSL的顶点位移贴图的更多相关文章

  1. [翻译]利用顶点位移的VR畸变校正

    文章英文原网址: http://www.gamasutra.com/blogs/BrianKehrer/20160125/264161/VR_Distortion_Correction_using_V ...

  2. 【ZZ】 DShader之位移贴图(Displacement Mapping)

    http://www.myexception.cn/other/1397638.html DShader之位移贴图(Displacement Mapping) www.MyException.Cn   ...

  3. DirectX11 With Windows SDK--34 位移贴图

    前言 在前面的章节中,我们学到了法线贴图和曲面细分.现在我们可以将这两者进行结合以改善效果,因为法线贴图仅仅只是改善了光照的细节,但它并没有从根本上改善几何体的细节.从某种意义上来说,法线贴图只是一个 ...

  4. 利用顶点位移进行VR畸变校正

    VR开发的最大挑战之一是对高帧率与高分辨率结合的要求.我们通过把顶点转化为“镜头空间”,删除了需要全屏渲染的纹理,这样就可以大规模提高手机性能. 下面的技术使用谷歌的Cardboard Unity S ...

  5. GLSL逐顶点光照[转]

    转载:http://blog.csdn.net/hgl868/article/details/7872350 引言 在OpenGL中有三种类型的光:方向光(directional).点光(point) ...

  6. firefox浏览器 插件--【维基百科+谷歌翻译】高级应用之 带图翻译

    [维基词典+谷歌翻译]插件地址: https://addons.mozilla.org/zh-CN/firefox/addon/google-dictionary-and-google-t/?src= ...

  7. java数据结构_附12_图、顶点和边的定义(双链存储)

    图--双链式存储结构 顶点 和 边 的定义 1.Vertex.java 2.Edge.java 3.AbstractGraph.java 1. public class Vertex {private ...

  8. 在 OpenGL ES 2.0 上实现视差贴图(Parallax Mapping)

    在 OpenGL ES 2.0 上实现视差贴图(Parallax Mapping) 视差贴图 最近一直在研究如何在我的 iPad 2(只支持 OpenGL ES 2.0, 不支持 3.0) 上实现 视 ...

  9. 翻译:探索GLSL-用几何着色器(着色器库)实现法线可视化

    翻译:探索GLSL-用几何着色器(着色器库)实现法线可视化 翻译自: Exploring GLSL – Normal Visualizer with Geometry Shaders (Shader ...

随机推荐

  1. 【Coursera】主成分分析

    一.问题 主方向的概念是什么?为什么降低维度的方法是使方差最大化? 假设某两个特征之间成线性关系,在二维平面上的表示就是数据点呈线性分布,那么可以通过将数据在主方向上进行投影,得到一个一维的数据,这个 ...

  2. 【Coursera】高斯混合模型

    一.高斯混合模型 软分类算法,即对每一个样本,计算其属于各个分布的概率,概率值最大的就是这个样本所属的分类. 对于训练样本的分布,看成为多个高斯分布加权得到的.其中每个高斯分布即为某一特定的类. 高斯 ...

  3. 电梯调度系统(界面由C图形库编绘)

    电梯调度系统编程 1.编程题目 电梯调度. 2.结对编程组员 黄冠译,刘畅. 3.编程语言 C语言图形库. 4.题目要求: 5.代码运行及结果调试: ① 运行界面为C++图形库支持,开始运行的初始界面 ...

  4. css border 制作三角形

    border 边框 上三角 是只有上面的border 有颜色,其余的边框都是tranparents,下三角只有下面的border 有颜色,其余的边框都是tranparents,左三角只有左面的bord ...

  5. 软工网络15团队作业8——Beta阶段敏捷冲刺(Day6)

    提供当天站立式会议照片一张 每个人的工作 1.讨论项目每个成员的昨天进展 赵铭: 数据库整理. 吴慧婷:我的世界界面完成部分. 陈敏: 我的世界功能--学习情况功能完成. 吴雅娟:我的世界功能--学习 ...

  6. 关于vue项目管理项目的架构管理平台

    关于vue项目管理项目的架构管理平台 https://panjiachen.github.io/vue-element-admin-site/#/zh-cn/faq 31.4k 次浏览 完整项目地址: ...

  7. CGOS 8 备用交换机(割点)

    题目链接:http://cojs.tk/cogs/problem/problem.php?pid=8 题意:n个城市之间有通讯网络,每个城市都有通讯交换机,直接或间接与其它城市连接.因电子设备容易损坏 ...

  8. Webpack简易入门教程

    <!-- 其实网上关于webpack的教程已经很多了,但是本人在学习过程中发现很多教程有错误,或者写的很不全面,结果做的过程出现各种各样的问题,对新手不但不友好还会让人浪费很多不必要的时间.所以 ...

  9. Make a Crystal UVA - 11014 (容斥定理)

    题意:给定一个NxNxN的正方体,求出最多能选几个整数点,使得任意两点PQ不会使PQO共线. 思路:利用容斥原理,设f(k)为点(x, y, z)三点都为k的倍数的点的个数(要扣掉一个原点O),那么所 ...

  10. SpringBoot之mongoTemplate的使用

    springboot的版本1.5.17.RELEASE. 1.mongo的IP和端口 在resources下的application.properties中加入如下内容 spring.data.mon ...