Отображение треугольных полигонов
сводка
Он отображает треугольные многоугольники в 3D-пространстве.
Операционная среда
Необходимые условия
Поддерживаемые версии XNA |
|
Поддерживаемые платформы |
|
Windows Требуемая версия вершинного шейдера | 2.0 |
Требуемая версия пиксельного шейдера Windows | 2.0 |
Операционная среда
платформа |
|
вещество
Что такое полигон?
Многоугольник – это грань, созданная путем определения нескольких вершин. В общем случае многоугольник — это треугольная грань, состоящая из трех вершин. А тригон – это самая маленькая единица многоугольника. Некоторые программы моделирования могут отображать многоугольники как четырехугольные или многоугольные, но в конечном итоге они будут разложены на треугольные многоугольники.
Модель, отображаемая в играх, формируется путем объединения нескольких этих треугольных многоугольников.
Многоугольники формируются вершинами. Вершины могут содержать такие данные, как положение и цвет. Этот образец также сделан из данных "position" и "color".
Цвет лица в этом примере аккуратно интерполирован по цвету и расстоянию, установленным для каждой вершины, но вы можете свободно изменить его с помощью собственной шейдерной программы (подробнее о шейдерных программах в другой раз).
Определения данных вершин
Для отображения многоугольника требуются «данные вершин», и программист должен решить, какие элементы включить в эту вершину. При рисовании многоугольника вы должны сообщить устройству, которое является механизмом рисования, с помощью каких данных вершин рисовать многоугольник. Для этого создадим класс "VertexDeclaration" и установим "Vertex Data Definition".
Однако, начиная с XNA Game Studio 4.0, эта настройка была упрощена, и вам не нужно готовить класс VertexDeclaration для этого совета. (Это связано с тем, что информация об определении уже встроена в данные вершин, предоставленные платформой.)
Данные вершин
Я писал, что данные вершин необходимы для рисования полигонов, но сначала мы должны решить, какие данные мы хотим иметь. В этом случае мы будем использовать данные "position" и "color". После того, как вы решили, какие данные вы хотите иметь, вам нужно создать структуру для хранения этих данных. У вас есть некоторая свобода в выборе данных вершин, но обычно используемые данные вершин уже определены в XNA Framework, поэтому в примере они используются.
Данные вершин с "position" и "color" определяются как структура "VertexPositionColor". Так как для формирования многоугольника необходимо несколько вершин, мы объявляем его в виде массива.
<summary>
頂点データリスト
</summary>
private VertexPositionColor[] vertices = null;
эффект
В XNA, когда вы рисуете полигон, вам приходится писать отдельную программу-шейдер, чтобы решить, как его рисовать. Для этого создайте отдельный файл эффектов, напишите программу, загрузите ее в виде класса эффектов и запустите программу-шейдер.
Однако, если вам не нужно рисовать простые треугольные многоугольники, как этот, или сложные эффекты рисования, это может быть очень трудоемкой задачей.
По этой причине XNA определяет расширенные эффекты, которые позволяют задавать необходимые элементы в качестве свойств, чтобы вам не приходилось писать программу-шейдер для базового рисования. Это класс "BasicEffect". Так как целью данной статьи является рисование полигонов, мы будем использовать "BasicEffect", который не требует больших усилий для рисования.
<summary>
基本エフェクト
</summary>
private BasicEffect basicEffect = null;
Подробнее об эффектах и BasicEffects я расскажу в другой раз.
Кстати, 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 для создания эффекта |
Матрица представления и матрица проекции
Задайте для параметра 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
метод
Создание матрицы представлений.
cameraPosition | Вектор3 | Положение камеры |
камераМишень | Вектор3 | Точка обзора камеры |
камераUpVector | Вектор3 | Направление камеры вверх |
Чтобы создать матрицу проекции, используйте метод "Matrix.CreatePerspectiveFieldOfView".
Первый аргумент – угол обзора в радианах. В выборке единица измерения степени преобразуется в радиан с помощью метода "MathHelper.ToRadians". Для получения дополнительной информации о Radian и Degree см. Radian и Degree.
Второй аргумент задает соотношение сторон (aspect ratio). Как правило, указывается значение для параметров View Width ÷ Height. В примере он рассчитывается на основе ширины и высоты, заданных для видового окна устройства.
Третий аргумент указывает позицию отсечения вперед, а четвертый аргумент указывает позицию отсечения назад.
Matrix.CreatePerspectiveFieldOfView
метод
Создает матрицу перспективной проекции на основе настроек поля вида.
fieldOfView | плавать | Угол обзора. Указывается в радианских единицах. |
aspectRatio | плавать | Aspect ratio (соотношение сторон). Обычно вы указываете значение для "View Width ÷ Height" |
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);
Существует два типа эффектов, называемых «техниками» и «контурами», с помощью которых вы запускаете саму программу рисования. Поскольку в одном эффекте может быть несколько путей, я стараюсь вызывать их несколько раз в foreach. Тем не менее, в BasicEffect есть один метод и один контур, поэтому вы можете указать индекс пути напрямую, но вышеприведенное описание будет чище, потому что вы можете заменить его для других эффектов.
Перед началом фактического рисования вызовите метод "EffectPass.Apply", чтобы начать проход. При вызове этого метода параметры эффекта, который будет использоваться на этот раз, применяются к графическому устройству.
Начав путь, нарисуйте многоугольник с помощью метода "GraphicsDevice.DrawUserPrimitives".
Первый аргумент указывает тип отрисовываемого примитива. В данном случае мы будем рисовать треугольный многоугольник, поэтому указываем "PrimitiveType.TriangleList".
Второй аргумент указывает на созданные данные вершины.
Третий аргумент указывает вершину, от которой нужно рисовать. Обычно это 0.
Четвертый аргумент указывает количество примитивов для рисования. В данном случае существует только один треугольный многоугольник, поэтому укажите 1. Обратите внимание, что это не количество вершин.
GraphicsDevice.DrawUserPrimitives
метод
Отрисовывает примитивы на основе предоставленных пользователем данных вершин.
T | Без ограничений | Структуры данных вершин |
primitiveType | Тип примитива | Тип примитива для рисования |
vertexData | T[] | Массив данных вершин для рисования |
vertexOffset | int | Указание количества данных вершин, которые будут использоваться для рисования |
примитивныйCount | 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);
}
}
}