聽聽聽 鎶婁笁緇寸墿浣撳彉涓轟簩緇村浘褰㈣〃紺虹殑榪囩▼縐頒負鎶曞獎鍙樻崲銆?/p>
鎶曞獎鍙樻崲鐨勫垎綾繪儏鍐靛涓嬭〃鎵紺猴細
聽聽聽 鐗╀綋鍦ㄧ┖闂寸殑琛ㄧず鏄敤涓栫晫鍧愭爣鏉ヨ〃紺猴紝浣嗘槸褰撲漢浠幓瑙傚療鐗╀綋鏃訛紝鍧愭爣緋誨氨杞寲涓鴻瀵熷潗鏍囩郴銆傝繖灝遍渶瑕佸湪涓や釜鍧愭爣緋諱箣闂磋繘琛岃漿鎹紝鍙互閫氳繃騫崇Щ銆佹棆杞疄鐜頒粠涓栫晫鍧愭爣鍒拌瀵熷潗鏍囩殑鍙樻崲銆?/p>
騫崇Щ鍚庯紝鐢ㄥ崟浣嶇煝閲忔硶寰楀埌鏃嬭漿鐭╅樀錛?/p>
鍙?/font> Zv 杞村悜涓鴻瀵熷鉤闈㈢殑娉曞悜 VPN錛屽叾鍗曚綅鐭㈤噺n=VPN/|VPN|=(nx,ny,nz)
鍙?/font> Xv 杞村悜涓鴻瀵熸柟鍚?/font>PREF錛屽叾鍗曚綅鐭㈤噺u=PREF/|PREF|=(ux,uy,uz)
鍙?font face="Times New Roman">Yv杞村悜鐨勫崟浣嶇煝閲?/font>v=u脳n=錛?/font>vx錛?/font>vy錛?/font>vz錛?/font>
![]()
鍥犳涓栫晫鍧愭爣鍒拌瀵熷潗鏍囧埌鍙樻崲鐭╅樀涓猴細
![]()
聽姝e鉤琛屾姇褰憋紙涓夎鍥撅級聽聽聽 鎶曞獎鏂瑰悜鍨傜洿浜庢姇褰卞鉤闈㈢殑鎶曞獎縐頒負姝e鉤琛屾姇褰?/a>錛屾垜浠氬父鎵璇寸殑涓夎鍥懼潎灞炰簬姝e鉤琛屾姇褰便備笁瑙嗗浘鐨勭敓鎴愬氨鏄妸 x 銆?/font> y 銆?/font> z 鍧愭爣緋葷殑褰綋鎶曞獎鍒?/font> z =0鐨勫鉤闈紝鍙樻崲鍒?/font> u 銆?/font> v 銆?/font> w 鍧愭爣緋匯備竴鑸繕闇灝嗕笁涓鍥懼湪涓涓鉤闈笂鐢誨嚭錛岃繖鏃跺氨寰楀埌涓嬮潰鐨勫彉鎹㈠叕寮忥紝鍏朵腑( a 錛?/font> b )涓?/font> u 銆?/font> v 鍧愭爣緋諱笅鐨勫鹼紝 tx 銆?/font> ty 銆?/font> tz 鍧囧鍥句腑鎵紺恒?br />聽聽 1錛変富瑙嗗浘
聽聽 2錛変刊瑙嗗浘
聽聽 3錛変晶瑙嗗浘
涓夎鍥?br />
鏂滃鉤琛屾姇褰?/font>
聽聽聽 鎶曞獎鏂瑰悜涓嶅瀭鐩翠簬鎶曞獎騫抽潰鐨勫鉤琛屾姇褰辮縐頒負鏂滃鉤琛屾姇褰?/font>錛岀幇鍦ㄨ鎴戜滑鏉ユ帹瀵兼枩騫寵鎶曞獎鐨勫彉鎹㈢煩闃點備笅鍥句腑鐨刏=0鐨勫潗鏍囧鉤闈負瑙傚療騫抽潰錛岀偣錛?/font>
x
錛?/font>
y
錛変負鐐癸紙
x
錛?/font>
y
錛?/font>
z
錛夊湪瑙傚療騫抽潰涓婄殑姝e鉤琛屾姇褰卞潗鏍囷紝鐐癸紙
x麓
錛?/font>
y
麓
錛変負鏂滄姇褰卞潗鏍囥傦紙
x
錛?/font>
y
錛変笌錛?/font>
x麓
錛?/font>
y
麓
錛夌殑璺濈涓?/font>
L
銆?
聽聽聽 閫忚鎶曞獎鐨勮綰匡紙鎶曞獎綰匡級鏄粠瑙嗙偣錛堣瀵熺偣錛夊嚭鍙戯紝瑙嗙嚎鏄笉騫寵鐨勩備笉騫寵浜庢姇褰卞鉤闈㈢殑瑙嗙嚎姹囪仛鐨勪竴鐐圭О涓虹伃鐐癸紝鍦ㄥ潗鏍囪醬涓婄殑鐏偣鍙仛涓葷伃鐐廣備富鐏偣鏁板拰鎶曞獎騫抽潰鍒囧壊鍧愭爣杞寸殑鏁伴噺鐩稿搴斻傛寜鐓т富鐏偣鐨勪釜鏁幫紝閫忚鎶曞獎鍙垎涓轟竴鐐歸忚銆佷簩鐐歸忚鍜屼笁鐐歸忚銆?
浠庝笂鍥?/font>
鐢ㄩ綈嬈″潗鏍囪〃紺轟負錛?/p>
涓嬮潰鎴戜滑鏉ユ帹瀵肩畝鍗曠殑涓鐐歸忚鐨勬姇褰卞叕寮忋?/p>
http://jpkc.swjtu.edu.cn/C15/imagination/jisuanjituxing/Chapter6/CG_Txt_6_018.htm
鐢變簬鐢ㄩ綈嬈″潗鏍囪〃紺猴紝涓夌淮鍑犱綍鍙樻崲鐨勭煩闃墊槸涓涓?闃舵柟闃碉紝鍏跺艦寮忓涓嬶細
聽聽聽聽 1錛夊鉤縐誨彉鎹?br />
聽聽聽聽 鍙傜収浜岀淮鐨勫鉤縐誨彉鎹紝鎴戜滑寰堝鏄撳緱鍒頒笁緇村鉤縐誨彉鎹㈢煩闃碉細
聽聽聽聽
聽聽聽聽 2錛夌緝鏀懼彉鎹?br />聽聽聽 鐩存帴鑰冭檻鐩稿浜庡弬鑰冪偣
錛?/font> xf 錛?/font> yf 錛?/font> zf 錛?/font> 鐨勭緝鏀懼彉鎹紝鍏舵楠や負錛?/font>聽聽聽聽 A. 灝嗗鉤縐誨埌鍧愭爣鍘熺偣澶勶紱
聽聽聽聽 B. 榪涜緙╂斁鍙樻崲錛?br />聽聽聽聽 C. 灝嗗弬鑰冪偣
聽聽聽聽 A.緇?/font>
x
杞存棆杞?br />
聽聽聽
聽聽聽聽 B.緇?/font>
y
杞存棆杞?br />
聽聽聽
聽聽聽聽 C.緇?/font>
z
杞存棆杞?br />
聽聽聽
聽聽聽聽
聽聽聽聽
涓夌淮絀洪棿鐨勫鉤縐匯佹棆杞強緙╂斁紺烘剰鍥?/font>
聽聽 4錛夌粫浠繪剰杞寸殑鏃嬭漿鍙樻崲
聽聽 璁炬棆杞醬
AB
鐢變換鎰忎竴鐐?/font>
A
錛?/font>
xa
錛?/font>
ya
錛?/font>
za
錛夊強鍏舵柟鍚戞暟(
a
錛?/font>
b
錛?/font>
c
)瀹氫箟錛?img height="29" src="http://necweb.neu.edu.cn/ncourse//tuxingxue/Chapter6/CG_Gif_6_288.gif" width="400" border="0" />
聽聽聽聽聽
聽聽 鍙互閫氳繃涓嬪垪姝ラ鏉ュ疄鐜?/font> P 鐐圭殑鏃嬭漿錛?/font>
聽聽聽聽 A. 灝?/font> A 鐐圭Щ鍒板潗鏍囧師鐐廣?/font>
聽聽聽聽 B. 浣?/p>
AB 鍒嗗埆緇?/font> X 杞淬?/font> Y 杞存棆杞傚綋瑙掑害涓?/font> Z 杞撮噸鍚堛?/font>
聽聽聽聽
聽聽聽聽 D.浣滀笂榪板彉鎹㈢殑閫嗘搷浣滐紝浣?/font> AB 鍥炲埌鍘熸潵浣嶇疆銆?/font>
鏄?/font>
AB
鍦?/font>
YOZ
騫抽潰涓?/font>
XOZ
騫抽潰鐨勬姇褰變笌
Z
杞寸殑澶硅銆?br />
http://necweb.neu.edu.cn/ncourse//tuxingxue/Chapter6/CG_Txt_6_012.htm
聽聽聽 姝e鎴戜滑鍦ㄩ檮褰曚腑鎻愬埌鐨勯偅鏍鳳紝鐢ㄩ綈嬈″潗鏍囪〃紺虹偣鐨勫彉鎹㈠皢闈炲父鏂逛究錛屽洜姝ゅ湪鏈妭涓墍鏈夌殑鍑犱綍鍙樻崲閮藉皢閲囩敤榻愭鍧愭爣榪涜榪愮畻銆備簩緇撮綈嬈″潗鏍囧彉鎹㈢殑鐭╅樀鐨勫艦寮忔槸錛? 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽
榪欎釜鐭╅樀姣忎竴涓厓绱犻兘鏄湁鐗規畩鍚箟鐨勩?br />
褰㈣繘琛屽鉤縐誨彉鎹紱[
g
h
]鏄鍥懼艦浣滄姇褰卞彉鎹紱[
i
]鍒欐槸瀵瑰浘褰㈡暣浣撹繘琛岀緝鏀懼彉鎹€?br />1錛夊鉤縐誨彉鎹?
2錛夌緝鏀懼彉鎹?
3錛夋棆杞彉鎹?img height="28" src="http://necweb.neu.edu.cn/ncourse//tuxingxue/Chapter6/CG_Gif_6_291.gif" width="502" border="0" />
4錛夊縐板彉鎹?br />
瀵圭О鍙樻崲鍏跺疄鍙槸 a 銆?/font> b 銆?/font> d 銆?/font> e 鍙?/font>0銆?/font>1絳夌壒孌婂間駭鐢熺殑涓浜涚壒孌婃晥鏋溿備緥濡傦細
褰?/font> b = d =0錛?/font> a =-1錛?/font> e =1鏃舵湁 x 麓=-x錛?/font>y麓=y錛屼駭鐢熶笌y杞村縐扮殑鍥懼艦銆?/i>
褰?/font> b = d =0錛?/font> a =-1錛?/font> e =-1鏃舵湁 x 麓=x錛?/font>y麓=-y錛屼駭鐢熶笌x杞村縐扮殑鍥懼艦銆?/font>
褰?/font> b = d =0錛?/font> a = e =-1鏃舵湁 x 麓=-x錛?/font>y麓=-y錛屼駭鐢熶笌鍘熺偣瀵圭О鐨勫浘褰€?/font>
褰?/font> b = d =1錛?/font> a = e =0鏃舵湁 x 麓=y錛?/font>y麓=x錛屼駭鐢熶笌鐩寸嚎y=x瀵圭О鐨勫浘褰€?/font>
褰?/font> b = d =-1錛?/font> a = e =0鏃舵湁 x 麓=-y錛?/font>y麓=-x錛屼駭鐢熶笌鐩寸嚎y=-x瀵圭О鐨勫浘褰€?/font>
5錛夐敊鍒囧彉鎹?br />
褰?/font>
d
=0鏃訛紝x麓=x+by錛?/font>y麓=y錛屾鏃訛紝鍥懼艦鐨?/font>y鍧愭爣涓嶅彉錛?/font>x鍧愭爣闅忓垵鍊悸?錛?/font>x錛?/font>y錛夊強鍙樻崲緋繪暟b浣滅嚎鎬у彉鍖栥?/font>
褰?/font>
b
=0鏃訛紝x麓=x錛?/font>y麓=dx+y錛屾鏃訛紝鍥懼艦鐨?/font>x鍧愭爣涓嶅彉錛?/font>y鍧愭爣闅忓垵鍊悸?錛?/font>x錛?/font>y錛夊強鍙樻崲緋繪暟d浣滅嚎鎬у彉鍖栥?/font>
6錛夊鍚堝彉鎹?/p>
濡傛灉鍥懼艦瑕佸仛涓嬈′互涓婄殑鍑犱綍鍙樻崲錛岄偅涔堝彲浠ュ皢鍚勪釜鍙樻崲鐭╅樀緇煎悎璧鋒潵榪涜涓姝ュ埌浣嶇殑鍙樻崲銆傚鍚堝彉鎹㈡湁濡備笅鐨勬ц川錛?/font>
瀵瑰悓涓鍥懼艦鍋氫袱嬈″鉤縐葷浉褰撲簬灝嗕袱嬈$殑騫崇Щ涓ゅ姞璧鋒潵錛?img height="63" src="http://necweb.neu.edu.cn/ncourse//tuxingxue/Chapter6/CG_Gif_6_224.gif" width="516" border="0" />
涓ゆ榪炵畫鐨勭緝鏀劇浉褰撲簬灝嗙緝鏀炬搷浣滅浉涔橈細
涓ゆ榪炵畫鐨勬棆杞浉褰撲簬灝嗕袱嬈$殑鏃嬭漿瑙掑害鐩稿姞錛?img height="50" src="http://necweb.neu.edu.cn/ncourse//tuxingxue/Chapter6/CG_Gif_6_283.gif" width="509" border="0" />
http://necweb.neu.edu.cn/ncourse//tuxingxue/Chapter6/CG_Txt_6_011.htm銆
聽聽聽 瀹為檯鐨勭獥鍙e尯涓庤鍥懼尯寰寰涓嶄竴鏍峰ぇ灝忥紝瑕佸湪瑙嗗浘鍖烘紜湴鏄劇ず褰綋鐨勶紝蹇呴』灝嗗叾浠庣獥鍙e尯鍙樻崲鍒拌鍥懼尯銆?/font>
聽
姣斾緥鍏崇郴錛屼袱鑰呯殑鍙樻崲鍏紡涓猴細
聽聽
鍙互綆鍗曞湴灝嗕袱鑰呯殑鍏崇郴琛ㄧず涓猴細
聽 聽
聽
http://necweb.neu.edu.cn/ncourse//tuxingxue/Chapter6/CG_Txt_6_010.htm
(^_^,鍙兘鐪嬪埌projection浠ュ悗媯遍敟涓婁笅鎴潰闂寸殑閮ㄥ垎)
The three input vectors represent the following, respectively:
聽
Set Up a Projection Matrix聽聽 |
This example demonstrates how to set up the projection transformation matrix, which transforms 3-D camera or view space coordinates into 2-D screen coordinates.
See the following C# code example, the Projection transformation matrix is set to be equal to the left-handed (LH) PerspectiveFovLH matrix. Input arguments to PerspectiveFovLH are as follows.
聽
A world transformation changes coordinates from model space, where vertices are defined relative to a model's local origin, to world space, where vertices are defined relative to an origin common to all of the objects in a scene. In essence, the world transformation places a model into the world; hence its name.
As with any other transformation, you create the world transformation by concatenating a series of transformation matrices into a single matrix that contains the sum total of their effects. In the simplest case, when a model is at the world origin and its local coordinate axes are oriented the same as world space, the world matrix is the identity matrix. More commonly, the world matrix is a combination of a translation into world space and possibly one or more rotations to turn the model as needed.
The following C# code example, from a fictitious 3-D model class written in C#, creates a world matrix that includes three rotations to orient a model and a translation to relocate it relative to its position in world space.
聽
The following transformation translates the point (x, y, z) to a new point (x', y', z').
You can manually create a translation matrix in managed code. The following C# code example shows the source code for a function that creates a matrix to translate vertices.
[C#]
private Matrix TranslateMatrix(float dx, float dy, float dz) { Matrix ret; ret = Matrix.Identity; ret.M41 = dx; ret.M42 = dy; ret.M43 = dz; return ret; }
For convenience, managed the Microsoft Direct3D supplies the Translation method.
The following transformation scales the point (x, y, z) by arbitrary values in the x-, y-, and z-directions to a new point (x', y', z').
聽
聽 |
The transformations described here are for left-handed coordinate systems, and so might be different from transformation matrices that you have seen elsewhere. For more information, see 3-D Coordinate Systems.
The following transformation rotates the point (x, y, z) around the x-axis, producing a new point (x', y', z').
The following transformation rotates the point around the y-axis.
The following transformation rotates the point around the z-axis.
In these example matrices, the Greek letter theta (?) stands for the angle of rotation, in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.
In a managed application, use the Matrix.RotationX, Matrix.RotationY, and Matrix.RotationZ methods to create rotation matrices. The following C# code example demonstrates how the Matrix.RotationX method performs a rotation.
[C#]
private Matrix MatrixRotationX(float angle) { double sin, cos; sin = Math.Sin(angle); cos = Math.Cos(angle); Matrix ret; ret.M11 = 1.0f; ret.M12 = 0.0f; ret.M13 = 0.0f; ret.M14 = 0.0f; ret.M21 = 0.0f; ret.M22 = (float)cos; ret.M23 = (float)sin; ret.M24 = 0.0f; ret.M31 = 0.0f; ret.M32 = (float)-sin; ret.M33 = (float)cos; ret.M34 = 0.0f; ret.M41 = 0.0f; ret.M42 = 0.0f; ret.M43 = 0.0f; ret.M44 = 1.0f; return ret; }
One advantage of using matrices is that you can combine the effects of two or more matrices by multiplying them. This means that, to rotate a model and then translate it to some location, you do not need to apply two matrices. Instead, you multiply the rotation and translation matrices to produce a composite matrix that contains all of their effects. This process, called matrix concatenation, can be written with the following formula.
In this formula, C is the composite matrix being created, and M1 through Mn are the individual transformations that matrix C contains. In most cases, only two or three matrices are concatenated, but there is no limit.
Use the Matrix.Multiply method to perform matrix multiplication.
The order in which the matrix multiplication is performed is crucial. The preceding formula reflects the left-to-right rule of matrix concatenation. That is, the visible effects of the matrices that you use to create a composite matrix occur in left-to-right order. A typical world transformation matrix is shown in the following example. Imagine that you are creating the world transformation matrix for a stereotypical flying saucer. You would probably want to spin the flying saucer around its center - the y-axis of model space - and translate it to some other location in your scene. To accomplish this effect, you first create a rotation matrix, and then multiply it by a translation matrix, as shown in the following formula.
In this formula, Ry is a matrix for rotation about the y-axis, and Tw is a translation to some position in world coordinates.
The order in which you multiply the matrices is important because, unlike multiplying two scalar values, matrix multiplication is not commutative. Multiplying the matrices in the opposite order has the visual effect of translating the flying saucer to its world space position, and then rotating it around the world origin.
No matter what type of matrix you are creating, remember the left-to-right rule to ensure that you achieve the expected effects.
鍒板簳浠涔堟椂鍊欏湪宸﹁竟浠涔堟椂鍊欏湪鍙寵竟?
鎬葷粨:
In applications that work with 3-D graphics, geometrical transformations can be used to do the following.
You can transform any point (x,y,z) into another point (x', y', z') using a 4 x 4 matrix.
Perform the following operations on (x, y, z) and the matrix to produce the point (x', y', z').
The most common transformations are translation, rotation, and scaling. You can combine the matrices that produce these effects into a single matrix to calculate several transformations at once.
铏界劧涓庨潪鎵樼鐗堟湰鐩告瘮錛屽叧浜庢墭綆?DirectX 鐨勬ц兘浜夎寰堝錛屼絾鍟嗕笟娓告垙宸蹭嬌鐢ㄦ墭綆?DirectX 榪涜鍒涘緩鐨勪簨瀹炲簲璇ヨ兘澶熶粠鏍規湰涓婂鉤鎭繖鏍風殑浜夎銆傝櫧鐒舵煇浜涢渶瑕佹瀬楂樻ц兘鐨勬父鎴忓彲鑳介渶瑕佷嬌鐢ㄩ潪鎵樼浠g爜錛屼絾澶у鏁版父鎴忓彲浠ヤ嬌鐢ㄦ墭綆′唬鐮佹垨鑰呯粨鍚堜嬌鐢ㄦ墭綆″拰闈炴墭綆′唬鐮佽繘琛屽垱寤恒傜紪鍐欐墭綆′唬鐮佷嬌寮鍙戜漢鍛樼殑鏁堢巼鏇撮珮錛屼粠鑰岀紪鍐欏嚭鏇村鐨勪唬鐮侊紝鐢熸垚鏇村畨鍏ㄧ殑浠g爜銆?
瀹夎 DirectX SDK 涔嬪悗錛屽湪 C:\WINDOWS\Microsoft.NET\Managed DirectX 搴旇鏈変竴涓洰褰曪紝鍦ㄦ満鍣ㄤ笂瀹夎鐨勬瘡涓増鏈殑 SDK 閮芥湁涓涓瓙鐩綍銆傛垜鏈哄櫒涓婁嬌鐢ㄧ殑宸茬粡鏄鍥涚増浜嗭紝鍥犳鎴戞湁鍥涗釜瀛愮洰褰曘傚湪姣忎釜瀛愮洰褰曚腑搴旇鏈変節涓?DLL 鍜屼節涓?XML 鏂囦歡銆傜敱浜庢墭綆$幆澧冧腑鐨?.NET 鍏佽鍚屼竴鍙版満鍣ㄤ笂鐨勫悓涓涓?DLL 鏂囦歡鏈夊涓増鏈紝鑰屼笉浼氬紩璧蜂互鍓嶈縐頒負 DLL Hell 鐨勯棶棰橈紝鎵浠ユ垜浠彲浠ヤ嬌鐢ㄥ鐗堟湰鐨勬墭綆?DirectX 搴撱傝繖灝卞厑璁告偍鍦ㄥ畨瑁呮柊鐗堟湰涔嬪悗杞繪澗鍦板洖婊氬埌浠ュ墠鐨勭増鏈?
濡傛灉鎮ㄤ互鍓嶆湁鍦?Windows 涓嬪鐞?DLL 鏂囦歡鐨勭粡楠岋紝鎮ㄥ彲鑳戒細鎷呭績鍦ㄥ悓涓鍙拌綆楁満涓婂畨瑁呭悓涓涓枃浠剁殑澶氫釜鐗堟湰浼氫駭鐢熼棶棰樸傝嚜浠?.NET 寮曞叆騫惰鐗堟湰鎺у埗錛岃繖浜涚増鏈帶鍒墮棶棰樺氨涓嶅瀛樺湪浜嗐傝繖鎰忓懗鐫褰撴柊鐗堟湰鐨?SDK 鍙戝竷鏃訛紝鎮ㄥ彲浠ヤ嬌鐢ㄥ涓増鏈潵媯鏌ュ吋瀹規ч棶棰橈紝鑰屼笉蹇呭己榪嚜宸辮繘琛屽崌綰с?/p>
涔濅釜 DLL 鏂囦歡澶ц嚧瀵瑰簲浜?DirectX 涓殑鍗佷釜鍛藉悕絀洪棿銆傚湪鍒涘緩娓告垙鏃訛紝鎴戜滑浣跨敤鍏朵腑鐨勫ぇ閲忓懡鍚嶇┖闂存潵鎻愪緵瀵硅緭鍏ヨ澶囥佸0闊熾佺綉緇滄挱鏀撅紙褰撶劧榪樻湁 3D 鍥懼艦錛夌殑鏀寔銆?/p>
鍛藉悕絀洪棿 | 鎻忚堪 |
Microsoft.DirectX |
鍏叡綾誨拰鏁板緇撴瀯 |
Microsoft.DirectX.Direct3D |
3D 鍥懼艦鍜屽姪鎵嬪簱 |
Microsoft.DirectX.DirectDraw |
Direct Draw 鍥懼艦 API銆傝繖鏄棫寮忓懡鍚嶇┖闂達紝鎮ㄤ笉闇瑕佷嬌鐢ㄥ畠銆?/p> |
Microsoft.DirectX.DirectPlay |
鐢ㄤ簬澶氱帺瀹舵父鎴忕殑緗戠粶 API |
Microsoft.DirectX.DirectSound |
澹伴煶鏀寔 |
Microsoft.DirectX.DirectInput |
杈撳叆璁懼鏀寔錛堜緥濡傦紝榧犳爣鍜屾父鎴忔潌錛?/p> |
Microsoft.DirectX.AudioVideoPlayback |
鎾斁瑙嗛鍜岄煶棰戯紙渚嬪錛屽湪 PC 涓婃挱鏀?DVD錛?/p> |
Microsoft.DirectX.Diagnostics |
鐤戦毦瑙g瓟 |
Microsoft.DirectX.Security |
璁塊棶瀹夊叏鎬?/p> |
Microsoft.DirectX.Security.Permissions |
璁塊棶瀹夊叏鏉冮檺 |
HEL鍜孒AL
銆銆鍦ㄥ浘5.2涓紝鍙互鐪嬪埌鍦―irectX涓嬫湁涓や釜灞傞潰錛屽垎鍒槸HEL錛堢‖浠舵ā鎷熷眰錛夊拰HAL錛堢‖浠舵娊璞″眰錛夈傝繖鏄竴涓害瀹氾細DirectX鏄竴縐嶉潪甯告湁榪滆鐨勮璁℃濊礬錛屽畠鍋囧畾鍙互閫氳繃紜歡鏉ュ疄鐜伴珮綰фц兘銆備絾鏄紝濡傛灉紜歡騫朵笉鏀寔鏌愪簺鎬ц兘錛岄偅鎬庝箞鍔炲憿錛熻繖灝辨槸HAL鍜孒EL鍙岄噸妯″紡璁捐鎬濊礬鐨勫熀紜銆?br />銆銆HAL錛堢‖浠舵娊璞″眰錛夋槸鎺ヨ繎紜歡鐨勫簳灞傘傚畠鐩存帴鍜岀‖浠朵氦嫻併傝灞傞氬父鏈夎澶囩敓浜у晢鎻愪緵鐨勮澶囬┍鍔ㄧ▼搴忋傚彲浠ラ氳繃甯歌DirectX璋冪敤鐩存帴鍜岀‖浠惰繘琛岃仈緋匯備嬌鐢℉AL瑕佹眰紜歡鑳藉鐩存帴鏀寔鎵瑕佹眰鐨勬ц兘錛岃繖鏃朵嬌鐢℉AL錛屽氨鑳藉鎻愰珮鎬ц兘銆備緥濡傦紝褰撶粯鍒朵竴涓綅鍥炬椂錛屼嬌鐢ㄧ‖浠惰姣旇蔣浠舵洿鑳滀換璇ラ」宸ヤ綔銆?br />銆銆褰撶‖浠朵笉鏀寔鎵瑕佹眰鐨勬ц兘鏃訛紝浣跨敤HEL錛堢‖浠朵豢鐪熷眰錛夈傛垜浠互浣跨敤瑙嗛鍗℃棆杞竴涓綅鍥句負渚嬫潵璇存槑銆傚鏋滅‖浠朵笉鏀寔鏃嬭漿鍔ㄤ綔錛屽垯浣跨敤HEL錛岃蔣浠剁畻娉曞彇浠g‖浠躲傚緢鏄庢樉榪欐牱鍋氶熷害瑕佹參涓浜涳紝浣嗗叧閿槸榪欐牱鍋氳嚦灝戜笉浼氫腑鏂簲鐢ㄧ▼搴忥紝搴旂敤紼嬪簭浠嶇劧鍦ㄨ繍琛岋紝浠呬粎鏄熷害鎱竴浜涜屽凡銆傚彟澶栵紝HAL鍜孒EL涔嬮棿鐨勫垏杞槸閫忔槑鐨勩傚鏋滆姹侱irectX鍋氭煇宸ヤ綔錛岃孒AL鐩存帴澶勭悊璇ュ伐浣滐紝涔熷氨鏄‖浠剁洿鎺ュ鐞嗚欏瑰伐浣溿傚惁鍒欙紝HEL灝嗚皟鐢ㄨ蔣浠朵豢鐪熸潵澶勭悊璇ュ伐浣溿?br />
Section 1 鈥?Introduction
Section 1.1 鈥?What is DirectX?
DirectX is the name given to a series of API for running and displaying multimedia rich applications. Using it, you can have graphics, video, 3D animation, surround sound and so on. The different API鈥檚 available in DirectX are Direct Graphics, Direct Input, Direct Sound, Direct Play and Direct Show.
Direct Graphics deals with everything related to graphics. With it you can load 3D meshes, render textures, animate 3D models, light your scene, add particle effects and much more. It is concentrated more towards 3D making it ideal for rendering 3D graphics, although it will also work just as well doing 2D graphics too.
Direct Input is the API that allows you to use many different kinds of input devices such as keyboards, mice, joysticks, joy pads and so on. It gives you much more control than the Win32 API does, and is ideal for games.
Direct Sound does everything you could ever want to do with audio. You can play midi files and wav files and other types of music. You can add special effects such as an echo or flanging. You can also add 3D surround sound effects by telling Direct Sound to apply special 3D algorithms and so on. Again, this is ideal for games.
Direct Play is the networking API used mainly in games. If you wish to make a game run over a network then you can use DirectPlay?. There isn鈥檛 much more to say about that really.
Direct Show can be used for all kinds of multimedia tasks such as video playback. It is ideal for audio or video recording, editing and manipulation.
Section 1.2 - Assumptions
Readers should have a basic understanding of the C# language and should have at least enough experience using it to understand the examples. The code examples are fairly simple and don鈥檛 use anything overly complicated, but you should still have a firm grasp of the language nevertheless. If you have any experience with using previous versions of DirectX in other languages then this would certainly help, but isn鈥檛 a requirement. The tutorial assumes you鈥檝e never used DirectX before.
I will be using the .Net framework version 1.1. Readers using the new .Net 2.0 Framework that comes with Microsoft Visual C# 2005 Express Edition should be able to convert the code without too much trouble. Most of it should be compatibl. I will be using the Microsoft Visual Studio .Net 2003 IDE so any screenshots or descriptions will explain how to perform the task in that IDE. If you are using a different IDE such as Sharp Develop, Borland C# Builder or Microsoft Visual C# 2005 Express Edition, then I assume that you鈥檙e competent enough in it鈥檚 use that you can understand how to do the tasks in your own IDE. You should at least know how to create a new project, add references to your project, add files and code to your project, save it, and build it. Obviously knowing how to do other important things such as use the debugger would be a strong advantage.
I will use the DirectX Summer Update 2004 SDK. That is: version 1.0.1901.0. There may be some slight incompatibilities with previous versions, but they shouldn鈥檛 be too hard to fix if you鈥檙e using a previous version. I suggest you get the update though if you don鈥檛 already have it.
Note that I won鈥檛 be using the DirectX wizards or any template files in my project. I鈥檒l be showing you how to do everything yourself so that we can gain a deeper understanding of what鈥檚 actually going on and what we鈥檙e actually writing.
Section 2 鈥?Creating a New DirectX Project
Section 2.1 鈥?Creating a New Project
Start up your IDE. As I mentioned above, I use Microsoft Visual Studio .Net 2003. Start a new project, and save it. Choose either 鈥淲indows Application鈥?or 鈥淐onsole Application鈥?depending on which type of project you wish to make. If you installed DirectX9? properly then you should be able to create a new DirectX project, which has a wizard to guide you through creating a simple application. As I mentioned, I won鈥檛 be using this. I prefer to write the code myself to gain a deeper understanding of what is actually going on in my project.
Section 2.2 鈥?Adding the DirectX References
In order to use DirectX in your applications, you must add a reference to the assemblies. To do this in Microsoft Visual Studio .Net 2003 you can click the project menu and click 鈥淎dd Reference鈥? or right click on the 鈥淩eferences鈥?section in the project explorer, and click 鈥淎dd Reference鈥?
Now you should be presented with the 鈥淎dd Reference鈥?dialog. Make sure the 鈥?Net鈥?tab is selected, and scroll down to 鈥淢icrosoft.DirectX鈥? You will see that there are several entries. At the very least, add 鈥淢icrosoft.DirectX鈥? The other assembly names reflect quite clearly what they contain. For example 鈥淢icrosoft.DirectX.Direct3D鈥?is the 3D graphics API, 鈥淢icrosoft.DirectX.DirectSound鈥?is the Direct Sound API and so on. Go ahead and add whichever ones you require.
Some of you may notice that you have 2 versions of each assembly with different versions. You will have this if you installed the Summer 2004 Update. I have one set using version 1.0.1901.0 and another set using version 1.0.900.0. I will be adding the assemblies with the newer version: 1.0.1901.0.
Adding the DirectX references in Microsoft Visual Studio .Net 2003.
Section 2.3 鈥?The 鈥渦sing鈥?Directives
You may wish to add some 鈥渦sing鈥?directives for the namespaces in DirectX. You should know what the 鈥渦sing鈥?directive does. Here are some simple ones for using Direct3D:
using Microsoft.DirectX; using Microsoft.DirectX.Direct3D;
Section 3 鈥?Direct Graphics Enumeration
Section 3.1 鈥?Enumerating Adapters and Display Modes
An adapter is basically a graphics card. Most systems will have just 1 adapter. Systems with multiple monitors may have more than 1 adapter. If you wish to support systems with multiple adapters then you will have to enumerate them, otherwise you can just use the default one. The code to enumerate and choose an adapter is incredibly simple though, so it鈥檚 worth the little bit of extra effort.
An adapter is described by an AdapterInformation? class located inside the Microsoft.DirectX.Direct3D namespace. This class has some useful properties such as the CurrentDisplayMode? property, which funnily enough, returns the current display mode; the AvailableDisplayModes? property that returns a list of supported display modes, which can be enumerated using a foreach loop; and an Information property, which returns an AdapterDetails? class. This class contains several useful properties which you can use to identify individual cards and so on. One of the most useful properties of this class is the Description property. This gives you a human readable description of the graphics card such as 鈥淣VIDIA GeForce2? MX/MX 400鈥?(My old crappy card). There are many other properties and methods inside the AdapterInformation? class too. Explore the properties and methods using the tooltips and the intellisense (Intellisense is the name given to the lists that pop up in the code editor containing all the accessible members of an object for those of you who don鈥檛 know what that is).
To actually enumerate an adapter, we use the Manager class located inside the Microsoft.DirectX.Direct3D namespace. You don鈥檛 create a new instance of this class as all of it鈥檚 methods are static. The Manager class contains a static property called 鈥淎dapters鈥?which returns a list of AdapterInformation? classes described above, that you can enumerate using a foreach loop. It really is that simple. If you wish to use the default adapter, or just want to know what it is at least, then you can get that simply by using Manager.Adapters.Default.
Here鈥檚 an example program showing the main things we鈥檝e learned so far:
using System; using Microsoft.DirectX; using Microsoft.DirectX.Direct3D; class AdapterEnumeration { static void Main(string[] args) { foreach(AdapterInformation adapter in Manager.Adapters) { // Check whether or not this is the default adapter if(adapter.Equals(Manager.Adapters.Default)) { Console.WriteLine("This is the default adapter\n"); } // Write out some information about the adapter Console.WriteLine("" + adapter.Information.ToString() + "\n\nDisplay Modes:\n"); // Write out each display mode foreach(DisplayMode display in adapter.SupportedDisplayModes) { Console.WriteLine("{0}x{1} : {2} @ {3} Hz", display.Width, display.Height, display.Format, display.RefreshRate); } // Write out the current display mode Console.WriteLine ("\nCurrent Display Mode: {0}x{1} : {2} @ {3} Hz", adapter.CurrentDisplayMode.Width, adapter.CurrentDisplayMode.Height, adapter.CurrentDisplayMode.Format, adapter.CurrentDisplayMode.RefreshRate); Console.WriteLine("\n\n"); } Console.ReadLine(); } }
That鈥檚 extremely simple, I think you鈥檒l agree. The output isn鈥檛 the nicest looking output in the world, but it shows you how to do it. You can make it look pretty quite easily. In a windows application you can add each adapter description to a combo box or some other suitable control. When an adapter in the combo box is selected, you could add information about that adapter to a listview, and add it鈥檚 available display modes to another combo box, selecting the current display mode by default. That鈥檚 how I usually do it, and that鈥檚 an example of the kind of things you can do with the very simple code above.
As a by the way, you can get a handle to the monitor associated with each adapter using the following code:
IntPtr MonitorHandle = Manager.GetAdapterMonitor(adapter.Adapter);
I鈥檓 not quite sure what you could do with that handle, but I鈥檓 sure it鈥檚 useful somewhere, such as with some Win32 API functions that return information about the monitor or something like that. Note that the 鈥淎dapter鈥?property of the AdapterInformation? class is the 鈥渁dapter ordinal鈥?which is just a fancy name for the adapter number. The first one has ordinal 0, the second ordinal 1 and so on. Usually there will be just one default adapter with an adapter ordinal of 0.
Section 3.2 鈥?Device Capabilities (Caps)
Device Caps is one of those terms you will hear a lot with DirectX programming. Caps is simply short for Capabilities. The Device Caps are therefore just what the device is and isn鈥檛 capable of doing. There are literally hundreds of things you can check. Retrieving device capabilities is very simple. Again, you use the Manager class to do this. Here is a short snippet of code showing you how to do it:
AdapterInformation ai = Manager.Adapters.Default; Caps caps = Manager.GetDeviceCaps(ai.Adapter, DeviceType.Hardware);
There鈥檚 nothing hard there, is there? The only thing that might confuse you is the DeviceType?. The 2 main types are 鈥淒eviceType.Hardware鈥?and 鈥淒eviceType.Reference鈥? There is also another device type called a Software Device, but this is very rarely used. I think it鈥檚 something to do with plugging in your own software renderer or something. Using the hardware device type will query the capabilities of the graphics adapter. Using the reference device type will query the capabilities of software emulation, basically. A lot of drivers will be able to make up for lack of hardware features by providing software emulation. A common difference for example, is that the hardware will only usually be able to do a few active lights such as 8 or 16 whereas the reference device may be able to do an unlimited amount. The software device will be able to do pretty much everything, but it鈥檚 much slower than the hardware.
Anyway, back to the point. You can probably figure out how to use the Caps class by looking at the intellisense again. This is a very powerful way to learn about classes. Most of it should be fairly self explanatory. You can test for all kinds of things. The tooltips will explain what all of the properties mean. For example, if you want to see whether or not textures must be square, you can test that using the following code:
if(caps.TextureCaps.SupportsSquareOnly) { Console.WriteLine("Square textures only are supported"); }
As I mentioned, there are literally hundreds of things you can check for. They are all organised into sensible properties. For example, all texture capabilities are stored inside the TextureCaps? property, vertex processing capabilities are inside the VertexProcessingCaps? property and so on. You can explore it using the object browser as well as the intellisense. (Press F2 in Visual Studio .Net 2003 to open the object browser):
Exploring the Caps class inside the object browser.
Section 3.3 鈥?Adapter Formats and BackBuffer? Formats
There are 3 main questions I will answer in this section: What is a format? What is a backbuffer (format), and what is an adapter format?
In answer to the first question, the format is just the way that pixel data is encoded. For example, you may have 5 bits to store the amount of red, 6 bits to store the amount of green and another 5 bits to store the amount of blue. This adds up to 16 bits, or 2 bytes per pixel. As a by the way, we give green more bits for 2 reasons. Firstly, to make the pixel data up to 2 bytes without wasting a pixel, and secondly, we chose the green component because our eyes are more sensitive to green and can therefore distinguish between more shades of green than they can red or blue, so it makes sense to give the green component the extra bit. The 2 most common formats are 16 bit and 32 bit. There is a 24 bit format and there are 8 bit formats, but these are rarely used. Some formats have some bits set aside for an 鈥渁lpha鈥?component. This is to do with something called alphablending, which is a type of transparency. You don鈥檛 need to know what that is exactly right now, but just bear in mind that some formats have an extra alpha component. Yet other formats have unused bits, denoted by 鈥淴鈥? For example, there is a 32 bit mode called 鈥淴8R8G8B8鈥?which means that the red, green and blue components are all 8 bits each, and there is an unused 8 bits to round the format up to 4 bytes per pixel. An example of a format with an alpha component is one called 鈥淎8R8G8B8鈥?which has the same as the other format, but instead of having an unused 8 bits, it uses the extra 8 bits for the alpha component.
Now in order to explain what the backbuffer format is, I suppose I better mention briefly what a backbuffer is. When you draw things on the screen, they aren鈥檛 all drawn at the same time obviously. So you may draw a tree, then draw a bush, then draw another tree, then draw a character, then draw a house for example. They are all drawn one after the other. There is a phenomena called 鈥渁rtifacts鈥?where the screen encounters a vertical resync (a refresh) while you鈥檙e in the middle of drawing your scene on to the screen. This results in flickering graphics where you can briefly see things being drawn on the screen. The way this is fixed is we draw everything offscreen to an area of memory, and only once the scene is finished, we draw this entire area of memory onto the screen at once. This way you don鈥檛 see each individual part being drawn. This area of memory where you do your drawing is called a 鈥渂ackbuffer鈥?and the process of drawing the backbuffer onto the screen is called 鈥渇lipping鈥?or 鈥減resenting鈥? Hopefully the term 鈥渂ackbuffer format鈥?should be quite clear now that I鈥檝e explained what a backbuffer is, and what a format is.
Now for the adapter format, this is basically just your display mode. The format of the pixels on the main screen. One question may arise from this 鈥?why aren鈥檛 the backbuffer format and the adapter format the exact same? Well the answer to that is in most cases they are. Although there is one difference. In a backbuffer you can have an alpha component, but you can鈥檛 have an alpha component in the adapter format. This is why they may differ.
Section 3.4 鈥?Device Types
This is quite a short section. I鈥檝e already mentioned device types before, but here it is again. There are 3 device types: Hardware, Software and Reference. Hardware means use the graphics card where possible, reference means use software emulation. And the software device is rarely used. It鈥檚 something to do with writing your own software renderer I think. Now you may be wondering why you would ever want to use software instead of hardware. Well there is actually a good reason. Because the reference device supports absolutely everything. You would need to fork out a huge amount of money to get a graphics card that can come anywhere near close to being able to do everything. I鈥檓 talking about a top of the range card 鈥?the best you can get. The problem with software is that it鈥檚 painfully slow compared to using hardware. So if you just want to test out some features in your game that your graphics card doesn鈥檛 support, you can switch to software emulated mode and check that it works. Or if you just really want to use some feature not supported by the hardware so much that you鈥檙e willing to slow down everything to a crawl to get it to work then you can use software emulation for that. You probably wouldn鈥檛 want to do that in a game unless you want a frame rate of about 0.5 frames per second. That would be for an application such as a 3D rendering application, where you really want to have some special effect in your scene, and don鈥檛 care if it takes an extra hour to render (These things take hours anyway).
Section 3.5 鈥?Using Manager.CheckDeviceType
At this point I鈥檝e explained the following things to you: how to enumerate adapters, how to enumerate display modes, device types and backbuffer and adapter formats. Now you need to begin choosing them. So choose an adapter, a device type, an adapter format (from your list of display modes), a backbuffer format, and a device type. Now you need to choose one more thing: whether or not you want to run this application in a window, or in full screen mode. You will need all of these to create a device (which I鈥檒l explain later. Lets just say for now that it鈥檚 incredibly important). So now you鈥檝e chosen all of these things. Unless you know what you鈥檙e doing or you got pretty lucky, they鈥檙e probably all incompatible with each other and wouldn鈥檛 work. Ideally you want to present a list of adapters to the user. Once they choose an adapter, you would then want to present a list of device types compatible with that adapter to them, and have them choose one of those. Once they鈥檝e chosen an adapter and a device type, you would like them to choose a display mode (the important part being the format, for the adapter format). Once they鈥檝e chosen that, you would then ideally like to present them with a list of backbuffer formats which are compatible with the adapter format to choose from. And finally, you want to present them with the option of fullscreen or windowed mode, if that鈥檚 still there.
The best way to do this is to check every possibly combination of the following: adapters, device types, available adapter formats, backbuffer formats, whether or not to use windowed or full screen mode. By checking all the combinations of the above, you鈥檒l get a list of all the compatible combinations which you can present to the user whatever way you see fit. The method used to check these is Manager.CheckDeviceType. The following code snippet shows you how you can check all possible combinations. When you get a valid combination, you can add that to your combo boxes or list boxes or your arrays or whatever method of storing the combinations you choose.
DeviceType[] deviceTypes = new DeviceType[] {DeviceType.Hardware, DeviceType.Software, DeviceType.Reference}; Format[] backBufferFormats = new Format[] {Format.A8R8G8B8, Format.X8R8G8B8, Format.A2R10G10B10, Format.R5G6B5, Format.A1R5G5B5, Format.X1R5G5B5}; bool[] windowModes = new bool[] {true, false}; // For each adapter foreach (AdapterInformation adapter in Manager.Adapters) { ArrayList adapterFormats = new ArrayList(); // Build the list of adapter formats foreach (DisplayMode dispMode in adapter.SupportedDisplayModes) { if (!adapterFormats.Contains (dispMode.Format)) adapterFormats.Add (dispMode.Format); } foreach (DeviceType deviceType in deviceTypes) { foreach (Format adapterFormat in adapterFormats) { foreach (Format backBufferFormat in backBufferFormats) { foreach (bool windowMode in windowModes) { if (Manager.CheckDeviceType ( adapter.Adapter, deviceType, adapterFormat, backBufferFormat, windowMode)) { // *** This combination is valid! } } // windowMode } // backBufferFormat } // adapterFormat } // deviceType } // adapter
Section 3.6 鈥?Vertex Processing
The last thing we need before we can create a device (As I said earlier, this will be explained. Just know that it鈥檚 important. This is the main object we use for all our rendering) is a vertex processing type. I assume you鈥檝e used something similar to the above code to enumerate all the possible combinations of adapters, device types, adapter/backbuffer formats and windowed or not and chosen one of each. Now before we can build a device, we need this vertex processing method. Basically the vertex processing method is just telling Direct3D where to do all of the vertex processing. How much should the hardware be involved, and how much should the software be involved, basically. Most cards these days should support hardware vertex processing. Lower end ones will support mixed vertex processing, where the processing is done by both hardware and software. Software only vertex processing will always work, but is slower. We can go through some methods to determine which type of processing is available like this:
Caps caps = Manager.GetDeviceCaps(Manager.Adapters.Default.Adapter, DeviceType.Hardware); if (caps.DeviceCaps.SupportsHardwareTransformAndLight) { if (caps.DeviceCaps.SupportsPureDevice) { Console.WriteLine ("Pure Device"); } Console.WriteLine ("Hardware Vertex Processing"); Console.WriteLine ("Mixed Vertex Processing"); } Console.WriteLine ("Software Vertex Processing");
You can see that first we get the device capabilities, as we use them to check the vertex processing available. Then we check if the device supports hardware processing. If it does, we know that at least it supports hardware and mixed processing. If it supports hardware processing, then we check if it supports the 鈥減ure device鈥?which means it also supports resterization and shading as well as just lighting and transformation. We know that software vertex processing will always be available so that鈥檚 a given.
Now you have everything you need to create a device. You can enumerate and choose an adapter, and a display mode, and a backbuffer format and a device type and finally you can choose whether or not to use windowed mode or full screen mode if it鈥檚 compatible with everything else you鈥檝e chosen.
Section 3.7 鈥?Enumerating Depth Stencil Formats
There is one other main thing you will need to be able to enumerate 鈥?depth stencil formats. Don鈥檛 worry about what these actually are, you will learn later. I鈥檓 just putting this in the enumeration section because that鈥檚 where it belongs 鈥?it is afterall enumeration. Just know how to do it. You already know what a format is. This is done quite easily. We first just check the format is valid for the device, then check if it鈥檚 compatible with the backbuffer format. If so, then we can use it (You鈥檒l see what it鈥檚 for later).
DepthFormat[] depthStencilFormats = new DepthFormat[] { DepthFormat.D16, DepthFormat.D15S1, DepthFormat.D24X8, DepthFormat.D24S8, DepthFormat.D24X4S4, DepthFormat.D32, }; foreach (DepthFormat depthStencilFormat in depthStencilFormats) { if(Manager.CheckDeviceFormat(adapter, deviceType, adapterFormat, Usage.DepthStencil, ResourceType.Surface, depthStencilFormat)) { if (Manager.CheckDepthStencilMatch(adapter, deviceType, adapterFormat, backbufferFormat, depthStencilFormat)) { // This depth stencil format is compatible } } }
Section 3.8 鈥?Final Word on Enumeration
Note that I鈥檝e covered more than enough on enumeration for you to get started. There is plenty more that you can figure out on your own though. Also remember all the stuff in the device capabilities (device caps) classes that can be checked. You check that stuff as you need it though. Unfortunately, enumeration is quite boring. I should have probably told you that at the start. We鈥檒l start doing some more interesting stuff in the next section.
Section 4 鈥?Rendering Something
Section 4.1 鈥?Creating the Device
Finally we get on to this device I鈥檝e mentioned so much in the enumeration section. What is a device? The device is the object we use in almost everything. It鈥檚 a representation of our actual adapter (well, in reality it鈥檚 driver). You will use the device to do all of the rendering (drawing, if I haven鈥檛 mentioned that yet) and lighting and so on. You can鈥檛 do very much without a device. So I think I鈥檝e stressed just how important it is. Now to actually create a device is a little bit trickier than anything we鈥檝e seen yet, but it鈥檚 still fairly trivial. Especially with all our enumeration done above.
// Assumes you have: // // AdapterInformation adapter; // DeviceType deviceType; // CreateFlags createFlags; // DisplayMode displayMode; // Format backbufferFormat; // bool windowed; PresentParameters presentation = new PresentParameters(); presentation.BackBufferFormat = backbufferFormat; presentation.BackBufferWidth = displayMode.Width; presentation.BackBufferHeight = displayMode.Height; presentation.SwapEffect = SwapEffect.Flip; presentation.Windowed = windowed; Device device = new Device( adapter.Adapter, deviceType, this, createFlags, presentation);
So first you need to choose an adapter, a device type, a vertex processing type (this is the createFlags variable) a display mode, a backbuffer format, and whether or not to use windowed mode. All of these are stored in the variables mentioned above. One you鈥檝e chosen these, you then create a new PresentParameters? object. This stores information about the backbuffer, and the display mode, and other important presentation information. You can change things like the number of back buffers to use and so on. We just change the backbuffer format, width and height as appropriate. Then we change the swap effect. The swap effect is just how the backbuffer is presented to the screen. We just tell it to flip the backbuffer and the screen around so that the backbuffer now becomes drawn on the screen, and what was previously on the screen now becomes the backbuffer. Lastly, we set whether or not we want to use windowed mode or not. Now to finally create the device, you pass first the adapter ordinal, then the device type. The next parameter, 鈥渢his鈥? must be a windows forms control! So this won鈥檛 work in console mode obviously. You must write the above code in a windows forms application. Using 鈥渢his鈥?will just draw onto the form. You could also draw onto a picturebox or something else if you pleased. The next parameter is the create flags, or the vertex processing type that I talked about a lot above in the enumeration section. And lastly, you pass the presentation parameters. This should hopefully give us a working device.
Section 4.2 鈥?Rendering Something
Now we get to the fun part 鈥?actually rendering! Don鈥檛 get too excited yet though, we鈥檙e only going to clear the window with a color. First we need to know where to actually render though. You could override the OnPaint? event and render everything in there. For a game or something, you will need a loop though. This is usually called 鈥渢he game loop鈥? This game loop usually goes after all the initialization code. Just remember to show your form before entering the loop. So now we know roughly where to put our rendering code, how do we actually write it? Well, we鈥檒l learn 2 new methods of the Device object: Clear and Present. The 鈥淐lear鈥?method simply clears the entire drawing area with your chosen color. The 鈥淧resent鈥?method performs the 鈥渇lip鈥? drawing the backbuffer to the screen. That鈥檚 all we鈥檒l use right now. So here鈥檚 the code for a typical rendering loop:
while (Running) { device.Clear(ClearFlags.Target, System.Drawing.Color.Blue, 1.0f, 0); device.Present(); Application.DoEvents(); }
Notice that we have a variable, Running. This would be a boolean that you would set to true if your initialization was successful. Then when you want to end the loop, for example when the escape key is pressed, or the form is closing, then you set the Running variable to false. Notice that we also use Application.DoEvents to continue processing messages.
Section 4.3 鈥?A Complete Sample Application
using System; using System.Drawing; using System.Windows.Forms; using Microsoft.DirectX; using Microsoft.DirectX.Direct3D; public class MainForm : Form { Device device = null; /// <summary> /// When the form is clicked, we close it and stop /// the application /// </summary> protected override void OnClick(EventArgs e) { this.Close(); base.OnClick (e); } /// <summary> /// In the constructor we initialize the device using /// the default adapter and the current display mode /// </summary> public MainForm() { AdapterInformation adapter = Manager.Adapters.Default; PresentParameters presentation = new PresentParameters (); presentation.BackBufferFormat = adapter.CurrentDisplayMode.Format; presentation.BackBufferWidth = adapter.CurrentDisplayMode.Width; presentation.BackBufferHeight = adapter.CurrentDisplayMode.Height; presentation.SwapEffect = SwapEffect.Flip; presentation.Windowed = false; // Place it in a try catch block just //in case it goes wrong for // some reason. try { // To make things simple, we'll just //use the reference device, and // software vertex processing. //Although this will be extrelemly slow // it doesn't matter in this case. // It will definetly work on // all machines, so it saves us doing //enumeration for now. device = new Device (adapter.Adapter, DeviceType.Reference, this, CreateFlags.SoftwareVertexProcessing, presentation); } catch (DirectXException e) { MessageBox.Show (e.Message); return; } } /// <summary> /// Clear the screen with a blue color /// </summary> public void Render() { device.Clear(ClearFlags.Target, Color.Blue, 1.0f, 0); device.Present(); } /// <summary> /// The entry point where the main render loop goes /// </summary> static void Main() { using (MainForm form = new MainForm()) { form.Show(); while (form.Created) { form.Render(); Application.DoEvents(); } } } }
As a simple exercise you could try changing the application so that it exits when the escape key is pressed instead of clicked. Also, try changing the color to red. And if you like you can try making the program run in windowed mode by commenting all the backbuffer parameters in the presentation parameters and just change the Windowed property to true.