【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 3990|回复: 4

[转帖][翻译]Direct3D8 ShaderX

[复制链接]
发表于 2006-9-13 13:31:07 | 显示全部楼层 |阅读模式
翻译非常烂 译自 《Direct3D.ShaderX. Vertex and Pixel Shader Tips and Tricks》

烂文翻译版权归 me所有 microsoftxiao

Direct3D ShaderX - Vertex and Pixel Shader Tips and Tricks

Edlted by Wolfgang F.Engel

目录

Microsoft DirectX 8.0革命性的可编程图形到来了。可编程几何管线和可编程像素管线,控制几何和像素给开发者。这对于图形开发者是空前的,一旦他们有了基本的着色器,现在有工具,并产生新的,作为未知的效果。Wolfgang和它的贡献者有选择它们相信它的说明将给你开启创建你自己的效果使用可编程图形管线的大门。

第1部分

这个介绍覆盖了顶点着色器和像素着色器的基础理论。你将学习这里必要的每个程序顶点和像素从写windows熟悉操作系统。另外,有篇介绍Shader Studio一个设计顶点和像素着色器的工具。

第一部分: 介绍着色器编程

顶点着色器基础

你需要知道什么设备

在管线上的顶点着色器

为什么使用顶点着色器?

顶点着色器工具

NVIDIA Effects Browser 2/3

NVIDIA Shader Debugger

Shader City

Vertex Shader Assembler

NVIDIA NVASM - Vertex and Pixel Shader Macro Assembler

Microsoft Verex Shader Assemler

Shader Studio

NVLink 2.x

NVIDIA Photoshop Plug-ins

Diffusion Cubemap Tool

DLL Detective with Direct3D Plug-in

3D Studio Max 4.x/gmax 1.1

顶点着色器体系

高级View of顶点着色器编程

检测顶点着色器支持

顶点着色器声明

设置顶点着色器常量寄存器

写和编译一个顶点着色器

应用提示

顶点着色器中的复杂指令

所有整合在一起

欺骗和掩饰

写顶点着色器的方针

编译顶点着色器

创建顶点着色器

设置顶点着色器

释放顶点着色器资源

下一步发生什么?

顶点着色器编程

顶点着色器基础

这篇文章讨论顶点着色器,顶点着色工具,和光照和变换使用顶点着色器。

顶点着色器编程

这篇文章描述怎样写和编译一个顶点着色器。

关于 顶点和像素着色器编程学习(适合读者) 这本书是GPU中的汇编的学习资料

对于想深入,想进一步优化着色器代码,读懂汇编的GPU代码是很好的资料。

而对于想快速创建着色器,使用HLSL GLSL来说,这本书并不适合。

目录

前言

你需要什么设备

管线的顶点着色器

为什么使用顶点着色器?

前言

(或者,为什么他又写了另一本 ?)

另一本书?这里我们反对...

我们已经看到曾经越来越多图形性能在PC上自从3dfx发布Voodoo卡在1995以来。虽然这个性能已经允许PCs运行更快的图形,它可能不允许更快的运行图形。基本限制他们大部分的固定渲染管限在PC图形加速卡沙锅内更快,意味着硅片设计者已经把图形算法集程到图形卡芯片,产生的结果是,游戏和应用开发使用不会使用这些指定固定的算法。

十年前,图形技术以及功能作为RenderMan从Pixar动画工作室有已经成为专业高质量真实渲染的手段。

Pixar的使用的RenderMan他们开发电影作为Toy Stary and A Bug's LIfe已经在真实图形产生了结果让全世界的观众吃惊。RenderMan'可编程的允许它发展主要的新的渲染技术在创造。

利用严格显示在计算,RaenderMan允许程序灵活和创建到了极限。然而这个可编程受到软件实现的限制。

现在,这次,廉价的硬件已经可以开始实现类似RenderMan使用的实时性能了。

重要的3DAPIs(DirectX和OpenGL)已经进化图形硬件。重要的新特性是可编程提供汇编语言结构来变换和光照硬件(顶点着色器)和像素管线(pixelShader).这个可编程管线为开发更自由的在以前的实时应用中是从来没有过的。

着色器编程是新的和实时向游戏程序员挑战。坚持到底...

你需要知道什么/设备

你需要基本的理解数学带边性的游戏引擎,你需要一个基本的理解DirectX 图形API的书籍。它帮助如果你知道怎样使用变换和光照(T&L)管线和SetTextureStageState()调用。如果你需要这写话题的帮助,我推荐从头的先看些介绍性的文字,像《Beginning Direct3D Game Programming》。

DirectX 8.1 SDK

Windows 2000 至少 Service Pack 2或者更高或 Windows XP 专业版(NVIDIA着色器仅可以运行在这些系统上)

Visual C/C++ 6.0至少Service Pack 5(需要DirectX 8.1 SDK)或者更高

至少128的内存

至少500MB的硬盘

硬件加速卡。可以获取最大可视化例子,你需要自己相关的图形硬件。像素着色器例子将仅仅运行在GeForce3/4 TI或者Radeon 8x00类的板卡上。

最新的图形加速卡驱动

如果不幸没有自己的GeForce33/4TI,Radeon 8x00,或者一个类似的图形卡(硬件支持着色器),汇编接口将提供更高的软件顶点着色器在AMD和Intel有优化为它们的CPUs.这些软件实习将跳国当没有顶点着色器有能力发现硬件。不兼容的软件模拟是像素着色器。

管线的顶点着色器

下面的图表展示了源或多边形,顶点和像素操作在Direct3D管线在非常简单的方式。

在原数据级别,顶点被集合和镶嵌。这个高目标的原始数据模块,工作在镶嵌高级原始像N-Patch(作为支持ATI RAdeon 8500在硬件上),五次贝塞尔曲线,B-splines,和矩形和三角形的块。

注意:它看气力是,开始使用21.81驱动,NVIDIA不在支持RT-Patches在GetForce3/4TI.

GPU支持N-Patches产生控制Bezier三角形点每个输入数据三角形。这个控制mesh是基于在位置和原始三角形的饿法线。Bezier表面是镶嵌和粗略值,创建更多三角形在芯片上[Vlachos01].

注意: N-Patch的功能在jDirect3D 8.1被增强。有更多控制覆盖在篡写位置的工作和产生顶点的法线。新的D3DRS_POSITIONORDER和D3DRS_NORMALORDER渲染状态控制这个插补目标。这个位置插补目标可以被也被设置D3DORDER_LINEAR或者D3DORDER_CUBIC.

注意:法线插补目标可以被设置为D3DORDER_LINEAR或者D3DORDER_QUADRATIC.在Direct3D 8.0,位置插补被硬件wire到D3DORDER_CUBIC和规格化插补被hard-wire到D3DORDER_LINEAR.

注意:如果N-Pathches整合使用可编程顶点着色器,你可以贮藏位置和规格化信息在输入寄存器的v0和v3.那是因为N-Patch tessellator需要知道通知的驱动在哪里。

