Visual C++ 高级编程

Post on 18-Mar-2016

99 views 5 download

description

Visual C++ 高级编程. 第七讲 进入 3D 世界. 什么是 DirectX SDK ?. 微软的 DirectX 软件开发工具包( SDK )提供了一套优秀的应用程序编程接口( APIs ),这个编程接口可以提供给你开发高质量、实时的应用程序所需要的各种资源。 DirectX 技术的出现将极大的有助于发展下一代多媒体应用程序和电脑游戏。. DirectX SDK 的主要组件. DirectDraw :通过直接访问显示硬件来提供高级的图象处理能力。 - PowerPoint PPT Presentation

Transcript of Visual C++ 高级编程

Visual C++Visual C++ 高级编程高级编程第七讲 进入第七讲 进入 3D3D 世界世界

什么是什么是 DirectX SDK DirectX SDK ? ? • 微软的 DirectX 软件开发工具包( SDK )提供了一套优秀的应用程序编程接口( API

s ),这个编程接口可以提供给你开发高质量、实时的应用程序所需要的各种资源。DirectX 技术的出现将极大的有助于发展下一代多媒体应用程序和电脑游戏。

DirectX SDKDirectX SDK 的主要组件 的主要组件 • DirectDraw :通过直接访问显示硬件来提供高级的图象处理能力。 • DirectSound :它提供了软硬件的低延迟声音混频( lo

w_latency sound mixing )和回放( Playback ),硬件加速,以及直接访问音频设备的能力。 • DirectPlay :它明确的提供了通用环境连接能力( gene

ralized communication capabilities ),来简化你应用程序之间的通讯服务。 • Direct3D :它为主流的桌上型计算机和 Internet 用户提供实时的、交互的 3D 技术。 • DirectInput :它简化你的应用程序访问鼠标、键盘和操纵杆设备的能力。

DirectXDirectX 的特色的特色• 直接读写内存 DDRAW 可以直接读写显存,并利用“切换页”的功能提高图形显示的性能。• 支持硬件加速 DirectX 对象建立时,程序自动查询可使用的硬件。提供 HAL 和 HEL 两种模式。• 网络联机功能 DirectPlay 可以程序员更容易地开发多人联机游戏。并支持各种通讯协议。

COMCOM

• COM 就是 Component Object Model ( 组件对象模型)。• COM 接口和 C++ 的抽象类相似, COM 描述了一套符号和语法而非实现过程。• DX 就提供了一套完整的设计 3D 游戏的库。使用

DX 时,不必直接接触硬件,而由 DX 进行代理。• 使用 COM 时应该注意,必须在程序结束前释放所有的 COM 对象(或接口)。而且,释放它们的顺序应该和创建它们的顺序相反。

设置设置 DirectXDirectX 开发环境开发环境• 步骤 1 :安装 DirectX SDK ;• 步骤 2 :设置应用程序中的头文件目录;• 步骤 3 :添加所需的头文件;• 步骤 4 :设置项目链接时所需的库文件,方法有两种:

– 1 、应用程序中使用 #pragma comment(lib,“xxxx.lib”) (推荐)– 2 、在项目设置中添加库文件

第一种方法第一种方法

第二种方法第二种方法

Direct3DDirect3D 的特色的特色WIN32 Application WIN32 Application

Direct3D API

Hal Device

Device Driver Interface(DDI)

Graphics Hardware

GDI

硬件抽象层硬件抽象层• Direct3D 通过硬件抽象层 (HAL) 提供设备无关性。 HAL 是一个设备相关的接口,由设备制造商提供, HAL 可以是显示驱动程序的一部分,或者是一个单独的动态链接库。• HAL 通过驱动程序开发人员定义的私有接口与显示驱动程序进行通信。应用程序则通过

Direct3D API 来实现显示。• Direct3D 选择 HAL 设备时,可以充分利用硬件的特性,如硬件加速等。

建立建立 3D3D 环境环境• 一个标准的 3D 框架可以分为以下几个部分:

– 创建 Direct3D 接口和设备接口。– WinMain : Win32 程序的入口点,代码会从这里开始执行。这是我们注册、创建、显示窗口的地方。然后,我们要初始化 Direct3D 并进入游戏循环( Game Loo

p )。– WinProc :这是应用程序的消息处理过程。 Windows发给我们的程序的消息,都要有它处理。– InitD3D :这个函数是用来初始化 Direct3D 的。首先,创建 IDirect3D9 对象,通过这个对象我们得到了当前屏幕的显示模式。然后,根据刚刚我们获取的信息(显示模式),创建了兼容的设备。

