“言论自由,莫谈国事!游戏研发中立论坛...”  (10-10)  “论坛主旨:激发你游戏制作的潜能”  (08-12)    

首页  列表  注册  登陆  搜索  用户  排行  帮助
欢迎光临何苦做游戏-游戏开发论坛,请登陆注册
会员总数:18029 新进会员:icePhoenix
用户   自动登录
密码    
主题总数:16092 回复总数:24457
今日主题:1 今日回复:2
访问峰值:723 发生时间:2005年06月01日
论坛首页--程序技术专区--[译] Direct3D 顶点着色指南
帖子主题:[译] Direct3D 顶点着色指南
    npc6
 
  
 注册:2004/7/21         

 状态:VIP会员            
 经验:10502

 帖子:357

楼主[2004/9/15 22:52:47]      

 译:zh1110

顶点着色是现代渲染的重要技术之一。在DirectX8中Microsoft公司引入了一些新的特性来帮助程序员。顶点着色是用汇编语言写的,插入到着色器流水线来修改顶点特性,一般的DX过程不受其影响。下面的图表显示在Direct3D 管道线内处理顶点及象素着色的过程:

 
按此在新窗口浏览图片

顶点渲染让渲染方式改变成为可能,其中最出名的是卡通渲染(在XBOX游戏中也使用它)。它跟VB的速度没有关系,因为它是汇编写的。

 

这是3D,但通过顶点渲染。

 
按此在新窗口浏览图片


这也是3D!

按此在新窗口浏览图片
 

使用顶点着色不仅要知道如何加载顶点着色文件我们还要学习如何编写其过程本身的汇编代码。幸运的是它比通常的X86汇编简单的多。

这个指南分为三部分:

I)  加载顶点渲染文件

II) 创建顶点渲染代码

III) 顶点渲染示例

第一部分: 加载顶点着色文件

首先我们学习加载顶点着色文件。拷贝下面代码到一文本文件中(*.txt)

vs.1.0 

dp4 r0.x, v0, c0 

dp4 r0.y, v0, c1 

dp4 r0.z, v0, c2 

dp4 r0.w, v0, c3 

mov oPos, r0 ; 

mov oD0, c4

在VB中是用一长串数据来代表顶点类型,它也将在汇编代码中使用。创建这一长串的常数可以放在一个*.bas模块中,microsoft SDK中就可以找到下面代码。

Function creaVShader(filesrc As String) As Long

Dim shaderArray() As Long

Dim shader As Long 

Dim decl(4) As Long 

Dim shaderCode As D3DXBuffer

decl(0) = D3DVSD_STREAM(0) 

decl(1) = D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)

decl(2) = D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3) 

decl(3) = D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2) 

decl(4) = D3DVSD_END()

Set shaderCode = D3DX.AssembleShaderFromFile(filesrc, 0, "", Nothing) 

ReDim shaderArray(shaderCode.GetBufferSize() / 4) 

D3DX.BufferGetData shaderCode, 0, 1, shaderCode.GetBufferSize(), shaderArray(0) 

Set shaderCode = Nothing 

device.CreateVertexShaderdecl(0), shaderArray(0),shader, D3DUSAGE_SOFTWAREPROCESSING

 creaVShader = shader 

End Function

"decl"数组中放入的数值用于保存标准的顶点信息,包含位置,法向,贴图(我们也可以创建两个位置坐标来实现弯曲)。数据在这个模块中创建,但我们只须记者一个。相似的数组也象这样

decl(0) = 536870912 

decl(1) = 1073872896 

decl(2) = 1073872899 

decl(3) = 1073807367 

decl(4) = -1

在声明文件路径后,把它放入另一个数组。最后通过它产生我们的渲染。这个过程产生一系列渲染,在每一我们需要的时刻,只要加载文件

ShaderL = creaVShader (“shader path”)

我们现在要连接汇编代码,我们通过渲染矩阵或四个数组。通过数组我们使用如下

Dim constants(3) as single

device.SetVertexShaderConstant 5, constants(0), 1

我们使用5号寄存器(详细介绍在下章)根据规定每个寄存器只能通过一个数组

