第13章 迈向三维世界——Direct3D 的四大变换

计算机图形学入门06:视口变换 计算机图形学入门,视口变换。 阅读详情

本章我们将介绍使用Direct3D 创建三维游戏的基础,四大变换的概念和使用的方方面面。所谓四大变换,其实是作者结合自己的经验,总结出来的对世界变换、取景变换、投影变换和视口变换的总称而已。

13.1 四大变换的基本认知

首先,我们来讲讲周边的概念。
在Direct3D 中,如果我们未进行任何空间坐标变换而直接绘制图形的话,图形将始终处于应用程序窗口的中心位置,在默认情况下这个位置就会成为世界坐标系的原点(0,0,0 ) 。另外,我们也不能改变观察图形的视角方向。默认情况下的观察方向是世界坐标系的Z 轴正方向,也就是垂直程序窗口并向里的方向。之前我们的几个demo 都是默认的Z 轴正方向为观察方向的。
为了迈向三维世界,为了能够随心所欲地在三维世界中绘制和观察游戏画面,我们需要了解四大变换的相关知识。
所谓四大变换,其实是作者自己在学习与运用Direct3D 的时候归纳出的,也就是世界变换、取景变换、投影变换和视口变换的总称。
下面我们先来大致概括一下这四大变换的用途。
  • 为了能在世界空间中的指定位置绘制图形,就需要在绘制图形前进行四大变换之一的世界变换运算。
  • 为了以不同的视角观察图形,就需要用到四大变换之二的取景变换运算。
  • 为了将相对较远的图形投影到同一个平面上并体现出“近大远小”的真实视觉效果,就需要用到四大变换之二的投影变换。
  • 为了控制显示图形的窗口的大小、比例以及深度等信息,就要用到四大变换之四的视口变换;
下面我们分别展开讲解这四大变换的细节知识。在讲解之前,有必要先跟大家脱明一下。这里的四大变换的前三个变换都是以矩阵作为载体的。这四大变换相关知识中或多或少会涉及到矩阵、向量、平面和射线等相关的数学知识。
好了,下面就开始依次讲解。

13.2 四大变换之一:世界变换

根据物体模型的大小、方向以及其他模型之间的相对关系,世界变换将物体模型从自身的局部坐标系中转换到世界坐标系中,并将所有的物体模型组织为一个场景,如下图。


