Hiển thị hộp bằng cách sử dụng bộ đệm chỉ mục
tóm tắt
Tôi sử dụng rất nhiều đa giác để tạo ra một hộp. Khi làm như vậy, một bộ đệm chỉ mục được sử dụng để giảm lượng dữ liệu trong dữ liệu đỉnh.
Môi trường hoạt động
Điều kiện tiên quyết
Các phiên bản XNA được hỗ trợ |
|
Nền tảng được hỗ trợ |
|
Phiên bản Vertex Shader bắt buộc của Windows | 2.0 |
Phiên bản Pixel Shader bắt buộc của Windows | 2.0 |
Môi trường hoạt động
nền tảng |
|
chất
Giới thiệu về hộp
Hộp bao gồm sáu mặt, một trong số đó bao gồm hai đa giác hình tam giác. Điều này có nghĩa là tổng số đa giác tam giác là "2×6 = 12". Hơn nữa, vì đa giác tam giác có ba đỉnh, tổng các đỉnh là "12×3 = 36". Do đó, khi chỉ tạo với "VertexBuffer", có thể hiển thị nó dưới dạng hộp nếu bạn quyết định thông tin vị trí sao cho 36 phần dữ liệu có hình hộp và ghi nó. (24 là bắt buộc cho TriangleStrip)
Nhưng hãy tưởng tượng một cái hộp. Các góc của hộp là 8 miếng. Tám là đủ cho thông tin vị trí. Khi số lượng dữ liệu đỉnh tăng lên, nó gây áp lực lên bộ nhớ. Để giảm điều này bằng cách nào đó, chúng tôi sử dụng "IndexBuffer".
Bạn chỉ cần 8 thông tin vị trí, nhưng bạn luôn cần 36 đỉnh cho một đa giác. Do đó, mục đích của việc sử dụng "IndexBuffer" là chia sẻ dữ liệu 8 đỉnh.
trường
<summary>
インデックスバッファ
</summary>
private IndexBuffer indexBuffer = null;
<summary>
インデックスバッファの各頂点番号配列
</summary>
private static readonly Int16[] vertexIndices = new Int16[] {
2, 0, 1, // 1枚目のポリゴン
1, 3, 2, // 2枚目のポリゴン
4, 0, 2, // 3枚目のポリゴン
2, 6, 4, // 4枚目のポリゴン
5, 1, 0, // 5枚目のポリゴン
0, 4, 5, // 6枚目のポリゴン
7, 3, 1, // 7枚目のポリゴン
1, 5, 7, // 8枚目のポリゴン
6, 2, 3, // 9枚目のポリゴン
3, 7, 6, // 10枚目のポリゴン
4, 6, 7, // 11枚目のポリゴン
7, 5, 4 // 12枚目のポリゴン
};
Trường được khai báo là "IndexBuffer", nhưng "mảng số đỉnh" được tạo trước bên dưới nó. Mảng này dự trữ một mảng cho 36 đỉnh, nhưng ý nghĩa của mỗi số là có bao nhiêu dữ liệu đỉnh của tám dữ liệu đỉnh mà mỗi đa giác tam giác sử dụng. Nếu bạn nhìn kỹ, bạn có thể thấy rằng dữ liệu bên trong được viết với một chỉ số giữa "0 ~ 7". Thật dễ dàng để xem trong các ý kiến.
Nhân tiện, loại mảng là "Int16 []", nhưng nó cũng có thể là "ngắn []" (2 byte). Trong một số trường hợp, một mảng được tạo bằng "int" (4 byte), nhưng điều này được sử dụng khi số đỉnh vượt quá "65535". Nếu số đỉnh không bao giờ vượt quá số này, hãy tạo một mảng dữ liệu 2 byte để giảm mức tiêu thụ bộ nhớ.
Sáng tạo
// 頂点の数
int vertexCount = 8;
// 頂点バッファ作成
this.vertexBuffer = new VertexBuffer(this.GraphicsDevice,
typeof(VertexPositionColor), vertexCount, BufferUsage.None);
// 頂点データを作成する
VertexPositionColor[] vertives = new VertexPositionColor[vertexCount];
vertives[0] = new VertexPositionColor(new Vector3(-2.0f, 2.0f, -2.0f), Color.Yellow);
vertives[1] = new VertexPositionColor(new Vector3(2.0f, 2.0f, -2.0f), Color.Gray);
vertives[2] = new VertexPositionColor(new Vector3(-2.0f, 2.0f, 2.0f), Color.Purple);
vertives[3] = new VertexPositionColor(new Vector3(2.0f, 2.0f, 2.0f), Color.Red);
vertives[4] = new VertexPositionColor(new Vector3(-2.0f, -2.0f, -2.0f), Color.SkyBlue);
vertives[5] = new VertexPositionColor(new Vector3(2.0f, -2.0f, -2.0f), Color.Orange);
vertives[6] = new VertexPositionColor(new Vector3(-2.0f, -2.0f, 2.0f), Color.Green);
vertives[7] = new VertexPositionColor(new Vector3(2.0f, -2.0f, 2.0f), Color.Blue);
// 頂点データを頂点バッファに書き込む
this.vertexBuffer.SetData(vertives);
Tạo bộ đệm đỉnh. Ban đầu, cần phải tạo 36 đỉnh, nhưng bằng cách sử dụng bộ đệm chỉ mục, bạn chỉ cần tạo 8 đỉnh.
// インデックスバッファを作成
this.indexBuffer = new IndexBuffer(this.GraphicsDevice,
IndexElementSize.SixteenBits, 3 * 12, BufferUsage.None);
// 頂点インデックスを書き込む
this.indexBuffer.SetData(vertexIndices);
Tạo bộ đệm chỉ mục. Đối số thứ hai chỉ định số bit của chỉ số đỉnh sẽ được viết. Vì một chỉ mục là 2 byte, hãy chỉ định "IndexElementSize.SixteenBits".
Đối số thứ ba là số lượng chỉ số. Trong trường hợp này, chúng ta sẽ vẽ 12 đa giác, vì vậy chỉ định 36, là số đỉnh × đa giác của đa giác tam giác. Tất nhiên, không có vấn đề gì nếu bạn chỉ định số lượng phần tử trong mảng chỉ mục như hiện tại, nhưng lần này các số được cố tình tách ra cho rõ ràng.
Vì chúng ta đã tạo một mảng các chỉ số đỉnh với các trường, chúng ta sẽ viết chúng bằng phương thức "IndexBuffer.SetData".
IndexBuffer
Constructor
Tạo một thể hiện của lớp IndexBuffer quản lý chỉ mục tham chiếu đến dữ liệu đỉnh.
đồ họaThiết bị | Đồ họaThiết bị | Chỉ định GraphicsDevice để liên kết với bộ đệm chỉ mục. |
indexElementSize | IndexElementSize | Kích thước của một chỉ số đỉnh duy nhất. Chỉ định "SixteenBits" cho 2 byte, "ThirtyTwoBits" cho 4 byte và chỉ định BufferUsage.None. |
indexCount | Int | Chỉ định số lượng chỉ mục. |
Sử dụng | Bộ đệmSử dụng | Sử dụng bộ đệm chỉ mục. Chỉ định BufferUsage.None trừ khi khác. |
IndexBuffer.SetData
phương pháp
Sao chép mảng các chỉ số đỉnh vào bộ đệm chỉ số.
T | Loại giá trị | Loại mảng chỉ số đỉnh |
dữ liệu | T | Mảng chỉ số đỉnh để sao chép |
Vẽ
// インデックスバッファをセット
this.GraphicsDevice.Indices = this.indexBuffer;
Nếu bạn muốn sử dụng bộ đệm chỉ mục, hãy đặt bộ đệm chỉ mục trên thiết bị trước khi vẽ đa giác.
// インデックスを使用してポリゴンを描画する
this.GraphicsDevice.DrawIndexedPrimitives(
PrimitiveType.TriangleList,
0,
0,
8,
0,
12
);
Nếu bạn đang sử dụng bộ đệm chỉ mục và đỉnh, hãy sử dụng phương thức "GraphicsDevice.DrawIndexedPrimitives" để vẽ đa giác.
Đối số thứ tư là số đỉnh được tạo. Trong mẫu, "8" được chỉ định vì dữ liệu 8 đỉnh được chia sẻ.
Đối số thứ sáu chỉ định số lượng nguyên thủy. Nó là "12" vì nó vẽ 12 đa giác hình tam giác.
Đối với các tham số số khác, 0 là tốt.
GraphicsDevice.DrawIndexedPrimitives
phương pháp
Vẽ một nguyên thủy dựa trên chỉ số đỉnh và bộ đệm đỉnh được chỉ định.
nguyên thủyLoại | PrimitiveType | Chỉ định nguyên thủy để vẽ. |
baseVertex | Int | Phần bù để thêm vào mỗi chỉ số đỉnh trong bộ đệm chỉ số. Ví dụ, khi chỉ số đỉnh đầu tiên trỏ đến dữ liệu đỉnh 2, nếu "1" được chỉ định trong đối số này, chỉ số đỉnh đầu tiên sẽ trỏ đến dữ liệu đỉnh 3. |
minVertexIndex | Int | Chỉ số đỉnh tối thiểu của đỉnh được sử dụng trong cuộc gọi. Ví dụ: minVertexIndex là 1 làm tăng chỉ số của dữ liệu đỉnh lên 1 (nó không làm tăng số lượng bộ đệm, do đó không thể chỉ định phần tử cuối cùng của dữ liệu đỉnh). Nếu chỉ số đỉnh trỏ đến dữ liệu đỉnh thứ hai, nó sẽ trỏ đến dữ liệu đỉnh thứ nhất. |
numVertices | Int | Số lượng dữ liệu đỉnh được sử dụng. |
startIndex | Int | Sự bù đắp bắt đầu của chỉ số đỉnh. Ví dụ: nếu bạn chỉ định TriangleList làm primitiveType, hãy chỉ định "3, 6, 9,..." để bỏ qua các đa giác bắt đầu vẽ. Nếu bạn chỉ định một giá trị khác với số được chia cho 3, mô hình sẽ thu gọn. (Vì tất cả các chỉ mục đều tắt) |
nguyên thủyBá tước | Int | Số lượng nguyên thủy để vẽ. Giá trị tối đa có thể được chỉ định là "Số chỉ số đỉnh÷ Số đỉnh của nguyên thủy - startIndex" |
Tất cả các mã
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 IndexBufferBox
{
<summary>
ゲームメインクラス
</summary>
public class GameMain : Microsoft.Xna.Framework.Game
{
<summary>
グラフィックデバイス管理クラス
</summary>
private GraphicsDeviceManager graphics = null;
<summary>
スプライトのバッチ化クラス
</summary>
private SpriteBatch spriteBatch = null;
<summary>
基本エフェクト
</summary>
private BasicEffect basicEffect = null;
<summary>
頂点バッファ
</summary>
private VertexBuffer vertexBuffer = null;
<summary>
インデックスバッファ
</summary>
private IndexBuffer indexBuffer = null;
<summary>
インデックスバッファの各頂点番号配列
</summary>
private static readonly Int16[] vertexIndices = new Int16[] {
2, 0, 1, // 1枚目のポリゴン
1, 3, 2, // 2枚目のポリゴン
4, 0, 2, // 3枚目のポリゴン
2, 6, 4, // 4枚目のポリゴン
5, 1, 0, // 5枚目のポリゴン
0, 4, 5, // 6枚目のポリゴン
7, 3, 1, // 7枚目のポリゴン
1, 5, 7, // 8枚目のポリゴン
6, 2, 3, // 9枚目のポリゴン
3, 7, 6, // 10枚目のポリゴン
4, 6, 7, // 11枚目のポリゴン
7, 5, 4 // 12枚目のポリゴン
};
<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;
// ビューマトリックスをあらかじめ設定 ((10, 10, 10) から原点を見る)
this.basicEffect.View = Matrix.CreateLookAt(
new Vector3(10.0f, 10.0f, 10.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
);
// 頂点の数
int vertexCount = 8;
// 頂点バッファ作成
this.vertexBuffer = new VertexBuffer(this.GraphicsDevice,
typeof(VertexPositionColor), vertexCount, BufferUsage.None);
// 頂点データを作成する
VertexPositionColor[] vertives = new VertexPositionColor[vertexCount];
vertives[0] = new VertexPositionColor(new Vector3(-2.0f, 2.0f, -2.0f), Color.Yellow);
vertives[1] = new VertexPositionColor(new Vector3(2.0f, 2.0f, -2.0f), Color.Gray);
vertives[2] = new VertexPositionColor(new Vector3(-2.0f, 2.0f, 2.0f), Color.Purple);
vertives[3] = new VertexPositionColor(new Vector3(2.0f, 2.0f, 2.0f), Color.Red);
vertives[4] = new VertexPositionColor(new Vector3(-2.0f, -2.0f, -2.0f), Color.SkyBlue);
vertives[5] = new VertexPositionColor(new Vector3(2.0f, -2.0f, -2.0f), Color.Orange);
vertives[6] = new VertexPositionColor(new Vector3(-2.0f, -2.0f, 2.0f), Color.Green);
vertives[7] = new VertexPositionColor(new Vector3(2.0f, -2.0f, 2.0f), Color.Blue);
// 頂点データを頂点バッファに書き込む
this.vertexBuffer.SetData(vertives);
// インデックスバッファを作成
this.indexBuffer = new IndexBuffer(this.GraphicsDevice,
IndexElementSize.SixteenBits, 3 * 12, BufferUsage.None);
// 頂点インデックスを書き込む
this.indexBuffer.SetData(vertexIndices);
}
<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);
// 描画に使用する頂点バッファをセット
this.GraphicsDevice.SetVertexBuffer(this.vertexBuffer);
// インデックスバッファをセット
this.GraphicsDevice.Indices = this.indexBuffer;
// パスの数だけ繰り替えし描画 (といっても BasicEffect は通常1回)
foreach (EffectPass pass in this.basicEffect.CurrentTechnique.Passes)
{
// パスの開始
pass.Apply();
// インデックスを使用してポリゴンを描画する
this.GraphicsDevice.DrawIndexedPrimitives(
PrimitiveType.TriangleList,
0,
0,
8,
0,
12
);
}
// 登録された DrawableGameComponent を描画する
base.Draw(gameTime);
}
}
}