📄 顶点着色器 (vertex shaders).htm
字号:
<H1><A name=_创建顶点着色器></A>创建顶点着色器</H1>
<DIV class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>
<HR align=center width="100%" SIZE=1>
</SPAN></DIV>
<P>本示例创建一个顶点着色器,把一固定颜色应用于物体。本示例将会给出着色器文件的内容,以及为了在应用程序中使用该着色器而设置<SPAN
lang=EN-US>Microsoft® Direct3D®流水线所需的代码。</SPAN></P>
<P>如果读者已经知道如何构建并运行<SPAN
lang=EN-US>Direct3D示例,那么可以从本示例中复制代码并粘贴到已有的应用程序中。</SPAN></P>
<P>本文讨论了以下几个步骤。</P>
<UL type=disc>
<LI class=MsoNormal
style="mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list 36.0pt; mso-list: l14 level1 lfo9"><U><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN"><A
href="http://www.gesoftfactory.com/developer/VertexShaders.htm#_第1步:声明顶点数据"><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第</SPAN>1<SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">步:声明顶点数据</SPAN></A></SPAN></U>
<LI class=MsoNormal
style="mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list 36.0pt; mso-list: l14 level1 lfo9"><U><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN"><A
href="http://www.gesoftfactory.com/developer/VertexShaders.htm#_第2步:设计着色器的功能"><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第</SPAN>2<SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">步:设计着色器的功能</SPAN></A></SPAN></U><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN"><o:p></o:p></SPAN>
<LI class=MsoNormal
style="mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list 36.0pt; mso-list: l14 level1 lfo9"><U><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN"><A
href="http://www.gesoftfactory.com/developer/VertexShaders.htm#_第3步:检查对顶点着色器的支持"><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第</SPAN>3<SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">步:检查对顶点着色器的支持</SPAN></A></SPAN></U><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN"><o:p></o:p></SPAN>
<LI class=MsoNormal
style="mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list 36.0pt; mso-list: l14 level1 lfo9"><U><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN"><A
href="http://www.gesoftfactory.com/developer/VertexShaders.htm#_第4步:声明顶点着色器数据"><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第</SPAN>4<SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">步:声明顶点着色器数据</SPAN></A></SPAN></U><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN"><o:p></o:p></SPAN>
<LI class=MsoNormal
style="mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list 36.0pt; mso-list: l14 level1 lfo9"><U><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN"><A
href="http://www.gesoftfactory.com/developer/VertexShaders.htm#_第5步:创建着色器"><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第</SPAN>5<SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">步:创建着色器</SPAN></A></SPAN></U>
<LI class=MsoNormal
style="mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list 36.0pt; mso-list: l14 level1 lfo9"><U><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN"><A
href="http://www.gesoftfactory.com/developer/VertexShaders.htm#_第6步:渲染输出像素"><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第</SPAN>6<SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">步:渲染输出像素</SPAN></A></SPAN></U>
</LI></UL>
<H2><A name=_第1步:声明顶点数据></A><SPAN
style="FONT-FAMILY: 黑体; mso-fareast-language: ZH-CN; mso-ascii-font-family: Arial">第</SPAN><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN">1</SPAN><SPAN
style="FONT-FAMILY: 黑体; mso-fareast-language: ZH-CN; mso-ascii-font-family: Arial">步:声明顶点数据</SPAN><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN"><o:p></o:p></SPAN></H2>
<P>本示例使用由两个三角形构成的四边形。顶点数据包含<SPAN lang=EN-US>(<SPAN
class=SpellE>x,y,z</SPAN>)位置和漫反射色。顶点数据在一个全局顶点数组(<SPAN
class=SpellE>g_Vertices</SPAN>)中声明。四个顶点以原点为中心。</SPAN></P><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">// 声明顶点数据结构。<o:p></o:p></SPAN></PRE><PRE><SPAN class=SpellE><SPAN class=GramE><SPAN lang=EN-US style="FONT-SIZE: 10pt">struct</SPAN></SPAN></SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt"> CUSTOMVERTEX<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">{<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt"><SPAN style="mso-spacerun: yes"> </SPAN>FLOAT x, y, z;<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">};<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt"><o:p> </o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">// 声明顶点位置和漫反射色。<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">CUSTOMVERTEX <SPAN class=SpellE>g_<SPAN class=GramE>Vertices</SPAN></SPAN><SPAN class=GramE>[</SPAN>]=<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">{<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt"><SPAN style="mso-spacerun: yes"> </SPAN>/<SPAN class=GramE>/<SPAN style="mso-spacerun: yes"> </SPAN>x</SPAN><SPAN style="mso-spacerun: yes"> </SPAN>y<SPAN style="mso-spacerun: yes"> </SPAN>z<SPAN style="mso-spacerun: yes"> </SPAN><o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt"><SPAN style="mso-spacerun: yes"> </SPAN><SPAN class=GramE>{ -</SPAN>1.0f, -1.0f, 0.0f }, <o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt"><SPAN style="mso-spacerun: yes"> </SPAN><SPAN class=GramE>{ +</SPAN>1.0f, -1.0f, 0.0f }, <o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt"><SPAN style="mso-spacerun: yes"> </SPAN><SPAN class=GramE>{ +</SPAN>1.0f, +1.0f, 0.0f }, <o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt"><SPAN style="mso-spacerun: yes"> </SPAN><SPAN class=GramE>{ -</SPAN>1.0f, +1.0f, 0.0f }, <o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">};<o:p></o:p></SPAN></PRE>
<H2><A name=_第2步:设计着色器的功能></A><SPAN
style="FONT-FAMILY: 黑体; mso-fareast-language: ZH-CN; mso-ascii-font-family: Arial">第</SPAN><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN">2</SPAN><SPAN
style="FONT-FAMILY: 黑体; mso-fareast-language: ZH-CN; mso-ascii-font-family: Arial">步:设计着色器的功能</SPAN><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN"><o:p></o:p></SPAN></H2>
<P>该着色器将一固定颜色应用于每个顶点。以下为着色器文件<SPAN class=SpellE><SPAN
lang=EN-US>VertexShader.vsh</SPAN></SPAN>:</P><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">vs_1_1<SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: blue">//</SPAN><SPAN style="COLOR: green"> 版本指令</SPAN><o:p></o:p></SPAN></PRE><PRE><SPAN class=SpellE><SPAN lang=EN-US style="FONT-SIZE: 10pt">dcl_position</SPAN></SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt"> v0<SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: blue">//</SPAN><SPAN style="COLOR: green"> 说明位置数据在寄存器v0中</SPAN><o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">m4x4 <SPAN class=SpellE>oPos</SPAN>, v0, c0<SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: blue">//</SPAN><SPAN style="COLOR: green"> 用视/投影矩阵变换顶点</SPAN><o:p></o:p></SPAN></PRE><PRE><SPAN class=SpellE><SPAN lang=EN-US style="FONT-SIZE: 10pt">mov</SPAN></SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt"> oD0, c4<SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: blue">//</SPAN><SPAN style="COLOR: green"> 载入固定颜色</SPAN><o:p></o:p></SPAN></PRE>
<P>该文件包含了三条数据运算指令和一个寄存器定义。着色器文件的第一条指令必须是着色器版本声明。<SPAN class=SpellE><SPAN
lang=EN-US>vs</SPAN></SPAN>指令用来声明顶点着色器的版本,此处为<SPAN lang=EN-US>1_1。</SPAN></P>
<P><SPAN class=SpellE><SPAN lang=EN-US>dcl_position</SPAN></SPAN>指令把寄存器<SPAN
lang=EN-US>v0定义为顶点位置数据的源。m4x4指令用视/投影矩阵对物体的顶点进行变换。矩阵被载入并保存在常量寄存器c0, c1, c2,
c3(如下所示)中。<SPAN
class=SpellE>Mov</SPAN>指令把寄存器c4中的固定颜色复制到输出漫反射色寄存器oD0中。这导致输出顶点的颜色被改变。<o:p></o:p></SPAN></P>
<H2><A name=_第3步:检查对顶点着色器的支持></A><SPAN
style="FONT-FAMILY: 黑体; mso-fareast-language: ZH-CN; mso-ascii-font-family: Arial">第</SPAN><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN">3</SPAN><SPAN
style="FONT-FAMILY: 黑体; mso-fareast-language: ZH-CN; mso-ascii-font-family: Arial">步:检查对顶点着色器的支持</SPAN><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN"><o:p></o:p></SPAN></H2>
<P>在使用顶点着色器之前,可以查询驱动程序对顶点着色器的支持。</P><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">D3DCAPS9 caps;<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">m_pd3dDevice-><SPAN class=SpellE>GetDeviceCaps</SPAN>(&caps);<SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: blue">//</SPAN><SPAN style="COLOR: green"> 在使用前初始化m_pd3dDevice</SPAN><o:p></o:p></SPAN></PRE><PRE><SPAN class=GramE><SPAN lang=EN-US style="FONT-SIZE: 10pt">if(</SPAN></SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt"> <SPAN class=SpellE>caps.VertexShaderVersion</SPAN> < D3DVS_VERSION(1,1) )<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt"><SPAN style="mso-tab-count: 1"> </SPAN><SPAN class=GramE>return</SPAN> E_FAIL;<o:p></o:p></SPAN></PRE>
<P>在调用<U><SPAN lang=EN-US>IDirect3DDevice9::GetDeviceCaps</SPAN></U>后,<SPAN
lang=EN-US>caps结构会返回硬件可用的能力。应该用D3DVS_VERSION宏测试硬件支持的版本号。如果版本号小于1_1,那么该调用将会失败。这个方法的结果应该被应用程序用来控制是否使用顶点着色器。<o:p></o:p></SPAN></P>
<H2><A name=_第4步:声明顶点着色器数据></A><SPAN
style="FONT-FAMILY: 黑体; mso-fareast-language: ZH-CN; mso-ascii-font-family: Arial">第</SPAN><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN">4</SPAN><SPAN
style="FONT-FAMILY: 黑体; mso-fareast-language: ZH-CN; mso-ascii-font-family: Arial">步:声明顶点着色器数据</SPAN><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN"><o:p></o:p></SPAN></H2>
<P>顶点声明用来描述顶点数据。</P><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: blue">//</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: green"> 创建着色器声明。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt"><o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">D3DVERTEXELEMENT9 <SPAN class=SpellE><SPAN class=GramE>decl</SPAN></SPAN><SPAN class=GramE>[</SPAN>] = <o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">{<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt"><SPAN style="mso-spacerun: yes"> </SPAN><SPAN class=GramE>{ 0</SPAN>, 0,<SPAN style="mso-spacerun: yes"> </SPAN>D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt"><SPAN style="mso-spacerun: yes"> </SPAN>D3DDECL_<SPAN class=GramE>END()</SPAN><o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">};<o:p></o:p></SPAN></PRE>
<P>这个声明说明了以下这些:数据来自数据流<SPAN
lang=EN-US>0,从数据流起始位置起偏移量为0处的位置开始,声明位置数据为三个浮点数(D3DDECLTYPE_FLOAT3),告诉<SPAN
class=SpellE>tessellator</SPAN>复制顶点数据(D3DDECLMETHOD_DEFAULT),定义数据的用途为顶点数据(D3DDECLUSAGE_POSITION),并说明用途索引为0。</SPAN></P>
<P><SPAN lang=EN-US>D3DDECLEND()宏用来结束顶点声明。</SPAN></P>
<H2><A name=_第5步:创建着色器></A><SPAN
style="FONT-FAMILY: 黑体; mso-fareast-language: ZH-CN; mso-ascii-font-family: Arial">第</SPAN><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN">5</SPAN><SPAN
style="FONT-FAMILY: 黑体; mso-fareast-language: ZH-CN; mso-ascii-font-family: Arial">步:创建着色器</SPAN><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN"><o:p></o:p></SPAN></H2>
<P>下一步汇编并创建着色器。</P><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">LPDIRECT3DPIXELSHADER9 <SPAN class=SpellE>m_pVertexShader</SPAN>;<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">TCHAR<SPAN style="mso-spacerun: yes"> </SPAN><SPAN class=SpellE><SPAN class=GramE>strShaderPath</SPAN></SPAN><SPAN class=GramE>[</SPAN>512];<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">LPD3DXBUFFER <SPAN class=SpellE>pCode</SPAN>;<SPAN style="mso-spacerun: yes"> </SPAN>// 包含经过汇编的着色器代码的缓存<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">LPD3DXBUFFER <SPAN class=SpellE>pErrorMsgs</SPAN>;<SPAN style="mso-spacerun: yes"> </SPAN>// 包含错误信息的缓存<o:p></o:p></SPAN></PRE><PRE><SPAN class=SpellE><SPAN lang=EN-US style="FONT-SIZE: 10pt">DXUtil_<SPAN class=GramE>FindMediaFileCb</SPAN></SPAN></SPAN><SPAN class=GramE><SPAN lang=EN-US style="FONT-SIZE: 10pt">(</SPAN></SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt"> <SPAN class=SpellE>strShaderPath</SPAN>, <SPAN class=SpellE>sizeof</SPAN>(<SPAN class=SpellE>strShaderPath</SPAN>), <o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt"><SPAN style="mso-spacerun: yes"> </SPAN>_<SPAN class=GramE>T(</SPAN>"<SPAN class=SpellE>VertexShader.vsh</SPAN>") );<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt"><o:p> </o:p></SPAN></PRE><PRE><SPAN class=GramE><SPAN lang=EN-US style="FONT-SIZE: 10pt">D3DXAssembleShaderFromFile(</SPAN></SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt"> <SPAN class=SpellE>strPixelShaderPath</SPAN>, NULL, NULL, 0,<SPAN style="mso-spacerun: yes"> </SPAN><o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt"><SPAN style="mso-spacerun: yes"> </SPAN>&<SPAN class=SpellE>pCode</SPAN>, &<SPAN class=SpellE>pErrorMsgs</SPAN>, <SPAN class=GramE>NULL )</SPAN>;<SPAN style="mso-spacerun: yes"> </SPAN><o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt">m_pd3dDevice-><SPAN class=SpellE><SPAN class=GramE>CreateVertexShader</SPAN></SPAN><SPAN class=GramE>(</SPAN>(DWORD*)<SPAN class=SpellE>pCode</SPAN>-><SPAN class=SpellE>GetBufferPointer</SPAN>(),<o:p></o:p></SPAN></PRE><PRE><SPAN lang=EN-US style="FONT-SIZE: 10pt"><SPAN style="mso-spacerun: yes"> </SPAN>&<SPAN class=SpellE>m_pVertexShader</SPAN>)<o:p></o:p></SPAN></PRE><PRE><SPAN class=SpellE><SPAN class=GramE><SPAN lang=EN-US style="FONT-SIZE: 10pt">pCode</SPAN></SPAN></SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt">->Release();<o:p></o:p></SPAN></PRE><PRE><SPAN class=SpellE><SPAN class=GramE><SPAN lang=EN-US style="FONT-SIZE: 10pt">pErrorMsgs</SPAN></SPAN></SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt">->Release()<o:p></o:p></SPAN></PRE>
<P>在定位了着色器文件后,<SPAN
lang=EN-US>D3DXAssembleShaderFromFile读取并验证着色器指令。然后<U>IDirect3DDevice9::CreateVertexShader</U>对指令进行汇编并创建着色器。该方法会返回用于绘制时调用的着色器对象。<o:p></o:p></SPAN></P>
<P><SPAN class=SpellE><I><SPAN
lang=EN-US>CreateVertexShader</SPAN></I></SPAN>用于创建一个可编程着色器。</P>
<H2><A name=_第6步:渲染输出像素></A><SPAN
style="FONT-FAMILY: 黑体; mso-fareast-language: ZH-CN; mso-ascii-font-family: Arial">第</SPAN><SPAN
lang=EN-US style="mso-fareast-language: ZH-CN">6</SPAN><SPAN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -