Menampilkan poligon segitiga

Halaman Diperbarui :
Tanggal pembuatan halaman :

ringkasan

Ini menampilkan poligon segitiga dalam ruang 3D.

3角形ポリゴンの表示

Lingkungan operasi

Prasyarat

Versi XNA yang Didukung
  • 4.0
Platform yang Didukung
  • Windows (XP SP2 atau lebih baru, Vista, 7)
  • Xbox 360
  • Telepon Windows 7
Versi Vertex Shader yang Diperlukan Windows 2.0
Versi Pixel Shader yang Diperlukan Windows 2.0

Lingkungan operasi

balei-balei
  • Jendela 7
  • Xbox 360
  • Windows Phone 7 Emulator

zat

Apa itu poligon?

Poligon adalah wajah yang dihasilkan oleh beberapa definisi simpul. Secara umum, poligon adalah wajah segitiga yang terdiri dari tiga simpul. Dan trigon adalah unit terkecil dari poligon. Beberapa perangkat lunak pemodelan mungkin menampilkan poligon sebagai segiempat atau poligonal, tetapi ini pada akhirnya akan diuraikan menjadi poligon segitiga.

Model yang ditampilkan dalam game dibentuk dengan menggabungkan beberapa poligon segitiga ini.

最小単位のポリゴン

Poligon dibentuk oleh simpul. Simpul dapat memiliki data seperti posisi dan warna. Sampel ini juga dibuat dari data "posisi" dan "warna".

ポリゴンと頂点

Warna wajah dalam contoh ini diinterpolasi dengan rapi oleh warna dan jarak yang ditetapkan untuk setiap simpul, tetapi Anda dapat dengan bebas mengubahnya dengan program shader Anda sendiri (lebih lanjut tentang program shader di lain waktu).

Definisi Data Vertex

Untuk menampilkan poligon, "data simpul" diperlukan, dan pemrogram harus memutuskan elemen apa yang akan disertakan dalam simpul itu. Saat menggambar poligon, Anda harus memberi tahu perangkat, yang merupakan mesin gambar, data simpul apa yang akan digunakan untuk menggambar poligon. Untuk melakukan ini, buat kelas "VertexDeclaration" dan atur "Definisi Data Vertex".

Namun, dimulai dengan XNA Game Studio 4.0, penyiapan ini telah disederhanakan, dan Anda tidak perlu menyiapkan kelas VertexDeclaration untuk tip ini. (Ini karena informasi definisi sudah disematkan dalam data simpul yang disediakan oleh kerangka kerja.)

Data simpul

Saya menulis bahwa data simpul diperlukan untuk menggambar poligon, tetapi pertama-tama kita harus memutuskan jenis data apa yang ingin kita miliki. Dalam hal ini, kita akan menggunakan data "posisi" dan "warna". Setelah Anda memutuskan data apa yang ingin Anda miliki, Anda perlu membuat struktur untuk menyimpan data tersebut. Anda memiliki kebebasan untuk memutuskan apa itu data simpul itu, tetapi data simpul yang umum digunakan sudah didefinisikan dalam Kerangka Kerja XNA, sehingga sampel menggunakannya.

Data simpul dengan "posisi" dan "warna" didefinisikan sebagai struktur "VertexPositionColor". Karena beberapa simpul diperlukan untuk membentuk poligon, kami mendeklarasikannya sebagai array.

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

efek

Di XNA, ketika Anda menggambar poligon, Anda harus menulis program shader terpisah untuk memutuskan cara menggambarnya. Untuk melakukan ini, buat file efek terpisah, tulis program, muat sebagai kelas efek, dan jalankan program shader.

Namun, jika Anda tidak perlu menggambar poligon segitiga sederhana seperti ini, atau efek gambar yang rumit, itu bisa menjadi tugas yang sangat rumit.

Untuk alasan ini, XNA mendefinisikan efek yang diperluas yang memungkinkan Anda mengatur item yang diperlukan sebagai properti sehingga Anda tidak perlu menulis program shader untuk menggambar dasar. Itu adalah kelas "BasicEffect". Karena tujuan artikel ini adalah untuk menggambar poligon, kita akan menggunakan "BasicEffect" yang tidak membutuhkan banyak usaha untuk menggambar.

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

Saya akan berbicara lebih banyak tentang efek dan BasicEffects di lain waktu.

Omong-omong, Windows Phone 7 tidak mengizinkan Anda untuk menggunakan efek Anda sendiri, hanya yang dibangun ke dalam kerangka kerja seperti BasicEffect.

Membuat definisi data simpul

Hingga XNA Framework 3.1, Anda harus membuatnya secara eksplisit secara terprogram, tetapi dimulai dengan 4.0, informasi simpul bawaan kerangka kerja sudah disertakan dalam informasi simpul sebagai "IVertexType.VertexDeclaration", jadi kita akan menggunakannya.

Membuat Efek

Buat kelas BasicEffect. Atur properti BasicEffect.VertexColorEnabled ke true untuk mempertahankan warna simpul.

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

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

BasicEffect pembangun

Buat instance kelas efek "BasicEffect" yang melakukan warna simpul, tekstur, dan pencahayaan menggunakan Shader Model 2.0.

