游戏开发基础(十七)

原创 2012年03月29日 12:39:15

第十七章

顶点着色器(vertex shader)是一段运行在图形卡GPU中的程序,可取代固定功能流水线中的变换和光照环节(当然,不是绝对的,在硬件部支持顶点着色器的情况下,Direct3D运行时就会用软件运算方式来模拟顶点着色器).

顶点着色器其实就是用HLSL语言编写的一段定制程序,这样在可实现的图形效果上就获得了很大的灵活性,例,借助顶点着色器,可使用任何可在顶点着色器中实现的光照算法

使用顶点数据结构也更加灵活,而且可编程流水线中的顶点结构可以包含比固定功能流水线更加丰富的数据

顶点着色器是一项比较新的特性,目前许多图形卡尚不支持该特性,尤其伴随DirectX 9.0发布的那些较新的顶点着色器版本,可通过检查D3DCAPS9结构的成员VertexShaderVersion并与宏D3DVS_VERSION进行比较,来检测图形卡是否支持某个顶点着色器版本

检测过程:

 //if the device's supported version is less than version 2.0
 if (caps.VertexShaderVersion < D3DVS_VERSION(2,0))//主次版本号
  // then vertex shader version 2.0 is not supported on this device
目前D3DXCompileShaderFromFile函数支持的顶点着色器版本为1.1,2.0和3.0

顶点声明:
在可编程流水线中,顶点结构甚至可以包含那些超出FVF描述能力的数据,因此,通常使用能力更强,功能更丰富的顶点声明(vertex declaration)

在可编程流水线中,如果顶点结构可用FVF来描述,仍可使用,但是,这是为了表示方便,实际上可编程流水线内部,FVF最终被转换为顶点声明。

顶点声明描述为一个D3DVERTEXELEMENT9类型的结构数组,该结构数组中的每个元素都描述了顶点结构的一个分量,所以,如果顶点结构具有3个分量(比如位置,法向量,颜色),则相应的顶点声明级可用一个维数为3的D3DVERTEXELEMENT9类型的结构数组来描述

typedef struct D3DVERTEXELEMENT9
{
 WORD Stream;//指定与顶点分量关联的数据流
 WORD Offset;//自顶点数据起始点到特定数据类型相关的数据的字节偏移量
 BYTE Type;//指定数据类型,该参数可取枚举类型D3DDECLTYPE的任何一个成员,D3DDECLTYPE_FLOAT1浮点类型标    //量,D3DDECLTYPE_FLOAT2浮点类型的2D向量,D3DDECLTYPE_FLOAT3浮点类型的3D向量,D3DDECLTYPE_FLOAT4浮点   //类型的4D向量,D3DDECLTYPE_D3DCOLOR一个被扩展为RGBA浮点类型颜色向量(r,g,b,a)的D3DCOLOR类型,其颜色  //向量的每个分量都被规范化至区间[0,1]内
 BYTE Method;//指定了网格化(tesselation)方法,该章默认使用D3DDECLMETHOD_DEFAULT来指定
 BYTE Usage;//指定了顶点分量的用途,例,即,某一个分量是作为位置向量,法向量还是纹理向量等,标识符取自枚举类    //型D3DDECLUSAHE;
 BYTE UsageIndex;//标识具有同用法的多个顶点分量,用法索引(usage index)是一个位于区间[0,15]内的整数,例,有3   //个顶点分量的用法都为D3DDECLUSAGE_NORMAL,则可按序将这3个顶点分量的用法索引分别指定为      //0,1,2,按照这种方式,可通过用法索引表示每个特定的法向量
}D3DVERTEXELEMENT9,*LPD3DVERTEXELEMENT9;

typedef enum D3DDECLUSAGE
{
 D3DDECLUSAGE_POSITION     = 0,//如果一个顶点声明中具有该标识,则表明该顶点已经经过了变换,并指示图形卡不要     //将该顶点输送到顶点处理环节中(变换和光照处理)
 D3DDECLUSAGE_BLENDWEIGHT  = 1,
 D3DDECLUSAGE_BLENDINDICES = 2,
 D3DDECLUSAGE_NORMAL       = 3,
 D3DDECLUSAGE_PSIZE        = 4,//用于指定顶点的点尺寸,该类型主要用于点精灵(point sprite),这样对每个尺寸进行     //控制
 D3DDECLUSAGE_TEXCOORD     = 5,

 D3DDECLUSAGE_TANGENT      = 6,
 D3DDECLUSAGE_BINORMAL     = 7,
 D3DDECLUSAGE_TESSFACTOR   = 8,
 D3DDECLUSAGE_POSITIONT    = 9,
 D3DDECLUSAGE_COLOR        = 10,
 D3DDECLUSAGE_FOG          = 11,
 D3DDECLUSAGE_DEPTH        = 12,
 D3DDECLUSAGE_SAMPLE       = 13
}D3DDECLUSAGE,*LPD3DECLUSAGE;