就像这个世界上有很多不同的个体,每个个体都有自己独特的局部坐标系, 而每个个体又仅仅是这个世界中的一份子而己。
世界变换包括平移、旋转和缩放变换,我们可以通过D3DX 库中D3DXMatrixTranslation 、D3DXMatrixRotation*和D3DXMatrixScaling 函数来进行变换, 并得到一个世界变换矩阵。
其中D3DXMatrixTranslation 用于矩阵的平移操作, D3DXMatrixRotation* 用于矩阵的旋转操作,D3DXMatrixScaling 用于矩阵的缩放操作(稍后会分别介绍〉。这3 种变换是矩阵的最常用的变换。
调用这些函数将我们矩阵调整好之后, 接着我们就调用IDirect3DDevice9 接口的SetTransform方法来运用世界变换矩阵, 表示认定某某矩阵就是我们的世界变换矩阵了。
我们可以在DirectX SDK 中查到SetTransform 方法的原型:

HRESULT SetTransform(
  [in]  D3DTRANSFORMSTATETYPE State,
  [in]  const D3DMATRIX *pMatrix
);

  • 第一个参数, D3DTRANSFORMSTATETYPE 类型的State ,可以看出, 它是一个D3DTRANSFORMSTATETYPE 枚举类型,用于表示变换的类型, 是四大变换前三者之中的一种。可以取值为D3DTS_WORLD , 表示世界矩阵, 或者是D3DTRANSFORMSTATETYPE 枚举中的一种,这个D3DTRANSFORMSTATETYPE 枚举类型定义如下:

typedef enum D3DTRANSFORMSTATETYPE {
  D3DTS_VIEW          = 2,
  D3DTS_PROJECTION    = 3,
  D3DTS_TEXTURE0      = 16,
  D3DTS_TEXTURE1      = 17,
  D3DTS_TEXTURE2      = 18,
  D3DTS_TEXTURE3      = 19,
  D3DTS_TEXTURE4      = 20,
  D3DTS_TEXTURE5      = 21,
  D3DTS_TEXTURE6      = 22,
  D3DTS_TEXTURE7      = 23,
  D3DTS_FORCE_DWORD   = 0x7fffffff 
} D3DTRANSFORMSTATETYPE, *LPD3DTRANSFORMSTATETYPE;
其中D3DTS_VIEW 表示取景变换,D3DTS_PROJECTION 表示投影变换。而D3DTS_TEXTURE0~7 显然表示的就是某层纹理

(0~7 层)对应的变换矩阵了。
第二个参数,const D3DMATRIX 类型的*pMatrix ,是一个有实实在在内容的矩阵,显然就是我们想要设置为与第一个参数中指定的类型相挂钩的候选人矩阵了。
接着我们分别来介绍经常会用到的矩阵的一些基本变换方法。

13.2.1 矩阵的平移

首先介绍D3DXMatrixTranslation 方法, D3D 中的平移函数。
在Direct3D里,平移矩阵应是使用最多的矩阵。这是因为每个物体的相对位置,都是通过平移矩阵来创造出来的。物体的整体移动,说白了就是坐标点的移动。比如从点(x、y、z)移动到新的位置(x’, y’, z’)。Direot3D 为我们提供了

D3DXMatrixTranslation 方法用于矩阵的平移。我们先来看一下这个函数的原型:

 D3DXMATRIX * D3DXMatrixTranslation(
  __inout  D3DXMATRIX *pOut,
  __in     FLOAT x,
  __in     FLOAT y,
  __in     FLOAT z
);
这个函数其实用于创造一个相对于原点(0, 0, 0)有偏移量的矩阵出来。我们先来看一下各个参数的意义。

  • 第一个参数, D3DXMATRIX 类型的*pOut ,从类型上来看就知道它是一个D3DXMATRIX类型的4 × 4 的矩阵,我们调用这个D3DXMatrixTranslation 方法,其实就是在为这个矩阵赋值,让这个矩阵相对于原点有一个偏移量,也就是我们需要平移的距离。但具体的平移操作其实并不是由这个函数完成的,这个函数其实是在创建一个平移矩阵。
  • 第二个参数, FLOAT 类型的x , 显然是X 轴的平移量。
  • 第三个参数, FLOAT 类型的y,显然是Y 轴的平移量。
  • 第四个参数, FLOAT 类型的z , 显然是Z 轴的平移量。
比如要沿着Z 轴的正方向平移10 个单位,就需要按下面代码来设置平移矩阵:
D3DXMATRIX mTrans;
D3DXMatrixTranslation(&mTrans,0,0,10);
然后我们把需要进行平移操作的矩阵,乘以这个创建好mTrans 矩阵,就完成了平移操作。比如说我们有一个mMtrix 矩阵,我们需要这个mMtrix 矩阵沿Z 轴正方向平移10 个单位,就让mTrans和mMtrix 相乘就可以了,他们相乘的结果就是mMtrix 矩阵向上平移10 个单位后的矩阵。其中相乘操作通过D3DXMatrixMultiply 来完成。
 D3DXMATRIX * D3DXMatrixMultiply(
  __inout  D3DXMATRIX *pOut,
  __in     const D3DXMATRIX *pM1,
  __in     const D3DXMATRIX *pM2
);
第一个参数,为输出的结果。第二和第三个参数为参加乘法的两个矩阵。这个函数的作用可以用一个式子来表示,

也就是pM1 * pM2 = pOut 。
所以, 整体来看,要把mMtrix 矩阵向Z 轴正方向平移10 个单位,就是如下的代码:

 D3DXMATRIX mTrans;
 D3DXMatrixTranslation (&mTrans , 0 , 0 , 10 );
 D3DXMatrixMultiply (&mMtrix, &mMtrix , &&mTrans) ;
再举一个例子, 如果我们仅仅是将一个物体沿X 轴正方向平移5 个单位, Y 轴负方向平移3个单位就可以了,也就是只做了平移操作,就可以直接把我们创建的这个中间矩阵作为世界矩阵使用,代码如下:

 D3DXMATRIX mTrans ;
 D3DXMatrixTranslation (&mTrans , 5 , - 3 , 0 );
 g_pd3dDevice->SetTransform (D3DTS_WORLD , &mTrans) ;
另外, 关于矩阵的乘法,因为Direct3D对D3DXMATRIX 矩阵类型进行了扩展,对矩阵乘法进行了重载,所以矩阵的乘法运算可以不用拘泥于使用上面讲到的D3DXMatrixMultiply()来实现了,可以简单地使用乘法运算符“ * ”就可以了,即多个矩阵的乘积可以这样写:

 matAnswer=matl*mat2*mat3*mat 4…··· * matN

13.2.2 矩阵的旋转

旋转和平移类似,也是先用一个函数创建好用于旋转的一个中间矩阵,然后让我们需要旋转的那个矩阵右乘这个中间矩阵就好了。关于这个旋转中间矩阵的创建,用的就是d9dx9.lib 库中的D3DXMatrixRotationX、D3DXMatrixRotationY 以及D3DXMatrixRotationZ 。这3 个函数非常相似,我们可以一走介绍,这3 个函数的原型声明如下:

 D3DXMATRIX * D3DXMatrixRotationX(
  __inout  D3DXMATRIX *pOut,
  __in     FLOAT Angle
);
 D3DXMATRIX * D3DXMatrixRotationY(
  __inout  D3DXMATRIX *pOut,
  __in     FLOAT Angle
);
 D3DXMATRIX * D3DXMatrixRotationZ(
  __inout  D3DXMATRIX *pOut,
  __in     FLOAT Angle
);

  • 第一个参数, D3DXMATRIX 类型的*pOut,是作为输出结果的旋转矩阵。
  • 第二个参数, FLOAT 类型的angle 表示要旋转的弧度值。
 下面举个例子,同样,如果我们只对某个物体在世界坐标系中进行旋转操作的话,也可以把D3DXMatrixRotationX系列函数创造出来的中间矩阵作为我们的世界矩阵。
若要将一个对象沿Y 轴旋转90度,也就是如下代码:

 D3DXMATRIX mTrans ;
 float fAngle = 90 * (2.0f*D3DX_PI) /360.0f;
 D3DXMatrixRotationY (&mTrans, fAngle) ;
 g_pd3dDevice- >SetTransform (D3DTS_WORLD, &mTrans) ;

13.2.3 矩阵的缩放

与旋转和平移类似, 矩阵缩放也是先用一个函数创建好用于缩放的一个中间矩阵,然后让需要缩放那个矩阵右乘这个中间矩阵就好了。关于这个缩放中间矩阵的创建,为D3DXMatrixScaling 函数,这个函数的原型如下:

 D3DXMATRIX * D3DXMatrixScaling(
  __inout  D3DXMATRIX *pOut,
  __in     FLOAT sx,
  __in     FLOAT sy,
  __in     FLOAT sz
);

  • 第一个参数, D3DXMATRIX 类型的*pOut , 是作为输出结果的缩放矩阵。
  • 第二个参数到第四个参数,显然就是浮点型的X,Y,Z 轴上的缩放比例了。
比如, 要将一个物体在Z 轴上放大5 倍, 代码就是这样写:

 D3DXMATRIX mTrans ;
 D3DMatrixScaling (&mTrans, 1.0f, 1.0f, 5.0f);
 g_pd3dDevice- >SetTransform(D3DTS_WORLD, &mTrans);
最后,我们来一个综合的调用实例,比如要将一个物体在X 轴上放大3 倍, 然后又绕Y 轴旋转120 度,最后又沿Z 轴平移正方向10 个单位,实现代码如下:
 D3DXMATRIX matWorld;
 D3DXMATRIX matTranslate , matRotation, matScale;
 D3DXMatrixScaling (&matScale , 3 . Of , 1. 时, 1. Of) ; // 定义出一个X 轴3 倍长的单位矩阵
 float fAngle=l20*(2.0f*D3DX_PI) /360.0f ; // 定义出一个120 度的角
 D3DXMatrixRotationY(&matRotation , fAngle) ; // 得到一个绕Y 轴旋转60度的角
 D3DXMatrixMultiply (&matWorld, & matScale, & matRotation) ; // matWorld=matScale*matRotation
 D3DXMatrixTranslation(&matTranslate,O.Of,O.Of,10.0f); // 定义出一个沿Z 轴平移10个单位的矩阵
 D3DXMatrixMultiply (&matWorld ,&matWorld,& matTranslate); // matWorld=matWorld *matTranslate
 g_pd3dDevice->SetTransform(D3DTS_WORLD, &mTrans); // 让计算出来的世界矩阵运用到Direct3D 程序中
对于缩放、旋转和平移都上场的情况,记住一个原则——先缩放、再旋转、最后平移。

另外提一个单位化矩阵的函数,即D3 DXMatrixIdentity 函数,其用法非常简单,唯一的参数就是单位化之后的输出矩阵,也就是这样写:

 D3DXMATRIX matWorld;
 D3DXMatrixIdentity(&matWorld); // 单位化世界矩阵

13.3 四大变换之二:取景变换

取景变换,人如其名,就是用来取景的,也就是设置Direct3D 中的虚拟摄像机的位置和观察点。

对于处于不同位置的虚拟摄像机和观察点,其观察物体模型的视角方向也有所差异,因此实际看到的物体模型的实际形状也有所不同。正所谓“横看成岭侧成峰”,就像这幅图所表达的观点一样:


为了确定一个虚拟摄像机的位置和观察方向,需要指定虚拟摄像机在世界坐标系中的位置、观察点位置以及正方向。为了能够进行取景变换,首先需要通过D3DX 库中的D3DXMatrixLookAtLH函数计算并得到一个取景变换矩阵(或观察矩阵〉, 然后同样调用IDirect3DDevice 接口的SetTransform 方法应用取景变换。
其中, D3DXMatrixLookAtLH 函数的声明如下:

 D3DXMATRIX * D3DXMatrixLookAtLH(
  __inout  D3DXMATRIX *pOut,
  __in     const D3DXVECTOR3 *pEye,
  __in     const D3DXVECTOR3 *pAt,
  __in     const D3DXVECTOR3 *pUp
);

然后依然是函数参数的介绍:
  •  第一个参数, D3DXMATRIX 类型的*pOut , 最终生成的观察矩阵。
  •  第二个参数, const D3DXVECTOR3 类型的*pEye ,指定虚拟摄像机在世界坐标系中的位置。
  •  第三个参数, const D3DXVECTOR3 类型的*pAt ,为观察点在世界坐标系中的位置。
  •  第四个参数, const D3DXVECTO阳类型的*pUp , 为摄像机的上向量,通常设为( 0, 1 ,0 )就可以了。
依然是一个使用的例子,代码如下:

//【四大变换之二】:取景变换矩阵的设置
	//--------------------------------------------------------------------------------------
	D3DXMATRIX matView; //定义一个矩阵
	D3DXVECTOR3 vEye(0.0f, 0.0f, -200.0f);  //摄像机的位置
	D3DXVECTOR3 vAt(0.0f, 0.0f, 0.0f); //观察点的位置
	D3DXVECTOR3 vUp(0.0f, 1.0f, 0.0f);//向上的向量
	D3DXMatrixLookAtLH(&matView, &vEye, &vAt, &vUp); //计算出取景变换矩阵
	g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView); //应用取景变换矩阵

13.4 四大变换之三:投影变换

经过上一步的取景变换之后,物体模型就位于观察坐标系中了。然而,为了能够将三维场景显示在二维的显示平面上(显示屏是二维的),还需要通过投影变换将三维物体投影到二维的平面上,这个过程我们把它叫做透视投影或投影变换。
下面这幅图就显示得很清楚了。

可以看到, 动漫角色眼睛处(即摄像机处)规定的距离和角度唯一确定了投影窗口的大小。.就好比一个人站在一间封闭房间里,房间唯一可以接收到光线的地方是一块高大的落地窗,而房间外面对着落地窗这边的是一堵无限长无限宽,绵延到世界尽头的白色的墙。人眼透过落地窗看到房子外边三维的世界, 最终投影在了那堵二维的墙上。
显然,投影窗口是一个二维平面,用于描述三维物体模型经过透视投影后的二维图像,在Direct3D 中投影窗口平面默认定义为z= 1的平面。虚拟摄像机与投影窗口平面共同构成了一个对观察者可见的三维空间。在3D 图形学中这部分空间称为视截体( View Frustum ) ,位于视截体内的物体模型被映射到二维投影平面上,而位于视截体外的物体模型或者其中一部分将不可见,这个过程我们称为裁剪( Clipping ,即取屏幕内的景物, 屏幕外的一律无视)。
投影变换负责将位于视截体内的物体模型映射到投影窗口中。D3DX 库中的D3DXMatrixPerspectiveFovLH 函数可以用来计算一个视截体, 并根据该视截体的描述信息创建一个投影矩阵变换。
这个D3DXMatrixPerspectiveFovLH 方法可以在MSDN 中查到其函数原型:

 D3DXMATRIX * D3DXMatrixPerspectiveFovLH(
  __inout  D3DXMATRIX *pOut,
  __in     FLOAT fovy,
  __in     FLOAT Aspect,
  __in     FLOAT zn,
  __in     FLOAT zf
);
  • 第一个参数, D3DXMATRIX 类型的*pOut , 它为我们最终生成的投影变换矩阵。
  • 第二个参数, FLOAT 类型的fovy , 用于指定以弧度为单位的虚拟摄像机在y 轴上的成像角度,即视域角度( View of View ),成像角度越大,映射到投影窗口中的图形就越小;反之,投影图像就越大。
  • 第三个参数, FLOAT 类型的Aspect,用于描述屏幕显示区的横纵比,他的值就为屏幕的宽度/高度。对应不同比例的显示屏幕,比如16/9, 4/3 等等, 最终显示的投影图像可能会使图像被拉伸。
  • 第四个参数, FLOAT 类型的zn , 表示视截体中近裁剪面距我们摄像机的位置, 即人眼到“室内落地窗”之间的距离。
  • 第五个参数, FLOAT 类型的zf,表示视截体中远裁剪面距我们摄像机的位置, 即人眼到“室外黑色墙壁”之间的距离。

依旧是一个调用实例:

	//【四大变换之三】:投影变换矩阵的设置
	//--------------------------------------------------------------------------------------
	D3DXMATRIX matProj; //定义一个矩阵
	D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4.0f, 1.0f, 1.0f, 1000.0f); //计算投影变换矩阵
	g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);  //设置投影变换矩阵