下一个阶段展示图1覆盖帝国难点在Direct3D管线操作。有两种不同的顶点处理方式:

1.固定渲染管线 - 这是标准的几何&光照(T&L)管线,功能是固定的。T&L管线可以被渲染状态控制,矩阵,光照和采制参数。

2.顶点着色器. -这是新的在DirectX8中的机制。取代设置参数来控制管线,你写一个着色器程序在图形硬件上执行。

焦点就在顶点着色器上。它明显的简化了图1的面裁剪,用户裁剪面,视锥裁剪,同质划分,和视口贴图操作在顶点着色器后。因此,这些状态是固定的不能变化,而顶点着色器可以。顶点着色器也不能些顶点,它不可以创建顶点;它产生一输出从每个接收的输入。

那么顶点着色器的好处呢?

为什么使用顶点着色器?

如果你使用顶点着色器,你越过固定渲染管线或T&L管线。但是为什么你想跳过它呢?

传统的T&L管线不支持流行的顶点计算它自己的属性,和处理经常要在几何引擎和CPU共享。有时,导致冗余。

这也缺乏自由。许多在游戏中看起来相似的hard-wired效果。固定渲染管线使开发者不能自由的的独特的和革命的图形效果。程序上的模块使用顶点着色器开启更多一般语法给指定公共操作。灵活的使用顶点着色器,开发者可以完成下面的包括:

几何程序(布模拟,肥皂泡[Isidoro/Gosselin])

角色的高级顶点混合和顶点morphing(tweening)

纹理产生[Riddle/Zecha]

高级关键帧interpolation(complex facial expression and speech)

粒子系统渲染[Le Grand]

实时修改透视视图(lens effects,underwater effects)

高级光照模型(often in cooperation with the pixel shader)[Bendel]

转置贴图步骤[Calver]

有更多的效果可以使用顶点着色器,一些还没有被想出来。例如,一些SIGGRAPH书中最后描述的图形学效果被在SGI硬件上实现。也许很快就向使用顶点和像素着色器向消费者硬件挑战。

另外开发者和艺术家开始创造性,着色器也强迫视频内存贷款被在着色器芯片硬件上执行。那走,例如,Bezier patches.每个顶点的浮点值(plus一个固定的每个原始像素值),一个可以设计顶点着色器到产生位置,法线,一系列的纹理坐标。顶点着色器相等给你解压缩能力,位置,法线,颜色,矩阵和纹理坐标数据和保存一些有价值的带宽没有另外的浪费。

在你未来的学习曲线上有好处。程序员模块使用顶点着色器是可升级的。因此,增加新的指令为开发者。

顶点着色工具

作为你将看到的,你被需要控制指定的RISC-系的汇编语言在程序里顶点着色器因为使用顶点着色器被执行责任为程序的几何处理器。因此,它重要的使用正确的工具开始开发着色器是快速的和可能卓有成效的。

I would like to present the tools that I am aware of at the time of publication.

NVIDIA提供了它自己的DirectX 8 SDK,并装入它的工具,demos和介绍DirectX 8.0.所有demos使用叫做效果浏览器的框架。

 楼主| 发表于 2006-9-13 13:31:25 | 显示全部楼层

这个Effects Browser是一款很棒的测试和开发顶点和像素着色器的工具。你可以选择你喜欢看的效果在左边圆柱。中间给你可能的看到顶点来源或像素着色器。正确的圆柱显示效果。

不是所有的图形卡都支持Effect Browser里的效果。 GeForce3/4TI将支持所有的效果。在你当前图形卡偏爱独立的,我推荐你下载NVIDIA的DirectX 8 SDK和试图。有许多例子,包括解释细节,展示给你使用顶点和像素着色器变化的效果。即将来临的NVIDIA效果浏览器3将提供自动在线更新能力。

顶点着色器体系

让我们更深入的获取图形信息看下顶点着色器的体系:

寄存器(128bits == 4floats 12 entries)->Vertex Input(128bits == 4floats 16entries)

->VertexShader 128 instructions -> VertexOutput(128bits == 4 floats 13entries)- ->

Constant Memory(128bits == 4floats 96entries RADEON 8500: 192entries)

顶点着色起上所有数据都用128bit四维-floats(4x32bit):

x y z w

一贯件顶点着色器已经被典型的SIMD(Single Instruction Multiple Data)处理器,作为你应用一个指令和影响到4个32bit变量的设置。数据格式非常有用因为大部分变换和关照计算使用4x4矩阵或四元组执行。指令非常简单和容易理解。顶点着色器不允许任何循环,跳转,或者条件分支,这意味着它执行起来是线性程序-一个接一个。DirectX 8.x最大的顶点着色器程序指令长度为128指令。整合顶点着色器到有计算转换和另一个计算光照难以忍受的。仅仅一个顶点着色器在一次可以被激活,而且活动的顶点着色器械=必须所有请求每个顶点输出数据。

所有顶点着色器使用16个输入积存器(命名为v0-v15,每个寄存器由128bit(4x32)quad-floats)组成用于存取顶点输入数据。顶点输入寄存器可以容易的从电点顶点获取数据:位置坐标,法线,扩散和反射颜色,雾坐标,和点大小信息为坐标多个纹理。