To pass a matrix we use

Dim m as D3Dmatrix

device.SetVertexShaderConstant 5, m, 4

这次我们通过八个数(因为矩阵是4个单精度实数组合一起的) 注册从5号到8号寄存器

通常最难的是世界矩阵,所有过程在VB中完成.我们不使用device.SetTransform。过程如下 :

通常世界矩阵转化使用矩阵乘法:世界矩阵x视图矩阵x投影矩阵.

D3DXMatrixMultiply m, matWorld, matView 

D3DXMatrixMultiply m, m, matProj

D3DXMatrixTranspose m, m

device.SetVertexShaderConstant 0, m, 4

也可单独处理,但通常用矩阵的方法.

顶点渲染不能直接使用网格,我们要将它加载到索引和顶点缓冲中。

Dim vBuf As Direct3DVertexBuffer8

Dim iBuf As Direct3DIndexBuffer8

Set vBuf = meshX.GetVertexBuffer

Set iBuf = meshX.GetIndexBuffer

device.SetStreamSource 0, vBuf, D3DX.GetFVFVertexSize(D3DFVF_VERTEX)

device.SetIndices iBuf, 0

device.DrawIndexedPrimitive D3DPT_TRIANGLELIST, 0,meshX.GetNumVertices, 0, meshX.GetNumFaces

网格须是标准的网格.

这种方法每一个网格都可有其自己的渲染方法,这个过程是不能用仅靠加载一个顶点着色文件取代的.

下载基本的示例查看所有细节。

第II部分: 创建顶点渲染代码

下步创建顶点渲染汇编代码。请看下图

按此在新窗口浏览图片

此图展示了算术逻辑单元在图形流水线中如何渲染3D对象的。每个方块代表一寄存器可包含四个单精度实数。共有四种寄存器:

Vector (V0 to V16)   包含顶点数值.(输入寄存器,只读)

Constant(C0 to C96)   包含数组,数据是在VB建立的(常量寄存器,只读)

Temporary(R0 to R16)   包含用于操作的代码数据  (临时寄存器,可读/可写)

Output (oPos, oPts, oT0 to oT3, oFog, oD0 & oD1)  包含通过 GPU 的数据(为了最后的渲染) 这是最后的结果.(输出寄存器,只读)

代码一次处理完所有的顶点,且非常迅速。汇编代码通过输入寄存器、常量寄存器输入,在临时寄存器进行计算。最后将结果输出到输出寄存器,输出寄存器包含了每个顶点的最后数值。

oPos寄存器包含顶点位置

oPts寄存器是点的尺寸

oT0 到 oT3寄存器是贴图的坐标 (注册一对值)

oFog寄存器是雾的浓度 (如果硬件支持雾)

oD0 & oD1寄存器是 顶点颜色

我说过输入寄存器包含顶点数值但要经过一系列声明。通常的声明顺序如下:

顶点注册部分:

· 位置Position : V0

· 权重值Blend Weight : V1

· 索引Blend Indices : V2

· 法向Normal : V3

· 点大小Point Size: V4

·反射 Diffuse : V5

·高光Specular : V6

·贴图坐标0 Texture Coordinate 0 : V7

· 贴图坐标1 Texture Coordinate 1 : V8

· 贴图坐标2 Texture Coordinate 2 : V9

·贴图坐标3  Texture Coordinate 3 : V10

· 贴图坐标4 Texture Coordinate 4 : V11

· 贴图坐标5 Texture Coordinate 5 : V12

· 贴图坐标6 Texture Coordinate 6 : V13

· 贴图坐标7 Texture Coordinate 7 : V14

·位置2 Position 2 : V15

· 法向2 Normal 2 : V16

但是要记住,我们只能使用我们声明过的顶点(我的示例中用了 位置、法向、贴图坐标),使用其他将会出错。如果要使用其他顶点只要改变渲染模式

decl(0) = D3DVSD_STREAM(0) 

decl(1) = D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)

decl(2) = D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3) 

decl(3) = D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2) 

decl(4) = D3DVSD_REG(D3DVSDE_POSITION2, D3DVSDT_FLOAT3) 

