Afișarea poligoanelor triunghiulare
rezumat
Afișează poligoane triunghiulare în spațiul 3D.
Mediul de operare
Cerințe preliminare
Versiuni XNA acceptate |
|
Platforme acceptate |
|
Versiunea Vertex Shader necesară pentru Windows | 2.0 |
Versiunea Pixel Shader necesară pentru Windows | 2.0 |
Mediul de operare
peron |
|
substanță
Ce este un poligon?
Un poligon este o față care este generată de mai multe definiții de noduri. În general, un poligon este o față triunghiulară formată din trei noduri. Iar trigonul este cea mai mică unitate a poligonului. Unele programe de modelare pot afișa poligoane ca patrulatere sau poligonale, dar acestea vor fi în cele din urmă descompuse în poligoane triunghiulare.
Modelul afișat în jocuri este format prin combinarea mai multor dintre aceste poligoane triunghiulare.
Poligoanele sunt formate din noduri. Nodurile pot avea date precum poziția și culoarea. Acest eșantion este, de asemenea, realizat din date de "poziție" și "culoare".
Culoarea feței din acest exemplu este bine interpolată de culoarea și distanța setate pentru fiecare nod, dar o puteți schimba liber cu propriul program de shader (mai multe despre programele de shader altă dată).
Definiții de date de nod
Pentru a afișa un poligon, sunt necesare "date de nod", iar programatorul trebuie să decidă ce elemente să includă în acel nod. Când desenați un poligon, trebuie să spuneți dispozitivului, care este motorul de desen, cu ce date de nod să desenați poligonul. Pentru a face acest lucru, creați o clasă "VertexDeclaration" și setați "Definiția datelor de nod".
Cu toate acestea, începând cu XNA Game Studio 4.0, această configurare a fost simplificată și nu este nevoie să pregătiți o clasă VertexDeclaration pentru acest sfat. (Acest lucru se datorează faptului că informațiile despre definiție sunt deja încorporate în datele de nod furnizate de cadru.)
Date de nod
Am scris că datele nodurilor sunt necesare pentru a desena poligoane, dar mai întâi trebuie să decidem ce fel de date vrem să avem. În acest caz, vom folosi datele de "poziție" și "culoare". După ce ați decis ce date doriți să aveți, trebuie să creați o structură pentru a păstra acele date. Aveți o anumită libertate de a decide ce sunt datele de nod, dar datele de nod utilizate în mod obișnuit sunt deja definite în XNA Framework, așa că eșantionul le utilizează.
Datele de vârf cu "poziție" și "culoare" sunt definite ca o structură "VertexPositionColor". Deoarece sunt necesare mai multe noduri pentru a forma un poligon, îl declarăm ca o matrice.
<summary>
頂点データリスト
</summary>
private VertexPositionColor[] vertices = null;
efect
În XNA, atunci când desenați un poligon, trebuie să scrieți un program de shader separat pentru a decide cum să-l desenați. Pentru a face acest lucru, creați un fișier de efect separat, scrieți un program, încărcați-l ca clasă de efecte și rulați programul shader.
Cu toate acestea, dacă nu trebuie să desenați poligoane triunghiulare simple ca acesta sau efecte de desen complexe, poate fi o sarcină foarte greoaie.
Din acest motiv, XNA definește efecte extinse care vă permit să setați elementele necesare ca proprietăți, astfel încât să nu fie nevoie să scrieți un program de shader pentru desenul de bază. Aceasta este clasa "BasicEffect". Deoarece scopul acestui articol este de a desena poligoane, vom folosi "BasicEffect" care nu necesită mult efort pentru a desena.
<summary>
基本エフェクト
</summary>
private BasicEffect basicEffect = null;
Voi vorbi mai multe despre efecte și BasicEffects altă dată.
Apropo, Windows Phone 7 nu vă permite să utilizați propriile efecte, ci doar pe cele încorporate în framework-uri precum BasicEffect.
Crearea unei definiții de date de nod
Până la XNA Framework 3.1, trebuia să le creați în mod explicit programatic, dar începând cu 4.0, informațiile de nod încorporate ale cadrului sunt deja incluse în informațiile de nod ca "IVertexType.VertexDeclaration", așa că le vom folosi.
Crearea efectelor
Creați o clasă BasicEffect. Setați proprietatea BasicEffect.VertexColorEnabled la true pentru a păstra culorile nodurilor.
// エフェクトを作成
this.basicEffect = new BasicEffect(this.GraphicsDevice);
// エフェクトで頂点カラーを有効にする
this.basicEffect.VertexColorEnabled = true;
BasicEffect
constructor
Creați o instanță a clasei de efecte "BasicEffect" care efectuează culoarea, textura și iluminarea nodurilor utilizând Shader Model 2.0.
dispozitiv | Dispozitiv grafic | Specifică GraphicsDevice pentru crearea efectului |
Vizualizați matricea și matricea de proiecție
Setați BasicEffect la o matrice de vizualizare și o matrice de proiecție. Pentru o explicație conceptuală a fiecăruia, consultați linkurile de mai jos.
- Despre transformarea coordonatelor modelelor 3D
- Vizualizați sistemul de coordonate
- Sistem de coordonate proiective
// ビューマトリックスをあらかじめ設定 ((0, 0, 15) から原点を見る)
this.basicEffect.View = Matrix.CreateLookAt(
new Vector3(0.0f, 0.0f, 15.0f),
Vector3.Zero,
Vector3.Up
);
// プロジェクションマトリックスをあらかじめ設定
this.basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(45.0f),
(float)this.GraphicsDevice.Viewport.Width /
(float)this.GraphicsDevice.Viewport.Height,
1.0f,
100.0f
);
Pentru a genera o matrice de vizualizare, utilizați metoda "Matrix.CreateLookAt".
Primul argument specifică poziția camerei, al doilea argument specifică punctul de interes al camerei, iar al treilea argument specifică direcția ascendentă a camerei.
În acest caz, este setat să privească originea din poziție (0, 0, 15).
Matrix.CreateLookAt
metodă
Creați o matrice de vizualizare.
camerăPoziție | Vector3 | Poziția camerei |
camerăȚintă | Vector3 | Punct de interes al camerei |
cameraUpVector | Vector3 | Direcția în sus a camerei |
Pentru a genera o matrice de proiecție, utilizați metoda "Matrix.CreatePerspectiveFieldOfView".
Primul argument este unghiul de vizualizare în radiani. În eșantion, unitatea de grad este convertită în radian folosind metoda "MathHelper.ToRadians". Pentru mai multe informații despre radian și grad, consultați Radian și grad.
Al doilea argument specifică raportul de aspect (raportul de aspect). De obicei, specificați o valoare pentru Lățimea ÷ Înălțimea vizualizării. În eșantion, se calculează din lățimea și înălțimea setate pentru fereastra de vizualizare a dispozitivului.
Al treilea argument specifică poziția de tăiere înainte, iar al patrulea argument specifică poziția de tăiere înapoi.
Matrix.CreatePerspectiveFieldOfView
metodă
Creează o matrice de proiecție în perspectivă bazată pe setările câmpului de vizualizare.
câmpOfView | pluti | Unghiul de vizualizare. Specificat în unități radiane. |
aspectRatio | pluti | Raport de aspect (raport de aspect). În mod normal, specificați o valoare pentru "Lățimea ÷ înălțimea vizualizării" |
nearPlaneDistance | pluti | Poziția clemei înainte. Obiectele din fața acestei poziții nu sunt desenate. |
farPlaneDistance | pluti | Poziția clemei din spate. Obiectele dincolo de această poziție nu sunt desenate. |
Crearea datelor de nod
Creați trei date de nod. În primul rând, vom crea o matrice și vom crea fiecare nod.
// 頂点データを作成する
this.vertices = new VertexPositionColor[3];
this.vertices[0] = new VertexPositionColor(new Vector3(0.0f, 3.0f, 0.0f),
Color.Red);
this.vertices[1] = new VertexPositionColor(new Vector3(3.0f, -2.0f, 0.0f),
Color.Blue);
this.vertices[2] = new VertexPositionColor(new Vector3(-3.0f, -2.0f, 0.0f),
Color.Green);
Pentru a crea date de nod, specificați "poziția nodului" și "culoarea nodului" în constructorul "VertexPositionColor".
VertexPositionColor
constructor
Creați o instanță a structurii "VertexPositionColor" cu datele de poziție și culoare ale nodului.
poziție | Vector3 | Poziția nodului |
culoare | Culoare | Culoarea nodului |
Setați poziția nodurilor la intervalul care poate fi văzut de la cameră. De asemenea, setați aranjamentul nodurilor să fie "în sensul acelor de ceasornic (în sensul acelor de ceasornic)". Dacă îl setați în "sens invers acelor de ceasornic", poligonul nu va fi vizibil. Pentru o explicație a acestui lucru, consultați Specificarea fețelor unui poligon de desenat.
Desenarea poligoanelor
// パスの数だけ繰り替えし描画 (といっても直接作成した BasicEffect は通常1回)
foreach (EffectPass pass in this.basicEffect.CurrentTechnique.Passes)
{
// パスの開始
pass.Apply();
// ポリゴンを描画する
this.GraphicsDevice.DrawUserPrimitives(
PrimitiveType.TriangleList,
this.vertices,
0,
1
);
}
// 登録された DrawableGameComponent を描画する
base.Draw(gameTime);
Există două tipuri de efecte, numite "tehnici" și "căi", prin care rulați programul de desen propriu-zis. Deoarece pot exista mai multe căi într-un singur efect, încerc să le chem în mod repetat în foreach. Cu toate acestea, în BasicEffect, există o tehnică și o singură cale, astfel încât puteți specifica direct indexul căii, dar descrierea de mai sus va fi mai curată, deoarece o puteți înlocui cu alte efecte.
Înainte de a începe desenul propriu-zis, apelați metoda "EffectPass.Apply" pentru a începe trecerea. Prin apelarea acestei metode, parametrii efectului care urmează să fie utilizat de data aceasta sunt aplicați dispozitivului grafic.
După ce ați început calea, desenați poligonul cu metoda "GraphicsDevice.DrawUserPrimitives".
Primul argument specifică tipul de primitivă care urmează să fie desenată. În acest caz, vom desena un poligon triunghiular, așa că specificați "PrimitiveType.TriangleList".
Al doilea argument specifică datele de nod create.
Al treilea argument specifică nodul din care se desenează. În mod normal, acesta este 0.
Al patrulea argument specifică numărul de primitive de desenat. În acest caz, există un singur poligon triunghiular, așa că specificați 1. Rețineți că nu este numărul de noduri.
GraphicsDevice.DrawUserPrimitives
metodă
Desenează primitivele pe baza datelor de nod furnizate de utilizator.
T | Fără limită | Structuri de date de nod |
primitiveType | PrimitiveType | Tipul de primitiv de desenat |
vertexData | T[] | O matrice de date de nod de desenat |
vertexOffset | Int | Specificați numărul de date de nod care urmează să fie utilizate pentru desen |
primitiveCount | Int | Numărul de primitive de desenat. |
Asta e tot pentru programul de desen. Dacă îl rulați efectiv și este afișat un triunghi, ați terminat.
Toate codurile
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
#if WINDOWS_PHONE
using Microsoft.Xna.Framework.Input.Touch;
#endif
namespace DrawTriangle
{
<summary>
ゲームメインクラス
</summary>
public class GameMain : Microsoft.Xna.Framework.Game
{
<summary>
グラフィックデバイス管理クラス
</summary>
private GraphicsDeviceManager graphics = null;
<summary>
スプライトのバッチ化クラス
</summary>
private SpriteBatch spriteBatch = null;
<summary>
頂点データリスト
</summary>
private VertexPositionColor[] vertices = null;
<summary>
基本エフェクト
</summary>
private BasicEffect basicEffect = null;
<summary>
GameMain コンストラクタ
</summary>
public GameMain()
{
// グラフィックデバイス管理クラスの作成
this.graphics = new GraphicsDeviceManager(this);
// ゲームコンテンツのルートディレクトリを設定
this.Content.RootDirectory = "Content";
#if WINDOWS_PHONE
// Windows Phone のデフォルトのフレームレートは 30 FPS
this.TargetElapsedTime = TimeSpan.FromTicks(333333);
// バックバッファサイズの設定
this.graphics.PreferredBackBufferWidth = 480;
this.graphics.PreferredBackBufferHeight = 800;
// フルスクリーン表示
this.graphics.IsFullScreen = true;
#endif
}
<summary>
ゲームが始まる前の初期化処理を行うメソッド
グラフィック以外のデータの読み込み、コンポーネントの初期化を行う
</summary>
protected override void Initialize()
{
// TODO: ここに初期化ロジックを書いてください
// コンポーネントの初期化などを行います
base.Initialize();
}
<summary>
ゲームが始まるときに一回だけ呼ばれ
すべてのゲームコンテンツを読み込みます
</summary>
protected override void LoadContent()
{
// テクスチャーを描画するためのスプライトバッチクラスを作成します
this.spriteBatch = new SpriteBatch(this.GraphicsDevice);
// エフェクトを作成
this.basicEffect = new BasicEffect(this.GraphicsDevice);
// エフェクトで頂点カラーを有効にする
this.basicEffect.VertexColorEnabled = true;
// ビューマトリックスをあらかじめ設定 ((0, 0, 15) から原点を見る)
this.basicEffect.View = Matrix.CreateLookAt(
new Vector3(0.0f, 0.0f, 15.0f),
Vector3.Zero,
Vector3.Up
);
// プロジェクションマトリックスをあらかじめ設定
this.basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(45.0f),
(float)this.GraphicsDevice.Viewport.Width /
(float)this.GraphicsDevice.Viewport.Height,
1.0f,
100.0f
);
// 頂点データを作成する
this.vertices = new VertexPositionColor[3];
this.vertices[0] = new VertexPositionColor(new Vector3(0.0f, 3.0f, 0.0f),
Color.Red);
this.vertices[1] = new VertexPositionColor(new Vector3(3.0f, -2.0f, 0.0f),
Color.Blue);
this.vertices[2] = new VertexPositionColor(new Vector3(-3.0f, -2.0f, 0.0f),
Color.Green);
}
<summary>
ゲームが終了するときに一回だけ呼ばれ
すべてのゲームコンテンツをアンロードします
</summary>
protected override void UnloadContent()
{
// TODO: ContentManager で管理されていないコンテンツを
// ここでアンロードしてください
}
<summary>
描画以外のデータ更新等の処理を行うメソッド
主に入力処理、衝突判定などの物理計算、オーディオの再生など
</summary>
<param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
protected override void Update(GameTime gameTime)
{
// Xbox 360 コントローラ、Windows Phone の BACK ボタンを押したときに
// ゲームを終了させます
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
{
this.Exit();
}
// TODO: ここに更新処理を記述してください
// 登録された GameComponent を更新する
base.Update(gameTime);
}
<summary>
描画処理を行うメソッド
</summary>
<param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
protected override void Draw(GameTime gameTime)
{
// 画面を指定した色でクリアします
this.GraphicsDevice.Clear(Color.CornflowerBlue);
// パスの数だけ繰り替えし描画 (といっても直接作成した BasicEffect は通常1回)
foreach (EffectPass pass in this.basicEffect.CurrentTechnique.Passes)
{
// パスの開始
pass.Apply();
// ポリゴンを描画する
this.GraphicsDevice.DrawUserPrimitives(
PrimitiveType.TriangleList,
this.vertices,
0,
1
);
}
// 登録された DrawableGameComponent を描画する
base.Draw(gameTime);
}
}
}