常量寄存器(常量内存)被在顶点着色器启动执行前通过CPU加载由程序员定义。顶点着色器不可以写常量寄存器。他们被使用存储程序员像光位置,矩阵,程序上的特殊动画效果,顶点插补数据为morphing/关键帧interpolation,更多。常量可以不使用程序,而且甚至被间接的定位地址使用地址寄存器(a0.x,但是每条指令仅仅可以使用一个常量。如果一个指令需要更多的常量,它必须加载一个在被请求之前被加载到临时的寄存器中。常量寄存器从c0-c95,在ATI RADEON 8500,c0-c191.

临时积存器由12个寄存器计算媒体组成。它们可以被用来加载数据和存储数据(读/写).临时寄存器被r0-r11.

顶点输出寄存器有13,依赖于硬件。输出寄存器总用于输出。输出寄存器也可以每个执行光栅,你的顶点着色器程序已经仅仅访问它。最后结果也被另一个顶点执行,顶点变换到同质的裁剪空间。下表是一个所有可用到的寄存器的表。

Input(v0-v15) 16 RO1

Output(o*) GetForce 3/4TI: 9; RADEON 8500: 11 WO

Consants(c0c=-c95) vs.1.1 Specification: 96; RADEON 8500: 192 RO1

Temporary(r0-r11) 12 R1W3

Adress(a0.x) 1(vs.1.1 and higher) WO(W: only with mov)

在输出寄存流自然是顶点着色器标识符只读的和输出寄存器是可写的。

高级视图的顶点着色器程序

每次仅仅可以激活一个顶点着色器。在每个基础任务上更好想法是写顶点着色器。在不同的着色器之间切换是很小消耗的,例如,纹理改变。所以如果对象需要特殊的几何或光照呢,它将获取适当的着色器信息。让我们构造一个抽象的例子:

你可以遭遇外部的行星。在正规马甲外穿女衣服仅仅使用jigsaw,you move through the candlelit cellars.一个怪物允许,你蜷缩在那些柳条箱里一个正常的找到其他行星。同时思考你的命运是英雄保存jigsaws,你启动计算在这个场景里的几个顶点着色器。

有一个或更多妖怪动画,光,也许反射它的环境。其他的顶点着色器将被用在地板,墙壁,箱子,摄影机,烛光和你的jigsaw.也许地板什么用同样的着色器,但是烛光和摄影机用它们自己的。这依赖于你的设计和图形卡硬件的强大。

注意:你也许使用顶点着色器在每个对象或者每个mesh基础。如果,例如,一个*.md3模型组成,我们说10个meshes,你可以执行10个不同的顶点着色器,但是也许损害你的游戏性能。

每个顶点着色器驱动程序必须运行使用下面的步骤:

检测D3DCAPS8::VertexShaderVersion检测顶点着色器的支持情况。

使用D3DVSD_*宏定义影射顶点缓冲流到输入寄存器

使用SetVertexShaderConstant()设置常量寄存器

当顶点着色器使用D3DXAssembleShader*()(这个预编译程序汇编)写在顶点着色器

使用CreateVertexShader()创建顶点着色器句柄

使用SetVertexShader()指定顶点着色器对象

使用DeleteVertexShader()删除顶点着色器。

检测顶点着色器版本支持

检测用户是否安装顶点着色器的软件或硬件实现是重要的。如果缺乏指定特性的支持,然后应用程序可以要求命令。下面的语句检测顶点着色器版本1.1:

if(pCaps->VertexShaderVersion < D3DVS_VERSION(1,1))

return E_FAIL;

下面的语句检测顶点着色器版本1.0:

if(pCaps->VertexShaderVersion < D3DVS_VERSION(1,0))

return E_FAIL;

D3DCPAS8结构必须调用GetDeviceCaps()函数来跳虫。如果你使用公共文件框架提供的DirectX 8.1 SDK,框架将帮你完成。如果你的图形硬件不支持你的顶点着色器版本,你必须使用D3DCREATE_SOFTWARE_VERTEXPROCESSING标志在CreateDevice()调用软件顶点着色器。先前提及的

优化软件实现在Intel和AMD提供它们的各自的CPUs将处理顶点着色器。

支持的顶点着色器版本:

Version

0.0 DirectX 7

1.0 DirectX 8 without addresss register a0

1.1 Direct 8 and DirectX 8.1 with one addresss register a0

2.0 DirectX 9

在1.0和1.1之间仅仅是a0寄存器的支持的不同。DirectX 8.0和DirectX 8.1引用光栅线和软件模拟设备被Intel和AMD它们各自的CPU支持1.1.在时间发布上,仅仅GeForce3/4TI和RADEON 8500驱动板卡在硬件上支持1.1.不知道仅仅支持vs 1.0的图形卡出版没有,所以是遗留下来的版本。

顶点着色器定义

你必须在使用顶点着色器之前定义它。这个定义可以叫做静态外部接口。一个例子也许是这样的:

float c[4] = {0.0f,0.5f,1.0f,2.0f};

DWORD dwDecl0[] - {

D3DVSD_STREAM(0),

D3DVSD_REG(0,D3DVSDT_FLOAT3),

D3DVSD_REG(5, D3DVSDT_D3DCOLOR),

D3DVSD_CONST(0,1),*(DWORD*)&c[0],*(DWORD*)&c[1],*(DWORD*)&c[2],*(DWORD*)&c[3],D3DVSD_END()

);

顶点着色器械定义设置数据流0使用D3DVSD_STREAM(0).之后,使用这个定义设置绑定到流的源

SetStreamSource().你可以引入不同的Direct3D流来渲染引擎。

注意: 例如,数据流可以控制位置和法线,同时第二个控制颜色值和纹理坐标。这也在单个纹理渲染和多纹理渲染产生不同的方式:使用第二个设置纹理坐标开启流。

你必须定义输入顶点属性或引入的顶点数据有输入寄存器的映射。D3DVSD_REG帮定单个顶点寄存器到顶点元素/属性从顶点流。在这个例子,一个D3DVSDT_FLOAT3值将被放在第一个输入寄存器,和D3DVSDT_D3DCOLOR颜色值将被放在六个输入寄存器。例如,位置数据将被输入寄存器使用D3DVSD_REG(0,D3DVSDT_FLOAT3)和法线数据压缩,可以被处理到输入寄存器3(v3)使用D3DVSD_REG(3,D3DVSDT_FLOAT3).

开发者绘制地图每个输入顶点属性到指定输入寄存器是仅仅重要的如果一个人想获得N-Patches音问N-Patch tessellator需要在v0和在v3法线数据。另外,开发者自由定义作为看发作映射。例如,位置数据将被输入寄存器0(v0)用D3DVSD_REG(0,D3DVSDT_FLOAT3),和法线数据将被输入寄存器3(v3_使用D3DVSD_REG(3,D3DVSDT_FLOAT3).

注意:对比,映射顶点数据输入指定寄存器是使用固定的函数管线 d3d8types.h有列表#defines那个预先确定顶点输入固定函数管线。指定顶点元素像位置或法线必须在指定寄存器的顶点输入内存位置。例如,顶点位置在D3DVSDE_POSITION到寄存器0,发散颜色是围绕D3DVSDE_DIFFUSE到寄存器5,等。这里完成从d3dtypes.h列表。

第二个参数D3DVSD_REG指定在维度和算法数据类型。下面的值被定义在d3d8types.h:

注意: GeForce3/4TI不支持D3DVSDT_UBYTE4,作为显示在D3DVTXPCAPS_NO_VSDT_UBYTE4 caps位。

D3DVSD_CONST加载常量值在顶点着色器常量内存。第一个参数在其实地址填充常量数组。可能的值范围从0-95或者,在RADEON 8500情况,从0-191.我们从0地址开始。第二个数值是从常量响亮(quad-float)被加载。一个向量是128位长,所以我们加载4个32bit浮点一次。如果你想加载4x4矩阵,你将使用下面语句加载为4个128bit quad-flaots到常量寄存器c0-c3:

D3DVSD_END产生结束符号到标记在顶点着色器定义。另外的例子是:

数据流被设置使用D3DVSD_STREAM(0).顶点位置(值,值,值,1.0)也许被发现在v0,法线值也许被发现v3,发散颜色也许在v5范围,和纹理坐标(值,值,0.0,1.0)也许被发现到v7.常量寄存器c0获取一个128bit的值。

设置顶点着色器常量寄存器

你将填充着色器使用SetVertexConstant()和使用GetVertexShaderConstant():从这些寄存器获取值:

SetVertexShaderConstant()被作为定义:

HRESULT SetVertexShaderConstant(DWORD Register,CONST Register,CONST void* pConstantData,DWORD ConstantCount);

作为状态初期,有至少96个常量寄存器(RADEON 8500有192)比可以用四个浮点值在顶点被执行前填充。第一个参数有加载数据到顶点常量数组。最后一个参数握有常量值(4x32位值)加载到顶点常量数组。所以在第一行以上,vZero将被加载到寄存器0,matTranspose将北加载到寄存器超过7,matViewTranspose将被加载到寄存器12超过15,寄存器16超过19没有被使用,fLight被加载到寄存器20,和寄存器25超过27被使用。

注意:suoyi zai D3DVSD_CONST使用顶点着色器不同定义和SetVertexShaderConstant() D3DVSD_CONST可以被仅仅一个使用,同时SetVertexShaderConstant()可以在DrawPrimitive()前被加载。

我们有学到怎样检测值顶点着色器的硬件版本,怎样定义和怎样在顶点着色器单元定义常量单元。下一个我们将学习怎样写和编译顶点着色器程序。

写和编写顶点着色器

在我们可以编译顶点着色器前,我们必须写。我们喜欢使用高级视图指令进行最初的设置和然后给未来在下篇文章进行顶点着色器编程,‘顶点着色器编程“。

语法每个指令像这样:

OpName dest,[-]s1,[,[-]s2,[,[-],s3]];comment

e.g.

mov r1,r2;

mad r1,r2,-r3,r4; contents of r3 are negated

你可以下载列表从www.shaderx.com。检测SDK附加的信息。

顶点着色器ALU被多线程向量处理器进行操作在quad-float数据。它包含两个函数单元。SIMD向量单元可依赖的mov,mul,add,mad,dp3,dst,min,max,slt,和sge指令。特殊的指令单元如rcp,rsq,logp,expp,和lit指令。大部分这些指令有一个执行周期,虽然rcp和rsq执行少于下面指定的状况的周期。它们仅仅在跟踪顶点着色器,但是它们实际上很长周期当结果使用只的因为开启寄存器延迟。

应用线索

rsq,例如,使用规格化响亮在光比较。可说明的expp可以被雾效果,程序上的产生糟点(看NVIDIA花边糟点例子在同伴CD),例子举止行为在例子系统上(看NVIDIA里子系统在同伴CD上),或者在实现系统怎样的对象在游戏中损害。你将使用它当快速改变函数是必要的。这个相反的使用对数函数使用logp,哪里是有用的如果极端的慢增长必要的(也它们增长漂亮快速在开始).在航行日志在函数可以在反转的支书函数,意味这它取消指数函数的操作的。

光质量处理默认使用直射光。它计算发散和反射光使用夹注基于在N*L和N*H在反射能力上。没有变薄,但是你可以使用衰减等级分别的使用dst指令产生结果。这对于构造稀释的因素为点和聚光灯是必要的。大的小的指令允许夹住和完全的计算值。

顶点着色器中的复杂指令

顶点着色器中也有复杂的指令支持。术语"macro"将被在这些指令中使用,因为它们不像简单的C-预处理器中的宏。在使用这些指令前,你应该仔细想想。如果你使用它们,你也许遗失控制你的有限的128bit指令优化路径。另一方面,软件模拟模式提供在Intel 或AMD可能的m4x4复杂指令的优化(也许其他或者在未来支持).也可能在未来,一些图形硬件也许使用大门计算和最优化的m4x4.所以,如果你需要,例如,4个dp4在你的顶点着色器被汇编源代码调用,它也许被高的思想取代它们m4x4.如果你决定使用一个m4x4指令在你的着色器,你将不可以使用dp4调用之后相同的数据因为有些微笑的转换结果的不同。如果,例如,计算位置的双指令,z-光照将是这样的结果:

Macro Parameters Action Clocks

expp frc log m3x2 m3x3 m3x4 m4x3 m4x4

你可以执行所有的变换和光照指令使用这些指令。如果它看起来像在你的一些指令缺少,休息保证在你可以完成它们通过存在的指令。例如,分开的两个成员可以实现使用响应的和增加。你甚至可以实现在顶点着色器中所有的固定函数。这里展示了NVLink例子在同伴CD上。

进行所有的设置

现在让我们看这些寄存器和典型的使用顶点着色器ALU.

在vs.1.1,有16个输入寄存器,96个常量寄存器,12临时寄存器,1地址寄存器,和向上的13个输出寄存器没光栅化。每个寄存器持有4x32bit值。每32bit位值是可理解的经过x,y,z,和w写在下放。换句话说,一个128bit值有x,y,z,w值组成。访问这些寄存器组件,你必须添加x,y,z,w在寄存器名字结束。让开始输入寄存器。

使用输入寄存器

16个输入寄存器被使用它们的名字进行访问v0-v15.典型的值提供输入顶点寄存器是:

位置(x,y,z,w)

发散颜色(r,g,b,a) - 0.0 到 + 1.0

反射颜色(r,g,b,a) - 0.0到 +1.0

向上到8个纹理坐标(每个作为s,t,r,q或u,v,w,q)但有四个或6个是规格化的,以来在硬件的支持

雾(f,*,*,*)-值在使用雾平衡

点大小(p,*,*,*)

你可以访问x-组件使用v0.x值,y-组件使用v0.y,等。如果你需要知道RGBA发散颜色组件,你检测v1.y.你也许设置雾值,例如,设置v7.x.其他三个32bit组件,v7.y,v7.z,和v7.w,将不被使用。输入寄存器被设为只读。每个指令也许仅仅访问顶点寄存器。不指定输入寄存器组件默认0.0到x,y,和z组件和到1.0为w组件。在下面的例子,4个组件点乘积在每c0-c3之间和v0被存储在oPos:

dp4 oPos.x,v0,c0

dp4 oPos.y,v0,c1

dp4 oPos.z,v0,c2

dp4 oPos.w,v0,c3

像代码片段通常设置从发射空间到裁减空间使用已经凹面的世界,视图和发射矩阵。下面的四组点乘:

oPos.x - (v0.x * c0.x) + (v0.y * c0.y) + (v0.z * c0.z) + (v0.w * c0.w)

给我们使用长度单元(规格化)向量,它点乘两个向量将总在范围[-1,1]。因此,oPos将总被获取值在这个范围内。二选一的,你将使用:

m4x4 oPos,v0,c0

不要忘记使用这些复杂指令一向经过你的顶点着色器因为被过早的讨论,这也许被在dp4和m4x4结果有些不同。你将限制仅仅使用输入寄存器在每个指令。

所有数据在输入寄存器仍然持久稳定通过顶点着色器执行和甚至比较。这意味者它们仍然在顶点着色器的生存器内比较。所以他可以再使用输入数据在下个顶点着色器。

使用常量寄存器

典型的使用常量寄存器包括:

矩阵类型-quad-floats是典型的4x4矩阵的行

光描述(位置,衰减等)

当前时间

顶点interpolation数据

程序上数据

有96个quad-floats(或着RADEON 8500,192quad-floats)提供存储常量数据。这个原因大的色绘制矩阵可以被使用,例如,顶点索引混合知道(矩阵角色调色板."

常量寄存器被从透视顶点着色器是只读的,然而应用可以被读和写信到常量寄存器中。常量寄存器仍然在它们的数据不再顶点着色器的生存器内,所以它重新使用这些数据在下个顶点着色器。这允许app避免多余的设置SetVertexShaderConstant()调用。从范围外读常量寄存器返回(0.0,0.0,0.0,0.0).

你将使用仅仅一个常量寄存器每个指令,但是你将使用它许多次。例如:

mul r5,c11,c11;

add v0,c4,c3

更多的复杂查看,但是有效的,例如:

mad r0,r0,c20,c20;

使用地址寄存器

你访问地址寄存器使用a0到an(更多的地址寄存器将可用到在顶点着色器版本比1.1高).在vs.1.1仅仅使用一个间接地址操作偏离常量内存。

c(a0.x + n);

这里一个使用地址寄存器的例子:

mov a0.x,r1.x

m4x3 r4,v0,c[a0.x + 9];

m3x3 r5,v3,c[a0.x + 9];

依赖在临时寄存器r1.x中存储的值,不同的常量寄存器被在m4x3和m3x3指令中使用。请注意寄存器a0仅仅存储同时数据和没有分数(仅仅整数)和a0.x是仅仅有效的组件a0.更远的,一个顶点着色器也许写到a0.x仅仅经过mov指令。

注意:小心a0.x如果有仅仅软件模拟模式;执行可以被意味深长的可以引出[Pallister].

使用临时寄存器

你可以使用12个临时寄存器使用r0-r11.这里有些例子:

dp3 r2,r1,-c4

mov r0.x,v0.x

mov r0.y, c4.w

mov r0.z,v0.y

mov r0.w,c4.w

每个临时寄存器有单个写和三倍的读访问。因此,一个指令有相同的临时寄存器作为源三次。顶点着色器在写之前不能读取里面的值。如果你试着读取临时寄存器不能使用值,API将给你一个错误信息创建顶点着色器。

使用输出寄存器

有向上到13仅仅写输出寄存器比可以被访问使用下面寄存器名字。它们被定义作为输入在光栅化,每个寄存器被用小写字母处理"o".输出寄存器被命名为建议他们使用像素着色器。

oDn oPos oTn oPts.x oFog.x

这里一个典型的例子将战士怎样使用oPos,oD0,和oT0寄存器:

dp4 oPos.x,v0,c4

dp4 oPos.y,v0,c5

dp4 oPos.z,v0,c6

dp4 oPos.w,v0,c7

mov oD0,v5

mov oT0,v2

使用4个dp4指令映射从发射裁减空间已经转道凹面世界,视图和投影矩阵被展示下。首先mov指令移动在v5输入寄存器到颜色输出寄存器,和第二个mov指令移动到值v2寄存器到输出到纹理寄存器。

使用oFog.x输出寄存器被展示在下面的例子里:

dp4 r2,v0,c2

sge r3,c0,c0

add r2,r2,-c5.x

mad r3.x,-r2.x,c5.z,r3.x

max oFog.x,c5.w,r3.x

有一个雾值许可更多普通的雾效果比使用z的位置或w值。雾距离在插补使用距离在标准雾方程使用管线后。

 楼主| 发表于 2006-9-13 13:32:06 | 显示全部楼层

[译]Direct3D8.ShaderX(二)

翻译自《Direct3D ShaderX Vertex and Pixel Shader Tips and Tricks》
翻译超级烂,仅供参考,建议直接看原版。
烂文版权归偶 microsoftxiao@163.com

适合读者: 有C/C++基础或其他高级语言等,理解基本的windows编程或同等的Linux编程,

对COM(组件对象模型)有初步的认识, 对3D图形和硬件工作方式有初步的了解,

对HLSL/GLSL有浓厚的兴趣, 有Direct3D/OpenGL的固定渲染管线的基本使用经历。

对Visual C++ BCB或其他编译器能够轻松的调试 设置,没有Visual C++的使用经验还请熟悉下

它的基本使用方法以避免不必要的精力浪费在工具的使用上。

第二章 顶点着色器编程

章目录概览

Wolfgang F.Engel

RacorX

公共文件框架

检测顶点着色器支持

顶点着色器定义

设置顶点着色器常量寄存器

顶点着色器

编译顶点着色器

创建顶点着色器

设置顶点着色器

释放顶点着色器资源

非着色器特效代码

摘要

RacorX2

创建顶点着色器

摘要

RacorX3

顶点着色器定义

设置顶点着色器常量寄存器

顶点着色器

直射光

发散反射

摘要

RacorX4

顶点着色器定义

设置顶点着色器常量

顶点着色器

镜面反射

非着色器特效代码

摘要

RacorX5

点光源

光衰减 for Point Lights

设置顶点着色器常量

顶点着色器

摘要

下一章?

//本章正文

在这章,一个非常简单程序展示旋转的方块将在进化为更多复杂的应用一个Bezier patch类使用发散和镜面反射模式和一光源源的特性。这个例子将用所有构造在每个其他的在大部分代码前例子被重复使用。这样,解释仍然聚焦在前进的指定的例子。

RacorX

RacorX显示绿色平坦的应用在方块上。例子示范使用DirectX 8.1 SDK提供的公共框架并展示怎样编译顶点着色器使用D3DXAssembleShader()函数。

作为所有即将来临的例子,基于公共的文件,<Alt>+<Enter>在窗口和全屏之间进行选择,利用<F2>可以让你选择可用的驱动,使用<Esc>将关闭应用程序。

首先让我们看下我们需要编译的程序:

源代码是RacorX.cpp,资源文件是winmain.rc和resource.h,icon文件是directx.ico,可执行文件是RacorX.exe.剩余文件为Visual C/C++ 6 IDE需要的文件。

编译这个例子,你将链接下面的 *.lib文件:

d3d8.lib d3dx8dt.lib dxguid.lib d3dxof.lib winmm.lib gdi32.lib user32.lib kernel32.lib advapi32.lib

大部分这些*.lib文件基于COM封装。d3dx8dt.lib是Direct3DX静态链接库。

注意:发布Direct3DX静态链接库被d3dx8.lib调用。也有 *.dll的构造的d3dx8d.dll在system32目录。它可以被COM封装的d3dx8d.lib调用。

所有这些*.lib文件不得不包含在Ojbejct/library模块实体 field.这个定位Project->Setting在Link tab:

Visual C/C++ 6 IDE工作区使用相同的文件名提供工作区。

它们被添加在选择项目->Add To Project->Fiels:

公共框架文件

公共框架文件帮助你加快建造的速度:

It helps to avoid how-tos for Direct3D in general, so the focus of this text is the real stuff.

It's common and is a tested foundation,which helps reduce the debug time.

在DirectX SDK中所有的Direct3D例子都使用它。学习时间非常短。

它的窗口模式方便调试。

Self-developed production code could be based on the common files,so knowing them is always an advantage.

A high-level view of the common files shows 14 *.cpp files in C:\DXSDK\Samples\Multimedia\Common\Src.

这写文件压缩了基本你需要的开始Direct3D编程的功能。最重要的包括,d3dapp.cpp,包括CD3DApplication.它提供了7个可以重载的函数 and used in the main *.cpp file of any project in this introduction:

virtual HRESULT OneTimeSceneInit(){return S_OK;}

virtual HRESULT InitDeviceObjects(){return S_OK;}

virtual HRESULT RestoreDeviceObjects(){return S_OK;}

virtual HRESULT DeleteDeviceObjects() {return S_OK;}

virtual HRESULT Render() { return S_OK;}

virtual HRESULT FrameMove(FLOAT) {return S_OK;}

virtual HRESULT FinalCleanup(){return S_OK;}

All that has to be done to create an application based on this framework code is to create a new project and new implementations of these overridable functions in the main source file.在DirectX SDK也展示了所有的Direct3D例子。

RacorX在RacorX.cpp里使用这些框架函数。它们可以被公共文件框架来调用。

Common files framework -> OneTimeSceneInit() etc InitDeviceObjects()

下面函数在RacorX.cpp被启动时调用:

ConfirmDevice() - (对硬件的支持进行检测)

OneTimeSceneInit() - (进行一次性的初始化)

InitDeviceObjects()

RestoreDeviceObjects()

(熟悉D3D Common Framework的相信这些函数已经很熟悉了)

同时应用程序在运行时还将调用:

FrameMove()

Render()

进行循环。

如果用户调整窗口大小,famework将调用:

InvalidateDeviceObjects()

RestoreDeviceObjects()

如果用户按下F2或点击File->Change Device且选择改变设备,例如,another resolution or color quality,框架将调用:

InvalidateDeviceObjects()

DeleteDeviceObjects()

InitDeviceObjects()

RestoreDeviceObjects()

如果用户退出应用程序,框架调用:

InvalidateDeviceObjects()

DeleteDeviceObjects()

FinalCleanup()

有匹配功能的成对儿函数。InvalidateDeviceObjects()释放和RestoreDeviceObjects()构造,

DeleteDeviceObjects()释放和InitDeviceObjects()构造。FinalCleanup()函数释放和OneTimeSceneInit()构造。

The idea is to give every functinal pair its own tasks.OneTimeSceneInit()/FinalCleanup()成对调用在开始和游戏结束阶段。一起用来加载或删除数据不依赖设备的数据。一个好的侯选也许是几何数据。目标InitDeviceObjects()/DeleteDeiceObjects()成对出现,像命名为暗示,数据依赖设备。如果已经加载数据改变当设备改变时,它将在这里被加载。下面的例子将加载,创建或破坏破坏它们的顶点缓冲区和索引缓冲区和它们的纹理。

InvalidateDeviceObjects()/RestoreDeviceOjbects()成对对改变窗口大小起反应。所以,例如,代码控制投影矩阵也许替换这里。另外,下面的例子将设置大部分的渲染状态在RestoreDeviceObjects().

现在再看RacorX. As shown in "Fundamentals of Vertex Shaders,"下面列表诡计在顶点生命器内:

检测顶点着色器支持使用D3DCAPS8::VertexShaderVersion片段。

使用D3DVSD_*定义顶点着色器映射顶点缓冲流到输入寄存器。

使用SetVerexShaderConstant()来设置顶点常量寄存器。

使用D3DXAssembleShader*()编译已经写好的顶点着色器(做为选择:使用着色器汇编预先编译)

使用CreateVertexShader()创建顶点着色器。

使用SetVertexShader()的指定的对象设置顶点着色器。

使用DeleteVertexShader()释放顶点着色器资源处理Direct3D引擎。

We will walk step by step throught this list in the following pages.

我们将在下面的页一步一步的做。

 楼主| 发表于 2006-9-13 13:32:43 | 显示全部楼层

基本的Direct3D8基本框架


#define STRICT
#include <basetsd.h>
#include <stdio.h>
#include <math.h>
#include <d3dx8.h>
#include "D3DApp.h"
#include "D3DFile.h"
#include "D3DFont.h"
#include "D3DUtil.h"
#include "DXUtil.h"

class CMyD3DApplication : public CD3DApplication
{
LPD3DXMESH m_pMesh;
private:
HRESULT ConfirmDevice(D3DCAPS8*,DWORD,D3DFORMAT);
protected:
HRESULT OneTimeSceneInit();
HRESULT FinalCleanup();
HRESULT InitDeviceObjects();
HRESULT DeleteDeviceObjects();
HRESULT RestoreDeviceObjects();
HRESULT InvalidateDeviceObjects();
HRESULT Render();
HRESULT FrameMove();
public:
CMyD3DApplication();
};

//------------------------------------
//Construction
//------------------------------------
CMyD3DApplication::CMyD3DApplication()
{
this->m_strWindowTitle = _T("DirectX 8 ShaderX");
this->m_bUseDepthBuffer = true;
}

HRESULT CMyD3DApplication::ConfirmDevice(D3DCAPS8*,DWORD,D3DFORMAT)
{

return S_OK;
}

HRESULT CMyD3DApplication::OneTimeSceneInit()
{

return S_OK;
}

HRESULT CMyD3DApplication::FinalCleanup()
{

return S_OK;
}

HRESULT CMyD3DApplication::InitDeviceObjects()
{
D3DXVECTOR3 eye(0.0f,0.0f,-5.0f);
D3DXVECTOR3 LookAt(0.0f,0.0f,0.0f);
D3DXVECTOR3 Up(0.0f,1.0f,0.0f);
D3DXMATRIX View;
D3DXMatrixLookAtLH(&View,&eye,&LookAt,&Up);
m_pd3dDevice->SetTransform(D3DTS_VIEW,&View);

D3DXMATRIX Identity;
D3DXMatrixIdentity(&Identity);
m_pd3dDevice->SetTransform(D3DTS_WORLD,&Identity);
return S_OK;
}

HRESULT CMyD3DApplication:eleteDeviceObjects()
{

return S_OK;
}

HRESULT CMyD3DApplication::RestoreDeviceObjects()
{
D3DXCreateTeapot(m_pd3dDevice,&m_pMesh,0);

D3DXMATRIX proj;
FLOAT fAspect = m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height;
D3DXMatrixPerspectiveFovLH(&proj,D3DX_PI/4,fAspect,1.0f,100.0f);
m_pd3dDevice->SetTransform(D3DTS_PROJECTION,&proj);
return S_OK;
}

HRESULT CMyD3DApplication::InvalidateDeviceObjects()
{

return S_OK;
}

HRESULT CMyD3DApplication::Render()
{
m_pd3dDevice->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0xffffffff,1.0f,0);
if(SUCCEEDED(m_pd3dDevice->BeginScene()))
{
D3DXMATRIX matTeapot;
D3DXMatrixRotationY(&matTeapot,timeGetTime()/1000.0f);
m_pd3dDevice->SetTransform(D3DTS_WORLD,&matTeapot);
m_pMesh->DrawSubset(0);

m_pd3dDevice->EndScene();
}
return S_OK;
}

HRESULT CMyD3DApplication::FrameMove()
{

return S_OK;
}

//----------------------------------------------------

//----------------------------------------------------

CMyD3DApplication g_d3dApp;

INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,INT)
{
MessageBox(NULL,"ddd","ddd",0);

if(FAILED(g_d3dApp.Create(hInst)))
return E_FAIL;
g_d3dApp.Run();
return 0;
}


然后在此基础进行Shader的检测,创建,设置等。

DirectX8在电驴里可以搜索"DX8a_SDK.exe"字样。

1.检测顶点着色器的支持

RacorX.cpp中ConfirmDevice()检测顶点着色器版本的支持:

HRESULT CMyD3DApplication::ConfirmDevice(D3DCAPS8* pCaps,DWORD dwBehavior,D3DFORMAT Format)

{

if(dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING) ||

(dwBehavior & D3DCREATE_MIXED_VERTEXPROCESSING))

{

if(pCaps->VertexShaderVersion < D3DVS_VERSION(1,1))

return E_FAIL;

}

return S_OK;

}

