図0011a
void CubeObject::CreateBuffers() {
float HelfSize = 0.5f;
vector<Vec3> PosVec = {
{ Vec3(-HelfSize, HelfSize, -HelfSize) },
{ Vec3(HelfSize, HelfSize, -HelfSize) },
{ Vec3(-HelfSize, -HelfSize, -HelfSize) },
{ Vec3(HelfSize, -HelfSize, -HelfSize) },
{ Vec3(HelfSize, HelfSize, HelfSize) },
{ Vec3(-HelfSize, HelfSize, HelfSize) },
{ Vec3(HelfSize, -HelfSize, HelfSize) },
{ Vec3(-HelfSize, -HelfSize, HelfSize) },
};
vector<UINT> PosIndeces = {
0, 1, 2, 3,
1, 4, 3, 6,
4, 5, 6, 7,
5, 0, 7, 2,
5, 4, 0, 1,
2, 3, 7, 6,
};
vector<Vec3> FaceNormalVec = {
{ Vec3(0, 0, -1.0f) },
{ Vec3(1.0f, 0, 0) },
{ Vec3(0, 0, 1.0f) },
{ Vec3(-1.0f, 0, 0) },
{ Vec3(0, 1.0f, 0) },
{ Vec3(0, -1.0f, 0) }
};
vector<VertexPositionNormalTexture> vertices;
vector<uint16_t> indices;
UINT BasePosCount = 0;
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 4; j++) {
VertexPositionNormalTexture Data;
Data.position = PosVec[PosIndeces[BasePosCount + j]];
if (m_Flat) {
//フラット表示の場合は法線は頂点方向にする
Data.normal = Data.position;
Data.normal.normalize();
}
else {
//フラット表示しない場合は、法線は面の向き
Data.normal = FaceNormalVec[i];
}
switch (j) {
case 0:
Data.textureCoordinate = Vec2(0, 0);
break;
case 1:
Data.textureCoordinate = Vec2(1.0f, 0);
break;
case 2:
Data.textureCoordinate = Vec2(0, 1.0f);
break;
case 3:
Data.textureCoordinate = Vec2(1.0f, 1.0f);
break;
}
vertices.push_back(Data);
}
indices.push_back((uint16_t)BasePosCount + 0);
indices.push_back((uint16_t)BasePosCount + 1);
indices.push_back((uint16_t)BasePosCount + 2);
indices.push_back((uint16_t)BasePosCount + 1);
indices.push_back((uint16_t)BasePosCount + 3);
indices.push_back((uint16_t)BasePosCount + 2);
BasePosCount += 4;
}
//メッシュの作成(変更できない)
m_CubeMesh = MeshResource::CreateMeshResource(vertices, indices, false);
}
void CubeObject::CreateRootSignature() {
auto Dev = App::GetApp()->GetDeviceResources();
//もしすでに登録されていたらそれを使用
m_RootSignature = Dev->GetRootSignature(L"SrvSmpCbv");
if (m_RootSignature != nullptr) {
return;
}
//デスクプリタレンジは3個
CD3DX12_DESCRIPTOR_RANGE ranges[3];
//0番目はシェーダリソースビュー
ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);
//1番目はサンプラー
ranges[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1, 0);
//2番目はコンスタントバッファ
ranges[2].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0);
//ルートパラメータも3個
CD3DX12_ROOT_PARAMETER rootParameters[3];
//0番目はシェーダリソースビューのレンジをピクセルシェーダへ
rootParameters[0].InitAsDescriptorTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_PIXEL);
//1番目はサンプラーのレンジをピクセルシェーダへ
rootParameters[1].InitAsDescriptorTable(1, &ranges[1], D3D12_SHADER_VISIBILITY_PIXEL);
//2番目はコンスタントバッファのレンジをすべてにシェーダに
rootParameters[2].InitAsDescriptorTable(1, &ranges[2], D3D12_SHADER_VISIBILITY_ALL);
//ルートシグネチャの定義
CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc;
//ルートシグネチャ定義の初期化(ルートパラメータを設定)
rootSignatureDesc.Init(_countof(rootParameters), rootParameters, 0, nullptr,
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
//各ブロブ(バイナリイメージ)
ComPtr<ID3DBlob> signature;
ComPtr<ID3DBlob> error;
//ルートシグネチャ定義のシリアライズ
ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1,
&signature, &error),
L"ルートシグネチャのシリアライズに失敗しました",
L"D3D12SerializeRootSignature()",
L"CubeObject::CreateRootSignature()"
);
//ルートシグネチャの作成
ThrowIfFailed(
Dev->GetDevice()->CreateRootSignature(0, signature->GetBufferPointer(),
signature->GetBufferSize(), IID_PPV_ARGS(&m_RootSignature)),
L"ルートシグネチャの作成に失敗しました",
L"Dev->GetDevice()->CreateRootSignature()",
L"CubeObject::CreateRootSignature()"
);
//ルートシグネチャの登録(Dx12には関係ない)
Dev->SetRootSignature(L"SrvSmpCbv", m_RootSignature);
}
void CubeObject::CreateDescriptorHeap() {
auto Dev = App::GetApp()->GetDeviceResources();
m_CbvSrvDescriptorHandleIncrementSize =
Dev->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
//コンスタントバッファとシェーダーリソース用デスクプリタヒープ(合計2個)
D3D12_DESCRIPTOR_HEAP_DESC CbvSrvHeapDesc = {};
CbvSrvHeapDesc.NumDescriptors = 2;
CbvSrvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
CbvSrvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
ThrowIfFailed(Dev->GetDevice()->CreateDescriptorHeap(&CbvSrvHeapDesc,
IID_PPV_ARGS(&m_CbvSrvUavDescriptorHeap)),
L"CbvSrvUav用のデスクプリタヒープの作成に失敗しました",
L"Dev->GetDevice()->CreateDescriptorHeap()",
L"CubeObject::CreateDescriptorHeap()"
);
//サンプラーデスクプリタヒープ(1個)
D3D12_DESCRIPTOR_HEAP_DESC SamplerHeapDesc = {};
SamplerHeapDesc.NumDescriptors = 1;
SamplerHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
SamplerHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
ThrowIfFailed(Dev->GetDevice()->CreateDescriptorHeap(&SamplerHeapDesc,
IID_PPV_ARGS(&m_SamplerDescriptorHeap)),
L"サンプラー用のデスクプリタヒープの作成に失敗しました",
L"Dev->GetDevice()->CreateDescriptorHeap()",
L"CubeObject::CreateDescriptorHeap()"
);
//GPU側デスクプリタヒープのハンドルの配列の作成
m_GPUDescriptorHandleVec.clear();
CD3DX12_GPU_DESCRIPTOR_HANDLE SrvHandle(
m_CbvSrvUavDescriptorHeap->GetGPUDescriptorHandleForHeapStart(),
0,
0
);
m_GPUDescriptorHandleVec.push_back(SrvHandle);
CD3DX12_GPU_DESCRIPTOR_HANDLE SamplerHandle(
m_SamplerDescriptorHeap->GetGPUDescriptorHandleForHeapStart(),
0,
0
);
m_GPUDescriptorHandleVec.push_back(SamplerHandle);
CD3DX12_GPU_DESCRIPTOR_HANDLE CbvHandle(
m_CbvSrvUavDescriptorHeap->GetGPUDescriptorHandleForHeapStart(),
1,
m_CbvSrvDescriptorHandleIncrementSize
);
m_GPUDescriptorHandleVec.push_back(CbvHandle);
}
void CubeObject::CreateSampler() {
//サンプラーデスクプリタヒープ内のCPU側ハンドルを得る
auto SamplerDescriptorHandle
= m_SamplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
//サンプラー定義
D3D12_SAMPLER_DESC samplerDesc = {};
//リニアクランプに設定
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D12_FLOAT32_MAX;
samplerDesc.MipLODBias = 0.0f;
samplerDesc.MaxAnisotropy = 1;
samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
auto Dev = App::GetApp()->GetDeviceResources();
//ハンドルとサンプラー定義を結びつける
Dev->GetDevice()->CreateSampler(&samplerDesc, SamplerDescriptorHandle);
}
void CubeObject::CreateShaderResourceView() {
auto Dev = App::GetApp()->GetDeviceResources();
//テクスチャハンドルを取得
CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle(
m_CbvSrvUavDescriptorHeap->GetCPUDescriptorHandleForHeapStart(),
0,
0
);
//テクスチャのシェーダリソースビューを作成
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
//フォーマット(テクスチャリソースから取得)
srvDesc.Format = m_TextureResource->GetTextureResDesc().Format;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = m_TextureResource->GetTextureResDesc().MipLevels;
//シェーダリソースビューの作成
Dev->GetDevice()->CreateShaderResourceView(
m_TextureResource->GetTexture().Get(),
&srvDesc,
srvHandle);
}
void CubeObject::CreateConstantBuffer() {
auto Dev = App::GetApp()->GetDeviceResources();
//コンスタントバッファは256バイトにアラインメント
UINT ConstBuffSize = (sizeof(StaticConstantBuffer) + 255) & ~255;
//コンスタントバッファリソース(アップロードヒープ)の作成
ThrowIfFailed(Dev->GetDevice()->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(ConstBuffSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_ConstantBufferUploadHeap)),
L"コンスタントバッファ用のアップロードヒープ作成に失敗しました",
L"Dev->GetDevice()->CreateCommittedResource()",
L"CubeObject::CreateConstantBuffer()"
);
//コンスタントバッファのビューを作成
D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
cbvDesc.BufferLocation = m_ConstantBufferUploadHeap->GetGPUVirtualAddress();
cbvDesc.SizeInBytes = ConstBuffSize;
//コンスタントバッファビューを作成すべきデスクプリタヒープ上のハンドルを取得
//コンスタントバッファはシェーダリソースビューのあとに設置する
//シェーダーリソースは1個で、先頭からインクリメントサイズだけ
//離れた場所がコンスタントバッファのハンドルの場所である
CD3DX12_CPU_DESCRIPTOR_HANDLE cbvHandle(
m_CbvSrvUavDescriptorHeap->GetCPUDescriptorHandleForHeapStart(),
1,
m_CbvSrvDescriptorHandleIncrementSize
);
Dev->GetDevice()->CreateConstantBufferView(&cbvDesc, cbvHandle);
//コンスタントバッファのアップロードヒープのマップ
CD3DX12_RANGE readRange(0, 0);
ThrowIfFailed(m_ConstantBufferUploadHeap->Map(0, &readRange,
reinterpret_cast<void**>(&m_pConstantBuffer)),
L"コンスタントバッファのマップに失敗しました",
L"pImpl->m_ConstantBufferUploadHeap->Map()",
L"CubeObject::CreateConstantBuffer()"
);
}
void CubeObject::CreatePipelineState() {
//ラスタライザステートの作成(デフォルト)
CD3DX12_RASTERIZER_DESC rasterizerStateDesc(D3D12_DEFAULT);
//裏面カリングに変更
rasterizerStateDesc.CullMode = D3D12_CULL_MODE_BACK;
//パイプラインステートの作成
D3D12_GRAPHICS_PIPELINE_STATE_DESC PineLineDesc;
ZeroMemory(&PineLineDesc, sizeof(PineLineDesc));
PineLineDesc.InputLayout = { VertexPositionNormalTexture::GetVertexElement(),
VertexPositionNormalTexture::GetNumElements() };
PineLineDesc.pRootSignature = m_RootSignature.Get();
PineLineDesc.VS =
{
reinterpret_cast<UINT8*>(VSPNTStatic::GetPtr()->GetShaderComPtr()->GetBufferPointer()),
VSPNTStatic::GetPtr()->GetShaderComPtr()->GetBufferSize()
};
PineLineDesc.PS =
{
reinterpret_cast<UINT8*>(PSPNTStatic::GetPtr()->GetShaderComPtr()->GetBufferPointer()),
PSPNTStatic::GetPtr()->GetShaderComPtr()->GetBufferSize()
};
PineLineDesc.RasterizerState = rasterizerStateDesc;
PineLineDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
PineLineDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
PineLineDesc.SampleMask = UINT_MAX;
PineLineDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
PineLineDesc.NumRenderTargets = 1;
PineLineDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
PineLineDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT;
PineLineDesc.SampleDesc.Count = 1;
//もし透明ならブレンドステート差し替え
if (m_Trace) {
D3D12_BLEND_DESC blend_desc;
D3D12_RENDER_TARGET_BLEND_DESC Target;
ZeroMemory(&blend_desc, sizeof(blend_desc));
blend_desc.AlphaToCoverageEnable = false;
blend_desc.IndependentBlendEnable = false;
ZeroMemory(&Target, sizeof(Target));
Target.BlendEnable = true;
Target.SrcBlend = D3D12_BLEND_SRC_ALPHA;
Target.DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
Target.BlendOp = D3D12_BLEND_OP_ADD;
Target.SrcBlendAlpha = D3D12_BLEND_ONE;
Target.DestBlendAlpha = D3D12_BLEND_ZERO;
Target.BlendOpAlpha = D3D12_BLEND_OP_ADD;
Target.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) {
blend_desc.RenderTarget[i] = Target;
}
PineLineDesc.BlendState = blend_desc;
}
auto Dev = App::GetApp()->GetDeviceResources();
//まずCullBackのパイプラインステートを作成
ThrowIfFailed(Dev->GetDevice()->CreateGraphicsPipelineState(&PineLineDesc,
IID_PPV_ARGS(&m_CullBackPipelineState)),
L"CullBackパイプラインステートの作成に失敗しました",
L"Dev->GetDevice()->CreateGraphicsPipelineState()",
L"CubeObject::CreatePipelineState()"
);
PineLineDesc.RasterizerState.CullMode = D3D12_CULL_MODE::D3D12_CULL_MODE_FRONT;
//続いてCullFrontのパイプラインステートを作成
ThrowIfFailed(Dev->GetDevice()->CreateGraphicsPipelineState(&PineLineDesc,
IID_PPV_ARGS(&m_CullFrontPipelineState)),
L"CullFrontパイプラインステートの作成に失敗しました",
L"Dev->GetDevice()->CreateGraphicsPipelineState()",
L"CubeObject::CreatePipelineState()"
);
}
void CubeObject::CreateCommandList() {
auto Dev = App::GetApp()->GetDeviceResources();
//コマンドリストは裏面カリングに初期化
ThrowIfFailed(Dev->GetDevice()->CreateCommandList(
0,
D3D12_COMMAND_LIST_TYPE_DIRECT,
Dev->GetCommandAllocator().Get(),
m_CullBackPipelineState.Get(),
IID_PPV_ARGS(&m_CommandList)),
L"コマンドリストの作成に失敗しました",
L"Dev->GetDevice()->CreateCommandList()",
L"CubeObject::CreateCommandList()"
);
ThrowIfFailed(m_CommandList->Close(),
L"コマンドリストのクローズに失敗しました",
L"commandList->Close()",
L"CubeObject::CreateCommandList()"
);
}
void CubeObject::UpdateConstantBuffer() {
//行列の定義
Mat4x4 World, View, Proj;
//ワールド行列の決定
World.affineTransformation(
m_Scale, //スケーリング
Vec3(0, 0, 0), //回転の中心(重心)
m_Qt, //回転角度
m_Pos //位置
);
//転置する
World.transpose();
//ビュー行列の決定
View = XMMatrixLookAtLH(Vec3(0, 2.0, -5.0f), Vec3(0, 0, 0), Vec3(0, 1.0f, 0));
//転置する
View.transpose();
//射影行列の決定
float w = static_cast<float>(App::GetApp()->GetGameWidth());
float h = static_cast<float>(App::GetApp()->GetGameHeight());
Proj = XMMatrixPerspectiveFovLH(XM_PIDIV4, w / h, 1.0f, 100.0f);
//転置する
Proj.transpose();
//ライティング
Vec4 LightDir(0.5f, -1.0f, 0.5f, 0.0f);
LightDir.normalize();
m_StaticConstantBuffer.World = World;
m_StaticConstantBuffer.View = View;
m_StaticConstantBuffer.Projection = Proj;
m_StaticConstantBuffer.LightDir = LightDir;
m_StaticConstantBuffer.Diffuse = Col4(1.0f, 1.0f, 1.0f, 1.0f);
m_StaticConstantBuffer.Emissive = Col4(0.4f, 0.4f, 0.4f, 0);
//更新
memcpy(m_pConstantBuffer, reinterpret_cast<void**>(&m_StaticConstantBuffer),
sizeof(m_StaticConstantBuffer));
}
void CubeObject::DrawObject(){
auto Dev = App::GetApp()->GetDeviceResources();
//コマンドリストのリセット
if (m_Trace) {
ThrowIfFailed(m_CommandList->Reset(Dev->GetCommandAllocator().Get(),
m_CullFrontPipelineState.Get()),
L"コマンドリストのリセットに失敗しました",
L"m_CommandList->Reset(Dev->GetCommandAllocator().Get(),pipelineState.Get())",
L"CubeObject::OnDraw()"
);
}
else {
ThrowIfFailed(m_CommandList->Reset(Dev->GetCommandAllocator().Get(),
m_CullBackPipelineState.Get()),
L"コマンドリストのリセットに失敗しました",
L"m_CommandList->Reset(Dev->GetCommandAllocator().Get(),pipelineState.Get())",
L"CubeObject::OnDraw()"
);
}
//メッシュが更新されていればリソース更新
m_CubeMesh->UpdateResources<VertexPositionNormalTexture>(m_CommandList);
//テクスチャが更新されていればリソース更新
m_TextureResource->UpdateResources(m_CommandList);
//ルートシグネチャのセット
m_CommandList->SetGraphicsRootSignature(m_RootSignature.Get());
ID3D12DescriptorHeap* ppHeaps[] =
{ m_CbvSrvUavDescriptorHeap.Get(), m_SamplerDescriptorHeap.Get() };
//デスクプリタヒープのセット
m_CommandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
//GPU側デスクプリタハンドルのセット
for (size_t i = 0; i < m_GPUDescriptorHandleVec.size(); i++) {
m_CommandList->SetGraphicsRootDescriptorTable(i, m_GPUDescriptorHandleVec[i]);
}
//ビューポートのセット
m_CommandList->RSSetViewports(1, &Dev->GetViewport());
//シザーレクトのセット
m_CommandList->RSSetScissorRects(1, &Dev->GetScissorRect());
//レンダーターゲットビューのハンドルを取得
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle = Dev->GetRtvHandle();
//デプスステンシルビューのハンドルを取得
CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle = Dev->GetDsvHandle();
//取得したハンドルをセット
m_CommandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle);
//描画方式(三角形リスト)をセット
m_CommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
//頂点バッファをセット
m_CommandList->IASetVertexBuffers(0, 1, &m_CubeMesh->GetVertexBufferView());
//インデックスバッファをセット
m_CommandList->IASetIndexBuffer(&m_CubeMesh->GetIndexBufferView());
//描画
m_CommandList->DrawIndexedInstanced(m_CubeMesh->GetNumIndicis(), 1, 0, 0, 0);
if (m_Trace) {
//透明の場合は、CullBackに変更して2回目描画
m_CommandList->SetPipelineState(m_CullBackPipelineState.Get());
m_CommandList->DrawIndexedInstanced(m_CubeMesh->GetNumIndicis(), 1, 0, 0, 0);
}
//コマンドリストのクローズ
ThrowIfFailed(m_CommandList->Close(),
L"コマンドリストのクローズに失敗しました",
L"m_CommandList->Close()",
L"CubeObject::OnDraw()"
);
//デバイスにコマンドリストを送る
Dev->InsertDrawCommandLists(m_CommandList.Get());
}