alat Perangkat grafis Menentukan GraphicsDevice untuk membuat efek

Lihat Matriks dan Matriks Proyeksi

Atur BasicEffect ke matriks tampilan dan matriks proyeksi. Untuk penjelasan konseptual masing-masing, lihat tautan di bawah ini.

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

Untuk membuat matriks tampilan, gunakan metode "Matrix.CreateLookAt".

Argumen pertama menentukan posisi kamera, argumen kedua menentukan titik menarik kamera, dan argumen ketiga menentukan arah ke atas kamera.

Dalam hal ini, diatur untuk melihat asal dari posisi (0, 0, 15).

Matrix.CreateLookAt Metode

Buat matriks tampilan.

kameraPosisi Vektor3 Posisi Kamera
KameraTarget Vektor3 Tempat Menarik Kamera
kameraUpVektor Vektor3 Arah kamera ke atas

Untuk menghasilkan matriks proyeksi, gunakan metode "Matrix.CreatePerspectiveFieldOfView".

Argumen pertama adalah sudut pandang dalam radian. Dalam sampel, satuan derajat diubah menjadi radian menggunakan metode "MathHelper.ToRadians". Untuk informasi selengkapnya tentang Radian dan Derajat, lihat Radian dan Derajat.

Argumen kedua menentukan rasio aspek (rasio aspek). Biasanya, Anda menentukan nilai untuk Lebar Tampilan ÷ Tinggi. Dalam sampel, ini dihitung dari lebar dan tinggi yang ditetapkan untuk viewport perangkat.

Argumen ketiga menentukan posisi kliping maju, dan argumen keempat menentukan posisi kliping mundur.

Matrix.CreatePerspectiveFieldOfView Metode

Membuat matriks proyeksi perspektif berdasarkan pengaturan bidang tampilan.

fieldOfView mengapung Sudut pandang. Ditentukan dalam satuan radian.
rasio aspek mengapung Rasio aspek (rasio aspek). Biasanya, Anda menentukan nilai untuk "View Width ÷ Height"
jarak dekat pesawat mengapung Posisi klip depan. Objek di depan posisi ini tidak digambar.
jarak pesawat jauh mengapung Posisi klip belakang. Objek di luar posisi ini tidak digambar.

Membuat Data Vertex

Buat tiga data simpul. Pertama, kita akan membuat array dan membuat setiap simpul.

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

Untuk membuat data simpul, tentukan "posisi simpul" dan "warna simpul" dalam konstruktor "VertexPositionColor".

VertexPositionColor pembangun

Buat instance struktur "VertexPositionColor" dengan data simpul posisi dan warna.

posisi Vektor3 Posisi Simpul
warna Warna Warna simpul

Atur posisi simpul ke rentang yang dapat dilihat dari kamera. Juga, atur susunan simpul menjadi "searah jarum jam (searah jarum jam)". Jika Anda mengaturnya ke "berlawanan arah jarum jam", poligon tidak akan terlihat. Untuk penjelasan tentang hal ini, lihat Menentukan Wajah Poligon yang akan Digambar.

Menggambar poligon

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

Ada dua jenis efek, yang disebut "teknik" dan "jalur", di mana Anda menjalankan program menggambar yang sebenarnya. Karena mungkin ada beberapa jalur dalam satu efek, saya mencoba memanggilnya berulang kali di foreach. Namun, di BasicEffect, ada satu teknik dan satu jalur, sehingga Anda dapat menentukan indeks jalur secara langsung, tetapi deskripsi di atas akan lebih bersih karena Anda dapat menggantinya dengan efek lain.

Sebelum memulai gambar yang sebenarnya, panggil metode "EffectPass.Apply" untuk memulai pass. Dengan memanggil metode ini, parameter efek yang akan digunakan kali ini diterapkan pada perangkat grafis.

Setelah Anda memulai jalur, gambar poligon dengan metode "GraphicsDevice.DrawUserPrimitives".

Argumen pertama menentukan jenis primitif yang akan digambar. Dalam hal ini, kita akan menggambar poligon segitiga, jadi tentukan "PrimitiveType.TriangleList".

Argumen kedua menentukan data simpul yang dibuat.

Argumen ketiga menentukan simpul yang akan diambil. Biasanya, ini adalah 0.

Argumen keempat menentukan jumlah primitif yang akan digambar. Dalam hal ini, hanya ada satu poligon segitiga, jadi tentukan 1. Perhatikan bahwa itu bukan jumlah simpul.

GraphicsDevice.DrawUserPrimitives Metode

Menggambar primitif berdasarkan data simpul yang disediakan pengguna.

T Tidak ada batas Struktur Data Vertex
tipe primitif Tipe Primitif Jenis primitif untuk menggambar
data simpul T[] Array data simpul untuk digambar
Offset puncak Int Tentukan jumlah data simpul yang akan digunakan untuk menggambar
primitifCount Int Jumlah primitif yang akan digambar.

Itu saja untuk program menggambar. Jika Anda benar-benar menjalankannya dan segitiga ditampilkan, Anda sudah selesai.

Semua Kode

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