如果框架已经初始化硬件或者混合顶点处理,顶点着色器版本将被检测。如果框架被初始化为软件顶点处理,软件实现由Intel和AMD模拟且硬件能力不需要检测。

 楼主| 发表于 2006-9-13 13:33:00 | 显示全部楼层

The globally available pCaps能力数据结构将填充来调用到GetDeviceCaps()被框架。pCaps->VertexShaderVersion将获取顶点着色器版本一个DWORD值。宏D3DVS_VERSION帮助检测版本号。例如

D3DVS_VERSION(2,0)检测硬件至少支持vs2.0.

之后检测顶点着色支持的硬件能力,顶点着色器已经被定义。

2.顶点着色器的定义

定义顶点着色意味着映射指定的顶点数据到顶点着色输入寄存器;

因此,顶点着色器定义必须反射顶点缓冲层因为顶点缓冲必须转换正确顺序的顶点数据。一种使用非常简单的例子。顶点着色器将获取v0中的有效位置数据。

DWORD dwDecl[] =

{

D3DVSD_STREAM(0),

D3DVSD_REG(0,D3DVSDT_FLOAT3),

D3DVSD_END()

};

符合顶点缓冲层的像这样:

struct VERTEX

{

FLOAT x,y,z;

};

#define D3DFVF_VERTEX (D3DFVF_XYZ)

