הצגת מצולעים משולשים

עודכן דף :
תאריך יצירת דף :

תקציר

הוא מציג מצולעים משולשים במרחב תלת ממדי.

3角形ポリゴンの表示

סביבת הפעלה

דרישות מוקדמות

גרסאות XNA נתמכות
  • 4.0
פלטפורמות נתמכות
  • Windows (XP SP2 ואילך, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Windows נדרש Vertex Shader גירסה 2.0
גירסת Pixel Shader נדרשת של Windows 2.0

סביבת הפעלה

פלטפורמה
  • חלונות 7
  • Xbox 360
  • אמולטור Windows Phone 7

חומר

מהו מצולע?

מצולע הוא פרצוף שנוצר על ידי הגדרות קודקודים מרובות. באופן כללי, מצולע הוא פרצוף משולש המורכב משלושה קודקודים. והטריגון הוא היחידה הקטנה ביותר של המצולע. תוכנות מידול מסוימות עשויות להציג מצולעים כמרובעים או מצולעים, אך אלה יפורקו בסופו של דבר למצולעים משולשים.

המודל המוצג במשחקים נוצר על ידי שילוב של מצולעים משולשים אלה.

最小単位のポリゴン

מצולעים נוצרים על ידי קודקודים. קודקודים יכולים להכיל נתונים כגון מיקום וצבע. מדגם זה עשוי גם מנתוני "מיקום" ו"צבע".

ポリゴンと頂点

צבע הפנים בדוגמה זו עובר אינטרפולציה מסודרת על-ידי הצבע והמרחק שהוגדרו עבור כל קודקוד, אך באפשרותך לשנות אותו באופן חופשי באמצעות תוכנית Shader משלך (עוד על תוכניות Shader בפעם אחרת).

הגדרות נתונים של Vertex

על מנת להציג מצולע, נדרשים "נתוני קודקודים", ועל המתכנת להחליט אילו אלמנטים לכלול בקודקוד זה. בעת ציור מצולע, אתה צריך להגיד למכשיר, שהוא מנוע השרטוט, עם אילו נתוני קודקוד לצייר את המצולע. לשם כך, צור מחלקה "VertexDeclaration" והגדר את "Vertex Data Definition".

עם זאת, החל מ-XNA Game Studio 4.0, הגדרה זו הפכה לפשוטה יותר, ואין צורך להכין מחלקת VertexDeclaration עבור עצה זו. (הסיבה לכך היא שמידע ההגדרה כבר מוטבע בנתוני הקודקודים שסופקו על-ידי המסגרת).

נתוני Vertex

כתבתי שנתוני קודקודים נדרשים כדי לצייר מצולעים, אבל קודם אנחנו צריכים להחליט איזה סוג של נתונים אנחנו רוצים שיהיו לנו. במקרה זה, נשתמש בנתוני "מיקום" ו"צבע". לאחר שהחלטת אילו נתונים ברצונך שיהיו לך, עליך ליצור מבנה שיחזיק נתונים אלה. יש לך חופש מסוים להחליט מהם נתוני קודקודים, אך נתוני הקודקודים הנפוצים כבר מוגדרים במסגרת XNA, כך שהמדגם משתמש בהם.

נתוני קודקוד עם "מיקום" ו"צבע" מוגדרים כמבנה "VertexPositionColor". מכיוון שיש צורך במספר קודקודים כדי ליצור מצולע, אנו מכריזים עליו כמערך.

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

אפקט

ב- XNA, כאשר אתה מצייר מצולע, עליך לכתוב תוכנית Shader נפרדת כדי להחליט כיצד לצייר אותו. לשם כך, צור קובץ אפקטים נפרד, כתוב תוכנית, טען אותה כמחלקת אפקטים והפעל את תוכנית Shader.

עם זאת, אם אינך צריך לצייר מצולעים משולשים פשוטים כמו זה, או אפקטים מורכבים של ציור, זו יכולה להיות משימה מסורבלת מאוד.

מסיבה זו, XNA מגדיר אפקטים מורחבים המאפשרים לך להגדיר את הפריטים הדרושים כמאפיינים כך שלא תצטרך לכתוב תוכנית Shader עבור ציור בסיסי. זוהי המחלקה "BasicEffect". מכיוון שמטרת מאמר זה היא לצייר מצולעים, נשתמש ב- "BasicEffect" שאינו דורש מאמץ רב לצייר.

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

אני אדבר יותר על אפקטים ואפקטים בסיסיים במועד אחר.

אגב, Windows Phone 7 אינו מאפשר לך להשתמש באפקטים משלך, אלא רק באלה המובנים במסגרות כמו BasicEffect.

יצירת הגדרת נתוני קודקוד

עד XNA Framework 3.1, היית צריך ליצור אותם במפורש באופן תכנותי, אבל החל מ- 4.0, מידע הקודקודים המובנה של המסגרת כבר כלול במידע הקודקוד כ- "IVertexType.VertexDeclaration", ולכן נשתמש בו.

יצירת אפקטים

צור מחלקה של BasicEffect. הגדר את המאפיין BasicEffect.VertexColorEnabled ל- true כדי לשמור על צבעי הקודקודים.

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

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

BasicEffect בנאי

צור מופע של מחלקת האפקטים "BasicEffect" המבצע צבע, מרקם ותאורה של קודקודים באמצעות Shader Model 2.0.

מכשיר GraphicsDevice מציין את GraphicsDevice ליצירת האפקט

הצגת מטריצה ומטריצת הקרנה

הגדר את BasicEffect למטריצת תצוגה ומטריצת הקרנה. להסבר מושגי של כל אחד מהם, ראו את הקישורים למטה.

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

כדי ליצור מטריצת תצוגה, השתמש בשיטה "Matrix.CreateLookAt".

הטיעון הראשון מציין את מיקום המצלמה, הטיעון השני מציין את נקודת העניין של המצלמה, והטיעון השלישי מציין את הכיוון כלפי מעלה של המצלמה.

במקרה זה, הוא מוגדר להסתכל על המקור מן המיקום (0, 0, 15).

Matrix.CreateLookAt שיטת

צור מטריצת תצוגה.

מצלמהמיקום וקטור3 מיקום המצלמה
cameraTarget וקטור3 נקודת עניין במצלמה
cameraUpVector וקטור3 כיוון כלפי מעלה של המצלמה

כדי ליצור מטריצת הקרנה, השתמש בשיטה "Matrix.CreatePerspectiveFieldOfView".

הטיעון הראשון הוא זווית הצפייה ברדיאנים. במדגם, יחידת התואר מומרת לרדיאנים בשיטת "MathHelper.ToRadians". לקבלת מידע נוסף אודות Radian ו- Degree, ראה Radian ו- Degree.

הארגומנט השני מציין את יחס הרוחב-גובה (יחס גובה-רוחב). בדרך כלל, יש לציין ערך בתיבה 'רוחב תצוגה' ÷'גובה'. במדגם, הוא מחושב מהרוחב והגובה שנקבעו עבור האשנב של המכשיר.

הארגומנט השלישי מציין את מיקום החיתוך קדימה, והארגומנט הרביעי מציין את מיקום החיתוך לאחור.

Matrix.CreatePerspectiveFieldOfView שיטת

יצירת מטריצת הקרנת פרספקטיבה המבוססת על הגדרות שדה התצוגה.

fieldOfView שט זווית צפייה. מצוין ביחידות רדיאן.
aspectRatio שט יחס גובה-רוחב (יחס גובה-רוחב). בדרך כלל, אתה מציין ערך עבור "רוחב תצוגה ÷ גובה"
nearPlaneDistance שט מיקום קליפ קדימה. אובייקטים לפני מיקום זה אינם מצוירים.
farPlaneDistance שט מיקום תפס אחורי. אובייקטים מעבר למיקום זה אינם מצוירים.

יצירת נתוני קודקוד

צור שלושה נתוני קודקודים. ראשית, ניצור מערך וניצור כל קודקוד.

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

כדי ליצור נתוני קודקודים, ציין את "מיקום הקודקוד" ואת "צבע הקודקוד" בבנאי של "VertexPositionColor".

VertexPositionColor בנאי

צור מופע של המבנה "VertexPositionColor" עם נתוני קודקודי המיקום והצבע.

מיקום וקטור3 מיקום קודקוד
צבע צבע צבע קודקוד

הגדר את מיקום הקודקודים לטווח שניתן לראות מהמצלמה. כמו כן, הגדר את סידור הקודקודים להיות "בכיוון השעון (בכיוון השעון)". אם תגדיר אותו ל"נגד כיוון השעון", המצולע לא יהיה גלוי. לקבלת הסבר על כך, ראה ציון פני מצולע לציור.

ציור מצולעים

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

ישנם שני סוגים של אפקטים, הנקראים "טכניקות" ו"נתיבים", שבאמצעותם אתה מפעיל את תוכנית הציור בפועל. מכיוון שיכולים להיות נתיבים מרובים באפקט אחד, אני מנסה לקרוא להם שוב ושוב בהקדמה. עם זאת, ב- BasicEffect, יש טכניקה אחת ונתיב אחד, כך שתוכל לציין את האינדקס של הנתיב ישירות, אך התיאור לעיל יהיה נקי יותר מכיוון שניתן להחליף אותו באפקטים אחרים.

לפני תחילת הציור בפועל, התקשר לשיטה "EffectPass.Apply" כדי להתחיל את המעבר. על ידי קריאה לשיטה זו, הפרמטרים של האפקט שישמש הפעם מוחלים על התקן הגרפיקה.

לאחר שהתחלת את הנתיב, צייר את המצולע בשיטה "GraphicsDevice.DrawUserPrimitives".

הארגומנט הראשון מציין את סוג הפרימיטיבי שיש לצייר. במקרה זה, נצייר מצולע משולש, לכן ציין "PrimitiveType.TriangleList".

הארגומנט השני מציין את נתוני הקודקודים שנוצרו.

הארגומנט השלישי מציין את הקודקוד שממנו יש להסיק. בדרך כלל, זה 0.

הארגומנט הרביעי מציין את מספר הפרימיטיביים שיש לצייר. במקרה זה, יש רק מצולע משולש אחד, לכן ציין 1. שים לב שזה לא מספר הקודקודים.

GraphicsDevice.DrawUserPrimitives שיטת

מצייר פרימיטיבים בהתבסס על נתוני קודקודים שסופקו על-ידי המשתמש.

T ללא הגבלה מבני נתונים של Vertex
סוג פרימיטיבי PrimitiveType סוג הפרימיטיבי לצייר
vertexData T[] מערך של נתוני קודקודים לציור
vertexOffset int ציון מספר נתוני הקודקודים שישמשו לציור
ספירה פרימיטיבית int מספר הפרימיטיביים לצייר.

זהו זה עבור תוכנית הציור. אם אתה באמת מפעיל אותו ומוצג משולש, סיימת.

כל הקודים

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