上一章学习使用原始的顶点缓冲区从头创建以及渲染带有纹理的3D立方体的方法。本章学习使用Direct3D函数来创建后援3D网格
的方法,以及从.X文件
中将网格装载到内存并使用纹理来渲染它的方法
我们现在只使用环境光照
1、创建以及渲染后援网格
后援网格
内建于Direct3D中,其是在程序运行时用算法创建的,所以可以在任何时候创建。
实际上,在制作某些类型的需要快速生成对象的游戏时后援网格极为有用
网格(也称为模型)
是由顶点组成的3D对象,它也可以包含普通的映射
、纹理坐标
、动画
以及其他特性
一些后援网格类型:立方体、球体、圆柱体、圆环、茶壶
光照和着色器
如果不关心材质或纹理
,那么网格的渲染可以使用ID3DXMesh::DrawSubset函数
来实现
1.1、编写着色器代码
着色器代码片段
保存在名为Shader.fx
的文件中。应该向对待其他asset文件
一样来处理这个文件
.fx文件
表示运行于GPU上的源代码
如下代码可能是最简单的着色器,它用光照所需的仅有的最小顶点普通数据
来渲染线框或者平面阴影的对象
//=============================================================================
// Shader effect file
//=============================================================================
uniform extern float4x4 matWorld;
uniform extern float4x4 matViewProj;
// Define a vertex shader output structure
struct OutputVS
{
float4 position : POSITION0;
float2 uv : TEXCOORD0;
float shade : TEXCOORD1;
};
// Define the vertex shader program
OutputVS TransformVS(float3 input : POSITION0)
{
// Zero out our output
OutputVS output = (OutputVS)0;
// multiply world with view/proj matrix
float4x4 matCombined = mul(matWorld, matViewProj);
// Transform to homogeneous clip space
output.position = mul(float4(input, 1.0f), matCombined);
// Done--return the output
return output;
}
// Define the pixel shader program
float4 TransformPS() : COLOR
{
return float4(0.0f, 0.0f, 0.0f, 1.0f);
}
technique technique1
{
pass P0
{
// Specify the vertex and pixel shader associated with this pass.
vertexShader = compile vs_2_0 TransformVS();
pixelShader = compile ps_2_0 TransformPS();
// Specify the render/device states associated with this pass.
FillMode = Wireframe;
}
}
使用着色器渲染网格前,必须要设置着色器中的两个全局变量——matWorld矩阵
和matViewProj矩阵
。这些变量通过一个名为SetMatrix
的ID3DXEffect的方法传递给着色器
这个简单着色器使用TransformVS方法
和TransformPS函数
来处理顶点
和像素
数据
着色器通过指定应该运行哪个顶点和像素着色器函数而描述了如何进行渲染,并且可以在着色器代码中定义多个技术
可编程图形管线
用可编程图形管线进行着色器编程
2、装载并渲染模型文件
在这里,我们只使用旧的修补管线的方法
来渲染
具体步骤:
- 1、定义新的
MODEL结构
- 2、装载网格:使用
D3DXLoadMeshFromX函数
来实现 - 3、装载材质和纹理
上述三个步骤中有太多的细节
网格可以使用多个纹理,这些纹理并不存储于网格文件自身中,而是在分开的位图文件中,在网格文件中存储的仅仅是纹理的文件名
在网格中可以有许多材质,但不是每个材质都需要有纹理。不过,纹理必须定义于材质之内
在网格文件装载完以后,材质存储于材质缓冲区中,不过,在渲染网格之前需要将它们转换成Direct3D材质和纹理。需要从材质缓冲区将材质和纹理复制到各个材质和纹理数组中去
FindFile函数:非常常见的,网格文件嵌入了带有完整路径名的、硬编码了的纹理文件名。在装载网格文件并试着分析纹理文件名时,我们将会得到硬编码了的、代表建模师计算机系统上的路径名,而这对我们的游戏项目毫无意义。所以该函数从.X文件
引用的文件名中去除掉任何直接编码的路径,从而解决这一问题
Maya和3ds Max
大多数.X文件
是二进制文件,所以无法打开它们并且编辑纹理路径名
在网格中遇到一个文件名时,为了定位纹理文件,需要三个函数一起工作
渲染纹理模型
首先,要设置材质、纹理,然后调用DrawPrimitive
来显示多边形,最大的不同在于我们现在必须使用material_count的值
来对模型进行迭代,并使用DrawSubset函数
来渲染每一个面
3D图形编程的关键是要记住,每个模型必须以完全相同的方式记录自己的位置和方向,每个精灵必须单独记录。每个网格对象的世界矩阵,只不过是网格的当前位置和变换
一个游戏
电梯推介
大多数游戏代码通常需要通过按需重复非常简单的代码来获得强大的能力,不建议进行复杂的改写,这是由现代处理器架构的设计方法所决定的