位置值竟存储在顶点缓冲区和围绕使用SetStreamSource()函数到设备数据流端口流入原始处理函数(这个HOS)层或直接在顶点着色,以来在使用HOS;在前面文章可以看Direct3D管线。

我们不使用顶点颜色这里,看定义是没有颜色值的。

3.设置顶点着色器常量寄存器

顶点着色器常量寄存器不得不填充调用SetVertexShaderConstant().例如,设置材质颜色在RestoreDeviceObjects()在c8:

FLOAT fMaterial[4] = {0,1,0,0};

m_pd3dDevice->SetVertexShaderconstant(8,fMaterial,1);

SetVertexShaderConstant()像这样定义:

HRESULT SetVertexShaderConstant(DWORD Register,CONST void* pConstantData,DWORD ConstantCount);

第一参数提供一系列常量寄存器将被使用;这种情况,它是8。第二参数存储128位数据在常量寄存器里,第三参数给你能力使用下面的寄存器更好。一个4x4矩阵可以存储在SetVertexShaderConstant()调用提讴歌能够在常量数。这些将在FrameMove()裁减矩阵中完成:

m_pd3dDevice->SetVertexShaderConstant(4,matTemp,4);

这样,c4,c5,c6和c7寄存器被使用矩阵存储。

4.顶点着色器

