翻译者 周波 zhoubo22@hotmail.com
  版权所有 Philipp Gerasimov
   Randima (Randy) Fernando
   Simon Green
   NVIDIA Corporation
  仅以此文赠与Rita 19周岁生日快乐
  Shader Model 3.0:Using Vertex Textures SM3:使用顶点纹理
   随着GPU可编程特性的发展,Vertex Shader与Pixel Shader的差别越来越大。现在,Geforce6系列gpu将Vertex Shader与Pixel Shader之间的通用性特征向前发展了一大步。这篇文章特别介绍了Shader Model3的一项技术,Vertex Shader Fetch。它允许Vertex Shader像Pixel Shader一样从纹理中读取数据。
   在现代图形处理中,顶点处理的性能表现不是受制于内存带宽、cpu速度,就是受制于Pixel Shader的处理能力。但这也意味着你可以实现一个复杂的Vertex Shader,提高画质,而且不会有多大损失。Vertex Shader的制作成本比Pixel Shader高,所以在最新的6800芯片里,Vertex Shader的数目要少于Pixel Shader。这样,我们就可以安心地实现一打漂亮的效果,比如流体的模拟等等。
   这篇白皮书将同时向您展示如何在OPENGL以及DIRECTX中实现Vertex Texture。最后,我们将用一个游戏的范例向您演示使用Vertex Texture的情况。
   
  Specification详解
   DIRECTX与OPENGL中都可以使用Vertex Texture。
   DIRECTX9
   MS DX9SDK的开发文档中已经包括了VERTEX TEXTURE的详细说明。
   Vertex Shader3(即使用Vertex Shader3编译器生成的Shader)支持vertex_fetch,4种纹理样本。Vertex Texture,单从名称上看就同传统的PIXEL TEXTURE类似,但是同PIXEL TEXTURE比起来有一些差别,
   硬件无法直接支持Bilinear Trilinear过滤,但是您可以手动在Vertex Shader中实现
   反锯齿,内容同上。
   自动Mipmap LOD,无效
   D3DCAPS成员MaxVertexShader30InstructionSlots标识Vertex Shader3中代码的上限行数。MaxVShaderInstructionsExecuted标识了Vertex Shader的上限代码行数,包括Texture Fetch的数目。
   DIRECTX9支持软件Vertex Processing模式下使用Vertex Texture,这样甚至当硬件不支持Vertex Texture时也可以运行。
   6800支持使用D3DFMT_R32F and D3DFMT_A32B32G32R32F的纹理格式实现Vertex Texture。
  OPENGL
   顶点纹理查找通过NV_V_PROGRAM3扩展实现。详情请参阅http://www.nvidia.com/dev_content/nvopenglspecs/GL_NV_vertex_program3.txt
  这是标准ARB vertex program language的一项Option(操作)。这就意味着你可以调用现有的ARB API,载入程序,设置参数。在程序开头加入以下代码就可以了:
   OPTION NV_VERTEX_PROGRAM3
  在程序里加入Vertex Texture
   使用Vertex Texture的步骤如下:
   检查硬件的Vertex Texture支持情况
   创建Vertex Texture资源
   在Vertex Shader中加入需要的代码
   下面具体来看看怎样在DIRECTX以及OPENGL中实现。
   
  DIRECTX
  第一,检查硬件是否支持,否则将不得不用软件方式实现。调用IDirect3D9::CheckDeviceFormat里的D3DUSAGE_QUERY_VERTEXTEXTURE旗标查询硬件支持的Vertex Texture格式。Software Vertex Texture支持所有Vertex Texture格式。
  OPENGL
   OPENGL里只需要检查硬件是否支持NV_VERTEX_PROGRAM3扩展。GLUT库的glutExtensionSupported函数可以完成这项任务。Vertex Texture数目的上限用下列代码获得
   glGetIntegerv(MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &vtex_units)
   6系列GPU最大支持4个活动纹理(Active Texture)。你可以尽情的在Vertex Shader中调用它们,不过要注意Vertex Shader的代码行数。
   
  创建Vertex Texture资源
   DIRECTX9
   库中的任何纹理创建函数都可以创建顶点纹理,IDirect3D9::CreateTexture,
  IDirect3D9::CreateCubeTexture, IDirect3D9::CreateVolumeTexture等等。
   当使用SVP时,顶点纹理必须创建在D3DPOOL_SCRATCH池中。
   OPENGL
   基本纹理调用操作已经包括了Vertex Texture的绑定,使用GL_TEXTURE_2D。目前只有GL_LUMINANCE_FLOAT32_ATI 与 GL_RGBA_FLOAT32_ATI这2种格式支持Vertex Texture。这些格式都包含了1个或4个32bit浮点数据通道。注意,使用其他的纹理格式,或者使用不支持的过滤方式都可以导致驱动调用Software Vertex Processing处理,导致性能下降。
   示例代码如下:
   GLuint vertex_texture;
  glGenTextures(1, &vertex_texture);
  glBindTexture(GL_TEXTURE_2D, vertex_texture);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_FLOAT32_ATI, width, height, 0,GL_LUMINANCE, GL_FLOAT, data);
   
  在Vertex Shader里访问Vertex Texture
   DIRECTX9
  程序调用IDirect3DDevice9::SetTexture设置Vertex Texture,样本索引为D3DVERTEXTEXTURESAMPLER1到D3DVERTEXTEXTURESAMPLER3。在D3DPOOL_DEFAULT里创建的Vertex Texture同时也可以设置成PIXEL TEXTURE。
   Vertex Shader里的纹理样本必须使用DEL_SAMPLEType标识。
  // 汇编代码
  dcl_texcoord0 v0
  dcl_2D s0
  texldl r0, o0, s0
  // HLSL / Cg代码
  sampler2D tex;
  vDisplacement = tex2Dlod ( tex, t ); // t.w 包括MIPMAP LOD数据
  OPENGL
   VP的纹理查找功能通过TEX,TXB, TXL or TXP实现,就像在Fragment Shader里一样(或者在其他高等级语言中比如CG)。与Fragment Shader的差异是,纹理查找功能无法自动计算LOD。
   LOD的意义是确定纹理在屏幕上缩放的尺寸大小。一般根据纹理坐标象素的改变频率计算,但这里的麻烦是,Vertex Texture由顶点访问,硬件很难计算LOD值。所以你不得不自己在Vertex Processing里计算LOD。
   MIPMAP类似普通的Pixel Shader纹理,它可以为Vertex Texture在性能与画质之间折中。早期的图形处理管线中没有Pixel-Level这一概念,无法计算顶点纹理的LOD。如果需要使用LOD我们不得不人工在Vertex Shader里计算mipmap。
   示例代码如下:
   #define maxMipLevels 10.0f
  Out.HPOS = mul( ModelViewProj, vPos );
  float mipLevel = ( Out.HPOS.z / Out.HPOS.w ) * maxMipLevels;
  float vDisplacement = tex2Dbias( tex, float4( t, mipLevel, mipLevel );
   这是根据顶点的深度计算LOD的算法,开销很小,精度能够让人满意。
   
  #define maxMipLevels 10.0f
  Out.HPOS = mul( ModelViewProj, vPos );
  float mipLevel = ( Out.HPOS.z / Out.HPOS.w ) * maxMipLevels;
  float mipLevelFloor = floor(mipLevel);
  float mipLevelCeiling = mipLevelFloor + 1;
  float mipLevelFrac = frac(mipLevel);
  float vDisplacementFloor = tex2D( tex, float4( t, mipLevelFloor,mipLevelFloor );
  float vDisplacementCeiling = tex2Dbias(tex,
  float4(t,mipLevelCeiling,mipLevelCeiling );
  float vDisplacement = vDisplacementFloor + vDisplacementCeiling
  Filter 过滤
   Vertex Texture允许纹理过滤,但是要根据硬件的支持情况。6系列只支持NEAREST-NEIGHBOR过滤模式。你也可以手动在Vertex Texture里实现过滤。
   Bilinear Filtering
  #define textureSize 512.0f
  #define texelSize 1.0f / 512.0f
  float4 tex2D_bilinear( uniform sampler2D tex, float2 t )
  {
  float2 f = frac( t.xy * textureSize );
  float4 t00 = tex2D( tex, t );
  float4 t10 = tex2D( tex, t + float2( texelSize, 0.0f );
  float4 tA = lerp( t00, t10, f.x );
  float4 t01 = tex2D( tex, t + float2( 0.0f, texelSize ) );
  float4 t11 = tex2D( tex, t + float2( texelSize, texelSize ) );
  float4 tB = lerp( t01, t11, f.x );
  return lerp( tA, tB, f.y );
  }
   Bilinear Filtering With Mipmapping
  float4 tex2D_bilinear( uniform sampler2D tex, float4 t )
  {
  float2 f = frac( t.xy * miplevelSize );
  float4 t00 = tex2Dbias( tex, t );
  float4 t10 = tex2Dbias( tex, t + float4( texelSize, 0.0f, 0.0f, 0,0f );
  float4 tA = lerp( t00, t10, f.x );
  float4 t01 = tex2Dbias( tex, t + float4( 0.0f, texelSize, 0.0f, 0.0f ) );
  float4 t11 = tex2Dbias( tex, t + float4(texelSize, texelSize, 0.0f, 0.0f));
  float4 tB = lerp( t01, t11, f.x );
  return lerp( tA, tB, f.y );
  }
   如果单纯站在性能的角度上考虑上述算法,还是Bilinear最好。Bicubic、Trilinear,以及其他的过滤算法都可以在Vertex Shader里实现。其中,Trilinear过滤对性能的要求要高一点,因为Shader需要从不同等级的mipmap里访问纹理。
  Performance Tips性能
   6800可以在一秒钟内生成6亿多个顶点。当然,这是在Vertex Shader没有任何“负载”的情况下测试的结果。如果使用Vertex Texture Fetch后是什么情况呢?我们的数字是每秒钟生成3千3百多万个位移顶点,计算了基本位移,使用NEAREST方式过滤。
   3千3百多万个位移顶点,意味着如果以每秒30帧的速度绘制画面,每一帧画面将有100多万个Displacement Vertics位移顶点。这比现在任何一款游戏在一帧画面里出现的顶点都要多,而且,并不是每个顶点都需要进行位移操作。你可以使用6系列gpu的动态分支功能,对每个定点是否需要进行位移操作进行预测。比如做一次dot(V,N)运算,测试顶点是否靠近阴影,如果远离阴影就可以避免位移操作。这时,你就可以把节省下来的硬件资源用于处理过滤等效果上。我们推荐,如果你的Vertex Shader很复杂,最好在处理过程的早期就对画面或顶点进行剪裁与剔除。
   // OpenGL example
  float4 vClipPos = mul( ModelViewProj, vPos );
  float3 bClip = abs( vClipPos.xyz ) < ( vClipPos.www + vClipOffset );
  if( all(bClip) )
  {
  DoLightingAndDisplacement();
  }
   还有一点非常重要,“顶点纹理不应看作连续的RAM。顶点纹理在提取数据时不是真正的连续读取,而是会产生等待时间。因此使用顶点纹理的最佳方法就是先进行纹理提取,然后进行逻辑算法计算,这样能在使用纹理提取前避免等待时间。顶点纹理不是用来代替大量的常量的阵列,而是用于减少顶点数据,这样每个顶点只有少量的顶点纹理需要提取数据。”——摘自《GPU_Programming_Guide_Chinese From NVIDIA》
  <Case Study>
   目前,一些游戏已经开始使用Vertex Texture。比如下面要提到的这款游戏,由Maddox GAME开发,Ubi Software发行的Pacific Fighter。
   现代游戏的设计中,飞行模拟类游戏最适合使用dm技术。这是因为,这些游戏的场景中包括大量的地形、河流、海洋等。Dm可以为这些场景提供更好的效果。让我们看一下这款使用Displacement Mapping的游戏。
   
  IL-2 Sturmovik系列游戏最近年来比较成功的飞行模拟类游戏,在中国武汉曾经进行过一场国际性比赛。游戏制作人员非常留心游戏业里出现的最新技术,并运用到他们的作品中。比如这款最新的Pacific Fighter,完全发挥了6系列gpu的性能。“Vertex Shader里可以访问纹理是3D加速硬件最值得期待的技术之一。” Yuri Kryachko,主程序员如是说。
   在这款游戏中,海水的绘制非常重要。开发人员采用了Vertex Texture,实现了目前游戏领域中最真实的流水效果。在没有采用Vertex Texture之前,开发人员一般使用凹凸贴图模拟水面,但是与采用Vertex Texture和几何位移算法实现的效果比起来有天壤之别。图片对比如下。
   
  这款游戏的WaterShader非常复杂,超过140行,用于用物理的方式计算水面的动画,以及反射折射效果。每一个顶点的位移都是由多个dynamic normal maps(动态向量映射)用几何方式计算出来的。而且Shader从多个纹理中读取数据进行过滤操作,使画面更加真实。
   Yuri Kryacko说,“当我们在Vertex Shader及Pixel Shader中同时使用动态分支功能时,性能得到了很大的提高。我们想再优化代码,使用新的Shader,提高整体的画质,使我们的引擎的真实性达到一个新的高度。”
  Downloads下载
   想学习关于Vertex Texture Fetch更多的东西吗?从NVIDIA的站点上下载范例吧
   http://download.nvidia.com/developer/SDK/Individual_Samples/samples.html
  http://download.nvidia.com/developer/SDK/Individual_Samples/effects.html(王朝网络 wangchao.net.cn)

Shader Model 3.0:Using Vertex Textures SM3:使用顶点纹理 (NVIDIA spec, 6800支持使用D3DFMT_R32F and D3DFMT_A32B32G32R32F的纹理格式实现Vertex Texture。)的更多相关文章

  1. 微软的HLSL Shader Model 6.0 compiler要转向LLVM了,开源的节奏. Apple/Khronos都有各自计划

    So, Microsoft is making an opensource HLSL-to-almost-LLVM compiler, and Khronos is making an opensou ...

  2. Asm Shader Reference --- Shader Model 2.0 part

    ps部分 ps_2_0 概览   Instruction Set                                   Name Description Instruction slot ...

  3. Asm Shader Reference --- Shader Model 3.0 part

    ps部分 概览   Instruction Set                                       Name Description Instruction slots S ...

  4. Shader Model 版本与DirectX的关系(OpenGL对应的呢?)

    http://blog.sina.com.cn/s/blog_6e521a600100q4dr.html DX9还是能支持到固定管线的,虽然说是在内部被转换成shader: DX10明确不再支持固定管 ...

  5. Asm Shader Reference --- Shader Model 2.x part

    ps部分 概览   Instruction Set                                       Name Description Instruction slots S ...

  6. Asm Shader Reference --- Shader Model 1 part

    ps部分 ps_1_1,ps_1_2,ps_1_3,ps_1_4 总览                   Instruction Set                               ...

  7. Vertex中实现每顶点光照的镜面高光效果

    1,基础知识讲解 一个物体在自然界会收到三种光的影响,周围的环境光.漫反射和镜面反射.那么对于计算机要想模拟现实中的光照,就应该也会实现这三种基本光照->环境光.漫反射.镜面高光.对于这三种光照 ...

  8. 【Android 应用开发】OpenGL ES 2.0 -- 制作 3D 彩色旋转三角形 - 顶点着色器 片元着色器 使用详解

    最近开始关注OpenGL ES 2.0 这是真正意义上的理解的第一个3D程序 , 从零开始学习 . 案例下载地址 : http://download.csdn.net/detail/han120201 ...

  9. VLine2.0——仿阿里巴巴VIPABC真人视频在线教育(基于Flash支持一对多多对多Web在线视频)

    感兴趣的朋友可与我联系:acsebt@qq.com 一.登陆页 二.功能页

随机推荐

  1. jquery2源码分析系列

    学习jquery的源码对于提高前端的能力很有帮助,下面的系列是我在网上看到的对jquery2的源码的分析.等有时间了好好研究下.我们知道jquery2开始就不支持IE6-8了,从jquery2的源码中 ...

  2. Virtualbox安装USB2.0/3.0

    系统:Ubuntu16.04 软件:Virtualbox5.1 1.打开Virtualbox,不启动虚拟系统. 2.点击设置->USB->启动usb2.0. 3.若发现不能启用,则到官网下 ...

  3. NoSQl简介(转)

    NoSQL,全称是“Not Only Sql”,指的是非关系型的数据库.这类数据库主要有这些特点:非关系型的.分布式的.开源的.水平可扩展的.原始的目的是为了大规模web应用,这场全新的数据库革命运动 ...

  4. 浅谈JavaScript原型对象与相关设计模式

    引言 本文先从介绍JavaScript中基本的几种设计模式开始,最后引出原型对象,然后对原型对象有一个较全面的介绍. 1.创建对象的几种设计模式 A.工厂模式 我们知道在JavaScript中创建对象 ...

  5. 【python】传入函数

    def add(x, y, f): return f(x) + f(y) 当我们调用add(-5, 6, abs)时,参数x,y和f分别接收-5,6和abs,根据函数定义,我们可以推导计算过程为: x ...

  6. Difference between applicationContext.xml and spring-servlet.xml in Spring Framework

    Question: Are applicationContext.xml and spring-servlet.xml related anyhow in Spring Framework? Will ...

  7. docker 数据共享,数据复制

    docker 提供的数据共享的方式有 docker   run  -it  -v:/dataname  image 数据复制使用 docker  cp  containerid:/dataname   ...

  8. foj 2044 1 M possible 二进制压缩

    题目链接: http://acm.fzu.edu.cn/problem.php?pid=2044 题意:  给出 一大堆数,找出2个出现次数模3 为1 的两个数字   题解: 把一个数分为几位拆开统计 ...

  9. js全局变量

    在做东钿微信公众号 ,首页有房产评估和产调,有个checkbox ,点击则选中使用积分,取消选中则不使用积分,html结构和css样式都一样,唯一不一样的就是数据不一样,于是我就分开来写,没有写同一个 ...

  10. 关于Css选择器优先级

    今天练习css的时候,重叠后的style发现不起作用,原来css选择器优先级大有文章. 声明: yi下内容选自 51cto.com  --加以自己的理解 以备日后参照使用,毕竟自己理解的才是自己的. ...