13.5 四大变换之四:视口变换

 终于讲到四大变换的最后一个了。其实这一步非常简单,也就是填下填空题, 然后设置一下就好了。并不像前三大变换一样要用到矩阵的相关知识。下面具体看看视口变换的相关概念吧。
视口变换用于将投影窗口中的图形转换到显示屏幕的程序窗口中。视口是程序窗口中的一个矩形区域,它可以是整个程序窗口, 可以是窗口的客户区,也可以是窗口中其他矩形区域,如下图所示。


在Direct3D 中,视口是由D3DVIEWPROT9 结构体来描述的, 其中定义了视口的位置、宽度高度等信息, 

在DirectX SDK 中我们可以查到该结构体的声明如下:

 typedef struct D3DVIEWPORT9 {
  DWORD X;        //表示视口相对于窗口的X坐标
  DWORD Y;        //视口相对于窗口的Y坐标
  DWORD Width;    //视口的宽度
  DWORD Height;   //视口的高度
  float MinZ;     //视口在深度缓存中的最小深度值
  float MaxZ;     //视口在深度缓存中的最大深度值
} D3DVIEWPORT9, *LPD3DVIEWPORT9;
每个参数的类型在注释中已经做了解释。
下面是这个结构体调用的实例, 看看如何定义视口。
方法一: 先做填空题,做完之后调用IDirect3D9Device9 接口的SetViewPort 方法设置当前窗口中的视口,然后Direct3D 将自动完成视口变换。
D3DVIEWPORT9 vp= { 0,0,800,600,0,1} ;
g_pD3dDevice->SetViewport(&vp);
方法二: 结构体的内容分开来赋值。

//【四大变换之四】:视口变换的设置
	//--------------------------------------------------------------------------------------
	D3DVIEWPORT9 vp; //实例化一个D3DVIEWPORT9结构体,然后做填空题给各个参数赋值就可以了
	vp.X      = 0;		//表示视口相对于窗口的X坐标
	vp.Y      = 0;		//视口相对对窗口的Y坐标
	vp.Width  = WINDOW_WIDTH;	//视口的宽度
	vp.Height = WINDOW_HEIGHT; //视口的高度
	vp.MinZ   = 0.0f; //视口在深度缓存中的最小深度值
	vp.MaxZ   = 1.0f;	//视口在深度缓存中的最大深度值
	g_pd3dDevice->SetViewport(&vp); //视口的设置
这两种方法其实也就是结构体填空题的两种方式而己,窗口类WNDCLASS 的定义也是这样的,可以触类旁通。

13.6 总结

我们的四大变换为: 世界变换,取景变换,投影变换,视口变换。
  • 为了能在世界空间中的指定位位置绘制图形,就需要在绘制图形前进行四大变换之一的世界变换运算。
  • 为了以不同的视角观察图形, 就需要用到四大变换之二的取景变换运算。
  • 为了将相对较远的图形投影到同一个平面上并体现出“近大远小” 的真实视觉效果,就需要用到四大变换之三的投影变换。
  • 为了控制显示图形的窗口的大小,比例以及深度等等信息,就要用到四大变换之四的视口变换。

13.7 示例程序D3Ddemo5

上一节讲解了绘制3D 图形时用到的四大变换, 本节将利用四大变换来绘制一个转动的颜色随机的彩色立方体的demo 。我们把四大变换封装在了一个全局的Matrix_Set()函数中,并在渲染五步曲的第三步中进行了Matrix_Set() 函数的调用。
在放出实现的核心源代码之前,我们首先来看一下本节介绍的核心知识,也就是实现了四大变换封装的Matrix_Set()函数的具体实现方法:

//-----------------------------------【Matrix_Set( )函数】--------------------------------------
//	描述:封装了Direct3D四大变换的函数,即世界变换,取景变换,投影变换,视口变换的设置
//--------------------------------------------------------------------------------------------------
VOID Matrix_Set()
{
	//--------------------------------------------------------------------------------------
	//【四大变换之一】:世界变换矩阵的设置
	//--------------------------------------------------------------------------------------
	D3DXMATRIX matWorld, Rx, Ry, Rz;
	D3DXMatrixIdentity(&matWorld);                  // 单位化世界矩阵
	D3DXMatrixRotationX(&Rx, D3DX_PI *(::timeGetTime() / 1000.0f));    // 绕X轴旋转
	D3DXMatrixRotationY(&Ry, D3DX_PI *( ::timeGetTime() / 1000.0f/2));    // 绕Y轴旋转
	D3DXMatrixRotationZ(&Rz, D3DX_PI *( ::timeGetTime() / 1000.0f/3));   // 绕Z轴旋转
	matWorld = Rx * Ry * Rz * matWorld;             // 得到最终的组合矩阵
	g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);  //设置世界变换矩阵

	//--------------------------------------------------------------------------------------
	//【四大变换之二】:取景变换矩阵的设置
	//--------------------------------------------------------------------------------------
	D3DXMATRIX matView; //定义一个矩阵
	D3DXVECTOR3 vEye(0.0f, 0.0f, -200.0f);  //摄像机的位置
	D3DXVECTOR3 vAt(0.0f, 0.0f, 0.0f); //观察点的位置
	D3DXVECTOR3 vUp(0.0f, 1.0f, 0.0f);//向上的向量
	D3DXMatrixLookAtLH(&matView, &vEye, &vAt, &vUp); //计算出取景变换矩阵
	g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView); //应用取景变换矩阵

	//--------------------------------------------------------------------------------------
	//【四大变换之三】:投影变换矩阵的设置
	//--------------------------------------------------------------------------------------
	D3DXMATRIX matProj; //定义一个矩阵
	D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4.0f, 1.0f, 1.0f, 1000.0f); //计算投影变换矩阵
	g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);  //设置投影变换矩阵

	//--------------------------------------------------------------------------------------
	//【四大变换之四】:视口变换的设置
	//--------------------------------------------------------------------------------------
	D3DVIEWPORT9 vp; //实例化一个D3DVIEWPORT9结构体,然后做填空题给各个参数赋值就可以了
	vp.X      = 0;		//表示视口相对于窗口的X坐标
	vp.Y      = 0;		//视口相对对窗口的Y坐标
	vp.Width  = WINDOW_WIDTH;	//视口的宽度
	vp.Height = WINDOW_HEIGHT; //视口的高度
	vp.MinZ   = 0.0f; //视口在深度缓存中的最小深度值
	vp.MaxZ   = 1.0f;	//视口在深度缓存中的最大深度值
	g_pd3dDevice->SetViewport(&vp); //视口的设置
}
其中timeGetTime 方法以毫秒为时间单位返回从Windows 系统开机时起所经过的时间。这样就可以通过(::timeGetTime() / 1000.0)这个式子来构造一个从0 到1的连续的时间周期。D3DX_PI 是Direct3D中定义的一个宏,原型为:
#define D3DX_PI    ((FLOAT)  3.141592654f)
接着我们就贴出本节示例程序的核心源代码,它现实的功能是按键盘上的1 键和2 键可以在线框填充模式和实体填充模式之间切换。
//------------------------------------------------------------------------------------------------
// 【顶点缓存使用四步曲之一】:设计顶点格式
//------------------------------------------------------------------------------------------------
struct CUSTOMVERTEX
{
	FLOAT x, y, z;
	DWORD color;
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)  //FVF灵活顶点格式

//-----------------------------------【全局变量声明部分】-------------------------------------
//	描述:全局变量的声明
//------------------------------------------------------------------------------------------------
LPDIRECT3DDEVICE9					g_pd3dDevice = NULL; //Direct3D设备对象
ID3DXFont*								g_pFont=NULL;    //字体COM接口
float											g_FPS = 0.0f;       //一个浮点型的变量,代表帧速率
wchar_t										g_strFPS[50];    //包含帧速率的字符数组
LPDIRECT3DVERTEXBUFFER9		g_pVertexBuffer = NULL;    //顶点缓冲区对象
LPDIRECT3DINDEXBUFFER9		g_pIndexBuffer  = NULL;    // 索引缓存对象

//-----------------------------------【Object_Init( )函数】--------------------------------------
//	描述:渲染资源初始化函数,在此函数中进行要被渲染的物体的资源的初始化
//--------------------------------------------------------------------------------------------------
HRESULT Objects_Init(HWND hwnd)
{
	//创建字体
	if(FAILED(D3DXCreateFont(g_pd3dDevice, 36, 0, 0, 1, false, DEFAULT_CHARSET, 
		OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, 0, _T("微软雅黑"), &g_pFont)))
		return E_FAIL;
	srand(timeGetTime());      //用系统时间初始化随机种子 

	//--------------------------------------------------------------------------------------
	// 【顶点缓存、索引缓存绘图四步曲之二】:创建顶点缓存和索引缓存
	//--------------------------------------------------------------------------------------
	//创建顶点缓存
	if( FAILED( g_pd3dDevice->CreateVertexBuffer( 8*sizeof(CUSTOMVERTEX),
		0, D3DFVF_CUSTOMVERTEX,
		D3DPOOL_DEFAULT, &g_pVertexBuffer, NULL ) ) )
	{
		return E_FAIL;
	}
	// 创建索引缓存
	if( FAILED( 	g_pd3dDevice->CreateIndexBuffer(36* sizeof(WORD), 0, 
		D3DFMT_INDEX16, D3DPOOL_DEFAULT, &g_pIndexBuffer, NULL)) )
	{
		return E_FAIL;

	}
	//--------------------------------------------------------------------------------------
	// 【顶点缓存、索引缓存绘图四步曲之三】:访问顶点缓存和索引缓存
	//--------------------------------------------------------------------------------------
	//顶点数据的设置,
	CUSTOMVERTEX Vertices[] =
	{
		{ -20.0f, 20.0f, -20.0f,  D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) },
		{ -20.0f, 20.0f, 20.0f,  D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) }, 
		{ 20.0f, 20.0f, 20.0f,  D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) },
		{ 20.0f, 20.0f, -20.0f,  D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) },
		{ -20.0f, -20.0f, -20.0f, D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) },
		{ -20.0f, -20.0f, 20.0f, D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) }, 
		{ 20.0f, -20.0f, 20.0f, D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) },
		{ 20.0f, -20.0f, -20.0f, D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) },

	};

	//填充顶点缓存
	VOID* pVertices;
	if( FAILED( g_pVertexBuffer->Lock( 0, sizeof(Vertices), (void**)&pVertices, 0 ) ) )
		return E_FAIL;
	memcpy( pVertices, Vertices, sizeof(Vertices) );
	g_pVertexBuffer->Unlock();

	// 填充索引数据
	WORD *pIndices = NULL;
	g_pIndexBuffer->Lock(0, 0, (void**)&pIndices, 0);

	// 顶面
	pIndices[0] = 0, pIndices[1] = 1, pIndices[2] = 2;
	pIndices[3] = 0, pIndices[4] = 2, pIndices[5] = 3;
	// 正面
	pIndices[6] = 0, pIndices[7]  = 3, pIndices[8]  = 7;
	pIndices[9] = 0, pIndices[10] = 7, pIndices[11] = 4;
	// 左侧面
	pIndices[12] = 0, pIndices[13] = 4, pIndices[14] = 5;
	pIndices[15] = 0, pIndices[16] = 5, pIndices[17] = 1;
	// 右侧面
	pIndices[18] = 2, pIndices[19] = 6, pIndices[20] = 7;
	pIndices[21] = 2, pIndices[22] = 7, pIndices[23] = 3;
	// 背面
	pIndices[24] = 2, pIndices[25] = 5, pIndices[26] = 6;
	pIndices[27] = 2, pIndices[28] = 1, pIndices[29] = 5;
	// 底面
	pIndices[30] = 4, pIndices[31] = 6, pIndices[32] = 5;
	pIndices[33] = 4, pIndices[34] = 7, pIndices[35] = 6;
	g_pIndexBuffer->Unlock();

  return S_OK;
}

//-----------------------------------【Direct3D_Render( )函数】-------------------------------
//	描述:使用Direct3D进行渲染
//--------------------------------------------------------------------------------------------------
void Direct3D_Render(HWND hwnd)
{
	//--------------------------------------------------------------------------------------
	// 【Direct3D渲染五步曲之一】:清屏操作
	//--------------------------------------------------------------------------------------
	g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255, 214, 158), 1.0f, 0);

	//定义一个矩形,用于获取主窗口矩形
	RECT formatRect;
	GetClientRect(hwnd, &formatRect);
	//--------------------------------------------------------------------------------------
	// 【Direct3D渲染五步曲之二】:开始绘制
	//--------------------------------------------------------------------------------------
	g_pd3dDevice->BeginScene();                     // 开始绘制

	//--------------------------------------------------------------------------------------
	// 【Direct3D渲染五步曲之三】:正式绘制,利用顶点缓存绘制图形
	//--------------------------------------------------------------------------------------
	//----------------------------------------------------------------
	// 【顶点缓存、索引缓存绘图四步曲之四】:绘制图形
	//----------------------------------------------------------------

		Matrix_Set();//调用封装了四大变换的函数,对Direct3D世界变换,取景变换,投影变换,视口变换进行设置
	// 获取键盘消息并给予设置相应的填充模式
	if (::GetAsyncKeyState(0x31) & 0x8000f)         // 若数字键1被按下,进行线框填充
		g_pd3dDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
	if (::GetAsyncKeyState(0x32) & 0x8000f)         // 若数字键2被按下,进行实体填充
		g_pd3dDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);

	g_pd3dDevice->SetStreamSource( 0, g_pVertexBuffer, 0, sizeof(CUSTOMVERTEX) );//把包含的几何体信息的顶点缓存和渲染流水线相关联
	g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );//指定我们使用的灵活顶点格式的宏名称
	g_pd3dDevice->SetIndices(g_pIndexBuffer);//设置索引缓存
	g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);//利用索引缓存配合顶点缓存绘制图形

	//在窗口右上角处,显示每秒帧数
	int charCount = swprintf_s(g_strFPS, 20, _T("FPS:%0.3f"), Get_FPS() );
	g_pFont->DrawText(NULL, g_strFPS, charCount , &formatRect, DT_TOP | DT_RIGHT, D3DCOLOR_XRGB(255,39,136));

	//--------------------------------------------------------------------------------------
	// 【Direct3D渲染五步曲之四】:结束绘制
	//--------------------------------------------------------------------------------------
	g_pd3dDevice->EndScene();                       // 结束绘制
	//--------------------------------------------------------------------------------------
	// 【Direct3D渲染五步曲之五】:显示翻转
	//--------------------------------------------------------------------------------------
	g_pd3dDevice->Present(NULL, NULL, NULL, NULL);  // 翻转与显示
}

多次运行这个程序, 我们会得到如下的、旋转着的随机颜色的立方体来,并且可以通过按键盘上的1 键和2 键在线框填充模式和实体填充模式之间切换。



13.8 章节小憩

通过这一章的学习, 我们己经从二维的平面世界转到了三维的立体世界。按这样的进度,离用Direcr3D 绘制出绚丽游戏场景还会远吗?