顶点着色器使用RacorX是非常简单的:

const char BasicVertexShader[] =

"vs.1.1 //Shader version 1.1 \n"
"dp4 oPos.x, v0,c4 //emit projected position \n"
"dp4 oPos.y, v0,c5 //emit projected position \n"
"dp4 oPos.z, v0,c6 //emit projected position \n"
"dp4 oPos.w, v0,v7 //emit projected position \n"
"mov oD0,c8 //material color - c8 \n";

它使用常量字符数组内联的在RacorX.cpp中。这个顶点着色器合并在vs.1.1顶点着色器械实现规则。它从连接和转换世界,视图,发射句镇到裁减矩阵或者使用dp4指令和kicks out到oD0材质颜色使用mov.

像上面战士的,c4-c7常量寄存器的值被在FrameMove()中设置。这些值将在下面的代码片段里设置:

D3DXMatrixRotationY(&m_matWorld,m_fTime * 1.5f);

D3DXMATRIX matTemp;

D3DXMatrixTranspose(&matTemp,&(m_matWorld * m_matView * m_matProj));

m_pd3dDevice->SetVertexShaderConstant(4,matTemp,4);

首先这quad是旋转围绕y轴被D3DXMatrixRotationY()调用,然后连接矩阵被转换和存储在常量寄存器c4-c7.这个源D3DMatrixRotationY()函数也许像这样:

