はかせのラボ

私の頭の中を書いていく雑記ブログです

DirectX 色付きキューブ

今日は時間があったのと意外とサクサク進んだので
2個目の記事書いちゃいますw

前回、といってもついさっきなんですが三角形の表示ができました。
三角形さえ出してしまえればあとは何でも出せます。
コンピュータの世界では形あるものはポリゴンで表現されます。
そしてポリゴンは三角形です。あとはそれを積み上げるだけです。

あと真っ白でカメラが動かないとわかりにくかったので
色付けてカメラがゆっくり回るようにしました。
ということでいつもより結構ボリューム多めです。

まず最初はいつも通り頂点情報を弄ります。
ですが今回は色も付けたいので少しいつもとは違います。

//頂点情報の構造体
struct VERTEX
{
        XMFLOAT3 V;
	XMFLOAT4 C;
}

//入力レイアウト
D3D11_INPUT_ELEMENT_DESC layout[] = 
{
	{
		"POSITION",
		0,
		DXGI_FORMAT_R32G32B32_FLOAT,
		0,
		0,
		D3D11_INPUT_PER_VERTEX_DATA,
		0
	},
	{
		"COLOR",
		0,
		DXGI_FORMAT_R32G32B32A32_FLOAT,
		0,
		12,
		D3D11_INPUT_PER_VERTEX_DATA,
		0
	}
};

//頂点データとバッファ生成
VERTEX vertex[] = 
{
	{ XMFLOAT3(-0.5f, -0.5f, 0.5f),  XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f) },
	{ XMFLOAT3(0.5f, -0.5f, 0.5f),   XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f) },
	{ XMFLOAT3(0.5f, -0.5f, -0.5f),  XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
	{ XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
	{ XMFLOAT3(-0.5f, 0.5f, 0.5f),   XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f) },
	{ XMFLOAT3(0.5f, 0.5f, 0.5f),    XMFLOAT4(1.0f, 0.0f, 1.0f, 1.0f) },
	{ XMFLOAT3(0.5f, 0.5f, -0.5f),   XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f) },
	{ XMFLOAT3(-0.5f, 0.5f, -0.5f),  XMFLOAT4(0.0f, 1.0f, 1.0f, 1.0f) },
};

いつもお世話になっていた頂点情報用の構造体に
色情報を付加しました。

また画面に入力される情報量が変わるので入力レイアウトも
変更しました。

COLOR情報を設定しているところに12という数字があります。
これはCOLOR情報が先頭から何バイト目にいるか示す数字らしいです。
ちゃんと設定しないとうまく情報を拾えず表示できません。
(私がそうなりましたw)

そして座標+色情報の組み合わせで頂点情報を追加しました。

次にポリゴンの頂点インデックスを設定します。
コンピュータの世界ではあらゆるものは三角形の組み合わせで表現されます。
ですが何も考えず三角形を作って組み合わせると点や辺が重複してしまい、
一つ頂点を動かすにしても隣接する三角形全てに影響が出てしまいます。

そこで三角形を貼って頂点を作るのではなく頂点を置いてからそこに合わせて
三角形を貼ることでその影響をなくすことができます。

そのために頂点インデックスがあるらしいです。
(なんとなくのふわっとした認識なので間違ってるかもしれませんw)

というわけで設定します。
といってもやることは頂点情報を弄った時と大差ありませんw

//ポリゴンのインデックス情報
int index[] =
{
	0, 2, 1,
	0, 3, 2,
	0, 5, 4,
	0, 1, 5,
	1, 6, 5,
	1, 2, 6,
	2, 7, 6,
	2, 3, 7,
	0, 4, 7,
	0, 7, 3,
	4, 5, 7,
	5, 6, 7,
};
mDrawNum = sizeof(index) / sizeof(index[0]);
D3D11_BUFFER_DESC bd_index;
bd_index.ByteWidth = sizeof(int) * mDrawNum;
bd_index.Usage = D3D11_USAGE_DEFAULT;
bd_index.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd_index.CPUAccessFlags = 0;
bd_index.MiscFlags = 0;
bd_index.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA data_index;
data_index.pSysMem = index;
mDevice->CreateBuffer(&bd_index, &data_index, &mIndexBuffer);

見ての通りほぼ変わりません。
変わったといえばBindFlagsぐらいでしょうか。

そしてまた解釈を変えます。
前回使った「~STRIP」系の解釈は
渡された情報を一筆書きのように描画するそうで
今回作るような立体だと
面の一部が内側にめり込んだような形になってしまいます。

なので単純に三角形のリストとして渡してあげます。

mDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

あとはカメラと色がついたので多少変更したシェーダですね。
長くなりすぎた気がするのでサクッと済ませますw

カメラ

float y = 0.0f;
XMMATRIX world = XMMatrixRotationY(y);
y += 0.001f;

XMMatrixRotationY()はY軸でカメラを回します。
あとは引数に渡す情報を毎フレーム足してあげればゆっくり回せます。

次にシェーダです。

cbuffer global
{
	matrix gWVP;
};

struct VS_OUTPUT
{
    float4 pos : SV_POSITION;
    float4 color : COLOR;
};

VS_OUTPUT VS(float4 pos:POSITION,float4 color:COLOR)
{
    VS_OUTPUT output;
    output.pos = mul(pos, gWVP);
    output.color = color;
    return output;
};

float4 PS(VS_OUTPUT input) : SV_Target
{
    return input.color;
};

貰う情報、渡す情報が増えたので一つにまとめる構造体を作って
それで受け渡しをしています。
また同じ型なのでセマンティクスを使って識別しています。
今回はタイポはしませんでしたw

それでは実行です。
f:id:hakase0274:20180925212830p:plain

静止画なのでわかりませんがちゃんと回ってます。

ふぅ・・思った以上に長い記事になってしまいました。
今回は頂点情報やらインデックスやらを手動で設定しましたが
多分実際の開発だとその辺がすでに入っているファイルから
読みだして使うんだと思います。
(fbxとか)

とりあえず今回でいろんなものを表現するための
基本中の基本は実戦出来たと思います。
さて、次は何をしましょうかね・・

今回作ったものはgithubに上げました。
https://github.com/hakase0724/DirectX/commits/PolygonTest