顶点——多边形——带纹理的多边形——带纹理的立方体
将在这里学习到实用的3D实现
,以便编写简单的3D游戏
1、3D编程简介
3D场景的3个关键组成部分:
- 1、
世界变换
:场景中3D对象的变换 - 2、
视图变换
:决定照相机的移动 - 3、
投影变换
:将照相机看到的对象绘制到屏幕上
Direct3D提供我们创建、渲染以及查看场景所需的所有的函数和变换,无需使用任何3D数学
创建整个3D游戏不能只使用源代码
,因为在一个典型的游戏中有太多的对象。我们最终会需要使用诸如3ds Max
或者免费的Anim8or建模程序来构建3D对象模型
1.1、顶点
为显卡提供力量的高级3D图形芯片所看到的只有顶点
。一个顶点时3D空间中的一个点,以X、Y、Z值来指定
在3D场景中所有的三角形都将是可以更为高效地进行渲染的直角三角形
在处理3D图形时,所有的一切都围绕着原点来工作。如果将对象平移到新的不以原点为中心的位置,那么再对其进行旋转就会导致它以圆形绕着原点移动(这是我们不想的)
关键点是:在指定位置上以指定的旋转和缩放值
绘制3D对象,而不移动原来的对象本身,只是在需要的时候在合适的地方绘制它,这种移动效果通过矩阵
来实现
我们的3D世界有自己的坐标系统,而场景中的所有对象也是如此,所以,我们可以彼此独立地操纵这些对象
在3D编程中最常见的错误中排名第一的是忘记了照相机和视图转换:
- 1、在场景中首先要设置好的是,使用一个测试的多边形或四边形来
设置透视、照相机和视图
,以便在继续之前确认场景已经正确设置 - 2、检查场景的
光照条件和摄像机位置
在这里,我们将学习如何使用非常低级的、带有顶点缓冲区的图形编程
来渲染简单的带纹理的立方体。在以这种方式处理顶点的时候,我们会深入Direct3D的内部核心(渲染管线相关的
),就如触碰GPU一样
1.2、掌握3D管线
顶点
struct VERTEX
{
float x, y, z;
float tu, tv;
}
前三个数据成员是顶点的位置,而tu和tv变量
则用于表述纹理的绘制方法
tu和tv
告诉Direct3D在表面上绘制纹理的的方法,Direct3D支持纹理围绕3D对象曲线进行包裹
我们使用tu=0.0、tv=0.0
来指定纹理的左上角
;使用tu=1.0、tv=1.0
来指定纹理的右下角
。这两者之间的所有多边形的纹理坐标
将通常是0,以此告诉Direct3D就在它们上面伸展纹理
纹理是高级主题。目前,我们只在一个四边形中的两个三角形上伸展纹理
四边形
// quadrangle
struct QUAD
{
VERTEX vertices[4];
LPDIRECT3DVERTEXBUFFER9 buffer;
LPDIRECT3DTEXTURE9 texture;
}
顶点缓冲区
顶点缓冲区其实只是我们存储组成多边形的点的地方
,以便Direct3D绘制多边形(polygon)
在程序中,只要需要,从技术上说可以有许多顶点缓冲区
——每个三角形一个(显然这是不现实的
)
为了能够清楚地描述,我让每个对象都有自己的顶点缓冲区
,以此展示获得屏幕上的3D对象的方法
大多数3D引擎采用包含了在照相机的视图中所有可见顶点的
称为顶点缓冲区缓存的东西。强大的3D引擎也使用称为纹理缓存
的东西,以便共享同一纹理的多边形可重用它们
在显卡中一次只能使用一个纹理
创建顶点缓冲区
LPDIRECT3DVERTEXBUFFER9 buffer;
#define D3DFVF_MYVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)
d3dd3v->CreateVertexBuffer(
4 * sizeof(VERTEX),
D3DUSAGE_WRITEONLY,
D3DFVF_MYVERTEX,
D3DPOOL_DEFAULT,
&buffer,
NULL);
这个函数真正重要的参数是顶点缓冲区长度
和指针
填写顶点缓冲区
创建顶点缓冲区的最后一个步骤是使用多边形的实际顶点来填写它。这一步骤必须跟随在任何生成或装载顶点数组的代码之后,因为它会将数据放入到顶点缓冲区中
void *temp = NULL;
buffer->Lock(0, sizeof(vertices), (void**)&temp, 0);
memcpy(temp, vertices, sizeof(vertices)); //load
buffer->Unlock();
渲染顶点缓冲区
在初始化顶点缓冲区之后,就为Direct3D图形管线
做好了准备,源顶点就不再有用了。这称为设置
让硬编码的芯片
从顶点缓冲区中将顶点和纹理
流到场景中要比软件快得多
要将当前正在处理的顶点缓冲区发送到屏幕上,要设置Direct3D设备的流源(stream source)
,让它指向顶点缓冲区,然后调用DrawPrimitive函数
。在此之前,必须首先设置要使用的纹理
具体的渲染步骤:
- 1、设置纹理
- 2、设置流源,以便Direct3D知道顶点的来源以及需要渲染的有多少
- 3、指定绘制流源的原语,包括
渲染方法
、起始顶点
以及要绘制的多边形数量
d3ddev->SetTexture(0, texture);
d3ddev->SetStreamSource(0, q.buffer, 0, sizeof(VERTEX));
d3d->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
创建四边形
绘制对象有两种方法:
- 1、独立绘制每个多边形的
三角形列表
,每个由三个一组的顶点组成 - 2、绘制
三角形条
(共享了顶点)
显然,第二种方法更为高效。不过我们不能使用三角形条
来渲染整个场景,因为大多数对象并不是互相连接的。三角形条
非常适合于地面地形、建筑物和其他大对象
无论所有的三角形是位于单个顶点缓冲区中还是多个顶点缓冲区中,Direct3D都将以同样的速度渲染场景。这一特性是十分重要的。建议把优化留给编译器
创建四边形所需的工作甚至要比创建两个互相连接的三角形更少,这要归功于三角形条渲染过程
2、带纹理的立方体示例
对3D系统而言三角形(其实是直角三角形)是至关重要的
创建带纹理的四边形
要比创建着色的四边形
更容易