VOID D3DMatrixRotationY(D3DMATRIX * mat,FLOAT fRads)

{

D3DXMatrixIdentity(mat);

mat._11 =cosf(fRads);

mat._13 = -sinf(fRads);

mat._31 = sinf(fRads);

mat._33 = cosf(fRads);

}

fRads相等于数量的你想旋转关于y轴。之后改变在矩阵方式的值,我们转换矩阵使用D3DXMatrixTranspose(),所以它的栏是存储行。为什么不得不转换矩阵?

一个4x4矩阵看起来像:

a b c d

e f g h

i j k l

m n o p

这个公式为转换向量(v0)通过矩阵是:

所以每个柱矩臻将使用每个向量乘以。我们的顶点着色器使用4个dp4指令:

dp4指令乘以使用每个向量组件行矩阵。没有变换,我们将结束:

变换的矩阵,它看起来像在常量内存:

a e i m

b f j n

c g k o

d h l p

所以4 dp4操作将现在生产:

被正确的怎样向量转换的工作。

dp4获取矩阵值有效常量寄存器c4-c7和顶点位置在输入寄存器v0.临时寄存器没有在例子里。dp4的点乘指令是写到oPos输出寄存器,值常量寄存器c8是移动到输出寄存器oD0,使用输出发散颜色值。

5.编译顶点着色器

顶点着色器被用字符数组编译然后调用用下面代码片段在RestoreDeviceObejcts():

rc = D3DXAssembleShader(BasicVertexShader,sizeof(BasicVertexShader) -1,0,NULL,&pVS,&pErrors);

if(FAILED(rc))

