DirectX12 ⑧ ポリゴンの描画
ポリゴンの描画
環境
言語 : C++
開発環境 : Visual Studio 2020
OS : Windows10
CPU : AMD Ryzen5 3600
RAM : 24.0GB
GPU : NVIDIA GeForce GTX 1050
ソースコード
Scene.h
#pragma once #include <d3d12.h> #include <dxgiformat.h> #include <DirectXMath.h> #include <wrl/client.h> #include <cstdint> #include <iostream> #include <vector> #include "Dx.h" #include "DxStruct.h" #include "VertexBuffer.h" #include "IndexBuffer.h" #include "ConstantBuffer.h" #include "RootSignature.h" #include "PipelineState.h" #pragma comment(lib, "d3d12.lib") using namespace Microsoft::WRL; class Scene { public: Scene(); bool Init(); void Draw(); private: VertexBuffer _vertexBuffer; IndexBuffer _indexBuffer; ConstantBuffer _constantBuffer[FRAME_BUFFER_COUNT]; RootSignature _rootSignature; PipelineState _pipelineState; }; extern Scene* scene;
Scene.cpp
#include "Scene.h" Scene* scene; Scene::Scene() { } bool Scene::Init() { //三角形の頂点を定義 Vertex vertices[3] = {}; vertices[0].Position = DirectX::XMFLOAT3(-1.0f, -1.0f, 0.0f); vertices[0].Color = DirectX::XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f); vertices[1].Position = DirectX::XMFLOAT3(1.0f, -1.0f, 0.0f); vertices[1].Color = DirectX::XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f); vertices[2].Position = DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f); vertices[2].Color = DirectX::XMFLOAT4(1.0f, 0.0f, 0.0f, 0.5f); //インデックスの定義 uint32_t indices[3] = {0, 1, 2}; //頂点バッファの作成とインデックスバッファの作成 _vertexBuffer.CreateVertexBuffer(sizeof(vertices), sizeof(Vertex), vertices); _indexBuffer.CreateIndexBuffer(sizeof(indices), indices); //視点変換行列 DirectX::XMVECTOR eyePos = DirectX::XMVectorSet(0.0f, 0.0f, 5.0f, 0.0f); //視点の位置 DirectX::XMVECTOR targetPos = DirectX::XMVectorZero(); //視点を向ける座標 DirectX::XMVECTOR upward = DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); //上方向を表すベクトル constexpr float fovY = DirectX::XMConvertToRadians(37.5f); float aspect = static_cast<float>(dx->GetWindowWidth()) / static_cast<float>(dx->GetWindowHeight()); //座標変換に使う定数バッファの作成 for (size_t i = 0; i < FRAME_BUFFER_COUNT; i++) { if (!_constantBuffer[i].CreateConstantBuffer(sizeof(Transform))) { return false; } auto ptr = _constantBuffer[i].GetPtr<Transform>(); ptr->World = DirectX::XMMatrixIdentity(); //ワールド座標変換 ptr->View = DirectX::XMMatrixLookAtRH(eyePos, targetPos, upward); //カメラ(視点)座標変換 ptr->Proj = DirectX::XMMatrixPerspectiveFovRH(fovY, aspect, 0.3f, 1000.0f); //投影変換 } //ルートパラメタの設定 const uint32_t rootPramNum = 1; D3D12_ROOT_PARAMETER rootParam[rootPramNum] = {}; //視点変換行列 rootParam[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; //定数バッファ rootParam[0].Descriptor.ShaderRegister = 0; //0番目 rootParam[0].Descriptor.RegisterSpace = 0; rootParam[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; //頂点シェーダから参照 _rootSignature.SetRootParameter(rootParam, rootPramNum); //ルートパラメータをセット _rootSignature.CreatRootSignature(); //ルートシグネチャの作成 //入力レイアウトの設定 const uint32_t elementCount = 2; D3D12_INPUT_ELEMENT_DESC elements[elementCount] = {}; elements[0].SemanticName = "POSITION"; //シェーダーのセマンティクス elements[0].SemanticIndex = 0; elements[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; //float型3つの配列 elements[0].InputSlot = 0; elements[0].AlignedByteOffset = D3D12_APPEND_ALIGNED_ELEMENT; elements[0].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA; elements[1].SemanticName = "COLOR"; //シェーダーのセマンティクス elements[1].SemanticIndex = 0; elements[1].Format = DXGI_FORMAT_R32G32B32A32_FLOAT; //float型4つの配列 elements[1].InputSlot = 0; elements[1].AlignedByteOffset = D3D12_APPEND_ALIGNED_ELEMENT; elements[1].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA; elements[1].InstanceDataStepRate = 0; D3D12_INPUT_LAYOUT_DESC inputLayout = { elements, elementCount }; _pipelineState.SetInputLayout(inputLayout); //頂点レイアウトのセット _pipelineState.SetRootSignature(_rootSignature.GetRootSignature()); //ルートシグネチャのセット _pipelineState.SetVertexShader(L"../x64/Debug/VertexShader.cso"); //頂点シェーダのセット _pipelineState.SetPixelShader(L"../x64/Debug/PixelShader.cso"); //ピクセルシェーダーのセット _pipelineState.CreatePipelineState(); //グラフィックスパイプラインの作成 return true; } void Scene::Draw() { uint32_t currentIndex = dx->GetCurrentBackBufferIndex(); //書き込むフレームのインデックスを取得 D3D12_VERTEX_BUFFER_VIEW vertexBufferView = _vertexBuffer.GetVertexBufferView(); //頂点バッファビューを取得 D3D12_INDEX_BUFFER_VIEW indexBufferView = _indexBuffer.GetIndexBufferView(); //インデックスバッファビューの取得 dx->GetCmdList()->SetGraphicsRootSignature(_rootSignature.GetRootSignature()); dx->GetCmdList()->SetGraphicsRootConstantBufferView(0, _constantBuffer[dx->GetCurrentBackBufferIndex()].GetAddress()); dx->GetCmdList()->SetPipelineState(_pipelineState.GetPipelineState()); dx->GetCmdList()->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); //ポリゴンの描画方法はトライアングルリスト dx->GetCmdList()->IASetVertexBuffers(0, 1, &vertexBufferView); dx->GetCmdList()->IASetIndexBuffer(&indexBufferView); dx->GetCmdList()->DrawIndexedInstanced(3, 1, 0, 0, 0); //描画 }
VertexShader.hlsl
cbuffer Transform : register(b0) { float4x4 World; //ワールド行列 float4x4 View; //ビュー行列 float4x4 Proj; //投影行列 } struct VSInput { float3 pos : POSITION; //頂点座標 float4 color : COLOR; //頂点の色 }; struct VSOutput { float4 svpos : SV_POSITION; //変換された座標 float4 color : COLOR; //頂点の色 }; VSOutput main(VSInput input) { VSOutput output; float4 localPos = float4(input.pos, 1.0f); //頂点座標 float4 worldPos = mul(World, localPos); //ワールド座標に変換 float4 viewPos = mul(View, worldPos); //ビュー座標に変換 float4 projPos = mul(Proj, viewPos); //投影変換 output.svpos = projPos; //投影変換された座標をピクセルシェーダに渡す output.color = input.color; //頂点の色をそのままピクセルシェーダに渡す return output; }
PixelShader.hlsl
struct PSInput { float4 svpos : SV_POSITION; // 頂点シェーダーから来た座標 float4 color : COLOR; }; struct PSOutput { float4 color : SV_TARGET; }; PSOutput main(PSInput input) : SV_TARGET { PSOutput output; output.color = input.color; return output; }
App.hとApp.cppの変更
App.hに追加
#include "Scene.h"
App.cppに追加
//初期化 bool App::InitApp() { if (!InitWindow()) { return false; } dx = new Dx(); if (!dx->Init(_width, _height, _hwnd)) { return false; } scene = new Scene(); if (!scene->Init()) { return false; } return true; }
//メインループ void App::MainLoop() { MSG msg = {}; while (WM_QUIT != msg.message) { if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE == true)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { // ここに描画処理を書く dx->BeginRender(); scene->Draw(); dx->EndRender(); UpdateWindow(_hwnd); } } }