Weergave van driehoekige veelhoeken

Pagina bijgewerkt :
Aanmaakdatum van pagina :

samenvatting

Het toont driehoekige polygonen in de 3D-ruimte.

3角形ポリゴンの表示

Werkomgeving

Voorwaarden

Ondersteunde XNA-versies
  • 4.0
Ondersteunde platforms
  • Windows (XP SP2 of hoger, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Windows vereist Vertex Shader-versie 2.0
Windows Vereiste Pixel Shader-versie 2.0

Werkomgeving

perron
  • Vensters 7
  • Xbox 360
  • Windows Phone 7-emulator

stof

Wat is een veelhoek?

Een veelhoek is een vlak dat wordt gegenereerd door meerdere hoekpuntdefinities. Over het algemeen is een veelhoek een driehoekig vlak dat bestaat uit drie hoekpunten. En de trigon is de kleinste eenheid van de veelhoek. Sommige modelleringssoftware kan polygonen weergeven als vierhoek of veelhoekig, maar deze zullen uiteindelijk worden ontleed in driehoekige veelhoeken.

Het model dat in games wordt weergegeven, wordt gevormd door meerdere van deze driehoekige veelhoeken te combineren.

最小単位のポリゴン

Polygonen worden gevormd door hoekpunten. Hoekpunten kunnen gegevens bevatten zoals positie en kleur. Dit monster is ook gemaakt van "positie" en "kleur" gegevens.

ポリゴンと頂点

De kleur van het gezicht in dit voorbeeld wordt netjes geïnterpoleerd door de kleur en afstand die voor elk hoekpunt zijn ingesteld, maar je kunt deze vrij veranderen met je eigen shader-programma (een andere keer meer over shader-programma's).

Definities van hoekpuntgegevens

Om een polygoon weer te geven, zijn "hoekpuntgegevens" vereist, en de programmeur moet beslissen welke elementen in dat hoekpunt moeten worden opgenomen. Bij het tekenen van een veelhoek moet u het apparaat, dat de tekenengine is, vertellen met welke hoekpuntgegevens de veelhoek moet worden getekend. Om dit te doen, maakt u een klasse "VertexDeclaration" aan en stelt u de "Vertex Data Definition" in.

Vanaf XNA Game Studio 4.0 is deze opzet echter vereenvoudigd en hoef je voor deze tip geen VertexDeclaration-klasse voor te bereiden. (Dit komt omdat de definitie-informatie al is ingebed in de hoekpuntgegevens die door het framework worden geleverd.)

Gegevens over hoekpunten

Ik schreef dat hoekpuntgegevens nodig zijn om polygonen te tekenen, maar eerst moeten we beslissen wat voor soort gegevens we willen hebben. In dit geval gebruiken we "positie" en "kleur" gegevens. Als u eenmaal hebt besloten welke gegevens u wilt hebben, moet u een structuur creëren om die gegevens te bewaren. U hebt enige vrijheid om te beslissen wat hoekpuntgegevens zijn, maar de veelgebruikte hoekpuntgegevens zijn al gedefinieerd in het XNA-framework, dus het voorbeeld gebruikt het.

Hoekpuntgegevens met 'positie' en 'kleur' worden gedefinieerd als een 'VertexPositionColor'-structuur. Aangezien er meerdere hoekpunten nodig zijn om een veelhoek te vormen, verklaren we deze als een matrix.

/// <summary>
/// 頂点データリスト
/// </summary>
private VertexPositionColor[] vertices = null;

effect

Als je in XNA een veelhoek tekent, moet je een apart shader-programma schrijven om te beslissen hoe je het moet tekenen. Om dit te doen, maakt u een afzonderlijk effectbestand, schrijft u een programma, laadt u het als een effectklasse en voert u het shader-programma uit.

Als u echter geen eenvoudige driehoekige veelhoeken zoals deze hoeft te tekenen, of complexe tekeneffecten, kan dit een zeer omslachtige taak zijn.

Om deze reden definieert XNA uitgebreide effecten waarmee u de vereiste items als eigenschappen kunt instellen, zodat u geen shader-programma hoeft te schrijven voor basistekeningen. Dat is de "BasicEffect" klasse. Aangezien het doel van dit artikel is om polygonen te tekenen, zullen we "BasicEffect" gebruiken dat niet veel moeite kost om te tekenen.

/// <summary>
/// 基本エフェクト
/// </summary>
private BasicEffect basicEffect = null;

Ik zal het op een ander moment meer hebben over effecten en BasicEffects.

Trouwens, Windows Phone 7 staat niet toe dat je je eigen effecten gebruikt, alleen die welke zijn ingebouwd in frameworks zoals BasicEffect.

Een gegevensdefinitie van een hoekpunt maken

Tot het XNA Framework 3.1 moest je ze expliciet programmatisch maken, maar vanaf 4.0 is de ingebouwde vertex-informatie van het framework al opgenomen in de vertex-informatie als "IVertexType.VertexDeclaration", dus we zullen het gebruiken.

Effecten creëren

Maak een BasicEffect-klasse. Stel de eigenschap BasicEffect.VertexColorEnabled in op true om de hoekpuntkleuren te behouden.

// エフェクトを作成
this.basicEffect = new BasicEffect(this.GraphicsDevice);

// エフェクトで頂点カラーを有効にする
this.basicEffect.VertexColorEnabled = true;

BasicEffect bouwer

Maak een exemplaar van de effectklasse 'BasicEffect' dat hoekpuntkleur, textuur en belichting uitvoert met behulp van Shader Model 2.0.

apparaat Grafisch apparaat Specificeert het grafische apparaat voor het maken van het effect

Bekijk matrix en projectiematrix

Stel het BasicEffect in op een weergavematrix en een projectiematrix. Voor een conceptuele uitleg van elk, zie de onderstaande links.

// ビューマトリックスをあらかじめ設定 ((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
    );

Om een weergavematrix te genereren, gebruikt u de methode "Matrix.CreateLookAt".

Het eerste argument specificeert de positie van de camera, het tweede argument specificeert het aandachtspunt van de camera en het derde argument specificeert de opwaartse richting van de camera.

In dit geval is het ingesteld om vanuit de positie naar de oorsprong te kijken (0, 0, 15).

Matrix.CreateLookAt methode

Maak een weergavematrix.

cameraPositie Vector 3 Positie van de camera
cameraDoel Vector 3 Bezienswaardigheid voor camera's
cameraOmhoogVector Vector 3 Opwaartse richting van de camera

Om een projectiematrix te genereren, gebruikt u de methode "Matrix.CreatePerspectiveFieldOfView".

Het eerste argument is de kijkhoek in radialen. In de steekproef wordt de graadeenheid omgezet in radiaal met behulp van de methode "MathHelper.ToRadians". Voor meer informatie over Radiaal en Graad, zie Radiaal en Graad.

Het tweede argument geeft de hoogte-breedteverhouding (beeldverhouding) aan. Meestal geeft u een waarde op voor Breedte ÷ Hoogte van de weergave. In de steekproef wordt deze berekend op basis van de breedte en hoogte die zijn ingesteld voor de viewport van het apparaat.

Het derde argument geeft de voorwaartse clipping-positie op en het vierde argument specificeert de achterwaartse clipping-positie.

Matrix.CreatePerspectiveFieldOfView methode

Hiermee maakt u een perspectiefprojectiematrix op basis van de instellingen van het weergaveveld.

fieldOfView drijven Kijkhoek. Gespecificeerd in radiale eenheden.
beeldverhouding drijven Beeldverhouding (beeldverhouding). Normaal gesproken geeft u een waarde op voor "Breedte ÷ hoogte van weergave"
nearPlaneDistance drijven Voorwaartse clippositie. Objecten voor deze positie worden niet getekend.
verrePlaneDistance drijven Positie clip achteraan. Objecten buiten deze positie worden niet getekend.

Vertex-gegevens maken

Maak drie hoekpuntgegevens. Eerst maken we een matrix en maken we elk hoekpunt.

// 頂点データを作成する
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);