建立建立 3D3D 环境环境– Render :首先,我们清除了后缓冲区准备作画。然后,调用了 BeginScene 函数来告知 DX 我们要作画了。结束了绘制后我们调用 EndScene 来告知 DX 我们画完了。最后,我们调用了 Present 来完成关键的一步:翻动后缓冲区到前缓冲区(屏幕)。这时,用户就能看到我们画的东西了。– CleanUp :我们在此做清洁工作:释放所有的被创建的对象 。

建立建立 3D3D 环境环境导入头文件声明接口指针

#include <d3d9.h>LPDIRECT3D9 g_pD3D=NULL;LPDIRECT3DDEVICE9 g_pd3dDevice=NULL;

注册窗口类

初始化 D3D 设备显示窗口

消息循环

释放所有对象程序结束

创建 DIRECT3D9 对象,获取显示卡的显示模式,然后根据这些信息创建DIRECT3D9 设备。

利用 DIRECT3D9 设备进行场景的绘制。

建立 3D 环境

绘制绘制 3D3D 几何图形几何图形• 所有的 3D 图形都是由三角形构成的。 • 顶点:顶点就是 3D空间中的一个点。在 3D空间中,你可以用三个顶点来指定一个三角形。 • 灵活顶点格式:是用来描述顶点属性的一种格式,而这种格式是可以由我们自定义的 。顶点属性一般有: X , Y , Z值,以及颜色和亮度等。• 顶点缓冲:顶点缓冲就是一块用于保存顶点的内存缓冲区。• 颜色:在 DirectX 中,如果我们要指定一种颜色,我们可以用 D3DCOLOR_XRGB宏。

绘制绘制 3D3D 几何图形几何图形• 坐标系: 3D 迪卡尔坐标系统

• 背面拣选:这所有的三角形面,面向我们的面将会被渲染出来(可见),否则将不被渲染(不可见,被拣选出来了)。

绘制绘制 3D3D 几何图形几何图形• 3D 环境:三个矩阵——世界矩阵 、视图矩阵 、投影矩阵 。• 创建模型:即定义 3D 图形的所有顶点属性。• 设备数据源:当 3D 模型设置好后,我们就可以绑定该顶点缓存区到设备数据源。进

行 3D 图形的渲染。

矩阵变换 矩阵变换 矩阵变换的基本公式

缩小或放大

矩阵变换的实现矩阵变换的实现D3DXMatrixMultiply(&mat2, & mat1, &mat0); // 矩阵相乘 , mat1* mat0-> mat2D3DXMATRIX *D3DXMatrixTranslation( // 矩阵平移

D3DXMATRIX* pOut, // 输出FLOAT x,FLOAT y, FLOAT z

);D3DXMATRIX *D3DXMatrixRotationX( // 矩阵旋转

D3DXMATRIX* pOut, // 输出FLOAT Angle // 角度 .

);D3DXMATRIX *D3DXMatrixScaling( // 矩阵缩放

D3DXMATRIX* pOut, // 输出FLOAT sx, FLOAT sy, FLOAT sz

);

Device->SetTransform(D3DTS_XXXX, &XXXXX);

顶点格式顶点格式• Direct3D让我们可以灵活的构造自己的顶点格式。换句话说,我们可以自己定义顶点的成员。 • 为了创建一个自定义的顶点结构,我们首先要创建一个包含能存放我们选择的顶点数据的结构 .

struct ColorVertex{

float _x, _y, _z; DWORD _color;

};struct NormalTexVertex{

float _x, _y, _z; float _nx, _ny, _nz; float _u, _v;

};

包含了位置和颜色信息

包含了位置法线向量纹理坐标

灵活顶点格式(灵活顶点格式( FVFFVF ) ) #define FVF_COLOR (D3DFVF_XYZ | D3DFVF_DIFFUSE)

顶点结构表明它包含位置和颜色属性

#define FVF_NORMAL_TEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)

顶点结构表明它包含了位置,法线向量,纹理坐标的属性

旋转的三角形

图元图元• 图元就是设备所支持的原始的类型。它包括:点列、线列、线代、三角形列、三角形带 和 三角扇形。

Triangle Strips( 三角形带 )

立方体的绘制立方体的绘制• 三角形带:

• 立方体的分割:

3D3D物体的绘制物体的绘制

旋转的三角棱

g_pD3DDevice->BeginScene(); //Rendering our triangleg_pD3DDevice->SetStreamSource(0, g_pVertexBuffer, sizeof(CUSTOMVERTEX));g_pD3DDevice->SetVFV(D3DFVF_CUSTOMVERTEX);g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); //End the scene

g_pD3DDevice->EndScene();

设置源缓冲区 设置顶点格式 绘制图元

