【DX12を学びたい】2D描画をスクリーン座標で描画できるようにしたい

座標変換の結果 DirextX

2Dテクスチャの対応が続きますが、今回は表示位置を分かりやすくしてみます。

今は-1~1のウィンドウ座標なので、0~ウィンドウサイズのスクリーン座標で表示の設定ができるように対応を行います。

そのために頂点シェーダーで行列の計算をするので、まずは定数(コンスタント)バッファーを作成します。

P1:定数バッファーの準備
  定数バッファーの作成
  定数バッファービューの作成
P2:表示クラスの修正
  スクリーン→ウィンドウ座標に変換して描画

スポンサーリンク

定数バッファーの準備

頂点シェーダーで定数バッファーを使用するための処理を追加していきます。

まずはルートシグネチャの設定からです。

 

ルートシグネチャの設定

ルートパラメーターに定数バッファーの設定を追加しましょう。

テクスチャーも必要なので、2つルートパラメーターを用意して、D3D12_ROOT_SIGNATURE_DESCのNumParametersも2に修正します。

サンプラーの設定は前回から変更なしです。

// ディスクリプタの範囲
D3D12_DESCRIPTOR_RANGE range[2] = {};
// シェーダーリソースビュー
range[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
// 数
range[0].NumDescriptors = 1;
// t0
range[0].BaseShaderRegister = 0;
// レジスタ領域
range[0].RegisterSpace = 0;
// 記述子テーブルの先頭からのオフセット
range[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;


// コンスタントバッファービュー
range[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
// 数
range[1].NumDescriptors = 1;
// b0
range[1].BaseShaderRegister = 0;
// レジスタ領域
range[1].RegisterSpace = 0;
// 記述子テーブルの先頭からのオフセット
range[1].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;

// ルートパラメーター
D3D12_ROOT_PARAMETER rootParameters[2] = {};
// パラメータのタイプ
rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
// 範囲の数
rootParameters[0].DescriptorTable.NumDescriptorRanges = 1;
// ディスクリプタの範囲
rootParameters[0].DescriptorTable.pDescriptorRanges = &range[0];
// アクセスできるシェーダー
rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;


// パラメータのタイプ
rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
// 範囲の数
rootParameters[1].DescriptorTable.NumDescriptorRanges = 1;
// ディスクリプタの範囲
rootParameters[1].DescriptorTable.pDescriptorRanges = &range[1];
// アクセスできるシェーダー
rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;

// サンプラーの設定
D3D12_STATIC_SAMPLER_DESC samplerDesc = {};
// サンプリングのフィルター
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
// uvwが範囲外のときの動作
samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
// ミップマップレベルのオフセット
samplerDesc.MipLODBias = 0;
// 指定のフィルターの場合に使うクランプ値
samplerDesc.MaxAnisotropy = 0;
// 比較オプション
samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
// D3D12_TEXTURE_ADDRESS_MODE_BORDERの場合に使用する色
samplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
// ミップマップの範囲
samplerDesc.MinLOD = 0.0f;
samplerDesc.MaxLOD = D3D12_FLOAT32_MAX;
// t0
samplerDesc.ShaderRegister = 0;
// レジスタ領域
samplerDesc.RegisterSpace = 0;
// サンプラーの可視性
samplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;

// ルートシグネチャの設定
D3D12_ROOT_SIGNATURE_DESC desc;
// ルートパラメーターをセット
desc.NumParameters = 2;
desc.pParameters = rootParameters;
// サンプラーをセット
desc.NumStaticSamplers = 1;
desc.pStaticSamplers = &samplerDesc;
// オプションの設定(入力アセンブラー)
desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;

この設定でルートシグネチャを作成すれば、頂点シェーダーで定数バッファーピクセルシェーダーでテクスチャーが使用できるようになります。

 

頂点シェーダーの修正

シェーダーに定数バッファーを追加しましょう。

cbuffer ~ register(b〇) に増やしたいデータを書きます。今回は行列だけです。

struct VSOutput
{
    float4 pos : SV_POSITION;
    float4 color : COLOR;
    float2 uv : TEXCOORD;
};

// 定数バッファー
cbuffer myMat : register(b0)
{
    matrix mat;
};

VSOutput VSMain( float4 pos : POSITION, float4 color : COLOR, float2 uv : TEXCOORD )
{
    VSOutput output;
    output.color = color;
    output.pos = mul(pos, mat);
    output.uv = uv;
	
    return output;
}

用意した行列はposと乗算させておきます。

行列は乗算の順番が違うと結果が異なるので注意です。

 

定数バッファーの作成

作成は頂点、インデックスバッファーとほぼほぼ同じですが、1つ違うポイントとして定数バッファーのサイズは256の倍数でないといけません。

UINT64 size = sizeof(XMMATRIX);

// 定数バッファーは256でアラインメントする
size = (size + 0xff) & ~0xff;

// ヒープのプロパティ
D3D12_HEAP_PROPERTIES prop;
// ヒープの種類
prop.Type = D3D12_HEAP_TYPE_UPLOAD;     // cpuは書き込み、gpuは読み取り
// CPUページプロパティ
prop.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; // プロパティ不明
// メモリプール
prop.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;  // プール不明
// マルチアダプター関連
prop.CreationNodeMask = 1;
prop.VisibleNodeMask = 1;

// リソースの設定
D3D12_RESOURCE_DESC desc;
// リソースのディメンション
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
// 配置の指定
desc.Alignment = 0;
// バッファーサイズ
desc.Width = size;
desc.Height = 1;
// リソース深さ
desc.DepthOrArraySize = 1;
// MIPレベル
desc.MipLevels = 1;
// リソースデータの形式
desc.Format = DXGI_FORMAT_UNKNOWN;  // バッファーはこれでいい
// マルチサンプリングの設定
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
// テクスチャのレイアウト
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;   // データを連続して配置する
// オプション
desc.Flags = D3D12_RESOURCE_FLAG_NONE;  // なし

// インデックスバッファーを作成
result = pDevice->CreateCommittedResource(
    &prop,
    D3D12_HEAP_FLAG_NONE,               // オプションなし
    &desc,
    D3D12_RESOURCE_STATE_GENERIC_READ,  // 読み取り状態
    nullptr,                            // クリアカラー
    IID_PPV_ARGS(pConstantBuffer)
);

 

定数バッファービューの作成

作成したバッファーを使って、CreateConstantBufferViewでバッファービューを作成します。

// CBVを作成
D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
cbvDesc.BufferLocation = m_pConstantBuffer->GetGPUVirtualAddress();
cbvDesc.SizeInBytes = static_cast<UINT>(m_pConstantBuffer->GetDesc().Width);
pDevice->CreateConstantBufferView(&cbvDesc, handle);

あとは定数バッファーをMapしてデータ更新すれば、頂点シェーダーで使用することができます。

 

次ページ:表示の対応です。

かれいど

ゲームをしたり、作ったり
色々な事に挑戦していきたい!

サッカー観戦も趣味で
主にJ1リーグを観ています。

かれいどをフォローする
DirextX
スポンサーリンク
シェアする

コメント