使用DirectX SDK之前,需要在标题搜索路径中包含INCLUDE\头文件路径,还要确认将此路径放在搜索路径列表的第一位,因为许多编译器自己带有旧版本的DirectX,编译器可能会在自己的INCLUDE\目录下找到旧版本的头文件,而使用这些头文件是错误的。具体做法如下(VC++6.0):
工具菜单--〉选项-〉目录-〉路径列表中设置相应路径即可,注意要将正确路径尽量放在靠前的位置。
固定管道 VS Programable Pipeline
以往显卡在顶点处理和像素处理过程中执行的是一套布在硬件上的固定的程序,D3D程序员只能设置一些参数,实际上就是你调用IDirect3DDevice::SetRenderState()时做的事,而这样的程序在IDirect3DDevice::DrawPrimitive()中自动执行,有些事情就很难办到。
现在的显卡,确切的说是现在的Direct3D允许你写这么一段程序替代固定的顶点处理过程和像素处理过程(记住,只是这两个过程,跟插值什么的没关系)。其中替换顶点处理的就叫Vertex Shader(暂时还没有确切的中文名),替换像素处理的就叫Pixel Shader。
渲染网格模型的两种方式
1.DrawSubset方法(未优化);
2.优化网络模型的属性列表,所有属于相同自己的表面事先都被分组到一起,然后调用DrawPrimitive或DrawIndexedPrimitive渲染它们。
Vertex Shader寄存器
使用16个输入寄存器;
一般的常量寄存器为c0-c95,但在ATI RADEOM 8500中是c0-c191;
暂存寄存器由12个寄存器组成;
至少13个输出寄存器;
...
从结构上讲,Direct3D设备包含一个变换模块、一个光照模块和一个光栅化模块。
Direct3D设备状态
Direct3D设备是一个状态机。应用程序设置光照、渲染和变换模块的状态,然后在渲染时传递数据给它们。
(1)渲染状态
设备渲染状态控制Direct3D设备光栅化模块的行为,它们通过改变渲染状态的属性,使用何种类型的着色算法,雾属性和其它光栅化器操作来达到这个目的。
固定功能顶点处理由IDirect3DDevice9::SetRenderState方法和以下设备渲染状态控制。这些控制中的大多数在使用可编程顶点着色器时没有任何作用。
另外,固定功能顶点处理流水线使用以下方法设置变换、材质和光照。
IDirect3DDevice9::SetTransform
IDirect3DDevice9::SetMaterial
IDirect3DDevice9::SetLight
IDirect3DDevice9::LightEnable
(2)取样器状态
SetSamplerState
(3)纹理层状态
SetTextureStageState
D3D SetRenderState
(1)禁用光照处理(缺省是打开的)
使用顶点颜色进行渲染,如果不禁用的话,将会看到一个黑糊糊的多边形。
m_pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);//因为使用顶点颜色渲染,所以要禁用光照处理
(2)允许渲染背面
缺省情况下Direct3D只挑选三角形的正面进行渲染,当旋转到一定角度,背面朝向观察者时,图像会消失,因此要关闭该项特性
m_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);//关闭“挑选”功能,允许渲染背面
(3)打开Z缓存
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16; //生成16 bit的Z缓存
m_pD3D->CreateDevice(...)
m_pDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);//启用Z缓存,允许消隐处理
m_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,255), 1.0f, 0);
(4)法线矢量进行归一化处理
在初始化函数CD3DWnd::InitD3D中设置渲染状态D3DRS_NORMALIZENORMALS为TRUE,确保顶点法线总是单位矢量,不受坐标变换的影响,这有助于提高渲染的精确性,但会增加处理器负担。
m_pDevice->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);//自动对法线矢量进行归一化处理
(5)纹理混合
当使用纹理时,实体的外观由纹理图片和材质经过某种计算获得,这个过程被称作纹理混合(Texture Blending),详细情况参见SDK的文章“Texture Blending”,下面的代码把第一层纹理的混合方式设为“纹理+材质的漫反射”:
pdevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_ADD); //运算类型:加
pdevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); //运算对象1:纹理
pdevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); //运算对象2:材质
D3D光照计算
对环境光的计算更像是直接赋值;
对漫反射光的计算是对光照和顶点法线的点积;
对镜面反射的计算还要考虑顶点到视点的方向,默认的光照状态不计算镜面反射高光。要启用镜面反射高光,需要将D3DRS_SPECULARENABLE设置为TRUE;
三种光照按照上述顺序迭加使用会产生一个比一个更真实的效果。
...
OGRE例子中robot.mesh只有在directx下才肯显示,openGL不行。
transform
Pitch ==> x-axis
Yaw ==> y-axis
Roll ==> z-axis
阴影产生方法相关
StandardMaterial:生成一张阴影贴图贴在受影响的模型上;
StencilShadow(模板阴影):生成影柱,判断每个顶点是否在阴影中;
ShadowMap(纹理阴影):生成阴影深度纹理,判断每个顶点与纹理上对应顶点的深度。
碰撞检测相关
AABB(axis-aligned bounding boxes)
OBB(oriented bounding boxes)
3D rigidbody,一般先AABB/OBB,再做精确的检测(点面,边边,边面。。。。)。
简单的碰撞检测可以自己实现,复杂些的(更精确、更真实)就要用专门的物理引擎了,商业的如PhysX、Havok,开源的非ODE莫属。
向量
点积:a.b = |a||b|cosθ,点积满足交换律
叉积:axb
当点乘和叉积在一起时,叉积优先计算。向量叉积不满足交换率,满足反交换率:axb=-(bxa) ,叉积也不满足结合率。
叉积得到的向量垂直于原来的两个向量。|axb|的长度等于向量的大小与向量夹角的sin值的积:|axb|=|a||b|sinθ,所以|axb|也等于以a和b为两边的平行四边形的面积。
如果a、b平行或任意一个为0,则axb=0。
垂直于a、b有两个方向,aXxb到底指向哪个方向呢?通过将a的头与b的尾相接,并检查从a到b是顺时针还是逆时针,能够确定axb的方向。在左手坐标系中,如果a和b呈顺时针,axb指向你;反之远离你。在右手坐标系中恰好相反,如果a和b呈顺时针,axb远离你;反之指向你。
获取DirectDraw7.0三种方法
OK,如果我们想要使用最新的 DirectDraw 即7.0版本(因为在 DirectX8.0 中微软去掉了DirectDraw)就需要一个 IDirectDraw7 接口。我们可以用基本的DirectDrawCreat()函数得到一个 IDirectDraw 1.0 接口,再从这里用 QueryInterface()来得到 IDirectDraw7 接口。另一方面,我们可以用底层COM函数直接得到 IDirectDraw7 ,或者用 DirectX7.0 版本其可用的DirectDrawCreatEx()函数直接创建接口。
骨骼蒙皮动画模型
一个典型的骨骼蒙皮动画模型保存如下信息:
网格信息
多边形(材质、纹理)、顶点(位置、法向量)
哪些骨骼影响该点,影响权重
骨骼信息
所有骨骼按照父子关系组成一棵树
每根骨骼包括在父骨骼坐标系中的变换矩阵
动画信息
关键帧(每一关键帧指出了每一骨骼在该时刻相对于父骨骼坐标系的变换矩阵,以及位置,朝向等变动)。
3ds max安装
安装安装的时候最好先装3ds max再装directx sdk,因为貌似在装dx sdk的时候,自动检测本机上的max版本,同时生成相应版本的插件供max文件导出为x文件时使用。貌似如此...
D3D光
┌环境光
光─┤ ┌点光源
└直射光─┼平行光
└聚光灯
环境光颜色的数据结构为D3DCOLOR,而直射光和材质采用同一数据结构表示颜色:D3DCOLORVALUE。
3D流水线
加载数据→多边形→局部坐标→世界坐标→剔除、背面消除→相机坐标→透视坐标 →屏幕坐标
│ ↑
└→光栅化─┘
↓
光照(着色)、纹理映射、投影