计算机图形学笔记(观测变换、模型变换、视图变换、投影变换、视口变换) 计算机图形学笔记(观测变换、模型变换、视图变换、投影变换、视口变换) 目录计算机图形学笔记(观测变换、模型变换、视图变换、投影变换、视口变换)一、介绍(一)模型变换(Model transformation)(二)视图变换(View transformation)(三)投影变换(Projection transformation)(四)视口变换(Viewport transformation)二、使用步骤1.引入库2.读入数据总结 一、介绍 我们可以这样来描述观测变换(Viewing transform 阅读详情

相关推荐

从萤石云到GB28181:海康4G摄像机接入第三方平台的曲折之路

本文深入探讨了海康4G摄像机接入第三方平台时遇到的协议冲突问题,特别是GB28181与萤石云服务的互斥性。通过技术分析揭示了4G模块的定向流量限制和协议栈资源竞争等核心问题,并提供了有线接入测试和萤石云API二次开发等解决方案。最后总结了设备选型的关键参数和协议兼容性检查清单,为安防监控系统集成提供实用指导。

mango的博客 991

DirectX三维空间旋转矩阵原理

三维空间的旋转分开来看其实就是二维空间的旋转,对于二维空间的旋转给位同学大家高中应该都学过,这里简单推导一下,由于我不会制作这种图,随便在网上找了一下图,意思到了就可以,我们假设一线段从如下图所标示的x'轴旋转到ov线段,也就是从原来的与x轴夹角为β变为α,再假设α-β=θ。 这里我们采用极坐标系思想,假设线段长度为ρ,那么原来的v坐标(x1,y1)为(ρcosβ,ρsinβ),变换之后的v坐标

小崽子图图的专栏 3434

STM32F407 BootLoader实战:从零搭建到OTA升级(附完整源码)

本文详细介绍了为STM32F407微控制器从零搭建BootLoader并实现稳定OTA升级的完整实战指南。内容涵盖Flash分区规划、链接脚本配置、核心跳转逻辑、中断向量表重定向、可靠的升级流程设计,并深入探讨了双备份与回滚机制以提升工业级可靠性。文章提供了可直接使用的代码框架,并分享了关键调试技巧,帮助开发者快速掌握STM32远程固件更新技术。

weixin_29192211的博客 438

OpenGL之几何、投影、裁剪、视口变换以及全局变换与局部变换

opengl 图形编程技术。

TxyITxs的博客 2507

用Python实现图片风格迁移,让你的图片更加的高逼格!

先来看下效果: 上图是老王在甘南合作的米拉日巴佛阁外面拍下的一张照片,采用风格迁移技术后的效果为: 一些其它效果图: 下面进入正题。 近年来,由深度学习所引领的人工智能(AI)技术浪潮,开始越来越广泛地应用到生活各个领域。这其中,人工智能与艺术的交叉碰撞,在相关技术领域和艺术领域引起了高度关注。就在上个月,由电脑生成的艺术品在佳士得(Christie’s)的拍卖价竟高达43.25万美元,...

Python追梦 6180

Emuelec系统安装全流程:超详细版指南(从零开始)

手把手带你完成emuelec系统的完整安装,从基础准备到系统配置一步不落,适合新手入门。深入解析emuelec在各类设备上的部署技巧,让复古游戏体验更流畅。

weixin_42594419的博客 1967

4.4 视口变换

一、投影变换和视口变换 投影变换是将viewing frustum(视景体)变换为一个cuboid(立方体) 视口变换在投影变换之后,是将这个cuboid中的物体变换到视口中,见下图 二、视口变换 glViewport(GLint x,GLint y,GLsizei width,GLsizei height)X,Y以像素为单位,指定了视口的左下角(在第一象限内,以(0,0)为原点的)位置。

夏木的博客 6711

【机器学习与数据挖掘实战 | 商务】案例03:基于k近邻算法的非侵入式电力负荷监测与分解的电力分析

本案例结合非侵入式电力负荷监测与分解的案例,重点介绍了在数据可视化的辅助下k近邻算法的应用。首先利用数据可视化寻找数据的特征,构建特征集合。然后构建k近邻模型,利用构建的特征集合训练模型,接着利用该模型对单一设备所属类别进行判定,最后计算实时用电量。

Morse_Chen的博客 2302

计算机图形学二:变换

计算机图形学基础

weixin_44683202的博客 1599

关节电机技术全解析:原理、双编码器、控制方法与硬件选型

关于关机电机的组成,技术原理,特点以及选型等方面的详细介绍,可以帮助快速学习关节电机相关内容!

start_up_go的博客 690

Wi-Fi QoS中AIFSN/CWmin/CWmax/TxOP参数是怎样计算的?

802.11e/WMM的EDCA机制通过AIFS、CWmin/CWmax和TxOP三组参数实现业务优先级控制。AIFS决定最短等待时间(AIFS=SIFS+AIFSN×SlotTime),CWmin/CWmax定义退避范围(2^ECW-1),TxOP设置最大占用时长(32µs单位)。默认配置中,语音业务(VO)优先级最高,其AIFSN最小(2)、CW范围最小(3-7)、TxOP适中(1.504ms);视频(VI)次之;普通数据(BE)和后台(BK)优先级最低。调优需根据网络特性调整参数:VoIP可降低AIF

1042484520@qq.com(邮箱) 1744

3、计算机图形学——模型视图变换、投影变换与视口变换

一、模型视图变换 模型视图变换主要是为了让摄像机回归到世界坐标的原点并且和拍摄物体一起进行变换,便于计算 模型视图变换的根据就是物体和相机的相对位置不变,那么,投影得到的图片也是不变的 首先规定相机拍摄方向朝向-Z,相机的位置位于e,相机的正上方可以用向量t来表示,那么将相机移动到世界坐标的原点的过程如下图 首先需要将相机平移值世界坐标原点,平移矩阵就可以写成 然后分别需要将g旋转到-Z,将t旋转到Y,将g叉积t的方向旋转到X,然而,这个旋转对应的旋转矩阵并不容易写出,但是如果将Z旋转到-

Master Cui的博客 4812

OD图 arcgis曲线制作插件 od图曲线 路径图曲线制作插件 航线图曲线制作插件

在ArcGIS 10.2 中导入节点数据,打开插件,选择输入起始节点和目标节点的节点文件Point,以Name字段(地名)为连接线的起始字段和目标字段,(Input Table File)选择连接关系表格SDLine.csv,(Origin Column 和 Destination Column)为起始节点和目标节点,(Output Path)为输出路径,应选择.gdb数据库路径,否则容易报错,(Chord Coefficient)为连线的曲率,数值越大,曲率越高。运行环境:ArcGIS10.2。...

JData_Engineer的博客 2669

视图矩阵揭秘:游戏摄像机背后的数学魔法

将标准化设备坐标(NDC)转换为屏幕坐标的过程是计算机图形学中的一个重要步骤。这个过程的原理主要涉及坐标系统的映射和转换。以下是详细的原理说明:标准化设备坐标(NDC):屏幕坐标:将NDC坐标转换为屏幕坐标的过程可以分为以下几个步骤:如果视口的左下角不在屏幕的(0, 0)位置,而是有一个偏移量(例如,左下角在(x_offset, y_offset)),则屏幕坐标的计算需要加上这个偏移量:将NDC坐标转换为屏幕坐标的原理主要是通过线性映射将标准化的坐标范围转换为实际的像素坐标,同时考虑坐标系统的方向和视口的偏

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 929

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

3.4 视口变换

视口变换,相当于选择照片大小。视口是一个矩形的窗口区域,图像就是在这个区域中绘制的。3.4.1 定义视口定义视口,使用函数glViewport。这个函数之前用过好多遍了。void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);在窗口中定义一个像素矩形,最终的图像将映射到这个矩形中。(x, y)参数指定了视口的左下角,width