按照这种方式,就可通过用法索引表示每个特定的法向量

例:要描述的顶点格式包含了一个位置向量和3个法向量,则相应的顶点声明可指定为
 D3DVERTEXELEMENT9 decl{} =
 {
 {0,0,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION,0},
 {0,12,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_NORMAL,0},
 {0,24,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_NORMAL,1},
 {0,36,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_NORMAL,2},
 D3DDECL_END()//初始化D3DVERTEXELEMENT9数组中的最后一个顶点元素
 };


顶点声明的创建: 将顶点声明描述为一个D3DVERTEXELEMENT9类型的数组,就可用如下方法获得指向接口IDirect3DVertexDeclaration9指针:
HRESULT CreateVertexDeclaration(
    CONST D3DVERTEXELEMENT9* pVertexElements,//指向一个D3DVERTEXELEMENT9类型的结构数组          //描述了要创建的顶点声明
    IDirect3DVertexDeclaration9** ppDecl//返回指向所创建的IDirect3DVertexDeclaration9接        //口指针
    );

例 :
 IDirect3DVertexDeclaration9* _decl = 0 ;
 hr = _device->CreateVertexDeclaration(decl,&_decl);

灵活顶点格式是一项很有用的特性,在可编程流水线内部它将被转换为顶点声明,所以,直接使用顶点声明时,无需调用:
 Device->SetFVF(fvf);
而只是调用:
 Device->SetVertexDeclaration(_decl);//_decl是一个指向接口IDirect3DVertexDeclaration的指针

需要一种方式来定义从顶点声明中的元素到顶点着色器的输入结构的数据成员的映射,在输入结构中通过为每个数据成员指定一种语义(:usage -type[usage-index])来定义这种映射,该语义通过用法类型和用法索引来标识顶点声明中的每个元素,由数据成员的语义所标识的那个顶点元素就被映射到该数据成员的那个元素
例:与前面提到的那个顶点声明对用的输入结构为:
struct VS_INPUT
{
 vector position:POSITION;
 vector normal  :NORMAL0;
 vector facenormal1  :NORMAL1;
 vector facenormal2  :NORMAL2;
};

如果略去了用法索引,就意味着该索引为0,例,POSITION含义与POSITION0完全相同

顶点着色器支持的输入用法包括:
#POSITION[n]位置
#BLENDWEIGHTS[n]位置融合权值(blend weights)
#BLENDINDICES[n]融合索引(blend indices)
#NORMAL[n]法向量
#PSIZE[n]顶点的点尺寸
#DIFFUSE[n]漫反射颜色
#SPECULAR[n]高光颜色(specular color)
#TEXCOORD[n]纹理坐标
#TANGENT[n]切向量(tangent vector)
#BINORMAL[n]副法向量(binormal vector)
#TESSFACTOR[n]网格化因子(tessellation factor)
n为一个可选整数,但必须取自区间[0,15]内

对于输出结构,必须指定每个成员的用途,例如,该数据成员应看作位置向量,颜色向量,还是纹理坐标等,对于各数据成员的用途,图形卡无从知晓,需要显示指定,这种指定也是在语义层次实现,例:
 struct VS_OUTPUT
 {
  vector position :POSITION;
  vector diffuse :COLOR0;
  vector specular :COLOR1;
 };

顶点着色器支持的输出用法包括:
#POSITION[n]位置
#PSIZE[n]顶点的点尺寸
#FOG[n]雾融合值(fog blend value)
#COLOR[n]顶点颜色,注意可输出多个顶点颜色,这些颜色混合在一起生成最终颜色
#TEXCOORD[n]顶点纹理坐标,注意,可能输出多个顶点纹理坐标
n为一个可选整数,但必须取自区间[0,15]内


使用顶点着色器的步骤:
1 编写顶点着色器程序,并进行编译
2 创建一个IDirect3DVertexShader9接口的对象,以表示基于所编译的着色器代码的顶点着色器
3 用IDirect3DDevice9::SetVertexShader方法启用顶点着色器

当顶点着色器使用完毕后,必须进行销毁


该方法获取IDirect3DVertexShader9接口指针,该接口代表一个顶点着色器
HRESULT IDirect3DDevice9::CreateVertexShader(
         const DWORD *pFunction,//指向经过编译的代码指针,
         IDirect3DVertexShader9** ppShader//指向IDirect3DVertexShader接口的指针
         );