decl(5) = D3DVSD_END()

我们可以注册两个位置 (V0 and V15).

每次注册四个单精度实数,我们可以访问修改它(x,y,z,w). 如果只要修改 X 部分我们可以写“R0.x”我们还可以这样修改多个值: R0.xy, R0.yzw ,修改全部只要写 R0. 渲染的汇编代码不同于一般的高级语言程序——无通常的符号 (=, + , /).它只使用一种注释符号( ; ). 所有在“;”后面,下一行前的字将忽略 。一个重要的指令是顶点渲染必须在开头声明版本号:

Vs.1.0 ; 通用版本

Vs.1.1 ; 更高级的版本,多一个寄存器(我们不用)

所以我们用 1.0 ,因为可以兼容现有的硬件.

 

第2个重要的指令是移动指令,来拷贝一个寄存器的数据到另一个寄存器

Mov r0, v1 ; 拷贝 V1寄存器的数据到 r0寄存器

Mov R0.x, V1.x ;拷贝V1寄存器的x值到R0寄存器的x.

记着只能对临时寄存器和输出寄存器写入数据,且输出寄存器只能写一次

 

DD , MUL, SUB

加法,乘法,减法,并将结果放到第1个寄存器

(Add r0, r1 ,v0 相当于 of R0=R1+V1 (修改全部)

(Mul r0.x, r1.x, v0.x 相当于R0.X=R1.x * V0.x)

(Sub r0.xy, r1.xy, v0.xy 相当于 R0.xy=R1.xy - V0.xy)

 

EXPP, LOGP

指数,对数运算

(Expp r0, v1 )

(Logp r0, v1 )

 

MAD

(Mad r0, r1, r2, r3 进行此操作后 r0=r1 * r2 + r3)

 

MAX, MIN

将最大或最小值放入指定寄存器

(Max r0, v1, v2)

(min r0, v1, v2)

 

DP4

点积运算. 一个重要的运算因为可以控制顶点位置(也可以是法向,灯光或其他东西)我们需要这个操作.

dp4 r0.x, v0, c0 

dp4 r0.y, v0, c1 

dp4 r0.z, v0, c2 

dp4 r0.w, v0, c3

这段代码中我们改变了顶点位置——通过c0 到c3寄存器分别进行了矩阵运算。如果矩阵是world x view x proj 这段代码相当于函数device.SetTransform. 通过r0寄存器输出到oPos寄存器后对象将会被平移,旋转及缩放.

 

DP3

类似于DP4但每个寄存器只用三个值计算 (忽略其他的值).

 

SGE

将1放入r0 如果 r1大于等于 r2;其他情况结果为0 .

(Sge r0, r1, r2)

 

SLT

将1放入 r0 如果 r1小于 r2;其他情况结果为0 .

(Slt r0, r1, r2)

 

宏可以完成不止一条指令,使功能增加.

M4x4, M4x3, M3x3, M3x4, M3x2

点积运算

(m4x4 oPos , v0 ,c0 类似于DP4例子,但一次完成)

 

EXP, LOG

类似于EXPP  LOGP,但更精确

 

FRC

将v1的分数部分放到 r0

( Frc r0, v1 )

 

这是一不进行改变的渲染代码(既默认的转化过程)

dp4 r0.x, v0, c0

dp4 r0.y, v0, c1

dp4 r0.z, v0, c2

dp4 r0.w, v0, c3

mov oD0, c4 ; 颜色为常数.

mov oPos, r0 ; 数据输出.

矩阵转换通过常量寄存器 (c0到c3). 反射的颜色从 c4.加载。

vs.1.0

dp4 r0.x, v0, c0

dp4 r0.y, v0, c1

dp4 r0.z, v0, c2

dp4 r0.w, v0, c3

mov oPos, r0 ; 输出位置

mov oD0, c4 ; 输出颜色

mul r1,v7,c5 ;贴图坐标乘以C5寄存器

mov oT0, r1 ; 输出贴图坐标

我们可以通过 C5 寄存器改变贴图数量(我第一个例子就是这样的).

一些错误的代码往往是发生在开头

在一些代码中可能会找到寄存器的书写如R[0]: 不用担心它就是R0!

第III部分: 顶点渲染例子

现在我们讨论单元渲染,单元渲染的另一种说法叫卡通渲染。这种渲染模仿卡通风格 ,包含连续不变的颜色和大块的阴影.

按此在新窗口浏览图片

有些结果看上去不象一个 3D 模型!!

按此在新窗口浏览图片

使用如下:

顶点渲染是一种重要的渲染方法——通过贴图法向及灯光转化. 我们要使用不同的顶点渲染两次,就是绘制两遍场景——第一次是主体,着色对象,第二次是轮廓,以线框的模式进行。

两次的渲染象这样:

主体

; Inputs: v0 = 位置

; v3 = 法向

; c0 = (0,0.5,xxx,xxx) 常数

;c1-4 = World*View 矩阵

; c5-9 = World*View*Projection 矩阵

; c9 = 灯/材料颜色

;c10 = 灯方向 (在视图空间) 

vs.1.0 ;渲染版本 1.0  

m4x4 oPos , v0 , c5 ; 用视/投影矩阵变换的顶点 

m3x3 r1 , v3 , c1 ;r1 = 经过视图空间转换的法向

dp3 r2 ,-r1 , c10 ; r2 = 灯光照明与转换的法向点积计算

max r2 , r2 , c0.x ; 取最值 r2 或0

mov oT0.x, r2 ; 贴图坐标X为r2 

mov oT0.y, c0.y ; 贴图坐标Y为 0  (c0,0.5) 

mov oD0 , c9 ; 反射颜色 = c9

轮廓

; Inputs: v0 = 位置

; v3 = 法向

; c0 = (0,0.5,xxx,xxx) 常数

; c1-4 = 世界视图矩阵

; c5-9 = 世界视图投影矩阵  

vs.1.0 ; 渲染版本 1.0 

m4x4 r0 , v0 , c1 ; r0 = 用视/投影矩阵变换的顶点 

m3x3 r1 , v3 , c1 ; r1 = 视图空间法向  

m4x4 oPos , v0 , c5 ; 投影位置

dp3 r2.x , r0 , r0 ; 单位化 r0 (位置) 

rsq r2.x , r2.x 

mul r0 , r0 , r2.x 

dp3 r3.x , r0 , -r1 ; 计算点积

mad oD0.w, r3.x , c0.y , c0.y ; 缩放到 [0,1] 并设置alpha ,oD0.w代表

mov oD0.xyz , c0.x ; 反射 RGB 为 0黑色,oD0.xyz代表

为渲染对象加载两次顶点渲染(基本的顶点缓冲)第一次要进行如下设置

device.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_MODULATE device.SetTextureStageState 0, D3DTSS_COLORARG1, D3DTA_TEXTURE

device.SetTextureStageState 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE device.SetRenderState D3DRS_ALPHATESTENABLE, False

第2次轮廓我们要将设置替代如下

device.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 device.SetTextureStageState 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE device.SetTextureStageState 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 device.SetTextureStageState 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE device.SetRenderState D3DRS_ALPHATESTENABLE, True

device.SetRenderState D3DRS_ALPHAFUNC, D3DCMP_LESS 

device.SetRenderState D3DRS_ALPHAREF, (dimeLines)

注意dimelines代表边缘线的宽度从0到255。最佳值为130 到 140.

再看一下渲染代码你会发现数据是怎么传递给了常量(别忘记转换的方法)



学而不思则罔,思而不学则殆,欢迎大家踊跃发言!

     cat

    
 经验:5844    

 帖子:332      
  状态:普通会员

  注册:2004/7/21

第1楼[2004/10/11 17:59:38]     

[译] Direct3D 顶点着色指南
超级好东东  顶~~~~~~~~~~~~~~~~~~

该主题帖子共[ 1 ]页 页码:第 1

论坛图例
开放帖 热门帖 被锁帖 总固顶 类固顶 固顶帖 精华帖
© 1998-2018 Npc6.Com 版权所有. ALL RIGHTS RESERVEDD
沪ICP备16050065号-3