Als u hoekpuntgegevens wilt maken, geeft u de "hoekpuntpositie" en "hoekpuntkleur" op in de constructor van "VertexPositionColor".

VertexPositionColor bouwer

Maak een exemplaar van de structuur "VertexPositionColor" met de positie- en kleurhoekpuntgegevens.

positie Vector 3 Hoekpunt positie
Kleur Kleur Hoekpunt kleur

Stel de positie van de hoekpunten in op het bereik dat vanaf de camera te zien is. Stel ook de opstelling van het hoekpunt in op "met de klok mee (met de klok mee)". Als u deze instelt op "tegen de klok in", is de veelhoek niet zichtbaar. Voor een uitleg hiervan, zie De vlakken van een te tekenen veelhoek opgeven.

Polygonen tekenen

// パスの数だけ繰り替えし描画 (といっても直接作成した 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);

Er zijn twee soorten effecten, genaamd "technieken" en "paden", waarmee u het eigenlijke tekenprogramma uitvoert. Omdat er meerdere paden in één effect kunnen zitten, probeer ik ze herhaaldelijk in foreach aan te roepen. In BasicEffect is er echter één techniek en één pad, dus u kunt de index van het pad rechtstreeks specificeren, maar de bovenstaande beschrijving zal schoner zijn omdat u deze kunt vervangen door andere effecten.

Voordat u met de eigenlijke tekening begint, roept u de methode "EffectPass.Apply" aan om de pas te starten. Door deze methode aan te roepen, worden de parameters van het effect dat deze keer moet worden gebruikt, toegepast op het grafische apparaat.

Nadat u het pad bent gestart, tekent u de polygoon met de methode "GraphicsDevice.DrawUserPrimitives".

Het eerste argument specificeert het type primitief dat moet worden getekend. In dit geval tekenen we een driehoekige veelhoek, dus specificeer "PrimitiveType.TriangleList".

Het tweede argument specificeert de gemaakte hoekpuntgegevens.

Het derde argument geeft het hoekpunt aan waaruit moet worden getrokken. Normaal gesproken is dit 0.

Het vierde argument geeft het aantal primitieven aan dat moet worden getrokken. In dit geval is er slechts één driehoekige veelhoek, dus geef 1 op. Merk op dat het niet het aantal hoekpunten is.

GraphicsDevice.DrawUserPrimitives methode

Tekent primitieven op basis van door de gebruiker aangeleverde hoekpuntgegevens.

T Geen limiet Gegevensstructuren van hoekpunten
primitief type Primitief type Het type primitief om te tekenen
hoekpuntGegevens T[] Een reeks hoekpuntgegevens om te tekenen
hoekpuntOffset Int Geef het aantal hoekpuntgegevens op dat voor de tekening moet worden gebruikt
primitiveCount Int Het aantal primitieven om te tekenen.

Dat is het voor het tekenprogramma. Als je het daadwerkelijk uitvoert en er wordt een driehoek weergegeven, ben je klaar.

Alle codes

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);
        }
    }
}