例;变量shader是一个指向ID3DXBuffer接口指针,则获取指向IDirect3DVertexShader9接口指针:
 IDirect3DVertexShader9* ToonShader = 0 ;
 hr = Device->CreateVertexShader(
     (DWORD*)Shader->GetBufferPointer(),
     &ToonShader);

D3DXCompileShaderFromFile函数能够返回经过编译的着色器代码(对应上面的shader)

该方法启用顶点着色器
HRESULT IDirect3DDevice9::SetVertexShader(IDirect3DVertexShader9 * pShader);
该方法接收一个单个参数,可将一个指向希望被启用的顶点着色器的指针赋给该参数
例:
 Device->SetVertexShader(ToonShader);

IDirect3DVertexShader9在使用完毕后,必须调用其自身的Release来释放资源
例:
 d3d::Release<IDirect3DVertexShader9*>(ToonShader);

Direct 3D和XNA游戏开发基础(C#语言版)(奋斗的小鸟)_PDF 电子书

下载地址:   内容简介   使用C#语言可以编写基于DirectX和微软最新游戏开发平台XNA(仅支持C#语言)的3D图形和3D游戏程序,其运行速度已接近于C++代码的运行速度,一些商业游戏已经使...
  • tjoy2005
  • tjoy2005
  • 2013年10月11日 19:32
  • 1536

游戏编程之十五 DirectDraw 的基本知识

DirectDraw 游戏编程基础(2) 游戏使计算机的发展超越了晶体管时代              例程1(DDEX1):DirectDraw 的基本知识 在使用 Dir...
  • zhangchen124
  • zhangchen124
  • 2016年06月22日 21:32
  • 700

OllyDbg 使用笔记 (十七)

OllyDbg 使用笔记 (十七) 参考 书:《加密与解密》 视频:小甲鱼 解密系列 视频 破解这个程序的注册机(keygen) 这个程序主界面就是两个输入框,跟check,abou...
  • billvsme
  • billvsme
  • 2014年09月06日 23:23
  • 944

USB开发基础:USB命令(请求)和USB描述符

在USB规范里,对命令一词提供的单词为“Request”,但这里为了更好的理解主机与设备之间的主从关系,将它定义成“命令”。...
  • kevinhg
  • kevinhg
  • 2010年10月01日 00:16
  • 3774

[原创]ExtAspNet秘密花园(十一) &mdash; 布局概述

在ExtAspNet开发中,页面中控件的合理布局是页面美观的基础,因此非常重要。同时由于这一块是普通Asp.Net控件所缺失的一环,因此也不大容易理解。本篇文章将对ExtAspNet控件中的各种布局做...
  • u010918003
  • u010918003
  • 2013年06月24日 11:33
  • 493

游戏开发基础(3)

游戏开发基础(3)第三章 DirectX SDK简介第一节 关于DirectX SDKMicrosoft DirectX提供了一套非常优秀的应用程序接口,包含了设计高性能、实时应用程序的源代码。Dir...
  • zhucde
  • zhucde
  • 2004年03月12日 17:52
  • 1325

游戏开发基础(4)

游戏开发基础(4)第四章 diectxdarw基础篇 第一节 DirectDraw简介Grubers的一个观点是DirectDraw“只是一个bltting发动机”。这是相当准确的,但却太简化了。更准...
  • zhucde
  • zhucde
  • 2004年03月12日 17:52
  • 1364

游戏开发基础(1)

写在前面的话:本来我的专栏就是以图形,图像,三维为宗旨,正好由于这些天比较忙,没有时间来整理。还请大家见谅!在此,我先转载几篇游戏开发基础类的文章与大家一起学习交流,该基础系列共有10篇:游戏开发基础...
  • zhucde
  • zhucde
  • 2004年03月12日 17:52
  • 3066

android 游戏开发基础学习

1、android系统的组件和布局,这些基础知识可以开发一些简单应用程序。 2、游戏界面是由大量美工资源图片构成,在设计游戏界面时, 千万不要使用layout布局。不利于界面刷新,事件消息处理。 ...
  • ouwen123
  • ouwen123
  • 2011年11月13日 11:32
  • 1987

【基础】web开发基础知识

摘要: 有时候是想分享一些知识给大家,但是鉴于各种原因实在是不能达到理想的博客状态。 今天有时间抽点时间给大家写下web开发的基础知识,也是整理。 这篇博客是基础知识,万丈高楼平地起从事web开...
  • my_God_sky
  • my_God_sky
  • 2016年01月19日 18:23
  • 1075
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:游戏开发基础(十七)
举报原因:
原因补充:

(最多只允许输入30个字)