snail_hunan的专栏 1301

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

计算机图形学二:视图变换-Viewing-Transformation

图形学,视图变换,变换矩阵

西电卢本伟的博客 2727

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

OpenGL--3D世界(视图变换,模型变换,投影变换,视口变换)

理论基础 1,OpenGL渲染3D物体到屏幕上的过程其实类似我们平时用照相机拍照的过程,这个步骤大致如下:一,把照相机固定在三脚架并让它对准场景(视图变换)二,把场景中的物体调整摆放好(模型变换)三,选择照相机的镜头,并调整放大倍数(投影变换)四,确定最终照片的大小(视口变换)。其中视图变换必须要在模型变换之前,其它可以在任何时候。 2,视图变换:设置摄像机的位置,gluLookAt(摄像机位置

疯狂的程序员 1万+

窗口-视口转换(详细)

宽倍数的计算: 初始窗口宽度/现窗口宽度。在构造函数中使用resize()函数。

qq_45303986的博客 1014

【必备知识】 三维空间/坐标转换/相机知识

以下内容包含了2D坐标与3D坐标系之间的转换以及关于相机场的基础知识,理解这部分内容可以更快入门SLAM相关、多视角合成、三维空间变换等内容。

weixin_39188311的博客 3216

透视变换和视口变换

透视变换和视口变换在渲染管线中起着至关重要的作用,它们分别负责处理三维场景的深度感知和二维屏幕上的正确显示。

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 1107

5.OpenGL视口变换、裁减、剪切与反馈(笔记)

但是必须说明的是,由于浮点数本身的工作机制,精度比较高的区域主要集中在0.0附近,而这个区域距离观察者可能是比较远的,但是我们期望的实际上是靠近观察者(近平面)的区域能够有更高的深度精度。在图元中剪切距离是线性插值的。如果需要改变一个偏移中心的物体大小,并且不希望它的位置同时发生改变,那么我们可以将物体中心移动到(0,0,0),然后再缩放大小,最后平移回到原来的位置。旋转都是沿着第一个轴的方向朝向第二个轴运动的,也就是说,按照各轴的正向顺序,从cos-sin形式的一行旋转到sin + cos的一行。

C++方向学习笔记 1287

【Visual C++】游戏开发笔记三十八 浅墨DirectX提高班之六 携手迈向三维世界:四大变换展身手...

本系列文章由zhmxy555(毛星云)编写,转载请注明出处。 文章链接:http://blog.youkuaiyun.com/zhmxy555/article/details/8408723 作者:毛星云(浅墨)邮箱:happylifemxy@163.com 本篇文章里,我们首先对Direct3D中固定功能渲染流水线相关概念进行了深入的剖析,然后介绍了创建三维游戏世界的四大变换的概念和使用的方方面面,...

轻轻草原 428

OpenGL 编程指南(第八版)学习笔记——5 视口变换、剪切与反馈

OpenGL 编程指南学习资料以及我整理的代码下载地址https://pan.baidu.com/s/1bqrcspD 文中提到的代码为下载文件中的“OpenGL编程指南 VS2015代码.zip”文件 5 视口变换、剪切与反馈 视口变换 这一部分涉及到很多数学知识,书中有讲解。看这一部分之前最好先把书中5.1和5.2看完,需要理解齐次坐标,以及矩阵是如何对物体进行移动、旋转、...

Wlk1229 2251

Direct3D基础(顶点坐标变换)

开始的话:顶点坐标变换时Direct3D学习中的入门基础,在这里将详述其原理: Direct3D中渲染三维对象的过程分为两个阶段:《1》T&L(Transforming and Lighting),即坐标变换和光照; 《2》光栅化处理阶段。 ...

dixuanzi9967的博客 490

OpenGL笔记--视图

本文内容摘自OpenGL编程指南第七版 #include "Test06.h" void Test06::Initialize(int* argc, char**argv, const char* title ) { base::Initialize(argc, argv, title); glClearColor(0.0, 0.0, 0.0, 0.0); gl

o_longzhong的专栏 725

DirectX 9.0中的坐标变换:从模型空间到屏幕坐标

局部坐标系到世界坐标系: 物体的局部坐标(模型坐标)通过世界变换(IDirect3DDevice9::SetTransform(D3DTS_WORLD, matrix))变换到世界坐标。 将一个物体的中心置于世界坐标系的点(-3, 2, 6): D3DXMATRIX matrix; D3DXMatrixTranslation(&matrix, -3.0f...

dd0406的博客 1203
上一篇: [VS2013]如何闪开安装VS2013必须要有安装IE10的限制
下一篇: 第14章 绘制出质感的世界——光照与材质
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独立游戏开发指南

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值