索引缓冲 索引缓冲 • 索引缓冲就是内存中的一块用于索引顶点的区域。 • 当渲染场景时, DX 会对每个顶点都进行许多计算,例如灯光、变幻等等,这样,运算量会很大。但是我们总是希望让 DX做最少的运算以增加程序的效率,因此,我们需要把顶点的数目减到最少。

索引缓冲例子索引缓冲例子

在上面的例子中,我们只用了 4 个顶点就定义了一个正方形,实际节约了 2 个顶点。

索引缓冲的实现索引缓冲的实现LPDIRECT3DINDEXBUFFER9 g_pIB; // 定义WORD indices[]={0,2,1,0,3,2,0,1,3,1,2,3}; // 定义数组g_pd3dDevice->CreateIndexBuffer(sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &g_pIB, NULL); // 创建索引缓冲void *pIndices;g_pIB->Lock( 0,sizeof(indices),(void**)&pIndices,0);memcpy( pIndices,indices,sizeof(indices) ); // 拷贝索引值g_pIB->Unlock();

g_pd3dDevice->SetIndices(g_pIB); // 设置索引缓冲g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,0,4,0,4); // 输出

灯光灯光• 可以模拟出真实世界中一样的光线反射效果,受计算机计算能力的限制,只能有限地进行模拟。

– 环境光( ambient) 的投射– 直射光的投射( DIRECT )– 阴影

• 在 3D 环境里,阴影分为:平面阴影和内插( GOURAUD )阴影• 平面阴影:

– 在每一个表而后第一个顶点上进行颜色与打光的计算。效果较差,但速度很快• 内插阴影:在每个表面上,利用三个顶点的颜色值进行内插计算,这种效果有点像渐变的模式。但计算量较大,速度慢

– 2.光的属性:• 光的投射方式:

– 漫射( DIFFUSE )– 反射( SPECULAR )– 环境光( AMBIENT )

• 光的类型– 点光源,无方向– 聚光灯,方向性较强– 指定光,有方向,但没位置,如太阳光等

– 3.光的色彩属性• 扩散( Diffuse Color) :当物体被光照射时,所能反射的光• 环绕( Ambient Color)• 放射 (Emissiv Color)• 反射 (Specular Color)

灯光灯光

灯光属性灯光属性• 想要不同的光可以指定不同的属性,不是所有类型的光都拥有下面的这些属性:

– Position (位置)这是在 3D空间中光源的位置,例如( 0, 10, 0 )。

– Direction (方向)这是一个向量(例如( 0, 1, 0 )),表示从光源发射出来的光的方向。– Range (范围)这是光从光源发出后所能到达的最大距离,范围以外的物体将不会接受到此光源的光。 – Attenuation (衰减)在光源到它的范围之间,光会逐渐衰减,这是很正常的。如果想要,你也可以指定让光不衰减,或反而越来越亮。– Diffuse Light (漫反射)光的漫反射颜色。漫射光是分散的,但仍然具有方向,不像环境光没有方向。– Ambient Light (环境光)这是环境光的颜色,它是通用的背景光,它是分散的且没有方向和光源,它充满整个场景。

灯光类型灯光类型• Ambient Light (环境光)可以为场景指定通用的环境光,与其它灯光互不影响,用红、绿、蓝三个分量来设置颜色。• Point Light (点光源)它没有方向(因为向全部方向发出),但是有颜色、范围和衰减。例如电灯 . • Directional Light (直射光)直射光具有颜色,没有位置。场景里的所有对象都会从同样的方向接收到同样的光。直射光也没有范围和衰减。例如太阳光 .• Spotlight (聚光灯)它具有位置、方向、范围、发光内径和发光外径属性,光照强度还会随距离而衰减。例如 :手电筒 .

设置灯光设置灯光• 打开光照处理: SetRenderState( D3DRS_LIGHTING, TRUE );• 创建灯光:

D3DLIGHT9 light;::ZeroMemory( &light, sizeof(D3DLIGHT9) );light.Type = D3DLIGHT_DIRECTIONAL;//灯光类型light.Diffuse.r = 1.0f;light.Diffuse.g = 1.0f;light.Diffuse.b = 1.0f;light.Direction = D3DXVECTOR3( -1.0f, -1.0f, 0.0f );light.Range = 1000.0f;

材质材质• 材质 : 用于描述对象(三角形)的反光性能,使它看起来有没有光泽和带有什么颜色。• 下面是描述材质的一些设置:

– Diffuse Reflection (漫反射)物体的漫反射颜色,能使物体看起来是什么颜色。– Ambient Reflection (环境反射)这也是一个颜色值,用于描述对象反射环境光的数量。你甚至可以指定它根本不反射环境光,这意味着它将不可见,除非接收到其它类型的光。– Specular Reflection and Power (镜面反射与高光强度)镜面反射的值,可以用镜面反射和高光强度设置对象,使它看起来发亮。– Emission (放射)使物体自发光,但不会影响到场景内的其它物体。