{

OutputDebugString("Failed to assembel the vertex Shader,errors:\n");

OutputDebugString((char*(pErrors->GetBufferPointer());

OutputDebugString("\n");

}

D3DXAssembleShader()创建一个二进制版本的着色器在有效的ID3DXBuffer接口在pVS的缓冲对象:

HRESULT D3DXAssembleShader(

LPVOID pSrcData,UINT SrcDataLen,DWORD Flags,LPD3DXBUFFER* ppConstants,LPD3DXBUFFER*

ppCompiledShader,LPD3DXBUFFER* ppComilationErrors

);

源数据被在第一个参数提供,且数据长度在字节被在第二个参数提供。有两个可能的第三个参数:

#define D3DXASM_DEBUG 1

#define D3DXASM_SKIPVALIDATION 2

第一个插入debug信息作为注释到着色器和第二个跳过确认。这个标志可以被工作着色器设置。

有效的第个参数,一个ID3DXBuffer接口可以一被输出获取顶点着色器定义常量片段。忽略这个参数,它设置NULL.这种情况的错误,这个错误解释将被存储在缓冲对象有效的ID3DXBuffer接口在pErrors.看OutputDebugString(),debug在Visual C/C++ IDE必须启动F5处理。

6.创建顶点着色器

顶点着色器被确认句柄提供他是找回到CreateVertexShader()在m_dwVertexShader.下面代码线可以发现在RestoreDeviceObjects():

rc - m_pd3dDevice->CreateVertexShader(dwDecl,(DWORD*)pVS->GetBufferPoint(),&m_dwVertexShader,0);

if(FAILED(rc))

{

OutputDebugString("Failed to create the vertex shader, errors: \n");

D3DXGetErrorStringA(rc,szBuffer,sizeof(szBuffer));

OutputDebugString(szBuffer);

OutputDebugString("\n");

}

CreateVerteShader()获取使用二进制版本的顶点有效果着色器ID3DXBuffer接口。这个获取顶点着色定义在有效的dwDecl,哪个映射顶点数据指定在顶点着色输入寄存器。如果一个错误发生,它的解释是可到达的有效指针的缓冲对象是重新回到有效的ID3DXBuffer接口在pVS->GetBufferPointer().D3DXGetErrorStringA()解释所有Direct3D和Direct3DX HRESULTS和返回一个错误的消息在szBuffer.

它可能强制的使用软件顶点处理D3DUSAGE_SOFTWAREPROCESSING标志。它必须当D3DRS_SOFTWAREVEREXPROCESSING数的D3DRENDERSTATETYPE枚举类型是真。

7.设置顶点着色器

顶点着色器被设置有效的SetVertexShader()在渲染函数:

m_pd3dDevice->SetVerexShader(m_dwVertexShader);

仅仅参数必须提供句柄到顶点着色器。 这个函数执行顶点着色器常常在顶点。

8.释放顶点着色器资源

顶点着色器资源必须调用完释放:

if(m_dwVertexShader != 0xffffffff)

{

m_pd3dDevice->DeleteVertexShader(m_dwVertexShader);

m_dwVertexShader = 0xffffffff;

}

这例子释放顶点着色器资源在InvalidateDeviceObjects()框架函数;如果窗口大小或者设备被改变必须发生。

9.非着色器代码

每有着色器指定的RacorX细节使用设置渲染管线和顶点和着色器缓冲句柄。一个小的渲染管线不得不设置在RestoreDeviceObjects():

m_pd3dDevice->SetRenderState(D3DRS_ZENABLE,TRUE);

m_pd3dDevice->SetRenderState(D3DRS_LIGHTING,FALSE);

m_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);

第一个指令开启z-buffer(符合标志设置构造Direct3D框架类所以设备被使用z-buffer创建).

固定函数光找不需要,所以使用第二个语句看quad边关闭,后表面裁减被用第三语句关闭。顶点和索引缓冲被在InitDeviceObjects()创建:

VERTEX Vertices[] =

{

{-1.0f,-1.0f,0.0f,},

{1.0f,-1.0f,0.0f,},

{1.0f,1.0f,0.0f,},

{-1.0f,1.0f,0.0f,},

};

m_dwSizeofVertices - sizeof(Vertices);

if(FAILED(m_pd3dDevice->CreateVertexBuffer(4*sizeof(VERTEX),D3DUSAGE_WRITEONLY,sizeof(VERTEX),D3DPOOL_MANAGED,&m_pVB)))

return E_FAIL;

VOID* pVertices;

if(FAILED(m_pVB->Lock(0,m_dwSizeofVertices,(BYTE**)&pVertices,0)))

return E_FAIL;

memecpy(pVertices,Vertices,m_dwSizeofVertices);

m_pVB->Unlock();

WORD wIndices[] = {0,1,2,0,2,3};

m_wSizeofIndices - sizeof(wIndices);

if(FAILED(m_pd3dDevice->CreateIndexBuffer(m_wSizeofIndices,0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&m_pIB)))

return E_FAIL;

VOID* pIndices;

if(FAILED(m_pIB->Lock(0,m_wSizeof(ndices,(BYTE**)&pIndices,0)))

return E_FAIL;

memcpy(pIndices,wIndices,m_wSizeofIndices);

m_pIB->Unlock();

四个顶点存储在VERTEX结构上,把握每个顶点三个FLOAT值给位置。

使用D3DFMT_INDEX16标志在CreateIndexBuffer()里,16bit变量使用存储在索引在wIndices结构。所以最大可能索引在64K.双缓冲使用D3DPOOL_MANAGED管理内存池,所以它们将缓冲系统内存。

注意: D3DPOOL_MANAGED资源被从系统内存读取,哪里更快,和写到系统内存和然后释放是否非系统复制到(AGP或者视频内存).当发生资源被释放时上传发生。总是有两个复制资源,一个在系统AGP或视频内存。这个至少生效但是bullet-proof方式。它工作任何类驱动和必须使用无定义内存体系板。使用这种D3DPOOL_DEFAULT处理资源更多的效率。这种情况驱动将选择最好资源的地方。

注意: 为什么我们使用两个顶点缓冲。顶点缓冲可以在你的图形卡或AGP,可以非常快速的被3D硬件访问,所以在系统内存和图形卡/AGP内存间可以被避免延迟。这对硬件加速转换和光照是非常重要的。没有顶点缓冲区,一些总线平静将在变换和光照顶点的时候发生。

注意: 为什么使用索引缓冲?当你处理复制顶点转换和发送跨总线到渲染设备过程中将发挥最大性能。没有索引三角形带,例如,完成没有顶点共享,所以它至少最佳方法因为DrawPrimitive*()是调用七次。

使用索引列表或者带处理调用覆盖到DrawPrimitive*()方法(减小DrawPrimitive*()方法也调用一定量)和因为减小顶点发送通过总线,它保存内存带宽。 索引带更多硬件缓存在新硬件 than indexed lists.

执行索引处理操作以来哪里的索引缓冲存在在内存里。那时发行,仅仅图形卡支持索引缓冲在RADEON 8x00系列上。

摘要

RacorX展示简单的顶点着色器使用它的基本构造。这个着色被内联在RacorX.cpp和使用D3DXAssembleShader()编译。它使用四个dp4指令来变换quad和仅仅一个材质颜色。

即将来临的例子构建在这个例子上,and only the functional addtions will be shown on the following pages.
书中带的第一个顶点着色器例子代码。

利用着色器着色一个平面(Quad)


本主题包含附件: sf_2006710124744.zip (265831bytes)

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2024-5-22 01:30

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表