こんにちは、ちゃらいプログラマです。
今回は今まで行ってきたプリミティブ描画を複数表示してみた結果になります。
以前まではmain.cppにべた書きを行っていましたが今回からちゃんとクラス分けをしました。
またスマートポインタの使用を廃止しております(あまり使い慣れていないので…)
クラス概要
- DirectXSystem:d3d12関連をまとめたクラス(シングルトン)
- CameraSystem:カメラ情報をまとめたクラス(シングルトン)
- ObjectBase:オブジェクト基礎クラス
- ObjectPrimitive:プリミティブオブジェクトクラス
シェーダー概要
- simple.hlsl:頂点カラーのみ反映
- simpleTexture.hlsl:テクスチャ+頂点カラーを反映
DirectXSystemクラス
使用するシェーダー毎に
- ID3D12RootSignature
- ID3D12PipelineState
を生成しています。
頂点レイアウトもそれぞれ用意して今回は以下のようにまとめました。
また
- DirectXSystem::renderBegin()
- DIrectXSystem::renderEnd()
の間に各オブジェクトの描画処理を記載する形式にしています。
DirectXSystem.h (一部抜粋)
{ public: struct VertexBase {}; //! 頂点構造体(シンプル) struct VertexSimple : VertexBase { XMFLOAT3 _position; XMFLOAT3 _normal; XMFLOAT4 _color; }; // 頂点構造体(シンプルテクスチャ) struct VertexSimpleTexture : VertexBase { XMFLOAT3 _position; XMFLOAT3 _normal; XMFLOAT4 _color; XMFLOAT2 _uv; }; public: // 描画開始 bool renderBegin( void ); // 描画終了 bool renderEnd( void ); // シンプル描画設定 void setRenderSimple( void ); // シンプルテクスチャ描画設定 void setRenderSimpleTexture( void ); private: // シンプル版ルートシグネチャ生成 bool createSimpleRootSignature( void ); // シンプルテクスチャ版ルートシグネチャ生成 bool createSimpleTextureRootSignature( void ); private: ID3D12RootSignature* _pSimpleRootSignature; ID3D12PipelineState* _pSimplePipelineState; ID3D12RootSignature* _pSimpleTextureRootSignature; ID3D12PipelineState* _pSimpleTexturePipelineState; } // アクセサ inline DirectXSystem* getDirectXSystem( void ) { return DirectXSystem::getInstance(); }
DirectXSystem.cpp (一部抜粋)
createSimpleRootSignature()ではDirectXSystem::VertexSimple用の頂点レイアウトを設定し「simple.hlsl」をビルド。
createSimpleTextureRootSignature()ではDirectXSystem::VertexSimpleTexture 用の頂点レイアウトを設定し「simpleTexture.hlsl」をビルド。
createSimpleTextureRootSignature()ではテクスチャも扱うので、サンプラの設定も合わせて行っています。
bool DirectXSystem::renderBegin(void) { _pCommandList->RSSetViewports( 1, &_viewPort ); _pCommandList->RSSetScissorRects( 1, &_viewRect ); // 表示準備 { D3D12_RESOURCE_BARRIER resourceBarrier = {}; resourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; resourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; resourceBarrier.Transition.pResource = _pRenderTargetArray[_frameIndex]; resourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; resourceBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; resourceBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; _pCommandList->ResourceBarrier( 1, &resourceBarrier ); } D3D12_CPU_DESCRIPTOR_HANDLE handle = {}; handle.ptr = _pHeap->GetCPUDescriptorHandleForHeapStart().ptr + _frameIndex * _heapSize; _pCommandList->OMSetRenderTargets( 1, &handle, false, nullptr ); // 描画開始 float clearColor[] = { 0.f, 0.2f, 0.4f, 1.f }; _pCommandList->ClearRenderTargetView( handle, clearColor, 0, nullptr ); return true; } bool DirectXSystem::renderEnd(void) { // 表示 { D3D12_RESOURCE_BARRIER resourceBarrier = {}; resourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; resourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; resourceBarrier.Transition.pResource = _pRenderTargetArray[_frameIndex]; resourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; resourceBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; resourceBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; _pCommandList->ResourceBarrier( 1, &resourceBarrier ); } if( FAILED( _pCommandList->Close() ) ) { return false; } // コマンドリスト実行 ID3D12CommandList* ppCommandListArray[] = {_pCommandList}; _pCommandQueue->ExecuteCommandLists( _countof(ppCommandListArray), ppCommandListArray ); // 出力 if( FAILED( _pSwapChain->Present( 1, 0 ) ) ) { return false; } if( !waitFrame() ) { return false; } // コマンドアロケータのリセット if( FAILED( _pCommandAllocator->Reset() ) ) { return false; } // コマンドリストのリセット if( FAILED( _pCommandList->Reset( _pCommandAllocator, nullptr ) ) ) { return false; } return true; } void DirectXSystem::setRenderSimple( void ) { _pCommandList->SetGraphicsRootSignature( _pSimpleRootSignature ); _pCommandList->SetPipelineState( _pSimplePipelineState ); } void DirectXSystem::setRenderSimpleTexture( void ) { _pCommandList->SetGraphicsRootSignature( _pSimpleTextureRootSignature ); _pCommandList->SetPipelineState( _pSimpleTexturePipelineState ); } bool DirectXSystem::createSimpleRootSignature( void ) { // ルートシグネチャ生成 { D3D12_ROOT_PARAMETER rootParameterArray[1]; // 定数バッファ設定 rootParameterArray[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; rootParameterArray[0].Descriptor.ShaderRegister = 0; rootParameterArray[0].Descriptor.RegisterSpace = 0; rootParameterArray[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // ルートシグネチャ生成 D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = {}; rootSignatureDesc.NumParameters = _countof(rootParameterArray); rootSignatureDesc.pParameters = rootParameterArray; rootSignatureDesc.NumStaticSamplers = 0; rootSignatureDesc.pStaticSamplers = nullptr; rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; ID3DBlob* pSignature = nullptr; ID3DBlob* pError = nullptr; if( FAILED( D3D12SerializeRootSignature( &rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &pSignature, &pError ) ) ) { return false; } if( FAILED( _pDevice->CreateRootSignature( 0, pSignature->GetBufferPointer(), pSignature->GetBufferSize(), IID_PPV_ARGS(&_pSimpleRootSignature) ) ) ) { return false; } } // パイプラインステートオブジェクト生成 { // シェーダーコンパイル ID3DBlob* pVertexShader = nullptr; ID3DBlob* pPixelShader = nullptr; UINT compileFlags = 0; if( FAILED( D3DCompileFromFile( L"resource/simple.hlsl", nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &pVertexShader, nullptr ) ) ) { return false; } if( FAILED( D3DCompileFromFile( L"resource/simple.hlsl", nullptr, nullptr, "PSMain", "ps_5_0", compileFlags, 0, &pPixelShader, nullptr ) ) ) { return false; } // 頂点入力レイアウト定義 D3D12_INPUT_ELEMENT_DESC inputElementDescs[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT , 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, {"NORMAL" , 0, DXGI_FORMAT_R32G32B32_FLOAT , 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, {"COLOR" , 0, DXGI_FORMAT_R32G32B32A32_FLOAT , 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, }; // グラフィックスパイプラインステート生成 D3D12_GRAPHICS_PIPELINE_STATE_DESC gpsDesc = {}; gpsDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) }; gpsDesc.pRootSignature = _pSimpleRootSignature; { // 頂点シェーダー D3D12_SHADER_BYTECODE shaderBytecode; shaderBytecode.pShaderBytecode = pVertexShader->GetBufferPointer(); shaderBytecode.BytecodeLength = pVertexShader->GetBufferSize(); gpsDesc.VS = shaderBytecode; } { // ピクセルシェーダー D3D12_SHADER_BYTECODE shaderBytecode; shaderBytecode.pShaderBytecode = pPixelShader->GetBufferPointer(); shaderBytecode.BytecodeLength = pPixelShader->GetBufferSize(); gpsDesc.PS = shaderBytecode; } { // ラスタライザ D3D12_RASTERIZER_DESC rasterizerDesc = {}; rasterizerDesc.FillMode = D3D12_FILL_MODE_SOLID; rasterizerDesc.CullMode = D3D12_CULL_MODE_BACK; rasterizerDesc.FrontCounterClockwise = false; rasterizerDesc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; rasterizerDesc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; rasterizerDesc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; rasterizerDesc.DepthClipEnable = true; rasterizerDesc.MultisampleEnable = false; rasterizerDesc.AntialiasedLineEnable = false; rasterizerDesc.ForcedSampleCount = 0; rasterizerDesc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; gpsDesc.RasterizerState = rasterizerDesc; } { // ブレンド D3D12_BLEND_DESC blendDesc = {}; blendDesc.AlphaToCoverageEnable = false; blendDesc.IndependentBlendEnable = false; for( UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; i ++ ) { blendDesc.RenderTarget[i].BlendEnable = true; blendDesc.RenderTarget[i].LogicOpEnable = false; blendDesc.RenderTarget[i].SrcBlend = D3D12_BLEND_SRC_ALPHA; blendDesc.RenderTarget[i].DestBlend = D3D12_BLEND_INV_SRC_ALPHA; blendDesc.RenderTarget[i].BlendOp = D3D12_BLEND_OP_ADD; blendDesc.RenderTarget[i].SrcBlendAlpha = D3D12_BLEND_ONE; blendDesc.RenderTarget[i].DestBlendAlpha = D3D12_BLEND_ZERO; blendDesc.RenderTarget[i].BlendOpAlpha = D3D12_BLEND_OP_ADD; blendDesc.RenderTarget[i].LogicOp = D3D12_LOGIC_OP_NOOP; blendDesc.RenderTarget[i].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; } gpsDesc.BlendState = blendDesc; } gpsDesc.DepthStencilState.DepthEnable = false; gpsDesc.DepthStencilState.StencilEnable = false; gpsDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT; // レンダーターゲット gpsDesc.NumRenderTargets = 1; gpsDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; gpsDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; // サンプラ gpsDesc.SampleMask = UINT_MAX; gpsDesc.SampleDesc.Count = 1; gpsDesc.SampleDesc.Quality = 0; if( FAILED( _pDevice->CreateGraphicsPipelineState( &gpsDesc, IID_PPV_ARGS(&_pSimplePipelineState) ) ) ) { return false; } } return true; } bool DirectXSystem::createSimpleTextureRootSignature( void ) { // ルートシグネチャ生成 { D3D12_DESCRIPTOR_RANGE rangeArray[1]; D3D12_ROOT_PARAMETER rootParameterArray[2]; D3D12_STATIC_SAMPLER_DESC samplerDesc{}; // 定数バッファ設定 rootParameterArray[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; rootParameterArray[0].Descriptor.ShaderRegister = 0; rootParameterArray[0].Descriptor.RegisterSpace = 0; rootParameterArray[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // テクスチャのデスクリプタヒープを渡すように設定 rangeArray[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; rangeArray[0].NumDescriptors = 1; rangeArray[0].BaseShaderRegister = 0; rangeArray[0].RegisterSpace = 0; rangeArray[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; rootParameterArray[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; rootParameterArray[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; rootParameterArray[1].DescriptorTable.NumDescriptorRanges = 1; rootParameterArray[1].DescriptorTable.pDescriptorRanges = &rangeArray[0]; // サンプラ設定 samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; samplerDesc.MipLODBias = 0.f; samplerDesc.MaxAnisotropy = 16; samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; samplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; samplerDesc.MinLOD = 0.f; samplerDesc.MaxLOD = D3D12_FLOAT32_MAX; samplerDesc.ShaderRegister = 0; samplerDesc.RegisterSpace = 0; samplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // ルートシグネチャ生成 D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = {}; rootSignatureDesc.NumParameters = _countof(rootParameterArray); rootSignatureDesc.pParameters = rootParameterArray; rootSignatureDesc.NumStaticSamplers = 1; rootSignatureDesc.pStaticSamplers = &samplerDesc; rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; ID3DBlob* pSignature = nullptr; ID3DBlob* pError = nullptr; if( FAILED( D3D12SerializeRootSignature( &rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &pSignature, &pError ) ) ) { return false; } if( FAILED( _pDevice->CreateRootSignature( 0, pSignature->GetBufferPointer(), pSignature->GetBufferSize(), IID_PPV_ARGS(&_pSimpleTextureRootSignature) ) ) ) { return false; } } // パイプラインステートオブジェクト生成 { // シェーダーコンパイル ID3DBlob* pVertexShader = nullptr; ID3DBlob* pPixelShader = nullptr; UINT compileFlags = 0; if( FAILED( D3DCompileFromFile( L"resource/simpleTexture.hlsl", nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &pVertexShader, nullptr ) ) ) { return false; } if( FAILED( D3DCompileFromFile( L"resource/simpleTexture.hlsl", nullptr, nullptr, "PSMain", "ps_5_0", compileFlags, 0, &pPixelShader, nullptr ) ) ) { return false; } // 頂点入力レイアウト定義 D3D12_INPUT_ELEMENT_DESC inputElementDescs[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT , 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, {"NORMAL" , 0, DXGI_FORMAT_R32G32B32_FLOAT , 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, {"COLOR" , 0, DXGI_FORMAT_R32G32B32A32_FLOAT , 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT , 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, }; // グラフィックスパイプラインステート生成 D3D12_GRAPHICS_PIPELINE_STATE_DESC gpsDesc = {}; gpsDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) }; gpsDesc.pRootSignature = _pSimpleTextureRootSignature; { // 頂点シェーダー D3D12_SHADER_BYTECODE shaderBytecode; shaderBytecode.pShaderBytecode = pVertexShader->GetBufferPointer(); shaderBytecode.BytecodeLength = pVertexShader->GetBufferSize(); gpsDesc.VS = shaderBytecode; } { // ピクセルシェーダー D3D12_SHADER_BYTECODE shaderBytecode; shaderBytecode.pShaderBytecode = pPixelShader->GetBufferPointer(); shaderBytecode.BytecodeLength = pPixelShader->GetBufferSize(); gpsDesc.PS = shaderBytecode; } { // ラスタライザ D3D12_RASTERIZER_DESC rasterizerDesc = {}; rasterizerDesc.FillMode = D3D12_FILL_MODE_SOLID; rasterizerDesc.CullMode = D3D12_CULL_MODE_BACK; rasterizerDesc.FrontCounterClockwise = false; rasterizerDesc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; rasterizerDesc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; rasterizerDesc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; rasterizerDesc.DepthClipEnable = true; rasterizerDesc.MultisampleEnable = false; rasterizerDesc.AntialiasedLineEnable = false; rasterizerDesc.ForcedSampleCount = 0; rasterizerDesc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; gpsDesc.RasterizerState = rasterizerDesc; } { // ブレンド D3D12_BLEND_DESC blendDesc = {}; blendDesc.AlphaToCoverageEnable = false; blendDesc.IndependentBlendEnable = false; for( UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; i ++ ) { blendDesc.RenderTarget[i].BlendEnable = true; blendDesc.RenderTarget[i].LogicOpEnable = false; blendDesc.RenderTarget[i].SrcBlend = D3D12_BLEND_SRC_ALPHA; blendDesc.RenderTarget[i].DestBlend = D3D12_BLEND_INV_SRC_ALPHA; blendDesc.RenderTarget[i].BlendOp = D3D12_BLEND_OP_ADD; blendDesc.RenderTarget[i].SrcBlendAlpha = D3D12_BLEND_ONE; blendDesc.RenderTarget[i].DestBlendAlpha = D3D12_BLEND_ZERO; blendDesc.RenderTarget[i].BlendOpAlpha = D3D12_BLEND_OP_ADD; blendDesc.RenderTarget[i].LogicOp = D3D12_LOGIC_OP_NOOP; blendDesc.RenderTarget[i].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; } gpsDesc.BlendState = blendDesc; } gpsDesc.DepthStencilState.DepthEnable = false; gpsDesc.DepthStencilState.StencilEnable = false; gpsDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT; // レンダーターゲット gpsDesc.NumRenderTargets = 1; gpsDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; gpsDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; // サンプラ gpsDesc.SampleMask = UINT_MAX; gpsDesc.SampleDesc.Count = 1; gpsDesc.SampleDesc.Quality = 0; if( FAILED( _pDevice->CreateGraphicsPipelineState( &gpsDesc, IID_PPV_ARGS(&_pSimpleTexturePipelineState) ) ) ) { return false; } } return true; }
CameraSystemクラス
View * Projection行列を設定しているだけのクラスです。。
CameraSystem.h
#ifndef CAMERASYSTEM_H #define CAMERASYSTEM_H #include <DirectXMath.h> using namespace DirectX; class CameraSystem { private: // コンストラクタ CameraSystem( void ); // デストラクタ ~CameraSystem( void ) {} public: // 初期化 bool initialize( void ); // 終了 void terminate( void ) {} public: // インスタンス取得 static CameraSystem* getInstance( void ) { if( !_pInstance ) { _pInstance = new CameraSystem(); } return _pInstance; } // View * Projection行列取得 inline XMMATRIX getViewProjection( void ) const { return _view * _projection; } private: static CameraSystem* _pInstance; XMMATRIX _view; XMMATRIX _projection; }; // アクセサ inline CameraSystem* getCameraSystem( void ) { return CameraSystem::getInstance(); } #endif // CAMERASYSTEM_H
CameraSystem.cpp
#include "CameraSystem.h" #include "DirectXSystem.h" CameraSystem* CameraSystem::_pInstance = nullptr; // コンストラクタ CameraSystem::CameraSystem( void ) : _view() , _projection() { } // 初期化 bool CameraSystem::initialize( void ) { _view = XMMatrixLookAtLH( {0.f, 0.f, -5.f}, {0.f, 0.f, 0.f}, {0.f, 1.f, 0.f} ); _projection = XMMatrixPerspectiveFovLH( XMConvertToRadians(60.f), getDirectXSystem()->getAspectRatio(), 1.f, 20.f ); return true; }
ObjectBaseクラス
基礎クラスとして作成しました。
更新や描画に必要な情報を定義しています。
ObjectBase.h
#ifndef OBJECTBASE_H #define OBJECTBASE_H #include <d3d12.h> #pragma comment(lib, "d3d12.lib") #include <DirectXMath.h> #include "d3dx12.h" #include "WICTextureLoader12.h" using namespace DirectX; class ObjectBase { public: // コンストラクタ ObjectBase( void ); // デストラクタ virtual ~ObjectBase( void ); // 初期化 virtual bool initialize( void ) { return true; } // 終了 virtual void terminate( void ); // 更新 virtual void update( void ) {} // 描画 virtual void render( void ) {} public: // 移動値設定 inline void setTransform( float x, float y, float z ) { _matrix = XMMatrixMultiply( _matrix, XMMatrixTranslation( x, y, z ) ); } // X回転値設定 inline void setRotationX( float x ) { _matrix = XMMatrixMultiply( _matrix, XMMatrixRotationX( XMConvertToRadians(x) ) ); } // Y回転値設定 inline void setRotationY( float y ) { _matrix = XMMatrixMultiply( _matrix, XMMatrixRotationY( XMConvertToRadians(y) ) ); } // Z回転値設定 inline void setRotationZ( float z ) { _matrix = XMMatrixMultiply( _matrix, XMMatrixRotationZ( XMConvertToRadians(z) ) ); } protected: ID3D12Resource* _pVertexBuffer; ID3D12Resource* _pIndexBuffer; ID3D12Resource* _pConstantBuffer; UINT _vertexBufferSize; UINT _indexBufferSize; XMMATRIX _matrix; }; #endif // OBJECTBASE_H
ObjectBase.cpp
#include "ObjectBase.h" ObjectBase::ObjectBase( void ) : _pVertexBuffer(nullptr) , _pIndexBuffer(nullptr) , _pConstantBuffer(nullptr) , _vertexBufferSize(0) , _indexBufferSize(0) { _matrix = XMMatrixIdentity(); } ObjectBase::~ObjectBase( void ) { terminate(); } void ObjectBase::terminate( void ) { if( _pVertexBuffer ) { _pVertexBuffer->Release(); _pVertexBuffer = nullptr; } if( _pIndexBuffer ) { _pIndexBuffer->Release(); _pIndexBuffer = nullptr; } if( _pConstantBuffer ) { _pConstantBuffer->Release(); _pConstantBuffer = nullptr; } }
プリミティブ描画クラス
プリミティブ描画処理をこのクラスにまとめています。
ObjectPrimitive.h
#ifndef OBJECTPRIMITIVE_H #define OBJECTPRIMITIVE_H #include "ObjectBase.h" #include "DirectXSystem.h" class ObjectPrimitive : public ObjectBase { public: // コンストラクタ ObjectPrimitive( void ); // デストラクタ ~ObjectPrimitive( void ) override {} // 三角形初期化 bool initializeTriangle( XMFLOAT4 color ); // 三角形初期化 bool initializeTriangle( XMFLOAT4 color0, XMFLOAT4 color1, XMFLOAT4 color2 ); // 四角形初期化 bool initializeRectangle( XMFLOAT4 color ); // 四角形初期化 bool initializeRectangle( const wchar_t* textureFilePath, XMFLOAT4 color ); // 四角形初期化 bool initializeRectangle( const wchar_t* textureFilePath, XMFLOAT4 color0, XMFLOAT4 color1, XMFLOAT4 color2, XMFLOAT4 color3 ); // 終了 void terminate( void ) override; // 更新 void update( void ) override; // 描画 void render( void ) override; private: // 初期化サブルーチン bool initializeSub( DirectXSystem::VertexBase* pVertexArray, uint32_t* pIndices, const wchar_t* textureFilePath ); // 三角形初期化基礎 bool initializeTriangleBase( XMFLOAT4 color0, XMFLOAT4 color1, XMFLOAT4 color2 ); // 四角形初期化基礎 bool initializeRectangleBase( const wchar_t* textureFilePath, XMFLOAT4 color0, XMFLOAT4 color1, XMFLOAT4 color2, XMFLOAT4 color3 ); private: ID3D12Resource* _pTexture; ID3D12Resource* _pTextureUploadHeap; ID3D12DescriptorHeap* _pTextureHeap; }; #endif // OBJECTPRIMITIVE_H
ObjectPrimitive.cpp
render()関数内で
テクスチャ使用時は
- getDirectXSystem()->setRenderSimpleTexture();
- getDirectXSystem()->getCommandList()->SetDescriptorHeaps( 1, &_pTextureHeap );
- getDirectXSystem()->getCommandList()->SetGraphicsRootDescriptorTable( 1, _pTextureHeap->GetGPUDescriptorHandleForHeapStart() );
テクスチャ未使用時は
- getDirectXSystem()->setRenderSimple();
をそれぞれ呼び出しています。
#include "ObjectPrimitive.h" #include "CameraSystem.h" // コンストラクタ ObjectPrimitive::ObjectPrimitive( void ) : _pTexture(nullptr) , _pTextureUploadHeap(nullptr) , _pTextureHeap(nullptr) { } // 三角形初期化 bool ObjectPrimitive::initializeTriangle( XMFLOAT4 color ) { return initializeTriangleBase( color, color, color ); } // 三角形初期化 bool ObjectPrimitive::initializeTriangle( XMFLOAT4 color0, XMFLOAT4 color1, XMFLOAT4 color2 ) { return initializeTriangleBase( color0, color1, color2 ); } // 四角形初期化 bool ObjectPrimitive::initializeRectangle( XMFLOAT4 color ) { return initializeRectangleBase( L"", color, color, color, color ); } // 四角形初期化 bool ObjectPrimitive::initializeRectangle( const wchar_t* textureFilePath, XMFLOAT4 color ) { return initializeRectangleBase( textureFilePath, color, color, color, color ); } // 四角形初期化 bool ObjectPrimitive::initializeRectangle( const wchar_t* textureFilePath, XMFLOAT4 color0, XMFLOAT4 color1, XMFLOAT4 color2, XMFLOAT4 color3 ) { return initializeRectangleBase( textureFilePath, color0, color1, color2, color3 ); } // 終了 void ObjectPrimitive::terminate( void ) { CoUninitialize(); if( _pTexture ) { _pTexture->Release(); _pTexture = nullptr; } if( _pTextureUploadHeap ) { _pTextureUploadHeap->Release(); _pTextureUploadHeap = nullptr; } if( _pTextureHeap ) { _pTextureHeap->Release(); _pTextureHeap = nullptr; } ObjectBase::terminate(); } // 更新 void ObjectPrimitive::update( void ) { } // 描画 void ObjectPrimitive::render( void ) { XMFLOAT4X4 mat; XMStoreFloat4x4( &mat, XMMatrixTranspose( _matrix * getCameraSystem()->getViewProjection() ) ); XMFLOAT4X4 * pBuffer = nullptr; _pConstantBuffer->Map( 0, nullptr, reinterpret_cast<void**>(&pBuffer) ); *pBuffer = mat; _pConstantBuffer->Unmap( 0, nullptr ); // 描画設定 if( _pTexture ) { getDirectXSystem()->setRenderSimpleTexture(); } else { getDirectXSystem()->setRenderSimple(); } // 定数バッファをシェーダレジスタに設定 getDirectXSystem()->getCommandList()->SetGraphicsRootConstantBufferView( 0, _pConstantBuffer->GetGPUVirtualAddress() ); // テクスチャ設定 if( _pTexture ) { getDirectXSystem()->getCommandList()->SetDescriptorHeaps( 1, &_pTextureHeap ); getDirectXSystem()->getCommandList()->SetGraphicsRootDescriptorTable( 1, _pTextureHeap->GetGPUDescriptorHandleForHeapStart() ); } // 頂点バッファビュー設定 D3D12_VERTEX_BUFFER_VIEW vertexBufferView; vertexBufferView.BufferLocation = _pVertexBuffer->GetGPUVirtualAddress(); if( _pTexture ) { vertexBufferView.StrideInBytes = sizeof(DirectXSystem::VertexSimpleTexture); } else { vertexBufferView.StrideInBytes = sizeof(DirectXSystem::VertexSimple); } vertexBufferView.SizeInBytes = _vertexBufferSize; getDirectXSystem()->getCommandList()->IASetPrimitiveTopology( D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); getDirectXSystem()->getCommandList()->IASetVertexBuffers( 0, 1, &vertexBufferView ); // インデックスバッファビュー設定 if( _pIndexBuffer ) { D3D12_INDEX_BUFFER_VIEW indexBufferView; indexBufferView.BufferLocation = _pIndexBuffer->GetGPUVirtualAddress(); indexBufferView.Format = DXGI_FORMAT_R32_UINT; indexBufferView.SizeInBytes = _indexBufferSize; getDirectXSystem()->getCommandList()->IASetIndexBuffer( &indexBufferView ); getDirectXSystem()->getCommandList()->DrawIndexedInstanced( (_indexBufferSize / sizeof(uint32_t)), 1, 0, 0, 0 ); } else { getDirectXSystem()->getCommandList()->DrawInstanced( 3, 1, 0, 0 ); } } // 初期化サブルーチン bool ObjectPrimitive::initializeSub( DirectXSystem::VertexBase* pVertexArray, uint32_t* pIndices, const wchar_t* textureFilePath ) { // 頂点バッファ生成 { D3D12_HEAP_PROPERTIES heapProperties = {}; heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD; heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; heapProperties.CreationNodeMask = 1; heapProperties.VisibleNodeMask = 1; D3D12_RESOURCE_DESC resourceDesc = {}; resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; resourceDesc.Alignment = 0; resourceDesc.Width = _vertexBufferSize; resourceDesc.Height = 1; resourceDesc.DepthOrArraySize = 1; resourceDesc.MipLevels = 1; resourceDesc.Format = DXGI_FORMAT_UNKNOWN; resourceDesc.SampleDesc.Count = 1; resourceDesc.SampleDesc.Quality = 0; resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE; if( FAILED( getDirectXSystem()->getDevice()->CreateCommittedResource( &heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&_pVertexBuffer) ) ) ) { return false; } // データ設定 UINT8* pVertexDataBegin; D3D12_RANGE readRange = {0, 0}; if( FAILED( _pVertexBuffer->Map( 0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin) ) ) ) { return false; } memcpy( pVertexDataBegin, pVertexArray, _vertexBufferSize ); _pVertexBuffer->Unmap( 0, nullptr ); } // インデックスバッファ生成 if( pIndices ) { D3D12_HEAP_PROPERTIES heapProperties = {}; heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD; heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; heapProperties.CreationNodeMask = 1; heapProperties.VisibleNodeMask = 1; D3D12_RESOURCE_DESC resourceDesc = {}; resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; resourceDesc.Alignment = 0; resourceDesc.Width = _indexBufferSize; resourceDesc.Height = 1; resourceDesc.DepthOrArraySize = 1; resourceDesc.MipLevels = 1; resourceDesc.Format = DXGI_FORMAT_UNKNOWN; resourceDesc.SampleDesc.Count = 1; resourceDesc.SampleDesc.Quality = 0; resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE; if( FAILED( getDirectXSystem()->getDevice()->CreateCommittedResource( &heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&_pIndexBuffer) ) ) ) { return false; } // データ設定 UINT8* pIndexDataBegin; if ( FAILED( _pIndexBuffer->Map( 0, nullptr, reinterpret_cast<void**>(&pIndexDataBegin) ) ) ) { return false; } memcpy( pIndexDataBegin, pIndices, _indexBufferSize ); _pIndexBuffer->Unmap( 0, nullptr ); } // 定数バッファ生成 { // 定数バッファリソース生成 D3D12_HEAP_PROPERTIES constantProperties = {}; constantProperties.Type = D3D12_HEAP_TYPE_UPLOAD; constantProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; constantProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; constantProperties.CreationNodeMask = 1; constantProperties.VisibleNodeMask = 1; D3D12_RESOURCE_DESC constantResource = {}; constantResource.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; constantResource.Alignment = 0; constantResource.Width = 256; constantResource.Height = 1; constantResource.DepthOrArraySize = 1; constantResource.MipLevels = 1; constantResource.Format = DXGI_FORMAT_UNKNOWN; constantResource.SampleDesc = { 1, 0 }; constantResource.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; constantResource.Flags = D3D12_RESOURCE_FLAG_NONE; if( FAILED( getDirectXSystem()->getDevice()->CreateCommittedResource( &constantProperties, D3D12_HEAP_FLAG_NONE, &constantResource, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&_pConstantBuffer) ) ) ) { return false; } } // テクスチャ生成 if( wcslen( textureFilePath ) > 0 ) { if( FAILED( CoInitializeEx( NULL, COINIT_MULTITHREADED ) ) ) { return false; } // 読み込み std::unique_ptr<uint8_t[]> wicData; D3D12_SUBRESOURCE_DATA subresourceData; if( FAILED( LoadWICTextureFromFile( getDirectXSystem()->getDevice(), textureFilePath, &_pTexture, wicData, subresourceData ) ) ) { return false; } D3D12_RESOURCE_DESC textureResourceDesc = _pTexture->GetDesc(); UINT64 uploadBufferSize = GetRequiredIntermediateSize( _pTexture, 0, 1 ); // GPUアップロードバッファ生成 D3D12_HEAP_PROPERTIES tmpHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); D3D12_RESOURCE_DESC tmpResourceDesc = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize); if( FAILED( getDirectXSystem()->getDevice()->CreateCommittedResource( &tmpHeapProperties, D3D12_HEAP_FLAG_NONE, &tmpResourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&_pTextureUploadHeap) ) ) ) { return false; } // テクスチャ情報更新 UpdateSubresources( getDirectXSystem()->getCommandList(), _pTexture, _pTextureUploadHeap, 0, 0, 1, &subresourceData ); D3D12_RESOURCE_BARRIER resourceBarrier = CD3DX12_RESOURCE_BARRIER::Transition( _pTexture, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE ); getDirectXSystem()->getCommandList()->ResourceBarrier( 1, &resourceBarrier ); // テクスチャデスクリプタヒープ生成 D3D12_DESCRIPTOR_HEAP_DESC textureHeapDesc = {}; textureHeapDesc.NumDescriptors = 1; textureHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; textureHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; textureHeapDesc.NodeMask = 0; if( FAILED( getDirectXSystem()->getDevice()->CreateDescriptorHeap( &textureHeapDesc, IID_PPV_ARGS(&_pTextureHeap) ) ) ) { return false; } // シェーダーリソースビュー生成 D3D12_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc = {}; shaderResourceViewDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; shaderResourceViewDesc.Format = textureResourceDesc.Format; shaderResourceViewDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; shaderResourceViewDesc.Texture2D.MipLevels = 1; getDirectXSystem()->getDevice()->CreateShaderResourceView( _pTexture, &shaderResourceViewDesc, _pTextureHeap->GetCPUDescriptorHandleForHeapStart() ); // アンロード getDirectXSystem()->getCommandList()->DiscardResource( _pTextureUploadHeap, nullptr ); } return true; } // 三角形初期化基礎 bool ObjectPrimitive::initializeTriangleBase( XMFLOAT4 color0, XMFLOAT4 color1, XMFLOAT4 color2 ) { DirectXSystem::VertexSimple vertexArray[3]; vertexArray[0]._position = { 0.f, 0.5f, 0.f}; vertexArray[0]._normal = {0.f, 0.f, -1.f}; vertexArray[0]._color = color0; vertexArray[1]._position = { 0.5f, -0.5f, 0.f}; vertexArray[1]._normal = {0.f, 0.f, -1.f}; vertexArray[1]._color = color1; vertexArray[2]._position = {-0.5f, -0.5f, 0.f}; vertexArray[2]._normal = {0.f, 0.f, -1.f}; vertexArray[2]._color = color2; _vertexBufferSize = sizeof(vertexArray); return initializeSub( vertexArray, nullptr, L"" ); } // 四角形初期化基礎 bool ObjectPrimitive::initializeRectangleBase( const wchar_t* textureFilePath, XMFLOAT4 color0, XMFLOAT4 color1, XMFLOAT4 color2, XMFLOAT4 color3 ) { bool isUseTexture = wcslen( textureFilePath ) > 0; uint32_t indices[] = { 0, 1, 2, 0, 2, 3 }; if( isUseTexture ) { DirectXSystem::VertexSimpleTexture vertexArray[4]; vertexArray[0]._position = { -1.f, 1.f, 0.f}; vertexArray[0]._normal = {0.f, 0.f, -1.f}; vertexArray[0]._color = color0; vertexArray[0]._uv = {0.f, 0.f}; vertexArray[1]._position = { 1.f, 1.f, 0.f}; vertexArray[1]._normal = {0.f, 0.f, -1.f}; vertexArray[1]._color = color1; vertexArray[1]._uv = {1.f, 0.f}; vertexArray[2]._position = { 1.f, -1.f, 0.f}; vertexArray[2]._normal = {0.f, 0.f, -1.f}; vertexArray[2]._color = color2; vertexArray[2]._uv = {1.f, 1.f}; vertexArray[3]._position = { -1.f, -1.f, 0.f}; vertexArray[3]._normal = {0.f, 0.f, -1.f}; vertexArray[3]._color = color3; vertexArray[3]._uv = {0.f, 1.f}; _vertexBufferSize = sizeof(vertexArray); _indexBufferSize = sizeof(indices); return initializeSub( vertexArray, indices, textureFilePath ); } else { DirectXSystem::VertexSimple vertexArray[4]; vertexArray[0]._position = { -1.f, 1.f, 0.f}; vertexArray[0]._normal = {0.f, 0.f, -1.f}; vertexArray[0]._color = color0; vertexArray[1]._position = { 1.f, 1.f, 0.f}; vertexArray[1]._normal = {0.f, 0.f, -1.f}; vertexArray[1]._color = color1; vertexArray[2]._position = { 1.f, -1.f, 0.f}; vertexArray[2]._normal = {0.f, 0.f, -1.f}; vertexArray[2]._color = color2; vertexArray[3]._position = { -1.f, -1.f, 0.f}; vertexArray[3]._normal = {0.f, 0.f, -1.f}; vertexArray[3]._color = color3; _vertexBufferSize = sizeof(vertexArray); _indexBufferSize = sizeof(indices); return initializeSub( vertexArray, indices, textureFilePath ); } }
シェーダー
前回から変わってないとは思いますが一応載せておきます
simple.hlsl
cbuffer cbTansMatrix : register(b0) { float4x4 WVP; } struct VSInput { float3 position : POSITION; float3 normal : NORMAL; float4 color : COLOR; }; struct PSInput { float4 position : SV_POSITION; float4 normal : NORMAL; float4 color : COLOR; }; PSInput VSMain( VSInput input ) { PSInput output; float4 position = float4(input.position, 1.0f); float3 normal = float4(input.normal, 1.0f); output.position = mul(position, WVP); output.normal = mul(normal, WVP); output.color = input.color; return output; } float4 PSMain( PSInput input ) : SV_TARGET { return input.color; }
simpleTexture.hlsl
cbuffer cbTansMatrix : register(b0) { float4x4 WVP; } Texture2D<float4> tex0 : register(t0); SamplerState samp0 : register(s0); struct VSInput { float3 position : POSITION; float3 normal : NORMAL; float4 color : COLOR; float2 uv : TEXCOORD; }; struct PSInput { float4 position : SV_POSITION; float4 normal : NORMAL; float4 color : COLOR; float2 uv : TEXCOORD; }; PSInput VSMain( VSInput input ) { PSInput output; float4 position = float4(input.position, 1.0f); float3 normal = float4(input.normal, 1.0f); output.position = mul(position, WVP); output.normal = mul(normal, WVP); output.color = input.color; output.uv = input.uv; return output; } float4 PSMain( PSInput input ) : SV_TARGET { return tex0.Sample(samp0, input.uv) * input.color; }
実際に使用する流れ(main.cpp)
最後に今までmain.cpp側で行っていた箇所の置き換えとなります。
前回までと変わった箇所を抜粋していきます。
#include "DirectXSystem.h" #include "CameraSystem.h" #include "ObjectPrimitive.h" ObjectPrimitive primitiveA; ObjectPrimitive primitiveB; ObjectPrimitive primitiveC; bool Initialize( HWND hWnd, D3D12_RECT& rect ) { if( !getDirectXSystem()->initialize( hWnd, rect ) ) { return false; } if( !getCameraSystem()->initialize() ) { return false; } if( !primitiveA.initializeRectangle( L"resource/image.png", {1.f, 0.f, 0.f, 1.f}, { 0.f, 1.f, 0.f, 1.f }, { 0.f, 0.f, 1.f, 1.f }, { 1.f, 0.f, 1.f, 1.f }) ) { return false; } primitiveA.setTransform( -2.f, 0.f, 0.f); primitiveA.setRotationY( -50.f ); if( !primitiveB.initializeRectangle( L"resource/image2.png", {1.f, 1.f, 1.f, 1.f} ) ) { return false; } primitiveB.setTransform( 2.f, 0.f, 0.f ); primitiveB.setRotationY( 30.f ); if( !primitiveC.initializeTriangle( {1.f, 1.f, 0.5f, 1.f} ) ) { return false; } return true; } void terminate( void ) { primitiveA.terminate(); primitiveB.terminate(); primitiveC.terminate(); getCameraSystem()->terminate(); getDirectXSystem()->terminate(); } void Update( void ) { primitiveA.update(); primitiveB.update(); primitiveC.update(); if( !getDirectXSystem()->renderBegin() ) { return; } primitiveA.render(); primitiveB.render(); primitiveC.render(); getDirectXSystem()->renderEnd(); }
次こそライト周りをしたい…
ではまた次回!