1.4怎么用HLSL着色器
1.4怎么用HLSL着色器
应用程序中对HLSL着色器的使用分为以下步骤:
1. 加载(称为编译更为妥当)着色器代码;
2. 创建(顶点/像素)着色器;
3. 对着色器中的变量进行赋值,完成应用程序和着色器之间的通信。
4. 把着色器设定到渲染管道中;
本例使用的着色器是一个顶点着色器,因此我们将通过顶点着色器的使用来讲解着色器的使用过程,像素着色器的使用过程与此大同小异,二者之间仅有些微差别。
IDirect3DVertexShader9* BasicShader = 0; //顶点着色器指针
ID3DXConstantTable* BasicConstTable = 0; //常量表指针
D3DXHANDLE WVPMatrixHandle = 0;
D3DXHANDLE ColorHandle = 0;
ID3DXMesh* Teapot = 0; //指向程序中D3D茶壶模型的指针
通过D3DXCompileShaderFromFile函数从应用程序外部的文本文件BasicHLSL.txt中编译一个着色器:
//编译后的着色器代码将被放在一个buffer中,可以通过ID3DXBuffer接口对其进行访问,之后的着色器将从这里创建
ID3DXBuffer* shaderBuffer = 0;
//用于接受错误信息
ID3DXBuffer* errorBuffer = 0;
//编译着色器代码
D3DXCompileShaderFromFile("BasicHLSL.txt", //着色器代码文件名
0,
0,
"SetColor", //入口函数名称
"vs_1_1", //顶点着色器版本号
D3DXSHADER_DEBUG,// Debug模式编译
&shaderBuffer, //指向编译后的着色器代码的指针
&errorBuffer,
&BasicConstTable); //常量表指针
应用程序通过CreateVertexShader创建一个顶点着色器,注意使用了上一步得到的shaderBuffer:
g_pd3dDevice->CreateVertexShader((DWORD*)shaderBuffer->GetBufferPointer(), &BasicShader);
1.4.3对着色器中的变量进行赋值
1.3.4节说到着色器的全局变量在应用程序中赋值而在着色器程序中使用,这是应用程序和着色器通信的关键所在,这里就具体说明赋值过程。
着色器中的全局变量在编译后都被放在一个叫常量表的结构中,我们可以使用ID3DXConstantTable接口对其进行访问,参照1.4.1中编译着色器函数D3DXCompileShaderFromFile的最后一个参数,该参数即返回了指向常量表的指针。
对一个着色器中变量进行赋值的步骤如下:
1. 通过变量名称得到指向着色器变量的句柄;
还记得在BasicHLSL.x着色器文件中我们声明的两个全局变量吗:
matrix WVPMatrix;
vector color;
我们在应用程序中相应的声明两个句柄:
D3DXHANDLE WVPMatrixHandle = 0;
D3DXHANDLE ColorHandle = 0;
然后通过变量名得到分别得到对应的两个句柄:
WVPMatrixHandle = BasicConstTable->GetConstantByName(0, "WVPMatrix");
ColorHandle = BasicConstTable->GetConstantByName(0, "color");
2. 通过句柄对着色器变量进行赋值;
我们可以先设置各变量为默认值:
BasicConstTable->SetDefaults(g_pd3dDevice);
之后,可以使用ID3DXConstantTable::SetXXX函数对各个变量进行赋值:
HRESULT SetXXX(
LPDIRECT3DDEVICE9 pDevice,
D3DXHANDLE hConstant,
XXX value
);
其中XXX代表变量类型,例如Matrix类型的变量就要使用SetMatrix函数赋值,而Vector类型的则要使用SetVector来赋值。
这里我们使用SetVertexShader方法把顶点着色器设定到渲染管道中:
g_pd3dDevice->SetVertexShader(BasicShader);
在渲染过程中,我们设定顶点的变换坐标和颜色值,渲染代码如下:
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(153,153,153), 1.0f, 0 );
//开始渲染
g_pd3dDevice->BeginScene();
//得到世界矩阵、观察矩阵和投影矩阵
D3DXMATRIX matWorld, matView, matProj;
g_pd3dDevice->GetTransform(D3DTS_WORLD, &matWorld);
g_pd3dDevice->GetTransform(D3DTS_VIEW, &matView);
g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &matProj);
D3DXMATRIX matWVP = matWorld * matView * matProj;
//通过句柄对着色器中的WVPMatrix变量进行赋值
BasicConstTable->SetMatrix(g_pd3dDevice, WVPMatrixHandle, &matWVP);
D3DXVECTOR4 color(1.0f, 1.0f, 0.0f, 1.0f);
//通过句柄对着色器中的color变量进行赋值,这里我们赋值为黄色
BasicConstTable->SetVector(g_pd3dDevice, ColorHandle, &color);
//把顶点着色器设定到渲染管道中
g_pd3dDevice->SetVertexShader(BasicShader);
//绘制模型子集
Teapot->DrawSubset(0);
//渲染完毕
g_pd3dDevice->EndScene();
g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
编译运行程序,运行效果如图1.2所示,这里我们将顶点颜色设置为黄色,如果读者在渲染过程中不断变换对着色器变量color的赋值,你将会得到一个色彩不断变幻的D3D茶壶。
D3DXVECTOR4 color(1.0f, 1.0f, 0.0f, 1.0f); //读者可以尝试改变颜色值
BasicConstTable->SetVector(g_pd3dDevice, ColorHandle, &color);
图1.2 着色器效果