会员: 密码:  免费注册 | 忘记密码 | 会员登录 网页功能: 加入收藏 设为首页 网站搜索  
游戏开发 > 程序设计 > 3D图形
开发工具与环境
发表日期:2007-01-26 17:46:28作者: 出处:  

    目录
    1、初始化
    2、Render
    3、.VSH文件
    4、使用纹理
    5、使用光照
    6、VertexShader的结构
    7、寄存器的性质
    8、各向异性

    参考资料:
      强烈建议看DX9SDK,里面有十分详尽的1.1到3.0的参考手册
      SDK理论:Direct3D Architecture::Programmable Vertex Shader Architecture
      SDK实例:ProgrammablePipeline::VertexShaders

    1、初始化部分,
D3DVSD_STREAMD3DVSD_REGD3DVSD_END用于定义顶点数据存储格式,D3DXAssembleShaderFromFile从.VSH文件中调入VertexShader处理程序,CreateVertexShader用于创建VertexShader,SetVertexShaderConstant用于设置寄存器参数,SetVertexShader用于设置VertexShader。我的显卡VertexShader版本是1.1,PixelShader的版本是0.0,看来是硬件不支持了。


//版本检测
D3DCAPS8 caps;
ZeroMemory(&caps,sizeof(caps));
m_pD3DDevice->GetDeviceCaps(&caps);

m_Debug.Add("VertexShader version:%x.%x",
D3DSHADER_VERSION_MAJOR(caps.VertexShaderVersion),
D3DSHADER_VERSION_MINOR(caps.VertexShaderVersion));

void CVShader::LoadVSH( TCHAR* strFilename )
{
// Create the vertex shader.开始创建VS
LPD3DXBUFFER pCode;
DWORD dwDecl2[] =
{
D3DVSD_STREAM(0),
D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR ),
D3DVSD_END()
};

// Assemble the vertex shader from the file.读取VSH文件
if( FAILED( D3DXAssembleShaderFromFile( strFilename, 0, NULL, &pCode, NULL ) ) )
{
return;
}

// Create the vertex shader.建立VS
if(SUCCEEDED( m_pD3DDevice->CreateVertexShader( dwDecl2,
(DWORD*)pCode->GetBufferPointer(), &m_dwVertexShader, 0 )))
{
pCode->Release();
}

}

    2、Render部分,需要matWorld、m_matView和m_matProj三个矩阵来对顶点处理。


m_pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

D3DXMATRIX mat;
D3DXMatrixMultiply( &mat, &matWorld, &m_pCamera->m_matView );
D3DXMatrixMultiply( &mat, &mat, &m_pCamera->m_matProj );
D3DXMatrixTranspose( &mat, &mat );
m_pD3DDevice->SetVertexShaderConstant( 0, &mat, 4 );          //将WVP矩阵设置在c0

float
color[4] = {0,1,0,0};                                   //RGBA
m_pD3DDevice->SetVertexShaderConstant( 4, &color, 1 );        //将指定颜色设置在c4

m_pD3DDevice->SetVertexShader( m_dwVertexShader );

//渲染
m_pD3DDevice->SetTexture(0, m_pTextures);
m_pD3DDevice->SetStreamSource( 0, m_pVB, sizeof(CUSTOMVERTEX) );
m_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 1 );

    3、Test.VSH文件,将 mov oD0, c4 改为 mov oD0, v5 可以显示原有颜色。

vs.1.0
m4x4 oPos, v0, c0   ; transform vertices by view/projection matrix,WMP矩阵变换顶点坐标
mov oD0, c4         ; load color from register 4 to diffuse color,设置顶点颜色

结果如图所示:

    4、使用纹理

struct CUSTOMVERTEX
{
float
x, y, z;
DWORD color;
float
tu,tv;
};

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)

CUSTOMVERTEX m_Vertices[] =
{
{ -1.0f, 0.0f, 0.0f, 0xffff0000, 0.0f, 1.0f },
{ 1.0f, 0.0f, 0.0f, 0xff0000ff, 1.0f, 1.0f },
{ 0.0f, 0.0f, 1.732f, 0xffffffff, 0.0f, 0.0f },
};

DWORD dwDecl2[] =
{
D3DVSD_STREAM(0),
D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR ),
D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2 ),
D3DVSD_END()
};

vs.1.0
m4x4 oPos, v0, c0
mov oT0, v7         ; move texture color to output texture register,设置纹理坐标

结果如图所示:

    5、使用光照

struct CUSTOMVERTEX
{
float
x, y, z;
float
nx, ny, nz;
DWORD color;
float
tu,tv;
};

CUSTOMVERTEX m_Vertices[] =
{
{ -1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0xffff0000, 0.0f, 1.0f },
{ 1.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0xff0000ff, 1.0f, 1.0f },
{ 0.0f, 0.0f, 1.732f, 0.0f, 0.0f, 1.0f, 0xffffffff, 0.0f, 0.0f },
};

DWORD dwDecl2[] =
{
D3DVSD_STREAM(0),
D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),   //v0,pos,顶点坐标设置在v0
D3DVSD_REG(D3DVSDE_NORMAL , D3DVSDT_FLOAT3),    //v3,nor,顶点法线设置在v3
D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR ), //v5,color,顶点diffuse颜色设置在v5
D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2 ), //v7,tex,纹理坐标设置在v7
D3DVSD_END()
};

float lightDir[4] = {-1,-1,1,0}; // fatter slice
m_pD3DDevice->SetVertexShaderConstant( 12, &lightDir, 1 );

vs.1.0 
m4x4 oPos, v0, c0
dp3 r0 , v3 , c12       // perform lighting N dot L calculation,计算法线点乘光线
mul oD0 , r0.x , v5     // calculate final pixel color from light intensity,根据光线强度计算颜色
                        // and interpolated diffuse vertex color
mov oT0.xy , v7         // copy texture coordinates to output,输出纹理坐标

结果如图所示:

    6、VertexShader的结构。VertexShader与T&L在Render流程中处于二选一的同等地位,我甚至怀疑T&L只是一种特殊的VertexShader(hoho,理论不行,恶补中...)。VertexShader算逻单元(ALU)有顶点数据寄存器(v0-15)、临时寄存器(r0-11)、常数寄存器(c0-95)、地址寄存器(a0)和若干输出寄存器,每个寄存器存储一个4D的矢量(4个32位的浮点数共128位)。
    DirectX 8.x中,一个VertexShader程序最多只能有128条指令,只能线性执行指令(没有循环、条件判断、跳转指令),同时只能有一个VertexShader程序被激活(无法将两个VertexShader程序依次执行,也就是要为每个特定的效果编写独立的程序)。
    通过前面3个例子总算有了一点感性认识。


图一、D3D的Render流程


图二、Vertex Shader的结构

    7、寄存器的性质。主要是读写属性、数量,特别是每条指令中能出现的次数。象 add oD0, v5, v5 这种指令在1.0版本中是无效的,在1.1版本中就可以了,效果见下图。

表一、性质列表

Name Type I/O Permissions Count Number allowed per instruction Versions
a0 address register write/use only 1 scalar 0 in version 1.0; 1 in version 1.1 1.0 - 1.1
cn constant register read-only 96 vectors 1 1.0 - 1.1
rn temporary register read/write 12 vectors 3 1.0 - 1.1
vn vertex register read-only 16 vectors 1 in version 1.0; 2 in version 1.1 1.0 - 1.1

vs.1.0 
m4x4 oPos, v0, c0
add oD0, v5, v5


    8、各向异性效果。

; v0 -- position
; v3 -- normal
; v7 -- tex coord
; v8 -- tex coord1
;
; c0-3 -- world/view/proj matrix
; c4 -- light vector
; c5-8 -- inverse/transpose world matrix
; c9 -- {0.0, 0.5, 1.0, -1.0}
; c10 -- eye point
; c11-14 -- world matrix

vs.1.0

;transform position
dp4 oPos.x, v0, c0
dp4 oPos.y, v0, c1
dp4 oPos.z, v0, c2
dp4 oPos.w, v0, c3

;transform normal
dp3 r0.x, v3, c5
dp3 r0.y, v3, c6
dp3 r0.z, v3, c7

;normalize normal
dp3 r0.w, r0, r0
rsq r0.w, r0.w
mul r0, r0, r0.w

;compute world space position
dp4 r1.x, v0, c11
dp4 r1.y, v0, c12
dp4 r1.z, v0, c13
dp4 r1.w, v0, c14

;vector from point to eye
add r2, c10, -r1

;normalize e
dp3 r2.w, r2, r2
rsq r2.w, r2.w
mul r2, r2, r2.w

;h = Normalize( l + e )
add r1, r2, c4

;normalize h
dp3 r1.w, r1, r1
rsq r1.w, r1.w
mul r1, r1, r1.w

;l dot n
dp3 oT0.x, r0, c4

;h dot n
dp3 oT0.y, r1, r0

返回顶部】 【打印本页】 【关闭窗口

关于我们 / 给我留言 / 版权举报 / 意见建议 / 网站编程QQ群   
Copyright ©2003- 2024 Lihuasoft.net webmaster(at)lihuasoft.net 加载时间 0.00378