设置材质设置材质D3DMATERIAL9 mtrl;::ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;mtrl.Diffuse.b = mtrl.Ambient.b = 1.0f;mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;

mtrl.Specular.r =mtrl.Emissive.r= 0.0f; mtrl.Specular.g =mtrl.Emissive.g= 0.0f; mtrl.Specular.b =mtrl.Emissive.b= 0.0f; mtrl.Specular.a =mtrl.Emissive.a= 0.0f; 灯光与材质

顶点法线 顶点法线 • Direct3D 需要知道顶点法线以便它能够确定灯光照射到物体表面的角度,并且一旦计算了每个顶点的灯光, Direct3D 需要知道每个顶点的表面方向。注意顶点法线不一定和面法线相同。 • 为了描述顶点的顶点法线,我们必须更新原来的顶点结构 .( 如前叙 )

阴影的实现

纹理 纹理 • 纹理 :赋于某物体一定的纹理属性

– 多种贴图方式 (参见 :3DMAX 里的材质与贴图演示 )• 纹理的基本概念

– 纹理坐标 : 纹理坐标的作用是在纹理上指定一个点,因为纹理是 2D 的,所以我们仅需要两个值 • U V值 :取值范围 :0-1.0f

– 纹理映射 :把纹理应用到对象上,这个过程就叫做“纹理映射”。在此过程中,纹理坐标会被映射到顶点上,所以,顶点将额外增加两个值: U 和 V 。

纹理映射举例纹理映射举例0 = (0, 1) 9 = (0, 0)1 = (0, 0) 10 = (1, 1)2 = (1, 1) 11 = (1, 0)3 = (1, 0) 12 = (0, 1)4 = (0, 1) 13 = (0, 0)5 = (0, 0) 14 = (0, 1)6 = (1, 1) 15 = (0, 0)7 = (1, 0) 16 = (1, 1)8 = (0, 1) 17 = (1, 0)

– 最近点取样 :• 过滤的效果不是很真实 ,但它的运算速度最快• 在匹配大小时 , 对材质进行同比放大 ,因此较为粗糙 .但因为速度快 ,因此常准备一些较大型的材质图做为贴图用 .

– 线性过滤• 将与像素点相邻的最近四个像素点之间做加权平均的运算 .• 也有失真 ,但比最近点取样要好

– Mipmap 过滤 :• 采用智能贴图技术 ,离观者近的 , 给高的细节 ,远的 , 则给出较粗的细节 , 这样 , 符合人们的观察习惯 ,又保证了精度• 缺点 : 计算时占用较多的系统资源

– 非线性过滤• 效果最好 ,但也最浪费系统资源

纹理过滤纹理过滤

设置纹理设置纹理Struct CUSTOMVERTEX{ FLOAT x, y, z; DWORD colour; FLOAT tu, tv; // 纹理坐标};

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)// 顶点格式

LPDIRECT3DTEXTURE9 m_pTexture;// 定义纹理

D3DXCreateTextureFromFile(g_pd3dDevice, szTextureFilePath, &m_pTexture))

// 加载纹理 , szTextureFilePath 为纹理图片为每个顶点设置纹理坐标

模型模型• 1.构成三角形的方法

–基础:任何 3D 模型(含平面模型)都是由三角形这个基本的几何图形来构成。–三角形清单:

• 在使用三角形之前,要先进行顶点的定义。• 特点:一个三角形由三个点决定, N 个三角形则需要 3*N 个顶点。

–三角形带:• 对于连成一片的三角形,进行重复使用• 使用一个三角形的后两个顶点与新的顶点构成新的三角形。

–三角形扇:– 以一个顶点为基准,以基他顶点来构成多个三角形。

两个三角形构成一个四边形,但只有 4 个顶点。

• 2 加载 .X 文件– 方法:

• 调用 D3D 的 D3DXLoadMeshFromX 函数将 .X 文件中的顶点数据读入到顶点缓冲区。• 加载必要的材质。• D3DXLoadMeshFromX 函数原型

HRESULT WINAPI D3DXLoadMeshFromX(      LPCTSTR pFilename,     DWORD Options,     LPDIRECT3DDEVICE9 pD3DDevice,     LPD3DXBUFFER *ppAdjacency,     LPD3DXBUFFER *ppMaterials,     LPD3DXBUFFER *ppEffectInstances,     DWORD *pNumMaterials,     LPD3DXMESH *ppMesh );

绘制模型文件