Microsoft Visual 2017 Community C++ Direct3D 11.0( SM 5.0 ) DirectXMath boost::Property Tree |
■Direct3D11 シャドウマッピング | Top Next |
関連ページ:なし |
行列やベクトルなどの算術ライブラリには DirectXMath を使用します。
インクルードファイルのダウンロードはGitHubから行ってください。
解凍後、Header\Commonフォルダ直下にコピーしてください。
XML形式であるdaeファイルのローダーにはboostのProperty Treeを使用します。
boost::Property Treeについては別ページで解説しているので合わせて確認してみてください。
UCommon.h | 共通で使用するヘッダファイル |
UException.h | 例外処理クラスのヘッダファイル |
UDirect3D11.h | Direct3Dクラスのヘッダーファイル。 レンダーターゲットビュー、深度ステンシルビュー、アンオーダードアクセスビュー、 およびシェーダーリソースビューを作成するための関数のヘッダーファイル。 |
UDirect3D11.cpp | Direct3Dクラスのソースファイル。 レンダーターゲットビュー、深度ステンシルビュー、アンオーダードアクセスビュー、 およびシェーダーリソースビューを作成するための関数のソースファイル。 |
UGraphicsPipeline.h | グラフィックパイプラインクラスのヘッダーファイル |
UGraphicsPipeline.cpp | グラフィックパイプラインクラスのソースファイル |
UDebugFont.h | デバッグ用のテキストを画面上に表示するためのクラスのヘッダファイル。 |
UDebugFont.cpp | デバッグ用のテキストを画面上に表示するためのクラスのソースファイル。 |
UColladaLoader_v2.h | daeファイルローダーに特化したクラスのヘッダファイル。 |
UColladaLoader_v2.cpp | daeファイルローダーに特化したクラスのソースファイル。 |
UD3DMeshDataCreater.h | daeファイルからロードしたデータをDirect3Dで扱うデータ形式にコンバートするクラスのヘッダファイル。 |
UD3DMeshDataCreater.cpp | daeファイルからロードしたデータをDirect3Dで扱うデータ形式にコンバートするクラスのソースファイル。 |
USRViewRenderer.h | レンダーターゲットサーフェスへの出力内容を確認するためのデバック用クラスのヘッダファイル。 |
USRViewRenderer.cpp | レンダーターゲットサーフェスへの出力内容を確認するためのデバック用クラスのソースファイル。 |
Aシェーダー系で使用するソースです。
ShadowMapping_Pass0.hlsl | シャドウマッピングのPass0のhlslファイル |
ShadowMapping_Pass1.hlsl | シャドウマッピングのPass1のhlslファイル |
ShadowMapping.h | シャドウマッピングクラスのヘッダーファイル |
ShadowMapping.cpp | シャドウマッピングクラスのソースファイル |
B個別に使用するソースです。
F14Mesh.h | F14メッシュクラスのヘッダーファイル |
F14Mesh.cpp | F14メッシュクラスのソースファイル |
PlaneMesh.h | 地面メッシュクラスのヘッダーファイル |
PlaneMesh.cpp | 地面メッシュクラスのソースファイル |
main.cpp | main関数のソースファイル |
#ifndef UCOMMON_H #define UCOMMON_H // 拡張機能が使用されています : 右辺値のクラスが左辺値に使用されます。このワーニングを抑制する。 #pragma warning(disable: 4238) #include <windows.h> #include <tchar.h> #include <memory> #include <mmsystem.h> // timeGetTime() #pragma comment( lib, "winmm.lib" ) // timeGetTime() // メモリリーク発生時にデバッガに出力する内容をわかりやすくする #if defined(DEBUG) || defined(_DEBUG) #define _CRTDBG_MAP_ALLOC // mallocによるメモリリーク検出でCPPファイル名と行数出力指定 #define NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) // new によるメモリリーク検出でCPPファイル名と行数出力指定 #else #define NEW new #endif // メモリ解放 #define SAFE_RELEASE(x) if( x != nullptr ){ x->Release(); x = nullptr; } #define SAFE_DELETE(x) if( x != nullptr ){ delete x; x = nullptr; } #define SAFE_DELETE_ARRAY(x) if( x != nullptr ){ delete[] x; x = nullptr; } #define SAFE_FREE(x) if( x != nullptr ){ free( x ); x = nullptr; } #endif
#ifndef UEXCEPTION_H #define UEXCEPTION_H #include <windows.h> #include <tchar.h> class UException { public: TCHAR m_pErrorStr[1024]; UException( HRESULT hr, TCHAR* pMsg ) { _stprintf_s( m_pErrorStr, _T("■□■HRESULT:0x%x [ %s ]\n"), hr, pMsg ); #if defined(DEBUG) || defined(_DEBUG) // エラーをデバッガに出力 OutputDebugString( m_pErrorStr ); #endif } }; #endif
#ifndef UDIRECT3D11_H #define UDIRECT3D11_H // インクルード #include "UCommon.h" #include <d3d11.h> #include "UException.h" // XMMATRIXで各要素へのアクセスを簡単にするために定義した #define _XM_NO_INTRINSICS_ // DirectXMath算術ライブラリ #include "DirectXMath-master/Inc/DirectXMath.h" using namespace DirectX; // ライブラリの追加 #pragma comment( lib, "dxguid.lib" ) #pragma comment( lib, "d3d11.lib" ) #pragma comment( lib, "dxgi.lib" ) #pragma comment( lib, "d3dcompiler.lib" ) // hlsl をコンパイルする #define UD3D11_FORMAT DXGI_FORMAT_R8G8B8A8_UNORM // 深度ステンシルビューとシェーダーリソースビューのどちらとしても使用できるようにするため型を指定しない // フォーマットについてはDXGI_FORMAT参照 #define UD3D11_DEPTH_FORMAT DXGI_FORMAT_R32_TYPELESS #define DDS_MAGIC 0x20534444 // "DDS " #define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT #define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT #define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH #define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH #define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE #define DDS_FOURCC 0x00000004 // DDPF_FOURCC #define DDS_RGB 0x00000040 // DDPF_RGB #define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS #define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE #define DDS_ALPHA 0x00000002 // DDPF_ALPHA class UMaps { private: struct DDS_PIXELFORMAT { DWORD dwSize; DWORD dwFlags; DWORD dwFourCC; DWORD dwRGBBitCount; DWORD dwRBitMask; DWORD dwGBitMask; DWORD dwBBitMask; DWORD dwABitMask; }; typedef struct { DWORD dwSize; DWORD dwHeaderFlags; DWORD dwHeight; DWORD dwWidth; DWORD dwPitchOrLinearSize; DWORD dwDepth; DWORD dwMipMapCount; DWORD dwReserved1[11]; DDS_PIXELFORMAT ddspf; DWORD dwSurfaceFlags; DWORD dwCubemapFlags; DWORD dwReserved2[3]; } DDS_HEADER; UMaps(); bool static IsBitMask(DDS_HEADER* pHeader, DWORD r, DWORD g, DWORD b, DWORD a); public: // DDSファイルをロードしてテクスチャーを作成する // R8G8B8A8またはR8G8B8X8フォーマットのみでミップマップは1のみ、ボリュームテクスチャーとキューブマップと圧縮フォーマットは未対応 void static CreateSRViewFromDDSFile( ID3D11Device* pD3DDevice, const TCHAR* szFileName, ID3D11ShaderResourceView** ppSRV ); // レンダーターゲットビューを作成する void static CreateRenderTargetView( ID3D11Device* pD3DDevice, DXGI_FORMAT format, UINT Width, UINT Height, ID3D11RenderTargetView** ppRTView, ID3D11ShaderResourceView** ppSRView, UINT ArraySize = 1, UINT MipmapCount = 1 ); // ボリュームテクスチャー用のレンダーターゲットビューを作成する void static CreateRenderTargetViewOfVolumeTexture( ID3D11Device* pD3DDevice, DXGI_FORMAT format, UINT Width, UINT Height, UINT Depth, ID3D11RenderTargetView** ppRTView, ID3D11ShaderResourceView** ppSRView ); // レンダーターゲットビューからシェーダーリソースビューを作成する void static CreateSRViewFromRTView( ID3D11Device* pD3DDevice, ID3D11RenderTargetView* pRTView, ID3D11ShaderResourceView** ppSRView ); // アンオーダードアクセスビューを作成する void static CreateRenderTargetViewOfRWTexture( ID3D11Device* pD3DDevice, DXGI_FORMAT format, UINT Width, UINT Height, ID3D11UnorderedAccessView** ppUAView, ID3D11ShaderResourceView** ppSRView, UINT ArraySize = 1 ); // アンオーダードアクセスビューからシェーダーリソースビューを作成する void static CreateSRViewFromUAView( ID3D11Device* pD3DDevice, ID3D11UnorderedAccessView* pUAView, ID3D11ShaderResourceView** ppSRView ); // 深度ステンシルビューを作成する void static CreateDepthStencilView( ID3D11Device* pD3DDevice, UINT Width, UINT Height, ID3D11DepthStencilView** ppDSView, ID3D11ShaderResourceView** ppSRView, UINT ArraySize = 1 ); // 深度ステンシルビューからシェーダーリソースビューを作成する void static CreateSRViewFromDSView( ID3D11Device* pD3DDevice, ID3D11DepthStencilView* pDSView, ID3D11ShaderResourceView** ppSRView ); // ノイズマップを作成する void static CreateSRViewOfNoiseMap( ID3D11Device* pD3DDevice, UINT Width, UINT Height, DXGI_FORMAT format, ID3D11ShaderResourceView** ppSRView ); }; class UBuffers { private: UBuffers(); public: // バッファを作成する共通関数 ID3D11Buffer static * CreateBuffer( ID3D11Device* pD3DDevice, void* pData, size_t size, UINT CPUAccessFlag, D3D11_BIND_FLAG BindFlag ); // 頂点バッファを作成する inline ID3D11Buffer static * CreateVertexBuffer( ID3D11Device* pD3DDevice, void* pData, size_t size, UINT CPUAccessFlag ) { return CreateBuffer( pD3DDevice, pData, size, CPUAccessFlag, D3D11_BIND_VERTEX_BUFFER ); } // インデックスバッファを作成する inline ID3D11Buffer static * CreateIndexBuffer( ID3D11Device* pD3DDevice, void* pData, size_t size, UINT CPUAccessFlag ) { return CreateBuffer( pD3DDevice, pData, size, CPUAccessFlag, D3D11_BIND_INDEX_BUFFER ); } }; class USamplers { private: USamplers(); public: // サンプラーステートを作成する ID3D11SamplerState static * CreateSamplerState(ID3D11Device* pD3DDevice, D3D11_TEXTURE_ADDRESS_MODE TextureAddressMode, D3D11_FILTER Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_COMPARISON_FUNC = D3D11_COMPARISON_ALWAYS); }; class UDirect3D11 { public: HWND m_hWnd; ID3D11Device* m_pD3DDevice; // Direct3D11 デバイス。 ID3D11DeviceContext* m_pD3DDeviceContext; // Direct3D11 デバイスコンテキスト。 private: IDXGIAdapter* m_pAdapter; // アダプター IDXGISwapChain* m_pSwapChain; // スワップチェーン ID3D11RenderTargetView* m_pRenderTargetView; // レンダリングターゲットビュー ID3D11DepthStencilView* m_pDepthStencilView; BOOL m_UseDepthBuffer, m_UseMultiSample; // アダプターを取得 void CreateAdapter(); // ウィンドウ作成 void InitWindow( TCHAR* AppName, HINSTANCE hInstance, WNDPROC WndProc, DXGI_MODE_DESC* pDisplayMode ); // デバイスの作成 void CreateDevice(); // スワップチェーンの作成 void CreateSwapChain( DXGI_MODE_DESC* pDisplayMode ); // レンダリングターゲットビューの作成 void CreateRenderTargetView(); // 深度ステンシルビューの作成 void CreateDepthStencilView(); // ビューポートの作成 void CreateViewport(); // ウィンドウアソシエーション void SetWindowAssociation(); // デフォルトのラスタライザを設定 void SetDefaultRasterize(); // デフォルトの深度ステンシルステートを設定 void SetDefaultDepthStencilState(); public: UDirect3D11(); virtual ~UDirect3D11(); // メモリ解放 void Invalidate(); // ディスプレイモード一覧を作成 void GetDisplayMode( DXGI_MODE_DESC* pModeDesc, UINT* pNum ); // Direct3Dを作成する void CreateDirect3D11( TCHAR* AppName, HINSTANCE hInstance, WNDPROC WndProc, DXGI_MODE_DESC* pDisplayMode, BOOL UseMultisample, BOOL UseDepthBuffer ); inline void ClearBackBuffer( const FLOAT ColorRGBA[4] ) { m_pD3DDeviceContext->ClearRenderTargetView( m_pRenderTargetView, ColorRGBA ); } inline void ClearDepthStencilView( UINT ClearFlags, FLOAT Depth, UINT8 Stencil ) { if( m_pDepthStencilView ) m_pD3DDeviceContext->ClearDepthStencilView( m_pDepthStencilView, ClearFlags, Depth, Stencil ); } HRESULT Present( UINT SyncInterval, UINT Flags ); }; #endif
#include "../../Header/Common/UDirect3D11.h" bool UMaps::IsBitMask(DDS_HEADER* pHeader, DWORD r, DWORD g, DWORD b, DWORD a) { return pHeader->ddspf.dwRBitMask == r && pHeader->ddspf.dwGBitMask == g && pHeader->ddspf.dwBBitMask == b && pHeader->ddspf.dwABitMask == a; } void UMaps::CreateSRViewFromDDSFile( ID3D11Device* pD3DDevice, const TCHAR* szFileName, ID3D11ShaderResourceView** ppSRV ) { HRESULT hr = E_FAIL; HANDLE hFile = nullptr; BYTE* pHeapData = nullptr; ID3D11Texture2D* pTex2D = nullptr; __try { // ファイルを開く hFile = ::CreateFile( szFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr ); if( INVALID_HANDLE_VALUE == hFile ) { TCHAR errstr[1024]; _stprintf_s(errstr, _T("LoadTextureDataFromFile()でエラーが発生しました。ファイルを開けません。 -> %s"), szFileName); throw(UException(HRESULT_FROM_WIN32(GetLastError()), errstr)); } // ファイルのサイズを取得する LARGE_INTEGER FileSize = {0}; ::GetFileSizeEx( hFile, &FileSize ); // 32ビット符号なし整数を超えるサイズはエラーとして処理する if( FileSize.HighPart > 0 ) throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。32ビット符号なし整数を超えています。") ) ); // ファイルサイズがヘッダー+マジックナンバーに満たない if( FileSize.LowPart < ( sizeof(DDS_HEADER) + sizeof(DWORD)) ) throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。ファイルサイズがヘッダー+マジックナンバーに満たない。") ) ); // ヘッダー領域確保 pHeapData = new BYTE[ FileSize.LowPart ]; DWORD BytesRead = 0; // ファイルを読む if( !::ReadFile( hFile, pHeapData, FileSize.LowPart, &BytesRead, nullptr ) ) throw( UException( HRESULT_FROM_WIN32( GetLastError() ), _T("LoadTextureDataFromFile()でエラーが発生しました。ファイルを読めません。") ) ); // 読み込んだデータサイズが不正のためエラー if( BytesRead < FileSize.LowPart ) throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。読み込んだデータサイズが不正。") ) ); // ファイルの先頭にあるマジックナンバーが 'DDS' 以外のときはファイルフォーマットが異なるためエラー DWORD dwMagicNumber = *(DWORD*)( pHeapData ); if( dwMagicNumber != DDS_MAGIC ) throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。マジックナンバーが 'DDS' 以外。") ) ); // ヘッダー領域のポインタを取得 DDS_HEADER* pHeader = reinterpret_cast<DDS_HEADER*>( pHeapData + sizeof( DWORD ) ); // サイズチェック if( pHeader->dwSize != sizeof(DDS_HEADER) || pHeader->ddspf.dwSize != sizeof(DDS_PIXELFORMAT) ) throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。ヘッダ領域に設定されているサイズが不正。") ) ); // RGBまたはRGBA の非圧縮フォーマット以外は未対応 if( !(pHeader->ddspf.dwFlags & DDS_RGB ) ) throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。RGBまたはRGBAフォーマット以外は未対応。") ) ); if( pHeader->dwHeaderFlags & DDS_HEADER_FLAGS_VOLUME ) throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。ボリュームテクスチャーは未対応。") ) ); if( pHeader->dwCubemapFlags != 0 ) throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。キューブマップは未対応。") ) ); // マジックナンバー + ヘッダーサイズ INT offset = sizeof( DWORD ) + sizeof( DDS_HEADER ); // データ領域の先頭ポインタを取得 BYTE* pBitData = pHeapData + offset; UINT iWidth = pHeader->dwWidth; UINT iHeight = pHeader->dwHeight; UINT iMipCount = pHeader->dwMipMapCount; if( iMipCount == 0 ) iMipCount = 1; else if( iMipCount > 1 ) throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。ミップマップは未対応。") ) ); D3D11_TEXTURE2D_DESC desc = {0}; desc.ArraySize = 1; if( pHeader->ddspf.dwRGBBitCount != 32 ) throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。32bitフォーマットのみ対応。") ) ); // R8G8B8A8またはR8G8B8X8のみサポートする if( IsBitMask( pHeader, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 ) ) desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; else if( IsBitMask( pHeader, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 ) ) desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; else throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。不明なフォーマット。") ) ); desc.Width = iWidth; desc.Height = iHeight; desc.MipLevels = iMipCount; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA InitData; // 最寄りのバイトに切り上げ UINT RowBytes = ( iWidth * 32 + 7 ) / 8; // データセット InitData.pSysMem = (void*)pBitData; // 1行当たりのバイト数 InitData.SysMemPitch = RowBytes; if( FAILED( hr = pD3DDevice->CreateTexture2D( &desc, &InitData, &pTex2D ) ) ) throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。テクスチャーの作成に失敗した。") ) ); D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; ::ZeroMemory( &SRVDesc, sizeof( SRVDesc ) ); SRVDesc.Format = desc.Format; SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MipLevels = desc.MipLevels; if( FAILED( hr = pD3DDevice->CreateShaderResourceView( pTex2D, &SRVDesc, ppSRV ) ) ) throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。シェーダーリソースビューの作成に失敗した。") ) ); } __finally { SAFE_RELEASE( pTex2D ); SAFE_DELETE_ARRAY( pHeapData ); if( hFile ) ::CloseHandle( hFile ); } } // レンダーターゲットビューを作成する void UMaps::CreateRenderTargetView( ID3D11Device* pD3DDevice, DXGI_FORMAT format, UINT Width, UINT Height, ID3D11RenderTargetView** ppRTView, ID3D11ShaderResourceView** ppSRView, UINT ArraySize, UINT MipmapCount ) { HRESULT hr = E_FAIL; ID3D11Texture2D* pTex2D = nullptr; __try { D3D11_TEXTURE2D_DESC Tex2DDesc; ::ZeroMemory( &Tex2DDesc, sizeof( D3D11_TEXTURE2D_DESC ) ); Tex2DDesc.ArraySize = ArraySize; Tex2DDesc.BindFlags = D3D11_BIND_RENDER_TARGET; if( ppSRView ) Tex2DDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; Tex2DDesc.Usage = D3D11_USAGE_DEFAULT; Tex2DDesc.Format = format; Tex2DDesc.Width = Width; Tex2DDesc.Height = Height; Tex2DDesc.MipLevels = MipmapCount; // 最大ミップマップ数。0のときは完全なミップマップチェーンを作成する Tex2DDesc.SampleDesc.Count = 1; // 1以外の場合はID3D11DeviceContext::GenerateMips()によりミップマップチェーンを作成するためのフラグを設定する if (MipmapCount != 1) Tex2DDesc.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; if( FAILED( hr = pD3DDevice->CreateTexture2D( &Tex2DDesc, nullptr, &pTex2D ) ) ) throw( UException( hr, _T("CreateRenderTargetView()でエラーが発生しました。テクスチャーが作成できません。") ) ); if( FAILED( hr = pD3DDevice->CreateRenderTargetView( pTex2D, nullptr, ppRTView ) ) ) throw( UException( hr, _T("CreateRenderTargetView()でエラーが発生しました。レンダーターゲットビューが作成できません。") ) ); if( ppSRView != nullptr ) UMaps::CreateSRViewFromRTView( pD3DDevice, *ppRTView, ppSRView ); } __finally { SAFE_RELEASE( pTex2D ); } } // ボリュームテクスチャー用のレンダーターゲットビューを作成する void UMaps::CreateRenderTargetViewOfVolumeTexture( ID3D11Device* pD3DDevice, DXGI_FORMAT format, UINT Width, UINT Height, UINT Depth, ID3D11RenderTargetView** ppRTView, ID3D11ShaderResourceView** ppSRView ) { HRESULT hr = E_FAIL; ID3D11Texture3D* pTex3D = nullptr; __try { D3D11_TEXTURE3D_DESC Tex3DDesc; ::ZeroMemory( &Tex3DDesc, sizeof( D3D11_TEXTURE3D_DESC ) ); Tex3DDesc.BindFlags = D3D11_BIND_RENDER_TARGET; if( ppSRView ) Tex3DDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; Tex3DDesc.Usage = D3D11_USAGE_DEFAULT; Tex3DDesc.Format = format; Tex3DDesc.Width = Width; Tex3DDesc.Height = Height; Tex3DDesc.Depth = Depth; Tex3DDesc.MipLevels = 1; if( FAILED( hr = pD3DDevice->CreateTexture3D( &Tex3DDesc, nullptr, &pTex3D ) ) ) throw( UException( hr, _T("CreateRenderTargetViewOfVolumeTexture()でエラーが発生しました。テクスチャーが作成できません。") ) ); if( FAILED( hr = pD3DDevice->CreateRenderTargetView( pTex3D, nullptr, ppRTView ) ) ) throw( UException( hr, _T("CreateRenderTargetViewOfVolumeTexture()でエラーが発生しました。レンダーターゲットビューが作成できません。") ) ); if( ppSRView != nullptr ) UMaps::CreateSRViewFromRTView( pD3DDevice, *ppRTView, ppSRView ); } __finally { SAFE_RELEASE( pTex3D ); } } // レンダーターゲットビューからシェーダーリソースビューを作成する void UMaps::CreateSRViewFromRTView( ID3D11Device* pD3DDevice, ID3D11RenderTargetView* pRTView, ID3D11ShaderResourceView** ppSRView ) { HRESULT hr = E_FAIL; ID3D11Resource* pResource = nullptr; __try { // レンダーターゲットビューからテクスチャーを取得する pRTView->GetResource( &pResource ); // シェーダーリソースビューを作成する if( FAILED( hr = pD3DDevice->CreateShaderResourceView( pResource, nullptr, ppSRView ) ) ) throw( UException( hr, _T("CreateSRViewFromRTView()でエラーが発生しました。シェーダーリソースビューが作成できません。") ) ); } __finally { SAFE_RELEASE( pResource ); } } // アンオーダードアクセスビューを作成する void UMaps::CreateRenderTargetViewOfRWTexture( ID3D11Device* pD3DDevice, DXGI_FORMAT format, UINT Width, UINT Height, ID3D11UnorderedAccessView** ppUAView, ID3D11ShaderResourceView** ppSRView, UINT ArraySize ) { HRESULT hr = E_FAIL; ID3D11Texture2D* pTex2D = nullptr; __try { D3D11_TEXTURE2D_DESC Tex2DDesc; ::ZeroMemory( &Tex2DDesc, sizeof( D3D11_TEXTURE2D_DESC ) ); Tex2DDesc.ArraySize = ArraySize; Tex2DDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; if( ppSRView ) Tex2DDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; Tex2DDesc.Usage = D3D11_USAGE_DEFAULT; Tex2DDesc.Format = format; Tex2DDesc.Width = Width; Tex2DDesc.Height = Height; Tex2DDesc.MipLevels = 1; Tex2DDesc.SampleDesc.Count = 1; if( FAILED( hr = pD3DDevice->CreateTexture2D( &Tex2DDesc, nullptr, &pTex2D ) ) ) throw( UException( hr, _T("CreateRenderTargetViewOfRWTexture()でエラーが発生しました。テクスチャーが作成できません。") ) ); if( FAILED( hr = pD3DDevice->CreateUnorderedAccessView( pTex2D, nullptr, ppUAView ) ) ) throw( UException( hr, _T("CreateRenderTargetViewOfRWTexture()でエラーが発生しました。アンオーダードアクセスビューが作成できません。") ) ); if( ppSRView != nullptr ) UMaps::CreateSRViewFromUAView( pD3DDevice, *ppUAView, ppSRView ); } __finally { SAFE_RELEASE( pTex2D ); } } // アンオーダードアクセスビューからシェーダーリソースビューを作成する void UMaps::CreateSRViewFromUAView( ID3D11Device* pD3DDevice, ID3D11UnorderedAccessView* pUAView, ID3D11ShaderResourceView** ppSRView ) { HRESULT hr = E_FAIL; ID3D11Resource* pResource = nullptr; __try { // アンオーダードアクセスビューからテクスチャーを取得する pUAView->GetResource( &pResource ); // シェーダーリソースビューを作成する if( FAILED( hr = pD3DDevice->CreateShaderResourceView( pResource, nullptr, ppSRView ) ) ) throw( UException( hr, _T("CreateSRViewFromUAView()でエラーが発生しました。シェーダーリソースビューが作成できません。") ) ); } __finally { SAFE_RELEASE( pResource ); } } // 深度ステンシルビューを作成する void UMaps::CreateDepthStencilView( ID3D11Device* pD3DDevice, UINT Width, UINT Height, ID3D11DepthStencilView** ppDSView, ID3D11ShaderResourceView** ppSRView, UINT ArraySize ) { HRESULT hr = E_FAIL; ID3D11Texture2D* pTex2D = nullptr; __try { D3D11_TEXTURE2D_DESC Tex2DDesc; ::ZeroMemory( &Tex2DDesc, sizeof( D3D11_TEXTURE2D_DESC ) ); Tex2DDesc.ArraySize = ArraySize; Tex2DDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; if( ppSRView ) Tex2DDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; Tex2DDesc.Usage = D3D11_USAGE_DEFAULT; Tex2DDesc.Format = DXGI_FORMAT_R32_TYPELESS; Tex2DDesc.Width = Width; Tex2DDesc.Height = Height; Tex2DDesc.MipLevels = 1; Tex2DDesc.SampleDesc.Count = 1; // 深度バッファ用のテクスチャー作成 hr = pD3DDevice->CreateTexture2D( &Tex2DDesc, nullptr, &pTex2D ); if( FAILED( hr ) ) throw( UException( hr, _T("CreateDepthStencilView()でエラーが発生しました。深度バッファ用のテクスチャー作成エラーです。") ) ); D3D11_DEPTH_STENCIL_VIEW_DESC DSVDesc; ::ZeroMemory( &DSVDesc, sizeof( D3D11_DEPTH_STENCIL_VIEW_DESC ) ); // テクスチャー作成時に指定したフォーマットと互換性があり、深度ステンシルビューとして指定できるフォーマットを指定する switch( Tex2DDesc.Format ) { case DXGI_FORMAT_R16_TYPELESS: DSVDesc.Format = DXGI_FORMAT_D16_UNORM; break; case DXGI_FORMAT_R32_TYPELESS: DSVDesc.Format = DXGI_FORMAT_D32_FLOAT; break; case DXGI_FORMAT_R24G8_TYPELESS: DSVDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; break; default: DSVDesc.Format = DSVDesc.Format; } switch( ArraySize ) { // 配列なし case 1: DSVDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; DSVDesc.Texture2D.MipSlice = 0; break; // 配列あり default: DSVDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; DSVDesc.Texture2DArray.ArraySize = ArraySize; DSVDesc.Texture2DArray.MipSlice = 0; DSVDesc.Texture2DArray.FirstArraySlice = 0; break; } // 深度ステンシルビューを作成 hr = pD3DDevice->CreateDepthStencilView( pTex2D, &DSVDesc, ppDSView ); if( FAILED( hr ) ) throw( UException( hr, _T("CreateDepthStencilView()でエラーが発生しました。深度ステンシルビューが作成できません。") ) ); if( ppSRView != nullptr ) UMaps::CreateSRViewFromDSView( pD3DDevice, *ppDSView, ppSRView ); } __finally { SAFE_RELEASE( pTex2D ); } } // 深度ステンシルビューからシェーダーリソースビューを作成する void UMaps::CreateSRViewFromDSView( ID3D11Device* pD3DDevice, ID3D11DepthStencilView* pDSView, ID3D11ShaderResourceView** ppSRView ) { HRESULT hr = E_FAIL; ID3D11Resource* pResource = nullptr; __try { D3D11_DEPTH_STENCIL_VIEW_DESC DSVDesc; pDSView->GetDesc( &DSVDesc ); D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; ::ZeroMemory( &SRVDesc, sizeof( D3D11_SHADER_RESOURCE_VIEW_DESC ) ); switch( DSVDesc.ViewDimension ) { case D3D11_DSV_DIMENSION_TEXTURE2D: SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MipLevels = 1; break; case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY; SRVDesc.Texture2DArray.ArraySize = DSVDesc.Texture2DArray.ArraySize; SRVDesc.Texture2DArray.MipLevels = 1; break; } switch( DSVDesc.Format ) { case DXGI_FORMAT_D16_UNORM: SRVDesc.Format = DXGI_FORMAT_R16_FLOAT; break; case DXGI_FORMAT_D32_FLOAT: SRVDesc.Format = DXGI_FORMAT_R32_FLOAT; break; case DXGI_FORMAT_D24_UNORM_S8_UINT: SRVDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; break; default: SRVDesc.Format = DSVDesc.Format; } // 深度ステンシルビューからテクスチャーを取得する pDSView->GetResource( &pResource ); // シェーダーリソースビューを作成する if( FAILED( hr = pD3DDevice->CreateShaderResourceView( pResource, &SRVDesc, ppSRView ) ) ) throw( UException( hr, _T("CreateSRViewFromDSView()でエラーが発生しました。シェーダーリソースビューが作成できません。") ) ); } __finally { SAFE_RELEASE( pResource ); } } // ノイズマップを作成する void UMaps::CreateSRViewOfNoiseMap( ID3D11Device* pD3DDevice, UINT Width, UINT Height, DXGI_FORMAT format, ID3D11ShaderResourceView** ppSRView ) { HRESULT hr = E_FAIL; ID3D11Texture2D* pTexture2D = nullptr; float* pBits = nullptr; DWORD BitsCount = 0; __try { D3D11_SUBRESOURCE_DATA SubResourceData; ::ZeroMemory( &SubResourceData, sizeof( D3D11_SUBRESOURCE_DATA ) ); switch( format ) { case DXGI_FORMAT_R32_FLOAT: BitsCount = Width * Height; pBits = NEW float[ BitsCount ]; for( DWORD i=0; i<BitsCount; i++ ) pBits[i] = (float)( rand() % 255 ) / 254.0f; SubResourceData.pSysMem = (LPVOID)pBits; SubResourceData.SysMemPitch = Width * sizeof( float ); break; case DXGI_FORMAT_R32G32B32A32_FLOAT: BitsCount = Width * Height * 4; pBits = NEW float[ BitsCount ]; for( DWORD i=0; i<BitsCount; i++ ) pBits[i] = (float)( rand() % 255 ) / 254.0f; SubResourceData.pSysMem = (LPVOID)pBits; SubResourceData.SysMemPitch = Width * sizeof( float ) * 4; break; default: throw( UException( hr, _T("CreateSRViewOfNoiseMap()でエラーが発生しました。未対応のフォーマットが指定されました。") ) ); break; } D3D11_TEXTURE2D_DESC Tex2DDesc; ::ZeroMemory( &Tex2DDesc, sizeof( D3D11_TEXTURE2D_DESC ) ); Tex2DDesc.ArraySize = 1; Tex2DDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; Tex2DDesc.Usage = D3D11_USAGE_DEFAULT; Tex2DDesc.Format = format; Tex2DDesc.Width = Width; Tex2DDesc.Height = Height; Tex2DDesc.MipLevels = 1; Tex2DDesc.SampleDesc.Count = 1; // テクスチャー作成 if( FAILED( hr = pD3DDevice->CreateTexture2D( &Tex2DDesc, &SubResourceData, &pTexture2D ) ) ) throw( UException( hr, _T("CreateSRViewOfNoiseMap()でエラーが発生しました。テクスチャーの作成に失敗しました") ) ); // シェーダーリソースビューを作成 if( FAILED( hr = pD3DDevice->CreateShaderResourceView( pTexture2D, nullptr, ppSRView ) ) ) throw( UException( hr, _T("CreateSRViewOfNoiseMap()でエラーが発生しました。シェーダーリソースビューの作成に失敗しました") ) ); } __finally { SAFE_DELETE_ARRAY( pBits ); SAFE_RELEASE( pTexture2D ); } } // 頂点、インデックスバッファを作成する ID3D11Buffer* UBuffers::CreateBuffer( ID3D11Device* pD3DDevice, void* pData, size_t size, UINT CPUAccessFlag, D3D11_BIND_FLAG BindFlag ) { HRESULT hr = E_FAIL; ID3D11Buffer* pBuffer = nullptr; // バッファー リソース。 D3D11_BUFFER_DESC BufferDesc = { 0 }; // サブリソース D3D11_SUBRESOURCE_DATA* resource = nullptr; D3D11_USAGE Usage = D3D11_USAGE_DEFAULT; UINT CPUAccessFlags = 0; __try { switch( CPUAccessFlag ) { // CPUアクセスを許可しない case 0: Usage = D3D11_USAGE_DEFAULT; CPUAccessFlags = CPUAccessFlag; break; // CPUアクセスを許可する default: Usage = D3D11_USAGE_DYNAMIC; CPUAccessFlags = CPUAccessFlag; break; } // 初期値を設定する if( pData ) { resource = new D3D11_SUBRESOURCE_DATA(); resource->pSysMem = pData; resource->SysMemPitch = 0; resource->SysMemSlicePitch = 0; } // バッファの設定 BufferDesc.ByteWidth = size; // バッファサイズ BufferDesc.Usage = Usage; // リソース使用法を特定する switch( BindFlag ) { case D3D11_BIND_STREAM_OUTPUT: BufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_STREAM_OUTPUT; break; default: BufferDesc.BindFlags = BindFlag; break; } BufferDesc.CPUAccessFlags = CPUAccessFlags; // CPU アクセス BufferDesc.MiscFlags = 0; // その他のフラグも設定しない // バッファを作成する hr = pD3DDevice->CreateBuffer( &BufferDesc, resource, &pBuffer ); if( FAILED( hr ) ) throw( UException( hr, _T("CreateBuffer()でエラーが発生しました。バッファ作成エラーです。") ) ); } __finally { SAFE_DELETE( resource ); } return pBuffer; } // サンプラーステートを作成する ID3D11SamplerState* USamplers::CreateSamplerState(ID3D11Device* pD3DDevice, D3D11_TEXTURE_ADDRESS_MODE TextureAddressMode, D3D11_FILTER Filter, D3D11_COMPARISON_FUNC ComparisonFunc) { HRESULT hr = E_FAIL; ID3D11SamplerState* pSamplerState = nullptr; // サンプラーステートを作成する D3D11_SAMPLER_DESC samplerDesc; ::ZeroMemory(&samplerDesc, sizeof(D3D11_SAMPLER_DESC)); samplerDesc.Filter = Filter; // サンプリング時に使用するフィルタ。 samplerDesc.AddressU = TextureAddressMode; // 0 〜 1 の範囲外にある u テクスチャー座標の描画方法 samplerDesc.AddressV = TextureAddressMode; // 0 〜 1 の範囲外にある v テクスチャー座標 samplerDesc.AddressW = TextureAddressMode; // 0 〜 1 の範囲外にある w テクスチャー座標 samplerDesc.MipLODBias = 0; // 計算されたミップマップ レベルからのバイアス samplerDesc.MaxAnisotropy = 1; // サンプリングに異方性補間を使用している場合の限界値。有効な値は 1 〜 16 。 samplerDesc.ComparisonFunc = ComparisonFunc; // 比較オプション。 samplerDesc.BorderColor[0] = 0; samplerDesc.BorderColor[1] = 0; samplerDesc.BorderColor[2] = 0; samplerDesc.BorderColor[3] = 0; samplerDesc.MinLOD = 0; // アクセス可能なミップマップの下限値 samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; // アクセス可能なミップマップの上限値 hr = pD3DDevice->CreateSamplerState(&samplerDesc, &pSamplerState); if (FAILED(hr)) throw(UException(-1, _T("UIMesh;;CreateSamplerState()でエラーが発生しました。サンプラーステートを作成できません。"))); return pSamplerState; } UDirect3D11::UDirect3D11() { m_hWnd = nullptr; m_pD3DDevice = nullptr; m_pD3DDeviceContext = nullptr; m_pAdapter = nullptr; m_pSwapChain = nullptr; m_pRenderTargetView = nullptr; m_pDepthStencilView = nullptr; m_UseDepthBuffer = TRUE; m_UseMultiSample = TRUE; } UDirect3D11::~UDirect3D11() { Invalidate(); } // メモリ解放 void UDirect3D11::Invalidate() { ULONG cnt; TCHAR s[256]; if( m_pDepthStencilView ) { cnt = m_pDepthStencilView->Release(); if( cnt != 0 ) { _stprintf_s( s, _T("■□■ID3D11DepthStencilViewの参照カウンタが不正です。:( %d )\n"), cnt ); OutputDebugString( s ); } m_pDepthStencilView = nullptr; } if( m_pRenderTargetView ) { cnt = m_pRenderTargetView->Release(); if( cnt != 0 ) { _stprintf_s( s, _T("■□■m_pRenderTargetViewの参照カウンタが不正です。:( %d )\n"), cnt ); OutputDebugString( s ); } m_pRenderTargetView = nullptr; } if( m_pSwapChain ) { // スワップ チェーンをフルスクリーン モードで解放できないことがあるらしい。 // フルスクリーンの場合ウィンドウモードに切り替えてから解放する必要があるらしい。 // DXGI の概要 BOOL FullScreen; m_pSwapChain->GetFullscreenState( &FullScreen, nullptr ); // フルスクリーンのとき if( FullScreen == TRUE ) m_pSwapChain->SetFullscreenState( FALSE, nullptr ); cnt = m_pSwapChain->Release(); if( cnt != 0 ) { _stprintf_s( s, _T("■□■m_pSwapChainの参照カウンタが不正です。:( %d )\n"), cnt ); OutputDebugString( s ); } m_pSwapChain = nullptr; } if( m_pD3DDeviceContext ) { cnt = m_pD3DDeviceContext->Release(); if( cnt != 0 ) { _stprintf_s( s, _T("■□■m_pD3DDeviceContextの参照カウンタが不正です。:( %d )\n"), cnt ); OutputDebugString( s ); } m_pD3DDeviceContext = nullptr; } if( m_pD3DDevice ) { cnt = m_pD3DDevice->Release(); if( cnt != 0 ) { _stprintf_s( s, _T("■□■m_pD3DDeviceの参照カウンタが不正です。:( %d )\n"), cnt ); OutputDebugString( s ); } m_pD3DDevice = nullptr; } if( m_pAdapter ) { cnt = m_pAdapter->Release(); if( cnt != 0 ) { _stprintf_s( s, _T("■□■m_pAdapterの参照カウンタが不正です。:( %d )\n"), cnt ); OutputDebugString( s ); } m_pAdapter = nullptr; } } // デフォルトディスプレイのモードを列挙する void UDirect3D11::GetDisplayMode(DXGI_MODE_DESC* pModeDesc, UINT* pNum) { HRESULT hr = E_FAIL; IDXGIOutput* pOutput = nullptr; __try { // アダプターを取得。 CreateAdapter(); // アダプターに接続されているプライマリディスプレイを取得。 hr = m_pAdapter->EnumOutputs( 0, &pOutput ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::GetDisplayMode()でエラーが発生しました。アダプターに接続されているプライマリディスプレイの取得に失敗しました。") ) ); // ディスプレイモードの一覧を取得 hr = pOutput->GetDisplayModeList( UD3D11_FORMAT, 0, pNum, pModeDesc ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::GetDisplayMode()でエラーが発生しました。ディスプレイモードの一覧の取得に失敗しました。") ) ); if( pModeDesc == nullptr ) { // 0 が返ることがあるか不明だが念のため if( *pNum == 0 ) throw( UException( hr, _T("UDirect3D11::GetDisplayMode()でエラーが発生しました。ディスプレイモードが1つも取得できません。") ) ); } } __finally { SAFE_RELEASE( pOutput ); } } // デフォルトアダプターのインターフェースを作成する // アダプターは1個に限定する void UDirect3D11::CreateAdapter() { HRESULT hr = E_FAIL; IDXGIFactory* pFactory = nullptr; if( m_pAdapter == nullptr ) { __try { // ファクトリを作成する。 hr = CreateDXGIFactory( __uuidof(IDXGIFactory), (void**)(&pFactory) ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::CreateAdapter()でエラーが発生しました。ファクトリの作成エラーです。") ) ); // デフォルトアダプターを取得 hr = pFactory->EnumAdapters( 0, &m_pAdapter ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::CreateAdapter()でエラーが発生しました。デフォルトアダプターの作成エラーです。") ) ); } __finally { SAFE_RELEASE( pFactory ); } } } // ウィンドウの作成 および Direct3Dの初期化 void UDirect3D11::CreateDirect3D11( TCHAR* AppName, HINSTANCE hInstance, WNDPROC WndProc, DXGI_MODE_DESC* pDisplayMode, BOOL UseMultisample, BOOL UseDepthBuffer ) { m_UseMultiSample = UseMultisample; m_UseDepthBuffer = UseDepthBuffer; __try { // ウィンドウを作成 InitWindow( AppName, hInstance, WndProc, pDisplayMode ); // アダプターを取得。 CreateAdapter(); // デバイスの作成 CreateDevice(); // スワップチェーンの作成 CreateSwapChain( pDisplayMode ); // レンダリングターゲットビューの作成 CreateRenderTargetView(); // 深度ステンシルビューの作成 CreateDepthStencilView(); // レンダーターゲットビューの設定 m_pD3DDeviceContext->OMSetRenderTargets( 1, &m_pRenderTargetView, m_pDepthStencilView ); // ビューポート作成 CreateViewport(); // 表示モードの自動切換えを無効にする。 // 自動切換えを有効にする場合はこの関数をコメントアウトする。 // しかしコメントアウトした場合、初期起動をフルスクリーンモードにしたとき正しく動作してくれない。 SetWindowAssociation(); // デフォルトのラスタライザを設定する SetDefaultRasterize(); // デフォルトの深度ステンシルステートを設定する SetDefaultDepthStencilState(); } __finally { SAFE_RELEASE( m_pAdapter ); } } // ウィンドウ作成 void UDirect3D11::InitWindow( TCHAR* AppName, HINSTANCE hInstance, WNDPROC WndProc, DXGI_MODE_DESC* pDisplayMode ) { // ウィンドウモード DWORD WindowStyle = WS_BORDER | WS_CAPTION | WS_SYSMENU; WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_VREDRAW | CS_HREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(DWORD); wc.hCursor = ::LoadCursor(nullptr, IDC_ARROW); wc.hIcon = nullptr; wc.hIconSm = nullptr; wc.lpszMenuName = nullptr; wc.lpszClassName = AppName; wc.hbrBackground = (HBRUSH)::GetStockObject( BLACK_BRUSH ); wc.hInstance = hInstance; ::RegisterClassEx(&wc); RECT rc; ::SetRect( &rc, 0, 0, pDisplayMode->Width, pDisplayMode->Height ); // ウィンドウモードのときタイトルバーを考慮して表示領域を設定するために必要なサイズを取得する ::AdjustWindowRect( &rc, WindowStyle, FALSE ); // ウィンドウを作成 m_hWnd = ::CreateWindow( wc.lpszClassName, wc.lpszClassName, WindowStyle, 0, 0, rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, hInstance, nullptr ); if( m_hWnd == nullptr ) throw( UException( -1, _T("UDirect3D11::InitWindow()でエラーが発生しました。ウィンドウが作成できません。") ) ); } // デバイスの作成 void UDirect3D11::CreateDevice() { HRESULT hr = E_FAIL; // デバイス作成時に使用するビデオカードの性能一覧 // Direct3D11.0の SM 5.0 のみサポートする D3D_FEATURE_LEVEL FeatureLevel[] = { D3D_FEATURE_LEVEL_11_0, // Direct3D 11.0 SM 5 }; #if defined(DEBUG) || defined(_DEBUG) // デバッグコンパイルの場合、デバッグレイヤーを有効にする。 // ソフトウェア レイヤー UINT createDeviceFlag = D3D11_CREATE_DEVICE_DEBUG; #else UINT createDeviceFlag = 0; #endif D3D_FEATURE_LEVEL level; // デバイスを作成する。 hr = D3D11CreateDevice( m_pAdapter, // 使用するアダプターを設定。nullptrの場合はデフォルトのアダプター。 D3D_DRIVER_TYPE_UNKNOWN, // D3D_DRIVER_TYPEのいずれか。ドライバーの種類。pAdapterが nullptr 以外の場合は、D3D_DRIVER_TYPE_UNKNOWNを指定する。 nullptr, // ソフトウェアラスタライザを実装するDLLへのハンドル。D3D_DRIVER_TYPE を D3D_DRIVER_TYPE_SOFTWARE に設定している場合は nullptr にできない。 createDeviceFlag, // D3D11_CREATE_DEVICE_FLAGの組み合わせ。デバイスを作成時に使用されるパラメータ。 FeatureLevel, // D3D_FEATURE_LEVELのポインタ 1, // D3D_FEATURE_LEVEL配列の要素数 D3D11_SDK_VERSION, // DirectX SDKのバージョン。この値は固定。 &m_pD3DDevice, // 初期化されたデバイス &level, // 採用されたフィーチャーレベル &m_pD3DDeviceContext // 初期化されたデバイスコンテキスト ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::CreateDevice()でエラーが発生しました。デバイスの作成エラーです。") ) ); // アダプターの情報を取得 DXGI_ADAPTER_DESC desc; m_pAdapter->GetDesc( &desc ); // DirectXのバージョン、シェーダモデルのバージョンと採用したアダプターの名前をデバックウィンドウに出力 TCHAR s[256]; _stprintf_s( s, _T("■□■デバイスの作成に成功!! Direct3D(11.0) SM(5) %s\n"), desc.Description ); OutputDebugString( s ); } // スワップチェーンの作成 void UDirect3D11::CreateSwapChain( DXGI_MODE_DESC* pDisplayMode ) { HRESULT hr = E_FAIL; TCHAR s[256]; IDXGIFactory* pFactory = nullptr; DXGI_SWAP_CHAIN_DESC sd; __try { ::ZeroMemory( &sd, sizeof(sd) ); ::CopyMemory( &(sd.BufferDesc), pDisplayMode, sizeof( DXGI_MODE_DESC ) ); sd.BufferDesc.Format = UD3D11_FORMAT; // バックバッファフォーマット // バックバッファのサーフェス使用法および CPU アクセス オプションを表す DXGI_USAGE 列挙型のメンバー sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // バックバッファにレンダリング可能にする。 // スワップ チェーンのバッファー数を表す値。 sd.BufferCount = 1; // 出力ウィンドウへの HWND ハンドル。このメンバーを nullptr にはできない。 sd.OutputWindow = m_hWnd; // 出力がウィンドウ モードの場合は TRUE。それ以外の場合は FALSE。 // 初期起動時の表示モードはウィンドウモードに固定とする。 sd.Windowed = TRUE; // サーフェスのスワップ処理後にバックバッファの内容を保持するか。 sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; // バックバッファの内容を保持しない。 // スワップ チェーンの動作のオプション。 sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // フルスクリーンモードに切り替えると、アプリケーション ウィンドウのサイズに合わせて解像度が変更される。 // ファクトリーを作成する // CreateDXGIFactoryで作成したファクトリーを使用すると実行できるがワーニングエラーになるので IDXGIAdapter から作成する。 hr = m_pAdapter->GetParent( __uuidof(IDXGIFactory), (void**)&pFactory ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::CreateSwapChain()でエラーが発生しました。ファクトリーの取得エラーです。") ) ); // マルチサンプリングの設定 // マルチサンプルを使用しない場合の設定 sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; int startMultisample; // サンプリング数が最大のものを採用する if( m_UseMultiSample == TRUE ) startMultisample = D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; // マルチサンプルを無効にする。 else startMultisample = 1; UINT Quality = 0; for( int i=startMultisample; i>=0; i-- ) { // サポートするクォリティレベルの最大値を取得する hr = m_pD3DDevice->CheckMultisampleQualityLevels( pDisplayMode->Format, (UINT)i, &Quality ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::CreateSwapChain()でエラーが発生しました。サポートするクォリティレベルの最大値の取得エラーです。") ) ); // 0 以外のときフォーマットとサンプリング数の組み合わせをサポートする // オンラインヘルプではCheckMultisampleQualityLevelsの戻り値が 0 のときサポートされないとかかれているが // pNumQualityLevels の戻り値が 0 かで判断する。 // Direct3D 10 版 のオンラインヘルプにはそうかかれているので、オンラインヘルプの間違い。 if( Quality != 0 ) { sd.SampleDesc.Count = i; sd.SampleDesc.Quality = Quality - 1; // スワップチェーンを作成する。 hr = pFactory->CreateSwapChain( m_pD3DDevice, &sd, &m_pSwapChain ); _stprintf_s( s, _T("■□■マルチサンプル:Count(%d) Quality(%d)"), sd.SampleDesc.Count, sd.SampleDesc.Quality ); if( SUCCEEDED( hr ) ) { if( sd.SampleDesc.Count == 1 ) m_UseMultiSample = FALSE; _tcscat_s( s, _T(" ⇒ OK\n") ); OutputDebugString( s ); break; } else { _tcscat_s( s, _T(" ⇒ NG\n") ); OutputDebugString( s ); } } } if( m_pSwapChain == nullptr ) throw( UException( -1, _T("UDirect3D11::CreateSwapChain()でエラーが発生しました。スワップチェーンが作成できませんでした") ) ); _stprintf_s( s, _T( "■□■ディスプレイモード:解像度( %d : %d ) リフレッシュレート( %d / %d )\n" ), pDisplayMode->Width, pDisplayMode->Height, pDisplayMode->RefreshRate.Denominator, pDisplayMode->RefreshRate.Numerator ); OutputDebugString( s ); } __finally { SAFE_RELEASE( pFactory ); } } // レンダリングターゲットビューの作成 void UDirect3D11::CreateRenderTargetView() { HRESULT hr = E_FAIL; ID3D11Texture2D* pBackBuffer = nullptr; __try { // スワップチェーンからバックバッファを取得する hr = m_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (void**)&pBackBuffer ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::CreateRenderTargetView()でエラーが発生しました。スワップチェーンからバックバッファの取得エラーです。") ) ); // レンダリングターゲットビューの作成 hr = m_pD3DDevice->CreateRenderTargetView( pBackBuffer, nullptr, &m_pRenderTargetView ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::CreateRenderTargetView()でエラーが発生しました。レンダリングターゲットビューの作成エラーです。") ) ); } __finally { SAFE_RELEASE( pBackBuffer ); } } // 深度ステンシルビューの作成 void UDirect3D11::CreateDepthStencilView() { HRESULT hr = E_FAIL; ID3D11Texture2D* pBackBuffer = nullptr; ID3D11Texture2D* pDepthBuffer = nullptr; D3D11_TEXTURE2D_DESC descDS; D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; DXGI_SWAP_CHAIN_DESC chainDesc; if( m_UseDepthBuffer == FALSE ) return; __try { // スワップチェーンの設定を取得する hr = m_pSwapChain->GetDesc( &chainDesc ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::CreateDepthStencilView()でエラーが発生しました。スワップチェーンの設定の取得エラーです。") ) ); ::ZeroMemory( &descDS, sizeof( D3D11_TEXTURE2D_DESC ) ); descDS.Width = chainDesc.BufferDesc.Width; // バックバッファと同じにする。 descDS.Height = chainDesc.BufferDesc.Height; // バックバッファと同じにする。 descDS.MipLevels = 1; // ミップマップを作成しない descDS.ArraySize = 1; // テクスチャーの配列数 descDS.Format = UD3D11_DEPTH_FORMAT; // フォーマット descDS.SampleDesc.Count = chainDesc.SampleDesc.Count; // バックバッファと同じにする。 descDS.SampleDesc.Quality = chainDesc.SampleDesc.Quality; // バックバッファと同じにする。 descDS.Usage = D3D11_USAGE_DEFAULT; // GPU による読み取りおよび書き込みアクセスを必要とするリソース。 descDS.BindFlags = D3D11_BIND_DEPTH_STENCIL | // 深度ステンシルバッファとして作成する D3D11_BIND_SHADER_RESOURCE; // シェーダーリソースビューとして作成する descDS.CPUAccessFlags = 0; // CPU アクセスが不要。 descDS.MiscFlags = 0; // その他のフラグも設定しない。 // 深度バッファ用のテクスチャー作成 hr = m_pD3DDevice->CreateTexture2D( &descDS, nullptr, &pDepthBuffer ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::CreateDepthStencilView()でエラーが発生しました。深度バッファ用のテクスチャー作成エラーです。") ) ); ::ZeroMemory( &descDSV, sizeof( D3D11_DEPTH_STENCIL_VIEW_DESC ) ); // テクスチャー作成時に指定したフォーマットと互換性があり、深度ステンシルビューとして指定できるフォーマットを指定する switch( descDS.Format ) { // 8ビットフォーマットは使用できない? case DXGI_FORMAT_R8_TYPELESS: descDSV.Format = DXGI_FORMAT_R8_UNORM; break; case DXGI_FORMAT_R16_TYPELESS: descDSV.Format = DXGI_FORMAT_D16_UNORM; break; case DXGI_FORMAT_R32_TYPELESS: descDSV.Format = DXGI_FORMAT_D32_FLOAT; break; case DXGI_FORMAT_R24G8_TYPELESS: descDSV.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; break; default: descDSV.Format = descDS.Format; } // マルチサンプルを使用している場合 if( chainDesc.SampleDesc.Count > 1 ) descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; // マルチサンプルを使用していない場合 else descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; descDSV.Texture2D.MipSlice = 0; // 深度ステンシルビューを作成 hr = m_pD3DDevice->CreateDepthStencilView( pDepthBuffer, &descDSV, &m_pDepthStencilView ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::CreateDepthStencilView()でエラーが発生しました。深度ステンシルビューの作成エラーです。") ) ); } __finally { SAFE_RELEASE( pDepthBuffer ); SAFE_RELEASE( pBackBuffer ); } } // ビューポートの作成 void UDirect3D11::CreateViewport() { HRESULT hr = E_FAIL; DXGI_SWAP_CHAIN_DESC chainDesc; // スワップチェーンの設定を取得する hr = m_pSwapChain->GetDesc( &chainDesc ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::CreateViewport()でエラーが発生しました。スワップチェーンの設定の取得エラーです。") ) ); D3D11_VIEWPORT Viewport[1]; Viewport[0].TopLeftX = 0; Viewport[0].TopLeftY = 0; Viewport[0].Width = (FLOAT)chainDesc.BufferDesc.Width; Viewport[0].Height = (FLOAT)chainDesc.BufferDesc.Height; Viewport[0].MinDepth = 0.0f; Viewport[0].MaxDepth = 1.0f; m_pD3DDeviceContext->RSSetViewports( 1, Viewport ); } // ウィンドウアソシエーション void UDirect3D11::SetWindowAssociation() { HRESULT hr = E_FAIL; IDXGIFactory* pFactory = nullptr; __try { // ファクトリーを作成する // CreateDXGIFactoryで作成したファクトリーを使用すると実行できるがワーニングエラーになるので IDXGIAdapter から作成する。 hr = m_pAdapter->GetParent( __uuidof(IDXGIFactory), (void**)&pFactory ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::SetWindowAssociation()でエラーが発生しました。ファクトリーの取得エラーです。") ) ); // 表示モードの自動切換えを無効にする。 hr = pFactory->MakeWindowAssociation( m_hWnd, DXGI_MWA_NO_WINDOW_CHANGES ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::SetWindowAssociation()でエラーが発生しました。ウィンドウアソシエーションの作成エラーです。") ) ); } __finally { SAFE_RELEASE( pFactory ); } } // デフォルトのラスタライザを設定 void UDirect3D11::SetDefaultRasterize() { HRESULT hr = E_FAIL; ID3D11RasterizerState* g_pRasterState = nullptr; D3D11_RASTERIZER_DESC rsState; __try { rsState.FillMode = D3D11_FILL_SOLID; // ポリゴン面描画 rsState.CullMode = D3D11_CULL_BACK; // 裏面を描画しない rsState.FrontCounterClockwise = TRUE; // 反時計回りを表面 rsState.DepthBias = 0; rsState.DepthBiasClamp = 0; rsState.SlopeScaledDepthBias = 0; rsState.DepthClipEnable = TRUE; rsState.ScissorEnable = FALSE; // シザー矩形無効 // スワップチェーンのマルチサンプリングの設定にあわせる DXGI_SWAP_CHAIN_DESC swapDesc; m_pSwapChain->GetDesc( &swapDesc ); if( swapDesc.SampleDesc.Count != 1 ) rsState.MultisampleEnable = TRUE; else rsState.MultisampleEnable = FALSE; rsState.AntialiasedLineEnable = FALSE; hr = m_pD3DDevice->CreateRasterizerState( &rsState, &g_pRasterState ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::SetDefaultRasterize()でエラーが発生しました。ラスタライザステートの作成エラーです。") ) ); m_pD3DDeviceContext->RSSetState( g_pRasterState ); } __finally { SAFE_RELEASE( g_pRasterState ); } } // デフォルトの深度ステンシルステートを設定 void UDirect3D11::SetDefaultDepthStencilState() { HRESULT hr = E_FAIL; ID3D11DepthStencilState* pDepthStencilState = nullptr; D3D11_DEPTH_STENCIL_DESC dsState; __try { ::ZeroMemory( &dsState, sizeof( D3D11_DEPTH_STENCIL_DESC ) ); dsState.DepthEnable = TRUE; dsState.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; dsState.DepthFunc = D3D11_COMPARISON_LESS; dsState.StencilEnable = FALSE; hr = m_pD3DDevice->CreateDepthStencilState( &dsState, &pDepthStencilState ); if( FAILED( hr ) ) throw( UException( hr, _T("UDirect3D11::SetDefaultDepthStencilState()でエラーが発生しました。深度ステンシルステートの作成エラーです。") ) ); m_pD3DDeviceContext->OMSetDepthStencilState( pDepthStencilState, 0 ); } __finally { SAFE_RELEASE( pDepthStencilState ); } } HRESULT UDirect3D11::Present( UINT SyncInterval, UINT Flags ) { HRESULT hr = E_FAIL; if( FAILED( hr = m_pSwapChain->Present( SyncInterval, Flags ) ) ) throw( UException( hr, _T("UDirect3D11::Present()でエラーが発生しました。") ) ); return hr; }
※と書きましたが、オブジェクト アンワインディングが必要な関数内で __try を使用できません。というエラーがうっとうしいのでそのうちやめるかも。
#ifndef UGRAPHICS_PIPELINE_H #define UGRAPHICS_PIPELINE_H #include "UCommon.h" #include <D3Dcompiler.h> #include "UException.h" #include "UDirect3D11.h" class UGraphicsPipeline { private: // 入力レイアウト ID3D11InputLayout* m_pLayout; // 頂点シェーダー // とりあえずストリームアウトプットは考慮しない ID3D11VertexShader* m_pVertexShader; // ハルシェーダー ID3D11HullShader* m_pHullShader; // ドメインシェーダー ID3D11DomainShader* m_pDomainShader; // ジオメトリシェーダー ID3D11GeometryShader* m_pGeometryShader; // ピクセルシェーダー ID3D11PixelShader* m_pPixelShader; // ラスタライザステート ID3D11RasterizerState* m_pRasterizerState; // 深度ステンシルステート ID3D11DepthStencilState* m_pDepthStencilState; // ブレンドステート ID3D11BlendState* m_pBlendState; public: enum class UEBLEND_STATE { NONE = 0, ADD = 1, ALIGNMENT = 2, DEPTH_TEST = 3, }; enum class UEACCESS_FLAG { CPU_NONE_GPU_READWRITE = 0, // CPUによるアクセスなし、GPUによる読込みと書込み. UPDATE_SUBRESOURCE = 1, // ID3D11DeviceContext::UpdateSubresource()を使用してコピーを行う場合 CPU_WRITE_GPU_READ = 2, // CPUによる書込み、GPUによる読込み }; UGraphicsPipeline(); virtual ~UGraphicsPipeline(); void Invalidate(); // 頂点シェーダーをファイルから作成する void CreateVertexShaderFromFile( ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR pFunctionName[], D3D11_INPUT_ELEMENT_DESC pInputElementDescs[], UINT NumElements ); // 頂点シェーダーをメモリから作成する void CreateVertexShaderFromMemory( ID3D11Device* pD3DDevice, BYTE* pShader, size_t size, D3D11_INPUT_ELEMENT_DESC pInputElementDescs[], UINT NumElements ); // ハルシェーダーをファイルから作成する void CreateHullShaderFromFile(ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR pFunctionName[]); // ハルシェーダーをメモリから作成する void CreateHullShaderFromMemory(ID3D11Device* pD3DDevice, BYTE* pShader, size_t size); // ドメインシェーダーをファイルから作成する void CreateDomainShaderFromFile(ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR pFunctionName[]); // ドメインシェーダーをメモリから作成する void CreateDomainShaderFromMemory(ID3D11Device* pD3DDevice, BYTE* pShader, size_t size); // ジオメトリシェーダーをファイルから作成する void CreateGeometryShaderFromFile( ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR pFunctionName[] ); // ジオメトリシェーダーをメモリから作成する void CreateGeometryShaderFromMemory( ID3D11Device* pD3DDevice, BYTE* pShader, size_t size ); // ピクセルシェーダーをファイルから作成する void CreatePixelShaderFromFile( ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR pFunctionName[] ); // ピクセルシェーダーをメモリから作成する void CreatePixelShaderFromMemory( ID3D11Device* pD3DDevice, BYTE* pShader, size_t size ); // ラスタライザステートを作成 void CreateRasterizerState( ID3D11Device* pD3DDevice, D3D11_CULL_MODE CullMode, D3D11_FILL_MODE FillMode = D3D11_FILL_SOLID ); // 深度ステンシルステートを作成 void CreateDepthStencilState( ID3D11Device* pD3DDevice, BOOL DepthEnable, D3D11_DEPTH_WRITE_MASK DepthWriteEnabled, D3D11_COMPARISON_FUNC DepthFunc = D3D11_COMPARISON_LESS ); // ブレンドステートを作成 void CreateBlendState( ID3D11Device* pD3DDevice, UEBLEND_STATE* BlendStateType, UINT BlendStateTypeLength, BOOL AlphaToCoverageEnable = FALSE ); // 定数バッファを作成する ID3D11Buffer* CreateConstantBuffer( ID3D11Device* pD3DDevice, void* pData, size_t size, UINT CPUAccessFlag ); // 頂点シェーダーをデバイスに設定する inline void SetVertexShader( ID3D11DeviceContext* pD3DDeviceContext ) { // 入力アセンブラー ステージを設定 pD3DDeviceContext->IASetInputLayout( m_pLayout ); // 頂点シェーダーをデバイスに設定する。 pD3DDeviceContext->VSSetShader( m_pVertexShader, nullptr, 0 ); } // ハルシェーダーをデバイスに設定する inline void SetHullShader( ID3D11DeviceContext* pD3DDeviceContext ) { pD3DDeviceContext->HSSetShader( m_pHullShader, nullptr, 0 ); } // ドメインシェーダーをデバイスに設定する inline void SetDomainShader( ID3D11DeviceContext* pD3DDeviceContext ) { pD3DDeviceContext->DSSetShader( m_pDomainShader, nullptr, 0 ); } // ジオメトリシェーダーをデバイスに設定する inline void SetGeometryShader( ID3D11DeviceContext* pD3DDeviceContext ) { pD3DDeviceContext->GSSetShader( m_pGeometryShader, nullptr, 0 ); } // ピクセルシェーダーをデバイスに設定する inline void SetPixelShader( ID3D11DeviceContext* pD3DDeviceContext ) { pD3DDeviceContext->PSSetShader( m_pPixelShader, nullptr, 0 ); } // ラスタライザステートをデバイスに設定する inline void SetRasterizerState( ID3D11DeviceContext* pD3DDeviceContext ) { pD3DDeviceContext->RSSetState( m_pRasterizerState ); } // 深度ステンシルステートをデバイスに設定する inline void SetDepthStencilState( ID3D11DeviceContext* pD3DDeviceContext ) { pD3DDeviceContext->OMSetDepthStencilState( m_pDepthStencilState, 0 ); } // ブレンドステートをデバイスに設定する inline void SetBlendState( ID3D11DeviceContext* pD3DDeviceContext ) { pD3DDeviceContext->OMSetBlendState( m_pBlendState, nullptr, 0xffffffff ); } }; #endif
#include "../../Header/Common/UGraphicsPipeline.h" UGraphicsPipeline::UGraphicsPipeline() { m_pLayout = nullptr; m_pVertexShader = nullptr; m_pHullShader = nullptr; m_pDomainShader = nullptr; m_pGeometryShader = nullptr; m_pPixelShader = nullptr; m_pRasterizerState = nullptr; m_pDepthStencilState = nullptr; m_pBlendState = nullptr; } UGraphicsPipeline::~UGraphicsPipeline() { Invalidate(); } void UGraphicsPipeline::Invalidate() { SAFE_RELEASE( m_pLayout ); SAFE_RELEASE( m_pVertexShader ); SAFE_RELEASE( m_pHullShader ); SAFE_RELEASE( m_pDomainShader ); SAFE_RELEASE( m_pGeometryShader ); SAFE_RELEASE( m_pPixelShader ); SAFE_RELEASE( m_pRasterizerState ); SAFE_RELEASE( m_pDepthStencilState ); SAFE_RELEASE( m_pBlendState ); } // 頂点シェーダーをファイルから作成する void UGraphicsPipeline::CreateVertexShaderFromFile( ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR pFunctionName[], D3D11_INPUT_ELEMENT_DESC pLayoutDesc[], UINT NumElements ) { HRESULT hr = E_FAIL; CHAR* Profile = "vs_5_0"; ID3DBlob* pBlob = nullptr; // 行列を列優先で設定し、古い形式の記述を許可しないようにする UINT Flag1 = D3D10_SHADER_PACK_MATRIX_COLUMN_MAJOR | D3D10_SHADER_ENABLE_STRICTNESS; // 最適化レベルを設定する #if defined(DEBUG) || defined(_DEBUG) Flag1 |= D3D10_SHADER_OPTIMIZATION_LEVEL0; #else Flag1 |= D3D10_SHADER_OPTIMIZATION_LEVEL3; #endif __try { // ファイルを元にエフェクトをコンパイルする if( FAILED( hr = D3DCompileFromFile( pSrcFile, nullptr, nullptr, pFunctionName, Profile, Flag1, 0, &pBlob, nullptr ) ) ) { TCHAR errstr[1024]; _stprintf_s(errstr, _T("UGraphicsPipeline::CreateVertexShaderFromFile()でエラーが発生しました。エフェクトファイルのコンパイルエラーです。 -> %s"), pSrcFile); throw(UException(hr, errstr)); } // 頂点シェーダーをメモリから作成する CreateVertexShaderFromMemory( pD3DDevice, (LPBYTE)pBlob->GetBufferPointer(), pBlob->GetBufferSize(), pLayoutDesc, NumElements ); } __finally { SAFE_RELEASE( pBlob ); } } // 頂点シェーダーをメモリから作成する void UGraphicsPipeline::CreateVertexShaderFromMemory( ID3D11Device* pD3DDevice, BYTE* pShader, size_t size, D3D11_INPUT_ELEMENT_DESC m_pLayoutDesc[], UINT NumElements ) { HRESULT hr = E_FAIL; // コンパイル済みシェーダーから、頂点シェーダー オブジェクトを作成する if( FAILED( hr = pD3DDevice->CreateVertexShader( pShader, size, nullptr, &m_pVertexShader ) ) ) throw( UException( hr, _T("UGraphicsPipeline::CreateVertexShaderFromMemory()でエラーが発生しました。頂点シェーダーの作成エラーです。") ) ); // シェーダーで使用される入力バッファーを記述するための入力レイアウトオブジェクトを作成する。 if( FAILED( hr = pD3DDevice->CreateInputLayout( m_pLayoutDesc, NumElements, pShader, size, &m_pLayout ) ) ) throw( UException( hr, _T("UGraphicsPipeline::CreateVertexShaderFromMemory()でエラーが発生しました。入力レイアウトの作成エラーです。") ) ); } // ハルシェーダーをファイルから作成する void UGraphicsPipeline::CreateHullShaderFromFile(ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR pFunctionName[]) { HRESULT hr = E_FAIL; CHAR* Profile = "hs_5_0"; ID3DBlob* pBlob = nullptr; UINT Flag1 = D3D10_SHADER_PACK_MATRIX_COLUMN_MAJOR | D3D10_SHADER_ENABLE_STRICTNESS; #if defined(DEBUG) || defined(_DEBUG) Flag1 |= D3D10_SHADER_OPTIMIZATION_LEVEL0; #else Flag1 |= D3D10_SHADER_OPTIMIZATION_LEVEL3; #endif __try { // ファイルを元にエフェクトをコンパイルする if (FAILED(hr = D3DCompileFromFile(pSrcFile, nullptr, nullptr, pFunctionName, Profile, Flag1, 0, &pBlob, nullptr))) { TCHAR errstr[1024]; _stprintf_s(errstr, _T("UGraphicsPipeline::CreateHullShaderFromFile()でエラーが発生しました。エフェクトファイルのコンパイルエラーです。 -> %s"), pSrcFile); throw(UException(hr, errstr)); } // ハルシェーダーをメモリから作成する CreateHullShaderFromMemory(pD3DDevice, (LPBYTE)pBlob->GetBufferPointer(), pBlob->GetBufferSize()); } __finally { SAFE_RELEASE(pBlob); } } // ハルシェーダーをメモリから作成する void UGraphicsPipeline::CreateHullShaderFromMemory(ID3D11Device* pD3DDevice, BYTE* pShader, size_t size) { HRESULT hr = E_FAIL; // コンパイル済みシェーダーから、ハルシェーダー オブジェクトを作成する if (FAILED(hr = pD3DDevice->CreateHullShader(pShader, size, nullptr, &m_pHullShader))) throw(UException(hr, _T("UGraphicsPipeline::CreateHullShaderFromMemory()でエラーが発生しました。ハルシェーダーの作成エラーです。"))); } // ドメインシェーダーをファイルから作成する void UGraphicsPipeline::CreateDomainShaderFromFile(ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR pFunctionName[]) { HRESULT hr = E_FAIL; CHAR* Profile = "ds_5_0"; ID3DBlob* pBlob = nullptr; UINT Flag1 = D3D10_SHADER_PACK_MATRIX_COLUMN_MAJOR | D3D10_SHADER_ENABLE_STRICTNESS; #if defined(DEBUG) || defined(_DEBUG) Flag1 |= D3D10_SHADER_OPTIMIZATION_LEVEL0; #else Flag1 |= D3D10_SHADER_OPTIMIZATION_LEVEL3; #endif __try { // ファイルを元にエフェクトをコンパイルする if (FAILED(hr = D3DCompileFromFile(pSrcFile, nullptr, nullptr, pFunctionName, Profile, Flag1, 0, &pBlob, nullptr))) { TCHAR errstr[1024]; _stprintf_s(errstr, _T("UGraphicsPipeline::CreateDomainShaderFromFile()でエラーが発生しました。エフェクトファイルのコンパイルエラーです。 -> %s"), pSrcFile); throw(UException(hr, errstr)); } // ドメインシェーダーをメモリから作成する CreateDomainShaderFromMemory(pD3DDevice, (LPBYTE)pBlob->GetBufferPointer(), pBlob->GetBufferSize()); } __finally { SAFE_RELEASE(pBlob); } } // ドメインシェーダーをメモリから作成する void UGraphicsPipeline::CreateDomainShaderFromMemory(ID3D11Device* pD3DDevice, BYTE* pShader, size_t size) { HRESULT hr = E_FAIL; // コンパイル済みシェーダーから、ドメインシェーダー オブジェクトを作成する if (FAILED(hr = pD3DDevice->CreateDomainShader(pShader, size, nullptr, &m_pDomainShader))) throw(UException(hr, _T("UGraphicsPipeline::CreateDomainShaderFromMemory()でエラーが発生しました。ドメインシェーダーの作成エラーです。"))); } // ジオメトリシェーダーをファイルから作成する void UGraphicsPipeline::CreateGeometryShaderFromFile( ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR pFunctionName[] ) { HRESULT hr = E_FAIL; CHAR* Profile = "gs_5_0"; ID3DBlob* pBlob = nullptr; UINT Flag1 = D3D10_SHADER_PACK_MATRIX_COLUMN_MAJOR | D3D10_SHADER_ENABLE_STRICTNESS; #if defined(DEBUG) || defined(_DEBUG) Flag1 |= D3D10_SHADER_OPTIMIZATION_LEVEL0; #else Flag1 |= D3D10_SHADER_OPTIMIZATION_LEVEL3; #endif __try { // ファイルを元にエフェクトをコンパイルする if( FAILED( hr = D3DCompileFromFile( pSrcFile, nullptr, nullptr, pFunctionName, Profile, Flag1, 0, &pBlob, nullptr ) ) ) { TCHAR errstr[1024]; _stprintf_s(errstr, _T("UGraphicsPipeline::CreateGeometryShaderFromFile()でエラーが発生しました。エフェクトファイルのコンパイルエラーです。 -> %s"), pSrcFile); throw(UException(hr, errstr)); } // ピクセルシェーダーをメモリから作成する CreateGeometryShaderFromMemory( pD3DDevice, (LPBYTE)pBlob->GetBufferPointer(), pBlob->GetBufferSize() ); } __finally { SAFE_RELEASE( pBlob ); } } // ジオメトリシェーダーをメモリから作成する void UGraphicsPipeline::CreateGeometryShaderFromMemory( ID3D11Device* pD3DDevice, BYTE* pShader, size_t size ) { HRESULT hr = E_FAIL; // コンパイル済みシェーダーから、ジオメトリシェーダー オブジェクトを作成する if( FAILED( hr = pD3DDevice->CreateGeometryShader( pShader, size, nullptr, &m_pGeometryShader ) ) ) throw( UException( hr, _T("UGraphicsPipeline::CreateGeometryShaderFromMemory()でエラーが発生しました。ジオメトリシェーダーの作成エラーです。") ) ); } // ピクセルシェーダーをファイルから作成する void UGraphicsPipeline::CreatePixelShaderFromFile( ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR pFunctionName[] ) { HRESULT hr = E_FAIL; CHAR* Profile = "ps_5_0"; ID3DBlob* pBlob = nullptr; UINT Flag1 = D3D10_SHADER_PACK_MATRIX_COLUMN_MAJOR | D3D10_SHADER_ENABLE_STRICTNESS; #if defined(DEBUG) || defined(_DEBUG) Flag1 |= D3D10_SHADER_OPTIMIZATION_LEVEL0; #else Flag1 |= D3D10_SHADER_OPTIMIZATION_LEVEL3; #endif __try { // ファイルを元にエフェクトをコンパイルする if( FAILED( hr = D3DCompileFromFile( pSrcFile, nullptr, nullptr, pFunctionName, Profile, Flag1, 0, &pBlob, nullptr ) ) ) { TCHAR errstr[1024]; _stprintf_s(errstr, _T("UGraphicsPipeline::CreatePixelShaderFromFile()でエラーが発生しました。エフェクトファイルのコンパイルエラーです。 -> %s"), pSrcFile); throw(UException(hr, errstr)); } // ピクセルシェーダーをメモリから作成する CreatePixelShaderFromMemory( pD3DDevice, (LPBYTE)pBlob->GetBufferPointer(), pBlob->GetBufferSize() ); } __finally { SAFE_RELEASE( pBlob ); } } // ピクセルシェーダーをメモリから作成する void UGraphicsPipeline::CreatePixelShaderFromMemory( ID3D11Device* pD3DDevice, BYTE* pShader, size_t size ) { HRESULT hr = E_FAIL; // コンパイル済みシェーダーから、ピクセルシェーダー オブジェクトを作成する if( FAILED( hr = pD3DDevice->CreatePixelShader( pShader, size, nullptr, &m_pPixelShader ) ) ) throw( UException( hr, _T("UGraphicsPipeline::CreatePixelShaderFromMemory()でエラーが発生しました。ピクセルシェーダーの作成エラーです。") ) ); } // ラスタライザステートを作成 void UGraphicsPipeline::CreateRasterizerState( ID3D11Device* pD3D11Device, D3D11_CULL_MODE CullMode, D3D11_FILL_MODE FillMode ) { HRESULT hr; D3D11_RASTERIZER_DESC RasterizerDesc; ::ZeroMemory( &RasterizerDesc, sizeof( RasterizerDesc ) ); RasterizerDesc.FillMode = FillMode; // ポリゴン面描画 RasterizerDesc.CullMode = CullMode; // 指定の方向を向いている三角形をカリングする RasterizerDesc.FrontCounterClockwise = TRUE; // 反時計回りを表面 RasterizerDesc.DepthBias = 0; RasterizerDesc.DepthBiasClamp = 0; RasterizerDesc.SlopeScaledDepthBias = 0; RasterizerDesc.DepthClipEnable = TRUE; RasterizerDesc.ScissorEnable = FALSE; // シザー矩形無効 RasterizerDesc.MultisampleEnable = FALSE; RasterizerDesc.AntialiasedLineEnable = FALSE; SAFE_RELEASE( m_pRasterizerState ); if( FAILED( hr = pD3D11Device->CreateRasterizerState( &RasterizerDesc, &m_pRasterizerState ) ) ) throw( UException( hr, _T("UGraphicsPipeline::CreateRasterizerState()でエラーが発生しました。ID3D11RasterizerStateインターフェースの作成エラーです。") ) ); } // 深度ステンシルステートを作成 void UGraphicsPipeline::CreateDepthStencilState( ID3D11Device* pD3DDevice, BOOL DepthEnable, D3D11_DEPTH_WRITE_MASK DepthWriteEnabled, D3D11_COMPARISON_FUNC DepthFunc ) { HRESULT hr; D3D11_DEPTH_STENCIL_DESC DSDesc; DSDesc.DepthEnable = DepthEnable; // 深度テストを行うか DSDesc.DepthWriteMask = DepthWriteEnabled; // 深度バッファへの書き込みを行うか DSDesc.DepthFunc = DepthFunc; DSDesc.StencilEnable = FALSE; SAFE_RELEASE( m_pDepthStencilState ); if( FAILED( hr = pD3DDevice->CreateDepthStencilState( &DSDesc, &m_pDepthStencilState ) ) ) throw( UException( hr, _T("UGraphicsPipeline::CreateDepthStencilState()でエラーが発生しました。ID3D11DepthStencilStateインターフェースの作成エラーです。") ) ); } // ブレンドステートを作成 void UGraphicsPipeline::CreateBlendState( ID3D11Device* pD3DDevice, UEBLEND_STATE* BlendStateType, UINT BlendStateTypeLength, BOOL AlphaToCoverageEnable ) { HRESULT hr; D3D11_BLEND_DESC BlendDesc; if( BlendStateTypeLength == 0 || BlendStateTypeLength >= 8 ) throw( UException( -1, _T("UGraphicsPipeline::CreateBlendState()でエラーが発生しました。仮引数が不正です。") ) ); ::ZeroMemory( &BlendDesc, sizeof( BlendDesc ) ); BlendDesc.AlphaToCoverageEnable = AlphaToCoverageEnable; if( BlendStateTypeLength == 1 ) BlendDesc.IndependentBlendEnable = FALSE; else BlendDesc.IndependentBlendEnable = TRUE; for( UINT i=0; i<BlendStateTypeLength; i++ ) { switch( BlendStateType[i] ) { case UEBLEND_STATE::NONE: BlendDesc.RenderTarget[i].BlendEnable = FALSE; BlendDesc.RenderTarget[i].SrcBlend = D3D11_BLEND_ONE; BlendDesc.RenderTarget[i].DestBlend = D3D11_BLEND_ONE; BlendDesc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD; BlendDesc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE; BlendDesc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO; BlendDesc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD; BlendDesc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; break; // 加算合成 case UEBLEND_STATE::ADD: BlendDesc.RenderTarget[i].BlendEnable = TRUE; BlendDesc.RenderTarget[i].SrcBlend = D3D11_BLEND_ONE; BlendDesc.RenderTarget[i].DestBlend = D3D11_BLEND_ONE; BlendDesc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD; BlendDesc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE; BlendDesc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO; BlendDesc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD; BlendDesc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; break; // 線形合成 case UEBLEND_STATE::ALIGNMENT: BlendDesc.RenderTarget[i].BlendEnable = TRUE; BlendDesc.RenderTarget[i].SrcBlend = D3D11_BLEND_SRC_ALPHA; BlendDesc.RenderTarget[i].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; BlendDesc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD; BlendDesc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE; BlendDesc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO; BlendDesc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD; BlendDesc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; break; // 深度テスト case UEBLEND_STATE::DEPTH_TEST: BlendDesc.RenderTarget[i].BlendEnable = TRUE; BlendDesc.RenderTarget[i].SrcBlend = D3D11_BLEND_ONE; BlendDesc.RenderTarget[i].DestBlend = D3D11_BLEND_ONE; BlendDesc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_MIN; // 最前面の深度値で上書きするために最小値を選択 BlendDesc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE; BlendDesc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ONE; BlendDesc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_MIN; BlendDesc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; break; } } SAFE_RELEASE( m_pBlendState ); if( FAILED( hr = pD3DDevice->CreateBlendState( &BlendDesc, &m_pBlendState ) ) ) throw( UException( hr, _T("UGraphicsPipeline::CreateBlendState()でエラーが発生しました。ID3D11BlendStateインターフェースの作成エラーです。") ) ); } // 定数バッファを作成する ID3D11Buffer* UGraphicsPipeline::CreateConstantBuffer( ID3D11Device* pD3DDevice, void* pData, size_t size, UINT CPUAccessFlag ) { HRESULT hr = E_FAIL; ID3D11Buffer* pBuffer = nullptr; // バッファー リソース。 D3D11_BUFFER_DESC BufferDesc = { 0 }; // サブリソース D3D11_SUBRESOURCE_DATA* resource = nullptr; D3D11_USAGE Usage = D3D11_USAGE_DEFAULT; UINT CPUAccessFlags = 0; __try { switch( CPUAccessFlag ) { // CPUアクセスを許可しない case 0: Usage = D3D11_USAGE_DEFAULT; CPUAccessFlags = CPUAccessFlag; break; // CPUアクセスを許可する default: Usage = D3D11_USAGE_DYNAMIC; CPUAccessFlags = CPUAccessFlag; break; } // 初期値を設定する if( pData ) { resource = new D3D11_SUBRESOURCE_DATA(); resource->pSysMem = pData; resource->SysMemPitch = 0; resource->SysMemSlicePitch = 0; } // バッファの設定 BufferDesc.ByteWidth = size; // バッファサイズ BufferDesc.Usage = Usage; // リソース使用法を特定する BufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; // バッファの種類 BufferDesc.CPUAccessFlags = CPUAccessFlags; // CPU アクセス BufferDesc.MiscFlags = 0; // その他のフラグも設定しない // バッファを作成する hr = pD3DDevice->CreateBuffer( &BufferDesc, resource, &pBuffer ); if( FAILED( hr ) ) throw( UException( hr, _T("UGraphicsPipeline::CreateConstantBuffer()でエラーが発生しました。バッファ作成エラーです。") ) ); } __finally { SAFE_DELETE( resource ); } return pBuffer; }
ちなみにここで公開しているソースは R8G8B8A8 または R8G8B8X8 フォーマットのみサポートし、ミップマップ、キューブマップ、ボリュームマップ、圧縮フォーマットには対応していません。
#ifndef UDRAWFONT_H #define UDRAWFONT_H #include "UCommon.h" #include "UException.h" #include "UGraphicsPipeline.h" #include "UDirect3D11.h" #include "../../HLSL/DebugFont_VS_Main.h" #include "../../HLSL/DebugFont_PS_Main.h" class UDebugFont { private: // 頂点定義 typedef struct _VERTEX { XMFLOAT3 pos; // 頂点の座標 XMFLOAT2 texel; // テクセル座標 }VERTEX; // 定数バッファの定義 typedef struct _CONSTANT_BUFFER { XMFLOAT2 Position; // スクリーン座標系上での表示位置 XMFLOAT2 TexelOffset; // テクスチャー上のテクセル位置を指定するオフセット値 XMFLOAT4 Color; // 頂点カラー _CONSTANT_BUFFER(){}; _CONSTANT_BUFFER( XMFLOAT2 position, XMFLOAT2 texelOffset, XMFLOAT4 color ) { ::CopyMemory( &Position, &position, sizeof( XMFLOAT2 ) ); ::CopyMemory( &TexelOffset, &texelOffset, sizeof( XMFLOAT2 ) ); ::CopyMemory( &Color, &color, sizeof( XMFLOAT4 ) ); }; }CONSTANT_BUFFER; // 頂点バッファ ID3D11Buffer* m_pVertexBuffer; // シェーダーリソースビュー ID3D11ShaderResourceView* m_pSRView; // サンプラーステート ID3D11SamplerState* m_pSamplerState; // シェーダー用定数バッファ ID3D11Buffer* m_pConstantBuffers; UGraphicsPipeline* m_pGraphicsPipeline; float m_FontWidth; // ポリゴンの横幅 float m_FontHeight; // ポリゴンの縦幅 static const int m_FontCnt = 95; // テクスチャー上のフォント数 TCHAR m_pStr[512]; XMFLOAT2 m_Position; XMFLOAT4 m_Color; public: UDebugFont(); virtual ~UDebugFont(); void Invalidate(); // 作成処理 // フォントサイズは、射影空間上での幅で指定する。1を指定するとスクリーンいっぱい分の大きさとなる // フォントサイズは作成時に設定した値を後で変更できない. void CreateMesh( ID3D11Device* pD3DDevice, float FontWidth, float FontHeight ); // 文字は半角英数字と半角記号のみサポートする.それ以外の文字をパラメータに渡した場合の動作は保証しない. // 表示位置は射影空間上での座標で設定する void NextFrame( TCHAR* pStr, XMFLOAT2* pPosition, XMFLOAT4* pColor ); // デバック用のテキストを描画する void Render( ID3D11DeviceContext* pD3DDeviceContext ); }; // ********************************************************************************** // FPS描画クラス // ********************************************************************************** class UFPS : private UDebugFont { private: DWORD m_PrevTime; // 前回時間 WORD m_FrameCounter; // FPS合計数 DWORD m_Frame; // FPS計測値 public: UFPS(); virtual ~UFPS(); void Invalidate(); void CreateMesh( ID3D11Device* pD3DDevice ); void NextFrame(); void Render( ID3D11DeviceContext* pD3DDeviceContext ); }; #endif
シェーダーソースはコンパイルしたバイナリデータをDebugFont_VS_Main.hとDebugFont_PS_Main.hに出力してインクルードしてください。
#include "../../Header/Common/UDebugFont.h" /* cbuffer cbBuffer : register( b0 ) { // 表示位置とテクセルのオフセット値 float4 g_Position : packoffset( c0 ); // 頂点カラー float4 g_Color : packoffset( c1 ); }; // テクスチャー Texture2D g_Tex : register( t0 ); // サンプラーステート SamplerState g_Sampler : register( s0 ); // 頂点シェーダーの入力パラメータ struct VS_IN { float3 pos : POSITION; // 頂点座標 float2 texel : TEXCOORD0; // テクセル }; // 頂点シェーダーの出力パラメータ struct VS_OUT_PS_IN { float4 pos : SV_POSITION; float2 texel : TEXCOORD0; float4 color : TEXCOORD1; // 頂点カラー }; // 頂点シェーダー VS_OUT_PS_IN DebugFont_VS_Main( VS_IN In ) { VS_OUT_PS_IN Out; float3 v = In.pos + float3( g_Position.xy, 0 ); Out.pos = float4( v, 1 ); Out.texel = In.texel + g_Position.zw; Out.color = g_Color; return Out; } // ピクセルシェーダ float4 DebugFont_PS_Main( VS_OUT_PS_IN In ) : SV_TARGET { float4 col = g_Tex.Sample( g_Sampler, In.texel ); return float4( col.rgb * In.color.rgb, col.a ); } */ UDebugFont::UDebugFont() { m_pVertexBuffer = nullptr; m_pSRView = nullptr; m_pSamplerState = nullptr; m_pConstantBuffers = nullptr; m_pGraphicsPipeline = nullptr; m_pStr[0] = '\0'; } UDebugFont::~UDebugFont() { Invalidate(); } void UDebugFont::Invalidate() { m_pStr[0] = '\0'; SAFE_DELETE( m_pGraphicsPipeline ); SAFE_RELEASE( m_pSamplerState ); SAFE_RELEASE( m_pSRView ); SAFE_RELEASE( m_pVertexBuffer ); SAFE_RELEASE( m_pConstantBuffers ); } void UDebugFont::CreateMesh( ID3D11Device* pD3DDevice, float FontWidth, float FontHeight ) { D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; m_pGraphicsPipeline = NEW UGraphicsPipeline(); // シェーダーを作成する m_pGraphicsPipeline->CreateVertexShaderFromMemory( pD3DDevice, (LPBYTE)g_DebugFont_VS_Main, sizeof( g_DebugFont_VS_Main ), layout, _countof( layout ) ); m_pGraphicsPipeline->CreatePixelShaderFromMemory( pD3DDevice, (LPBYTE)g_DebugFont_PS_Main, sizeof( g_DebugFont_PS_Main ) ); // ラスタライザーステートを作成する m_pGraphicsPipeline->CreateRasterizerState( pD3DDevice, D3D11_CULL_MODE::D3D11_CULL_BACK ); // 深度ステンシルステートを作成する m_pGraphicsPipeline->CreateDepthStencilState( pD3DDevice, FALSE, D3D11_DEPTH_WRITE_MASK::D3D11_DEPTH_WRITE_MASK_ALL ); // ブレンドステートを線形合成で作成する UGraphicsPipeline::UEBLEND_STATE BlendStateType[1] = { UGraphicsPipeline::UEBLEND_STATE::ALIGNMENT }; m_pGraphicsPipeline->CreateBlendState( pD3DDevice, BlendStateType, 1 ); m_FontWidth = FontWidth; // ポリゴンの横幅 m_FontHeight = FontHeight; // ポリゴンの縦幅 float TU = 1.0f / (float)m_FontCnt; // 1フォント当たりのテクセルの横幅 // 頂点のデータ UDebugFont::VERTEX v[] = { XMFLOAT3( m_FontWidth * 0.5f, m_FontHeight * 0.5f, 0 ), XMFLOAT2( TU, 0 ), XMFLOAT3( -m_FontWidth * 0.5f, m_FontHeight * 0.5f, 0 ), XMFLOAT2( 0, 0 ), XMFLOAT3( m_FontWidth * 0.5f, -m_FontHeight * 0.5f, 0 ), XMFLOAT2( TU, 1 ), XMFLOAT3( -m_FontWidth * 0.5f, -m_FontHeight * 0.5f, 0 ), XMFLOAT2( 0, 1 ) }; // 頂点バッファを作成する m_pVertexBuffer = UBuffers::CreateVertexBuffer( pD3DDevice, v, sizeof( v ), 0 ); // デカールマップをロード UMaps::CreateSRViewFromDDSFile( pD3DDevice, _T("../Resource\\DebugFont.dds"), &m_pSRView ); // サンプラーステートを作成する m_pSamplerState = USamplers::CreateSamplerState( pD3DDevice, D3D11_TEXTURE_ADDRESS_CLAMP ); // 定数バッファを作成する m_pConstantBuffers = m_pGraphicsPipeline->CreateConstantBuffer( pD3DDevice, nullptr, sizeof( UDebugFont::CONSTANT_BUFFER ), D3D11_CPU_ACCESS_WRITE ); } void UDebugFont::NextFrame( TCHAR* pStr, XMFLOAT2* pPosition, XMFLOAT4* pColor ) { _tcscpy_s( m_pStr, pStr ); ::CopyMemory( &m_Position, pPosition, sizeof( XMFLOAT2 ) ); ::CopyMemory( &m_Color, pColor, sizeof( XMFLOAT4 ) ); } void UDebugFont::Render( ID3D11DeviceContext* pD3DDeviceContext ) { HRESULT hr = E_FAIL; if (_tcsclen(m_pStr) == 0) return; XMFLOAT2 pos = m_Position; // 各種グラフィックパイプラインを設定 m_pGraphicsPipeline->SetVertexShader( pD3DDeviceContext ); m_pGraphicsPipeline->SetHullShader( pD3DDeviceContext ); m_pGraphicsPipeline->SetDomainShader( pD3DDeviceContext ); m_pGraphicsPipeline->SetGeometryShader( pD3DDeviceContext ); m_pGraphicsPipeline->SetPixelShader( pD3DDeviceContext ); m_pGraphicsPipeline->SetRasterizerState( pD3DDeviceContext ); m_pGraphicsPipeline->SetDepthStencilState( pD3DDeviceContext ); m_pGraphicsPipeline->SetBlendState( pD3DDeviceContext ); // 頂点バッファ設定 UINT stride = sizeof( UDebugFont::VERTEX ); UINT offset = 0; pD3DDeviceContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset ); // プリミティブ タイプおよびデータの順序に関する情報を設定 pD3DDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ); // ピクセルシェーダーのサンプラーステートを設定する pD3DDeviceContext->PSSetSamplers( 0, 1, &m_pSamplerState ); // デカールマップを設定する pD3DDeviceContext->PSSetShaderResources( 0, 1, &m_pSRView ); D3D11_MAPPED_SUBRESOURCE mappedResource; UDebugFont::CONSTANT_BUFFER* cBuffer; // 文字数分ループ for( int i=0; i<(int)_tcsclen( m_pStr ); i++ ) { if (m_pStr[i] == '\n') { pos.x = m_Position.x; pos.y -= m_FontHeight; continue; } if( FAILED( hr = pD3DDeviceContext->Map( m_pConstantBuffers, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource ) ) ) throw( UException( hr, _T("UDebugFont::RenderDebugText()でエラーが発生しました。ロックできません") ) ); cBuffer = (UDebugFont::CONSTANT_BUFFER*)(mappedResource.pData); // 表示位置 ::CopyMemory( &cBuffer->Position, &pos, sizeof( XMFLOAT2 ) ); // テクセル cBuffer->TexelOffset.x = (float)( m_pStr[i] - 32 ) / m_FontCnt; // TU cBuffer->TexelOffset.y = 0.0f; // TV // 頂点カラー ::CopyMemory( &cBuffer->Color, &m_Color, sizeof( XMFLOAT4 ) ); pD3DDeviceContext->Unmap( m_pConstantBuffers, 0 ); // 頂点シェーダーに定数バッファを設定する。 pD3DDeviceContext->VSSetConstantBuffers( 0, 1, &m_pConstantBuffers ); // ピクセルシェーダーに定数バッファを設定する。 pD3DDeviceContext->PSSetConstantBuffers( 0, 1, &m_pConstantBuffers ); // 描画 pD3DDeviceContext->Draw( 4, 0 ); pos.x += m_FontWidth; } } // ********************************************************************************** // FPS描画クラス // ********************************************************************************** UFPS::UFPS() { m_PrevTime = ::timeGetTime(); m_FrameCounter = 0; m_Frame = 0; } UFPS::~UFPS() { Invalidate(); } void UFPS::Invalidate() { UDebugFont::Invalidate(); } void UFPS::CreateMesh( ID3D11Device* pD3DDevice ) { UDebugFont::CreateMesh( pD3DDevice, 0.03f, 0.08f ); } void UFPS::NextFrame() { DWORD now = ::timeGetTime(); TCHAR fps[20]; if( now - m_PrevTime > 1000 ) { m_PrevTime = now; m_Frame = m_FrameCounter; m_FrameCounter = 0; } else m_FrameCounter++; _stprintf_s( fps, _T("FPS : %d"), m_Frame ); UDebugFont::NextFrame( fps, &XMFLOAT2( -0.97f, 0.95f ), &XMFLOAT4( 1, 1, 1, 1 ) ); } void UFPS::Render( ID3D11DeviceContext* pD3DDeviceContext ) { UDebugFont::Render( pD3DDeviceContext ); }
#pragma once #include <Shlwapi.h> #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/xml_parser.hpp> #include <boost/algorithm/string.hpp> #include "UCommon.h" #include "UException.h" // DirectXMath算術ライブラリ #include "DirectXMath-master/Inc/DirectXMath.h" using namespace DirectX; #pragma comment( lib, "Shlwapi.lib" ) // PathFileExists() using namespace boost::property_tree; class UColladaLoader_v2 { public: // 頂点エレメントの格納方法の種類の一覧 enum class COLLADA_GEOMETRY { UNKNOWN = 0, POLYGONS = 1, POLYLIST = 2, TRIANGLES = 3, TRIFANS = 4, TRISTRIPS = 5, }; // 頂点エレメントごとにデータを格納するための構造体 typedef struct _VERTEX_ELEMENT { // 頂点エレメントの種類 std::wstring Semantic; // 頂点エレメントで必要となるデータ数。例えば頂点座標の場合 x, y, z で 3 UINT Stride; // 実データ。Stride数分使用する std::vector<XMFLOAT4> Vector; // インデックスデータを示す std::vector<UINT> Index; _VERTEX_ELEMENT::_VERTEX_ELEMENT() { Semantic.clear(); Stride = 0; Vector.clear(); Index.clear(); } }VERTEX_ELEMENT; // COLLADAから取得した全データを格納する構造体 typedef struct _COLLADA_DATA { // 頂点エレメントの格納方法の種類 COLLADA_GEOMETRY GeometryType; // 1ポリゴンの頂点数を示す配列 std::vector<UINT> VCount; // 頂点エレメントごとのデータ配列 std::vector<VERTEX_ELEMENT> VertexElement; // テクスチャーへのパス。とりあえず1つのみとする。 std::wstring ImageFileName; _COLLADA_DATA::_COLLADA_DATA() { GeometryType = COLLADA_GEOMETRY::UNKNOWN; VCount.clear(); VertexElement.clear(); ImageFileName.clear(); } }COLLADA_DATA; typedef struct _INPUT_DATA { std::string semantic; std::string source; int offset; _INPUT_DATA::_INPUT_DATA() { semantic.clear(); source.clear(); offset = -1; } }INPUT_DATA; // 空の property tree object を作成 ptree pt; std::vector<COLLADA_DATA> m_ColladaData; private: // ジオメトリの種類を取得 UColladaLoader_v2::COLLADA_GEOMETRY GetGeometryType(); // Polylistデータを取得 void GetPolylist(); // Triangleデータを取得 void GetTriangles(); // ※ジオメトリ情報は1つのみである前提 // instance_geometryのidを取得する std::string GetGeometryId(); // ※マテリアル情報は1つのみである前提 // instance_materialのidを取得する std::string GetMaterialId(const std::string* pGeometryId); // GeometryTypeから名称を取得する std::string GetGeometryName(COLLADA_GEOMETRY GeometryType); // ポリゴン数を取得する UINT GetPolygonCount(const std::pair<const std::string, basic_ptree<std::string, std::string>>* pLibraryGeometries, const COLLADA_GEOMETRY GeometryType); // polylistまたはtrianglesタグ直下のinputタグの各属性値をセット void SetInputData(const std::pair<const std::string, basic_ptree<std::string, std::string>>* pLibraryGeometries, const COLLADA_GEOMETRY GeometryType, std::vector<INPUT_DATA>* pInputData); // VERTEXのIdからPOSITIONのIdを取得する std::string GetPositionId(const std::pair<const std::string, basic_ptree<std::string, std::string>>* pLibraryGeometries, const std::string* pVertexId); // vcountデータをセット void SetVCount(const std::pair<const std::string, basic_ptree<std::string, std::string>>* pLibraryGeometries, const COLLADA_GEOMETRY GeometryType, std::vector<UINT>* pVcount); // vcountデータをセット void SetVCount(const UINT PolygonCount, // ポリゴン数 const UINT VertexCount, // 1ポリゴンあたりの頂点数 std::vector<UINT>* pVcount); // pデータをセット void SetP(const std::pair<const std::string, basic_ptree<std::string, std::string>>* pLibraryGeometries, const COLLADA_GEOMETRY GeometryType, std::vector<UINT>* pP); // 各座標値をCOLLADA_DATAにセット void SetValues(const std::pair<const std::string, basic_ptree<std::string, std::string>>* pLibraryGeometries, const std::vector<INPUT_DATA>* pInputDataList, const std::vector<UINT>* pPDataList, COLLADA_DATA* pColladaData); // instance_effectのidを取得 std::string GetInstanceEffectId(const std::string* pMaterialId); // imageのidを取得 std::string GetImageId(const std::string* pInstanceEffectId); // imageのinit_form(テクスチャーパス)をCOLLADA_DATAにセット void SetImagePath(const std::string* pImageId, COLLADA_DATA* pColladaData); // target や url 属性値の頭の#を取り除く std::string GetID(const std::string* pTarget); std::wstring ConvertMultiByteToWideChar(const std::string* pSrcString); public: UColladaLoader_v2(); virtual ~UColladaLoader_v2(); void Invalidate(); void LoadMesh(const TCHAR * pFileName, const std::string Version = "1.4.1"); };
#include "../../Header/Common/UColladaLoader_v2.h" UColladaLoader_v2::UColladaLoader_v2() { } UColladaLoader_v2::~UColladaLoader_v2() { Invalidate(); } void UColladaLoader_v2::Invalidate() { m_ColladaData.clear(); } void UColladaLoader_v2::LoadMesh(const TCHAR* pFileName, const std::string Version) { CHAR fileName[100]; if (pFileName == nullptr) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。pFileName が NULL です。"))); } Invalidate(); if (!PathFileExists(pFileName)) { TCHAR msg[100]; _stprintf_s(msg, _T("UColladaLoader_v2でエラーが発生しました。%s:ファイルが存在しません。"), pFileName); throw(UException(-1, msg)); } #ifdef _UNICODE // boostの内部コードがワイド文字列となっているためマルチバイト文字列に変換 const int size = ::WideCharToMultiByte(CP_ACP, 0, pFileName, -1, fileName, 0, nullptr, nullptr); ::WideCharToMultiByte(CP_ACP, 0, pFileName, -1, fileName, size, nullptr, nullptr); #else strcpy_s(fileName, pFileName); #endif // XMLファイルを読み込みproperty treeにセット read_xml(fileName, pt); // バージョンチェック if (auto str = pt.get_optional<std::string>("COLLADA.<xmlattr>.version")) { if (str.get() != Version) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。未対応のCOLLADAのバージョンです。"))); } } else { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。COLLADAのバージョンを取得できません。"))); } // ジオメトリ情報を取得 UColladaLoader_v2::COLLADA_GEOMETRY type = GetGeometryType(); switch (type) { case UColladaLoader_v2::COLLADA_GEOMETRY::POLYLIST: GetPolylist(); break; case UColladaLoader_v2::COLLADA_GEOMETRY::TRIANGLES: GetTriangles(); break; default: throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。不明なメッシュタイプです。"))); } } UColladaLoader_v2::COLLADA_GEOMETRY UColladaLoader_v2::GetGeometryType() { if (pt.get_optional<std::string>("COLLADA.library_geometries.geometry.mesh.polylist")) { return UColladaLoader_v2::COLLADA_GEOMETRY::POLYLIST; } else if (pt.get_optional<std::string>("COLLADA.library_geometries.geometry.mesh.triangles")) { return UColladaLoader_v2::COLLADA_GEOMETRY::TRIANGLES; } return UColladaLoader_v2::COLLADA_GEOMETRY::UNKNOWN; } // Polylist void UColladaLoader_v2::GetPolylist() { COLLADA_DATA polylist = {}; std::string geometryId, materialId; UINT count = 0; std::vector<INPUT_DATA> inputDataList; std::vector<UINT> pdataList; std::string instanceEffectId; std::string imageId; geometryId.clear(); materialId.clear(); inputDataList.clear(); pdataList.clear(); instanceEffectId.clear(); imageId.clear(); // ジオメトリ種別を設定 polylist.GeometryType = UColladaLoader_v2::COLLADA_GEOMETRY::POLYLIST; // ※ジオメトリ情報は1つのみである前提 // instance_geometryのidを取得する geometryId = GetGeometryId(); // ※マテリアル情報は1つのみである前提 // instance_materialのidを取得する materialId = GetMaterialId(&geometryId); for (auto library_geometries : pt.get_child("COLLADA.library_geometries")) { if (library_geometries.first == "geometry") { if (auto gid = library_geometries.second.get_optional<std::string>("<xmlattr>.id")) { // geometryIdが一致 if (gid.get() == geometryId) { // ポリゴン数を取得 count = GetPolygonCount(&library_geometries, polylist.GeometryType); // polylistタグ直下のinputタグの各属性値を取得する SetInputData(&library_geometries, polylist.GeometryType, &inputDataList); // vcountデータを取得 SetVCount(&library_geometries, polylist.GeometryType, &polylist.VCount); if (count != polylist.VCount.size()) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。vcountの数が不正です。"))); } // pデータを取得 SetP(&library_geometries, polylist.GeometryType, &pdataList); // 各座標値をCOLLADA_DATAにセット SetValues(&library_geometries, &inputDataList, &pdataList, &polylist); break; } } } } if (materialId.size() != 0) { // instance_effectのidを取得 instanceEffectId = GetInstanceEffectId(&materialId); // imageのidを取得 imageId = GetImageId(&instanceEffectId); // imageのinit_form(テクスチャーパス)をCOLLADA_DATAにセット SetImagePath(&imageId, &polylist); } // データ格納 m_ColladaData.push_back(polylist); } // Triangles void UColladaLoader_v2::GetTriangles() { COLLADA_DATA triangles = {}; std::string geometryId, materialId; UINT count = 0; std::vector<INPUT_DATA> inputDataList; std::vector<UINT> pdataList; std::string instanceEffectId; std::string imageId; geometryId.clear(); materialId.clear(); inputDataList.clear(); pdataList.clear(); instanceEffectId.clear(); imageId.clear(); // ジオメトリ種別を設定 triangles.GeometryType = UColladaLoader_v2::COLLADA_GEOMETRY::TRIANGLES; // ※ジオメトリ情報は1つのみである前提 // instance_geometryのidを取得する geometryId = GetGeometryId(); // ※マテリアル情報は1つのみである前提 // instance_materialのidを取得する materialId = GetMaterialId(&geometryId); for (auto library_geometries : pt.get_child("COLLADA.library_geometries")) { if (library_geometries.first == "geometry") { if (auto gid = library_geometries.second.get_optional<std::string>("<xmlattr>.id")) { // geometryIdが一致 if (gid.get() == geometryId) { // ポリゴン数を取得 count = GetPolygonCount(&library_geometries, triangles.GeometryType); // trianglesタグ直下のinputタグの各属性値を取得する SetInputData(&library_geometries, triangles.GeometryType, &inputDataList); // vcountデータを取得 SetVCount(count, 3, &triangles.VCount); // pデータを取得 SetP(&library_geometries, triangles.GeometryType, &pdataList); // 各座標値をCOLLADA_DATAにセット SetValues(&library_geometries, &inputDataList, &pdataList, &triangles); break; } } } } if (materialId.size() != 0) { // instance_effectのidを取得 instanceEffectId = GetInstanceEffectId(&materialId); // imageのidを取得 imageId = GetImageId(&instanceEffectId); // imageのinit_form(テクスチャーパス)をCOLLADA_DATAにセット SetImagePath(&imageId, &triangles); } // データ格納 m_ColladaData.push_back(triangles); } // ※ジオメトリ情報は1つのみである前提 // instance_geometryのidを取得する std::string UColladaLoader_v2::GetGeometryId() { std::string geometryId; geometryId.clear(); // ジオメトリ情報のidを取得 for (auto node : pt.get_child("COLLADA.library_visual_scenes.visual_scene")) { if (node.first == "node") { for (auto instance_geometry : node.second.get_child("")) { if (instance_geometry.first == "instance_geometry") { for (auto url : instance_geometry.second.get_child("<xmlattr>")) { if (url.first == "url") { geometryId = GetID(&url.second.data()); } } break; } } } } if (geometryId.size() == 0) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。geometryIdが取得できません。"))); } return geometryId; } // ※マテリアル情報は1つのみである前提 // instance_materialのidを取得する std::string UColladaLoader_v2::GetMaterialId(const std::string* pGeometryId) { std::string geometryId; geometryId.clear(); std::string materialId; materialId.clear(); for (auto node : pt.get_child("COLLADA.library_visual_scenes.visual_scene")) { if (node.first == "node") { for (auto instance_geometry : node.second.get_child("")) { if (instance_geometry.first == "instance_geometry") { for (auto url : instance_geometry.second.get_child("<xmlattr>")) { if (url.first == "url") { geometryId = GetID(&url.second.data()); if (geometryId == *pGeometryId) { if (auto target = instance_geometry.second.get_optional<std::string>("bind_material.technique_common.instance_material.<xmlattr>.target")) { materialId = GetID(&target.get()); break; } } } } break; } } } } return materialId; } std::string UColladaLoader_v2::GetGeometryName(COLLADA_GEOMETRY GeometryType) { std::string geometryName; geometryName.clear(); switch (GeometryType) { case COLLADA_GEOMETRY::POLYLIST: geometryName = "polylist"; break; case COLLADA_GEOMETRY::TRIANGLES: geometryName = "triangles"; break; default: throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。GeometryNameが未設定です"))); } return geometryName; } // ポリゴン数を取得する UINT UColladaLoader_v2::GetPolygonCount(const std::pair<const std::string, basic_ptree<std::string, std::string>>* pLibraryGeometries, const COLLADA_GEOMETRY GeometryType) { UINT count = 0; if (auto c = pLibraryGeometries->second.get_optional<UINT>("mesh." + GetGeometryName(GeometryType) + ".<xmlattr>.count")) { count = c.get(); } else { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。ポリゴン数を取得できません"))); } return count; } // ポリゴンタイプ直下のinputタグの各属性値を取得する void UColladaLoader_v2::SetInputData(const std::pair<const std::string, basic_ptree<std::string, std::string>>* pLibraryGeometries, const COLLADA_GEOMETRY GeometryType, std::vector<INPUT_DATA>* pInputData) { // ポリゴンタイプ を検索 for (auto geometrylist : pLibraryGeometries->second.get_child("mesh." + GetGeometryName(GeometryType))) { // inputタグからidを取得 if (geometrylist.first == "input") { INPUT_DATA input_data = {}; for (auto input_attr : geometrylist.second.get_child("<xmlattr>")) { // semantic をセット if (input_attr.first == "semantic") { input_data.semantic = input_attr.second.data(); } // VERTEXの場合POSITIONのidをセット else if (input_attr.first == "source") { // ※属性値の最初がsemanticである前提 // VERTEXの場合 if (input_data.semantic == "VERTEX") { std::string vertexId = GetID(&input_attr.second.data()); input_data.source = GetPositionId(pLibraryGeometries, &vertexId); } // VERTEX以外の場合 else { input_data.source = GetID(&input_attr.second.data()); } } // offset値をセット else if (input_attr.first == "offset") { input_data.offset = std::stoi(input_attr.second.data()); } } // INPUT_DATAに追加 pInputData->push_back(input_data); } } if (pInputData->size() == 0) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。input要素を取得できません。"))); } for (auto input : *pInputData) { if (input.semantic.size() == 0) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。input要素のsemantic属性値を取得できません"))); } if (input.source.size() == 0) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。input要素のsource属性値を取得できません"))); } if (input.offset == -1) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。input要素のoffset属性値を取得できません"))); } } } // VERTEXのIdからPOSITIONのIdを取得する std::string UColladaLoader_v2::GetPositionId(const std::pair<const std::string, basic_ptree<std::string, std::string>>* pLibraryGeometries, const std::string* pVertexId) { std::string semantic, positionId; semantic.clear(); positionId.clear(); for (auto vertices : pLibraryGeometries->second.get_child("mesh")) { // verticesを対象として検索 if (vertices.first == "vertices") { for (auto vertices_id : vertices.second.get_child("<xmlattr>")) { // vertexIdが一致しているか if (vertices_id.first == "id" && vertices_id.second.data() == *pVertexId) { // vertexIdが一致している場合、その子要素のinputの属性値を取得 for (auto input_attr : vertices.second.get_child("input.<xmlattr>")) { if (input_attr.first == "semantic") { semantic = input_attr.second.data(); } else if (input_attr.first == "source") { if (semantic == "POSITION") { // ※属性値の最初がsemanticである前提 positionId = GetID(&input_attr.second.data()); } } } break; } } } } return positionId; } void UColladaLoader_v2::SetVCount(const std::pair<const std::string, basic_ptree<std::string, std::string>>* pLibraryGeometries, const COLLADA_GEOMETRY GeometryType, std::vector<UINT>* pVcount) { // ポリゴンタイプ を検索 for (auto polylist_list : pLibraryGeometries->second.get_child("mesh." + GetGeometryName(GeometryType))) { // vcountで検索 if (polylist_list.first == "vcount") { std::vector<std::string> temp1; std::string str = polylist_list.second.data(); // 両端のスペース除去 boost::trim(str); // 半角スペースでばらす boost::split(temp1, str, boost::is_space()); for (auto t : temp1) { pVcount->push_back(std::stoi(t.data())); } break; } } if (pVcount->size() == 0) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。vcount要素を取得できません"))); } } void UColladaLoader_v2::SetVCount(const UINT PolygonCount, // ポリゴン数 const UINT VertexCount, // 1ポリゴンあたりの頂点数 std::vector<UINT>* pVcount) { pVcount->resize(PolygonCount); for (UINT i = 0; i < PolygonCount; i++) { (*pVcount)[i] = VertexCount; } } void UColladaLoader_v2::SetP(const std::pair<const std::string, basic_ptree<std::string, std::string>>* pLibraryGeometries, const COLLADA_GEOMETRY GeometryType, std::vector<UINT>* pP) { // ポリゴンタイプ を検索 for (auto polylist_list : pLibraryGeometries->second.get_child("mesh." + GetGeometryName(GeometryType))) { if (polylist_list.first == "p") { std::vector<std::string> temp1; std::string str = polylist_list.second.data(); // 両端のスペース除去 boost::trim(str); // 半角スペースでばらす boost::split(temp1, str, boost::is_space()); for (auto t : temp1) { pP->push_back(std::stoi(t.data())); } } } if (pP->size() == 0) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。p要素を取得できません"))); } } // 各座標値をCOLLADA_DATAにセット void UColladaLoader_v2::SetValues(const std::pair<const std::string, basic_ptree<std::string, std::string>>* pLibraryGeometries, const std::vector<INPUT_DATA>* pInputDataList, const std::vector<UINT>* pPDataList, COLLADA_DATA* pColladaData) { for (auto source : pLibraryGeometries->second.get_child("mesh")) { // sourceを対象として検索 if (source.first == "source") { for (auto source_id : source.second.get_child("<xmlattr>")) { for (auto input : *pInputDataList) { if (source_id.first == "id" && source_id.second.data() == input.source) { VERTEX_ELEMENT element = {}; // semanticをセット element.Semantic = ConvertMultiByteToWideChar(&input.semantic); // strideをセット if (auto stride = source.second.get_optional<UINT>("technique_common.accessor.<xmlattr>.stride")) { element.Stride = stride.get(); } if (element.Stride == 0) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。stride要素の数が不正です。"))); } UINT count = 0; // 総要素数を取得 if (auto c = source.second.get_optional<UINT>("float_array.<xmlattr>.count")) { count = c.get(); } if (count == 0) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。countが取得できません"))); } // 座標値をセット if (auto float_array = source.second.get_optional<std::string>("float_array")) { std::vector<std::string> temp1; std::string str = float_array.get(); // 両端のスペース除去 boost::trim(str); // 半角スペースでばらす boost::split(temp1, str, boost::is_space()); float VectorElement[4]; for (UINT i = 0; i < temp1.size(); i += element.Stride) { ::ZeroMemory(VectorElement, sizeof(VectorElement)); for (UINT j = 0; j < element.Stride; j++) { VectorElement[j] = std::stof(temp1[i + j].data()); } XMFLOAT4 v = { VectorElement[0], VectorElement[1], VectorElement[2], VectorElement[3] }; element.Vector.push_back(v); } } if (count != element.Vector.size() * element.Stride) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。count値と実際のデータ数が一致しません"))); } // インデックス値をセット for (UINT i = input.offset; i < pPDataList->size(); i += pInputDataList->size()) { element.Index.push_back((*pPDataList)[i]); } // COLLADA_DATAにジオメトリ情報を追加 pColladaData->VertexElement.push_back(element); } } } } } } // instance_effectのidを取得 std::string UColladaLoader_v2::GetInstanceEffectId(const std::string* pMaterialId) { std::string instanceEffectId; instanceEffectId.clear(); for (auto library_materials : pt.get_child("COLLADA.library_materials")) { if (library_materials.first == "material") { if (auto mid = library_materials.second.get_optional<std::string>("<xmlattr>.id")) { // materialIdが一致しているか if (mid == *pMaterialId) { if (auto eid = library_materials.second.get_optional<std::string>("instance_effect.<xmlattr>.url")) { instanceEffectId = GetID(&eid.get()); break; } break; } } } } if (instanceEffectId.size() == 0) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。instance_effectのidを取得できません"))); } return instanceEffectId; } // imageのidを取得 std::string UColladaLoader_v2::GetImageId(const std::string* pInstanceEffectId) { std::string imageId; imageId.clear(); for (auto library_effects : pt.get_child("COLLADA.library_effects")) { if (library_effects.first == "effect") { if (auto eid = library_effects.second.get_optional<std::string>("<xmlattr>.id")) { // instanceEffectIdが一致しているか if (eid == *pInstanceEffectId) { if (auto init_from = library_effects.second.get_optional<std::string>("profile_COMMON.newparam.surface.init_from")) { imageId = init_from.get(); break; } } } } } if (imageId.size() == 0) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。imageのidが取得できません"))); } return imageId; } // imageのinit_form(テクスチャーパス)をCOLLADA_DATAにセット void UColladaLoader_v2::SetImagePath(const std::string* pImageId, COLLADA_DATA* pColladaData) { for (auto library_images : pt.get_child("COLLADA.library_images")) { if (library_images.first == "image") { if (auto iid = library_images.second.get_optional<std::string>("<xmlattr>.id")) { // imageIdが一致しているか if (iid == *pImageId) { if (auto init_from = library_images.second.get_optional<std::string>("init_from")) { pColladaData->ImageFileName = ConvertMultiByteToWideChar(&init_from.get()); break; } } } } } if (pColladaData->ImageFileName.size() == 0) { throw(UException(-1, _T("UColladaLoader_v2でエラーが発生しました。imageのinit_formが取得できません"))); } } // target や url 属性値の頭の#を取り除く std::string UColladaLoader_v2::GetID(const std::string* pTarget) { int ind; std::string ret; ret.clear(); ret = *pTarget; if (ret.length() > 0) { // 第二引数は開始位置 // 戻り値が-1のとき見つからない if ((ind = ret.find('#', 0)) == 0) { ret.erase(0, 1); } } return ret; } std::wstring UColladaLoader_v2::ConvertMultiByteToWideChar(const std::string* pSrcString) { WCHAR convStr[100]; std::wstring wString; // boostの内部コードがマルチバイト文字列となっているためワイド文字列に変換 const int size = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pSrcString->data(), -1, convStr, 0); ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pSrcString->data(), -1, convStr, size); wString = convStr; return wString; }
#ifndef UD3DMESHDATA_CREATER_H #define UD3DMESHDATA_CREATER_H #include "UColladaLoader_v2.h" #include "UCommon.h" #include "UException.h" #include "UDirect3D11.h" class UD3DMeshDataCreater { public: typedef struct _VERTEX { XMFLOAT3 Position; XMFLOAT3 Normal; XMFLOAT2 Texcoord; }VERTEX; private: UColladaLoader_v2 m_ColladaLoader; void SetTrianglePolygon( VERTEX* pVertices, UINT MeshIndex, UINT ElementMaxCount, ULONG* pIndex, ULONG PIndex ); void SetTriangle2ndPolygon( VERTEX* pVertices, UINT MeshIndex, UINT ElementMaxCount, ULONG* pIndex, ULONG PIndex ); public: UD3DMeshDataCreater(); virtual ~UD3DMeshDataCreater(); void Invalidate(); // COLLADAフォーマットのdaeファイルを読み込む void LoadMesh( TCHAR* pFileName ); inline UINT GetMeshCount(){ return m_ColladaLoader.m_ColladaData.size(); }; // 頂点座標を取得する // 頂点バッファ作成後、自分でメモリ開放する必要があるので注意 void GetVertexes( UINT MeshIndex, VERTEX** ppVertices, ULONG* pCount ); // テクスチャーのパスを取得する std::wstring GetTextureFileName( UINT MeshIndex ); }; #endif
#include "../../Header/Common/UD3DMeshDataCreater.h" UD3DMeshDataCreater::UD3DMeshDataCreater() { } UD3DMeshDataCreater::~UD3DMeshDataCreater() { } void UD3DMeshDataCreater::Invalidate() { } // COLLADAフォーマットのdaeファイルを読み込む void UD3DMeshDataCreater::LoadMesh( TCHAR* pFileName ) { m_ColladaLoader.LoadMesh( pFileName ); } void UD3DMeshDataCreater::SetTrianglePolygon( VERTEX* pVertices, UINT MeshIndex, UINT ElementMaxCount, ULONG* pIndex, ULONG PIndex ) { ULONG VertexIndex; for( int j=2; j>=0; j-- ) { // 頂点エレメントのループ for( UINT k=0; k<ElementMaxCount; k++ ) { if( wcscmp( m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Semantic.data(), L"VERTEX" ) == 0 ) { VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + j]; ::CopyMemory( &( pVertices[*pIndex].Position), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) ); } else if( wcscmp( m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Semantic.data(), L"NORMAL" ) == 0 ) { VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + j]; ::CopyMemory( &( pVertices[*pIndex].Normal), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) ); } else if( wcscmp( m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Semantic.data(), L"TEXCOORD" ) == 0 ) { VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + j]; ::CopyMemory( &( pVertices[*pIndex].Texcoord), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT2 ) ); } } ( *pIndex )++; } } void UD3DMeshDataCreater::SetTriangle2ndPolygon( VERTEX* pVertices, UINT MeshIndex, UINT ElementMaxCount, ULONG* pIndex, ULONG PIndex ) { ULONG VertexIndex; for( UINT k=0; k<ElementMaxCount; k++ ) { if( wcscmp( m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Semantic.data(), L"VERTEX" ) == 0 ) { VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 0]; ::CopyMemory( &( pVertices[(*pIndex) + 0].Position ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) ); VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 3]; ::CopyMemory( &( pVertices[(*pIndex) + 1].Position ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) ); VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 2]; ::CopyMemory( &( pVertices[(*pIndex) + 2].Position ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) ); } else if( wcscmp( m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Semantic.data(), L"NORMAL" ) == 0 ) { VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 0]; ::CopyMemory( &( pVertices[(*pIndex) + 0].Normal ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) ); VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 3]; ::CopyMemory( &( pVertices[(*pIndex) + 1].Normal ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) ); VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 2]; ::CopyMemory( &( pVertices[(*pIndex) + 2].Normal ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) ); } else if( wcscmp( m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Semantic.data(), L"TEXCOORD" ) == 0 ) { VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 0]; ::CopyMemory( &( pVertices[(*pIndex) + 0].Texcoord ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT2 ) ); VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 3]; ::CopyMemory( &( pVertices[(*pIndex) + 1].Texcoord ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT2 ) ); VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 2]; ::CopyMemory( &( pVertices[(*pIndex) + 2].Texcoord ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT2 ) ); } } (*pIndex) += 3; } // 頂点座標を取得する // 頂点バッファ作成後、自分でメモリ開放する必要があるので注意 void UD3DMeshDataCreater::GetVertexes( UINT MeshIndex, VERTEX** ppVertices, ULONG* pCount ) { *pCount = 0; if( ppVertices != nullptr ) *ppVertices = nullptr; if( GetMeshCount() <= MeshIndex ) throw( UException( -1, _T("UD3DMeshDataCreater::GetVertexes()でエラーが発生しました。MeshIndexが不正です。") ) ); ULONG VcountCnt = m_ColladaLoader.m_ColladaData[MeshIndex].VCount.size(); // 総頂点数を取得 ULONG MaxVCount = 0; for( ULONG i=0; i<VcountCnt; i++ ) { // 三角ポリゴンの場合 if( m_ColladaLoader.m_ColladaData[MeshIndex].VCount[i] == 3 ) MaxVCount += 3; // 四角ポリゴンの場合、三角ポリゴン2個に展開する else if( m_ColladaLoader.m_ColladaData[MeshIndex].VCount[i] == 4 ) MaxVCount += 6; // 以外はエラー else throw( UException( -1, _T("UD3DMeshDataCreater::GetVertexes()でエラーが発生しました。頂点数数が3,4以外です。") ) ); } UINT ElementMaxCount = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement.size(); *pCount = MaxVCount; *ppVertices = NEW VERTEX[MaxVCount]; ULONG PIndex = 0, Index = 0; // インデックスで頂点を共有しない方針で配列に設定していく... for( ULONG i=0; i<VcountCnt; i++ ) { switch( m_ColladaLoader.m_ColladaData[MeshIndex].VCount[i] ) { // 三角ポリゴンの場合 case 3: SetTrianglePolygon( *ppVertices, MeshIndex, ElementMaxCount, &Index, PIndex ); PIndex += 3; break; // 四角ポリゴンの場合 case 4: // 三角ポリゴン1つめ SetTrianglePolygon( *ppVertices, MeshIndex, ElementMaxCount, &Index, PIndex ); // 三角ポリゴン2つめ SetTriangle2ndPolygon( *ppVertices, MeshIndex, ElementMaxCount, &Index, PIndex ); PIndex += 4; break; } } if( MaxVCount != Index ) throw( UException( -1, _T("UD3DMeshDataCreater::GetVertexes()でエラーが発生しました。設定後の頂点数が不正です。") ) ); // 右手座標系を左手座標系に変換 for (ULONG i = 0; i<MaxVCount; i++) { (*ppVertices)[i].Position.z *= -1.0f; (*ppVertices)[i].Normal.z *= -1.0f; (*ppVertices)[i].Texcoord.y *= -1.0f; } VERTEX temp; for (ULONG i = 0; i<MaxVCount; i+=3) { ::CopyMemory(&temp, &((*ppVertices)[i + 1]), sizeof(VERTEX)); ::CopyMemory(&((*ppVertices)[i + 1]), &((*ppVertices)[i + 2]), sizeof(VERTEX)); ::CopyMemory(&((*ppVertices)[i + 2]), &temp, sizeof(VERTEX)); } } // テクスチャーのパスを取得する std::wstring UD3DMeshDataCreater::GetTextureFileName( UINT MeshIndex ) { if( GetMeshCount() <= MeshIndex ) throw( UException( -1, _T("UD3DMeshDataCreater::GetTextureFileName()でエラーが発生しました。MeshIndexが不正です。") ) ); return m_ColladaLoader.m_ColladaData[MeshIndex].ImageFileName; }
#ifndef USRVIEW_RENDERER_H #define USRVIEW_RENDERER_H #include "UCommon.h" #include "UException.h" #include "UGraphicsPipeline.h" #include "UDirect3D11.h" #include "../../HLSL/SRViewRenderer_VS_Main.h" #include "../../HLSL/SRViewRenderer_PS_Main.h" class USRViewRenderer { private: // 頂点定義 typedef struct _VERTEX { XMFLOAT3 pos; // 頂点の座標 XMFLOAT2 texel; // テクセル座標 }VERTEX; typedef struct _CBUFFER { int SrcRGBA[4]; int Dimension; float VolumeLevel; int Dummy2; int Dummy3; }CBUFFER; // 頂点バッファ ID3D11Buffer* m_pVertexBuffer; // シェーダーリソースビュー ID3D11ShaderResourceView* m_pSRView; // サンプラーステート ID3D11SamplerState* m_pSamplerState; // グラフィックパイプライン UGraphicsPipeline* m_pGraphicsPipeline; // シェーダー用定数バッファ ID3D11Buffer* m_pConstantBuffers; int m_SrcRGBA[4]; // レンダーターゲットの出力先の成分を変更する。 float m_VolumeLevel; public: USRViewRenderer(); virtual ~USRViewRenderer(); void Invalidate(); // 表示領域は射影空間上での座標系で指定する。つまり( -1.0f 〜 1.0f ) void Create( ID3D11Device* pD3DDevice, float Left, float Top, float Right, float Bottom ); void SetSRView( const ID3D11ShaderResourceView* pSRView, int SrcRGBA[4], float VolumeLevel = 0.0f ); void Render( ID3D11DeviceContext* pD3DDeviceContext ); }; #endif
シェーダーソースはコンパイルしたバイナリデータをSRViewRenderer_VS_Main.hとSRViewRenderer_PS_Main.hに出力してインクルードしてください。
2Dテクスチャー、2Dテクスチャー配列、ボリュームテクスチャーに対応しています。
#include "../../Header/Common/USRViewRenderer.h" /* // 定数バッファ cbuffer CBuffer : register( b0 ) { int4 g_SrcRGBA : packoffset( c0 ); int g_Dimension : packoffset( c1.x ); float g_VolumeLevel : packoffset( c1.y ); }; // テクスチャー Texture2D g_Tex0 : register( t0 ); Texture2DArray g_Tex1 : register( t1 ); Texture3D g_Tex2 : register( t2 ); // サンプラーステート SamplerState g_Sampler : register( s0 ); // 頂点シェーダーの入力パラメータ struct VS_IN { float3 pos : POSITION; // 頂点座標 float2 texel : TEXCOORD0; // テクセル }; // 頂点シェーダーの出力パラメータ struct VS_OUT_PS_IN { float4 pos : SV_POSITION; float2 texel : TEXCOORD0; }; // 頂点シェーダー VS_OUT_PS_IN SRViewRenderer_VS_Main( VS_IN In ) { VS_OUT_PS_IN Out; Out.pos = float4( In.pos, 1 ); Out.texel = In.texel; return Out; } // ピクセルシェーダ float4 SRViewRenderer_PS_Main( VS_OUT_PS_IN In ) : SV_TARGET { float4 col = 0; float4 colRet = 0; switch( g_Dimension ) { case 4: col = g_Tex0.Sample( g_Sampler, In.texel ); break; case 5: col = g_Tex1.Sample( g_Sampler, float3( In.texel, g_VolumeLevel ) ); break; case 8: col = g_Tex2.Sample( g_Sampler, float3( In.texel, g_VolumeLevel ) ); break; } for( int i=0; i<4; i++ ) colRet[i] = col[g_SrcRGBA[i]]; return colRet; } */ USRViewRenderer::USRViewRenderer() { m_pVertexBuffer = nullptr; m_pSRView = nullptr; m_pSamplerState = nullptr; m_pGraphicsPipeline = nullptr; m_pConstantBuffers = nullptr; } USRViewRenderer::~USRViewRenderer() { Invalidate(); } void USRViewRenderer::Invalidate() { SAFE_RELEASE( m_pConstantBuffers ); SAFE_DELETE( m_pGraphicsPipeline ); SAFE_RELEASE( m_pSamplerState ); SAFE_RELEASE( m_pVertexBuffer ); } void USRViewRenderer::Create( ID3D11Device* pD3DDevice, float Left, float Top, float Right, float Bottom ) { D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; m_pGraphicsPipeline = NEW UGraphicsPipeline(); // シェーダーを作成する m_pGraphicsPipeline->CreateVertexShaderFromMemory( pD3DDevice, (LPBYTE)g_SRViewRenderer_VS_Main, sizeof( g_SRViewRenderer_VS_Main ), layout, _countof( layout ) ); m_pGraphicsPipeline->CreatePixelShaderFromMemory( pD3DDevice, (LPBYTE)g_SRViewRenderer_PS_Main, sizeof( g_SRViewRenderer_PS_Main ) ); // ラスタライザーステートを作成する m_pGraphicsPipeline->CreateRasterizerState( pD3DDevice, D3D11_CULL_MODE::D3D11_CULL_BACK ); // 深度ステンシルステートを作成する m_pGraphicsPipeline->CreateDepthStencilState( pD3DDevice, FALSE, D3D11_DEPTH_WRITE_MASK::D3D11_DEPTH_WRITE_MASK_ALL ); // ブレンドステートを無効にする UGraphicsPipeline::UEBLEND_STATE BlendStateType[1] = { UGraphicsPipeline::UEBLEND_STATE::NONE }; m_pGraphicsPipeline->CreateBlendState( pD3DDevice, BlendStateType, 1 ); // 頂点のデータ VERTEX v[] = { XMFLOAT3( Right, Top, 0 ), XMFLOAT2( 1, 0 ), XMFLOAT3( Left, Top, 0 ), XMFLOAT2( 0, 0 ), XMFLOAT3( Right, Bottom, 0 ), XMFLOAT2( 1, 1 ), XMFLOAT3( Left, Bottom, 0 ), XMFLOAT2( 0, 1 ) }; // 頂点バッファを作成する m_pVertexBuffer = UBuffers::CreateVertexBuffer( pD3DDevice, v, sizeof( v ), 0 ); // サンプラーステートを作成する m_pSamplerState = USamplers::CreateSamplerState( pD3DDevice, D3D11_TEXTURE_ADDRESS_CLAMP ); // 定数バッファを作成する m_pConstantBuffers = m_pGraphicsPipeline->CreateConstantBuffer( pD3DDevice, nullptr, sizeof( CBUFFER ), D3D11_CPU_ACCESS_WRITE ); } void USRViewRenderer::SetSRView( const ID3D11ShaderResourceView* pSRView, int SrcRGBA[4], float VolumeLevel ) { m_pSRView = const_cast<ID3D11ShaderResourceView*>( pSRView ); ::CopyMemory( m_SrcRGBA, SrcRGBA, sizeof( int ) * _countof( m_SrcRGBA ) ); m_VolumeLevel = VolumeLevel; }; void USRViewRenderer::Render( ID3D11DeviceContext* pD3DDeviceContext ) { if( m_pSRView == nullptr ) return; HRESULT hr = E_FAIL; // 各種グラフィックパイプラインを設定 m_pGraphicsPipeline->SetVertexShader( pD3DDeviceContext ); m_pGraphicsPipeline->SetHullShader( pD3DDeviceContext ); m_pGraphicsPipeline->SetDomainShader( pD3DDeviceContext ); m_pGraphicsPipeline->SetGeometryShader( pD3DDeviceContext ); m_pGraphicsPipeline->SetPixelShader( pD3DDeviceContext ); m_pGraphicsPipeline->SetRasterizerState( pD3DDeviceContext ); m_pGraphicsPipeline->SetDepthStencilState( pD3DDeviceContext ); m_pGraphicsPipeline->SetBlendState( pD3DDeviceContext ); // 頂点バッファ設定 UINT stride = sizeof( VERTEX ); UINT offset = 0; pD3DDeviceContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset ); // プリミティブ タイプおよびデータの順序に関する情報を設定 pD3DDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ); // ピクセルシェーダーのサンプラーステートを設定する pD3DDeviceContext->PSSetSamplers( 0, 1, &m_pSamplerState ); // シェーダーリソースビューから情報取得 D3D11_SHADER_RESOURCE_VIEW_DESC Desc; m_pSRView->GetDesc( &Desc ); D3D11_MAPPED_SUBRESOURCE mappedResource; if( FAILED( hr = pD3DDeviceContext->Map( m_pConstantBuffers, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource ) ) ) throw( UException( hr, _T("USRViewRenderer::Render()でエラーが発生しました。ロックできません") ) ); CBUFFER* cBuffer = (CBUFFER*)(mappedResource.pData); ::CopyMemory( cBuffer->SrcRGBA, m_SrcRGBA, sizeof( int ) * _countof( m_SrcRGBA ) ); cBuffer->Dimension = Desc.ViewDimension; cBuffer->VolumeLevel = m_VolumeLevel; pD3DDeviceContext->Unmap( m_pConstantBuffers, 0 ); // 定数バッファを設定 pD3DDeviceContext->PSSetConstantBuffers( 0, 1, &m_pConstantBuffers ); // デカールマップを設定する switch( Desc.ViewDimension ) { case D3D11_SRV_DIMENSION_TEXTURE2D: pD3DDeviceContext->PSSetShaderResources( 0, 1, &m_pSRView ); break; case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: pD3DDeviceContext->PSSetShaderResources( 1, 1, &m_pSRView ); break; case D3D11_SRV_DIMENSION_TEXTURE3D: pD3DDeviceContext->PSSetShaderResources( 2, 1, &m_pSRView ); break; } // 描画 pD3DDeviceContext->Draw( 4, 0 ); ID3D11ShaderResourceView* pNull[] = { nullptr, nullptr, nullptr }; pD3DDeviceContext->PSSetShaderResources( 0, _countof( pNull ), pNull ); }
---ShadowMapping_Pass0.hlsl---
// ************************************************************ // Shadow Mapping Pass0 // ************************************************************ // 定数バッファ cbuffer CBuffer : register( b0 ) { column_major float4x4 g_matLightWorldViewProj : packoffset( c0 ); // ライトビューの正射影行列 }; // 頂点シェーダーの入力パラメータ struct VS_IN { float3 pos : POSITION; // 頂点座標 float3 normal : NORMAL; // 法線ベクトル float2 texel : TEXCOORD; // テクセル }; // 頂点シェーダーの出力パラメータ struct VS_OUT_PS_IN { float4 pos : SV_POSITION; }; // 頂点シェーダー VS_OUT_PS_IN ShadowMapping_Pass0_VS_Main( VS_IN In ) { VS_OUT_PS_IN Out; Out.pos = mul( float4( In.pos, 1.0f ), g_matLightWorldViewProj ); return Out; }
---ShadowMapping_Pass1.hlsl---
// ************************************************************ // Shadow Mapping Pass1 // ************************************************************ // 定数バッファ cbuffer CBuffer : register( b0 ) { column_major float4x4 g_matCameraWorldViewProj : packoffset( c0 ); // カメラビューの射影行列 column_major float4x4 g_matLightWorldViewProj : packoffset( c4 ); // ライトビューの正射影行列 float4 g_vecLightPos : packoffset( c8 ); // ローカル座標系での平行光源の位置ベクトル float4 g_DepthMapSize : packoffset( c9 ); // 深度マップのサイズ }; // 頂点シェーダーの入力パラメータ struct VS_IN { float3 pos : POSITION; // 頂点座標 float3 normal : NORMAL; // 法線ベクトル float2 texel : TEXCOORD; // テクセル }; // テクスチャー Texture2D g_DecalMap : register( t0 ); // 深度マップ Texture2D g_DepthMap : register( t1 ); // サンプラーステート SamplerState g_Sampler : register( s0 ); // 頂点シェーダーの出力パラメータ struct VS_OUT_PS_IN { float4 pos : SV_POSITION; float3 normal : NORMAL; float2 texel : TEXCOORD0; float4 posLWVP : TEXCOORD1; }; // 頂点シェーダー VS_OUT_PS_IN ShadowMapping_Pass1_VS_Main( VS_IN In ) { VS_OUT_PS_IN Out; Out.pos = mul( float4( In.pos, 1.0f ), g_matCameraWorldViewProj ); Out.posLWVP = mul( float4( In.pos, 1.0f ), g_matLightWorldViewProj ); Out.normal = In.normal; Out.texel = In.texel; return Out; } // ピクセルシェーダ float4 ShadowMapping_Pass1_PS_Main( VS_OUT_PS_IN In ) : SV_TARGET { float shadowColor; // テクセルを計算 float2 texel = float2( In.posLWVP.x / In.posLWVP.w * 0.5f + 0.5f, In.posLWVP.y / In.posLWVP.w * -0.5f + 0.5f ); // 深度マップの範囲外はとりあえず影なしにする if( texel.x < 0 || texel.x > 1 || texel.y < 0 || texel.y > 1 ) shadowColor = 1.0f; else { // 深度マップから深度値を取得 float sm = g_DepthMap.Load( float3( texel * g_DepthMapSize.xy, 0 ) ).r; // 現在の深度値と深度マップ上の深度値を比較 if( sm < In.posLWVP.z / In.posLWVP.w - 0.002f ) shadowColor = 0.3f; else shadowColor = 1.0f; } // ハーフランバート float lambert = dot( g_vecLightPos.xyz, In.normal ); lambert = lambert * 0.5f + 0.5f; // デカールマップ float4 decalmap = g_DecalMap.Sample( g_Sampler, In.texel ); return ( decalmap * min( lambert, shadowColor ) ).bgra; }
#ifndef SHADOW_MAPPING_H #define SHADOW_MAPPING_H #include "../Common/UCommon.h" #include "../Common/UException.h" #include "../Common/UGraphicsPipeline.h" #include "../Common/UDirect3D11.h" class ShadowMapping { private: // Direct3D用定数バッファ設定用構造体 typedef struct _CBUFFER_PASS0 { XMMATRIX matLightWorldViewProj; }CBUFFER_PASS0; typedef struct _CBUFFER_PASS1 { XMMATRIX matCameraWorldViewProj; XMMATRIX matLightWorldViewProj; XMFLOAT4 vecLightDir; XMFLOAT4 vecShadowMapSize; }CBUFFER_PASS1; ID3D11DepthStencilView* m_pDSView; ID3D11ShaderResourceView* m_pSRView; ID3D11RenderTargetView* m_pOldRTView; ID3D11DepthStencilView* m_pOldDSView; D3D11_VIEWPORT m_pOldViewport[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; UINT m_ViewportCount; // シェーダー用定数バッファ ID3D11Buffer* m_pConstantBuffers[2]; UGraphicsPipeline* m_pGraphicsPipeline[2]; DWORD m_Width, m_Height; int m_Pass; XMMATRIX m_MatLightViewProj; XMMATRIX m_MatCameraViewProj; XMFLOAT4 m_VecLightPos; public: ShadowMapping(); virtual ~ShadowMapping(); void Invalidate(); void Create( ID3D11Device* pD3DDevice, DWORD Width, DWORD Height ); void BeginPass( ID3D11DeviceContext* pD3DDeviceContext, UINT Pass, XMFLOAT4* pVecLightPos, XMMATRIX* pMatLightProj, XMMATRIX* pMatCameraView, XMMATRIX* pMatCameraProj ); void SetConstantBuffers( ID3D11DeviceContext* pD3DDeviceContext, XMMATRIX* pMatWorld ); void EndPass( ID3D11DeviceContext* pD3DDeviceContext ); inline UINT GetMaxPass(){ return 2; }; inline const ID3D11ShaderResourceView* GetDepthMap(){ return m_pSRView; }; }; #endif
#include "../../Header/Shader/ShadowMapping.h" #include "../../HLSL/ShadowMapping_Pass0_VS_Main.h" #include "../../HLSL/ShadowMapping_Pass1_VS_Main.h" #include "../../HLSL/ShadowMapping_Pass1_PS_Main.h" ShadowMapping::ShadowMapping() { m_pDSView = nullptr; m_pSRView = nullptr; for( int i=0; i<_countof( m_pGraphicsPipeline ); i++ ) { m_pGraphicsPipeline[i] = nullptr; m_pConstantBuffers[i] = nullptr; } m_Pass = -1; } ShadowMapping::~ShadowMapping() { for( int i=0; i<_countof( m_pGraphicsPipeline ); i++ ) { SAFE_DELETE( m_pGraphicsPipeline[i] ); SAFE_RELEASE( m_pConstantBuffers[i] ); } SAFE_RELEASE( m_pSRView ); SAFE_RELEASE( m_pDSView ); } void ShadowMapping::Create( ID3D11Device* pD3DDevice, DWORD Width, DWORD Height ) { m_Width = Width; m_Height = Height; m_Pass = -1; // ******************************************************************************************************* // パス0用のUGraphicsPipelineの作成 // ******************************************************************************************************* m_pGraphicsPipeline[0] = NEW UGraphicsPipeline(); // ラスタライザーステートを作成する m_pGraphicsPipeline[0]->CreateRasterizerState( pD3DDevice, D3D11_CULL_MODE::D3D11_CULL_BACK ); // 深度ステンシルステートを作成する m_pGraphicsPipeline[0]->CreateDepthStencilState( pD3DDevice, TRUE, D3D11_DEPTH_WRITE_MASK::D3D11_DEPTH_WRITE_MASK_ALL ); // ブレンドステートを作成する UGraphicsPipeline::UEBLEND_STATE BlendStateType[1] = { UGraphicsPipeline::UEBLEND_STATE::NONE }; m_pGraphicsPipeline[0]->CreateBlendState( pD3DDevice, BlendStateType, 1 ); D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; // シェーダーを作成する #if defined(DEBUG) || defined(_DEBUG) m_pGraphicsPipeline[0]->CreateVertexShaderFromFile( pD3DDevice, _T("../HLSL/ShadowMapping_Pass0.hlsl"), "ShadowMapping_Pass0_VS_Main", layout, _countof( layout ) ); #else m_pGraphicsPipeline[0]->CreateVertexShaderFromMemory( pD3DDevice, (LPBYTE)g_ShadowMapping_Pass0_VS_Main, sizeof( g_ShadowMapping_Pass0_VS_Main ), layout, _countof( layout ) ); #endif // 深度ステンシルバッファを作成する UMaps::CreateDepthStencilView( pD3DDevice, m_Width, m_Height, &m_pDSView, &m_pSRView ); // 定数バッファを作成する m_pConstantBuffers[0] = m_pGraphicsPipeline[0]->CreateConstantBuffer( pD3DDevice, nullptr, sizeof( ShadowMapping::CBUFFER_PASS0 ), D3D11_CPU_ACCESS_WRITE ); // ******************************************************************************************************* // パス1用のUGraphicsPipelineの作成 // シェーダーと定数バッファ以外はパス0の使いまわし // ******************************************************************************************************* m_pGraphicsPipeline[1] = NEW UGraphicsPipeline(); // シェーダーを作成する #if defined(DEBUG) || defined(_DEBUG) m_pGraphicsPipeline[1]->CreateVertexShaderFromFile( pD3DDevice, _T("../HLSL/ShadowMapping_Pass1.hlsl"), "ShadowMapping_Pass1_VS_Main", layout, _countof( layout ) ); m_pGraphicsPipeline[1]->CreatePixelShaderFromFile( pD3DDevice, _T("../HLSL/ShadowMapping_Pass1.hlsl"), "ShadowMapping_Pass1_PS_Main" ); #else m_pGraphicsPipeline[1]->CreateVertexShaderFromMemory( pD3DDevice, (LPBYTE)g_ShadowMapping_Pass1_VS_Main, sizeof( g_ShadowMapping_Pass1_VS_Main ), layout, _countof( layout ) ); m_pGraphicsPipeline[1]->CreatePixelShaderFromMemory( pD3DDevice, (LPBYTE)g_ShadowMapping_Pass1_PS_Main, sizeof( g_ShadowMapping_Pass1_PS_Main ) ); #endif // 定数バッファを作成する m_pConstantBuffers[1] = m_pGraphicsPipeline[1]->CreateConstantBuffer( pD3DDevice, nullptr, sizeof( ShadowMapping::CBUFFER_PASS1 ), D3D11_CPU_ACCESS_WRITE ); } void ShadowMapping::BeginPass( ID3D11DeviceContext* pD3DDeviceContext, UINT Pass, XMFLOAT4* pVecLightPos, XMMATRIX* pMatLightProj, XMMATRIX* pMatCameraView, XMMATRIX* pMatCameraProj ) { if( m_Pass != -1) { throw(UException(-1, _T("ShadowMapping::BeginPass()はCreate()またはEndPass()実行後に使用してください"))); } m_Pass = (int)Pass; switch( m_Pass ) { case 0: { // レンダーターゲットビューと深度ステンシルビューとビューポートを切り替える pD3DDeviceContext->OMGetRenderTargets( 1, &m_pOldRTView, &m_pOldDSView ); pD3DDeviceContext->OMSetRenderTargets( 0, nullptr, m_pDSView ); pD3DDeviceContext->RSGetViewports( &m_ViewportCount, nullptr ); pD3DDeviceContext->RSGetViewports( &m_ViewportCount, &m_pOldViewport[0] ); D3D11_VIEWPORT Viewport[1]; Viewport[0].TopLeftX = 0; Viewport[0].TopLeftY = 0; Viewport[0].Width = (FLOAT)m_Width; Viewport[0].Height = (FLOAT)m_Height; Viewport[0].MinDepth = 0.0f; Viewport[0].MaxDepth = 1.0f; pD3DDeviceContext->RSSetViewports( 1, Viewport ); // レンダーターゲットビューは使用しないのでクリアの必要なし。 // 深度バッファをクリアする。 pD3DDeviceContext->ClearDepthStencilView( m_pDSView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 ); m_VecLightPos = *pVecLightPos; // ライトビュー × 射影行列を作成 XMMATRIX matLightView = XMMatrixLookAtLH(XMLoadFloat3((XMFLOAT3*)&m_VecLightPos), XMLoadFloat3(&XMFLOAT3(0, 0, 0)), XMLoadFloat3(&XMFLOAT3(0, 1, 0))); m_MatLightViewProj = matLightView * (*pMatLightProj); m_MatCameraViewProj = XMMatrixIdentity(); } break; case 1: { // 深度マップをシェーダーに設定 pD3DDeviceContext->PSSetShaderResources( 1, 1, &m_pSRView ); // ライトビューはPass0と同じにするためここでは設定しない // カメラビュー × 射影行列を作成 m_MatCameraViewProj = (*pMatCameraView) * (*pMatCameraProj); } break; default: throw(UException(-1, _T("ShadowMapping::BeginPass()で無効なPassが指定されました"))); } // 各種ステートを設定する m_pGraphicsPipeline[0]->SetRasterizerState( pD3DDeviceContext ); m_pGraphicsPipeline[0]->SetDepthStencilState( pD3DDeviceContext ); m_pGraphicsPipeline[0]->SetBlendState( pD3DDeviceContext ); // 各種グラフィックパイプラインを設定 m_pGraphicsPipeline[m_Pass]->SetVertexShader( pD3DDeviceContext ); m_pGraphicsPipeline[m_Pass]->SetHullShader( pD3DDeviceContext ); m_pGraphicsPipeline[m_Pass]->SetDomainShader( pD3DDeviceContext ); m_pGraphicsPipeline[m_Pass]->SetGeometryShader( pD3DDeviceContext ); m_pGraphicsPipeline[m_Pass]->SetPixelShader( pD3DDeviceContext ); } void ShadowMapping::SetConstantBuffers( ID3D11DeviceContext* pD3DDeviceContext, XMMATRIX* pMatWorld ) { HRESULT hr = E_FAIL; if (m_Pass == -1) { throw(UException(-1, _T("ShadowMapping::SetConstantBuffers()はBeginPass()実行後に使用してください"))); } switch( m_Pass ) { case 0: { XMMATRIX matLightWorldViewProj; matLightWorldViewProj = (*pMatWorld) * m_MatLightViewProj; matLightWorldViewProj = XMMatrixTranspose( matLightWorldViewProj ); // 定数バッファを作成する D3D11_MAPPED_SUBRESOURCE mappedResource; if( FAILED( hr = pD3DDeviceContext->Map( m_pConstantBuffers[m_Pass], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource ) ) ) throw( UException( -1, _T("ShadowMapping::SetConstantBuffers()でエラーが発生しました。Map()が失敗しました。") ) ); ShadowMapping::CBUFFER_PASS0* cbuffer = (ShadowMapping::CBUFFER_PASS0*)mappedResource.pData; ::CopyMemory( &cbuffer->matLightWorldViewProj, &matLightWorldViewProj, sizeof( XMMATRIX )); pD3DDeviceContext->Unmap( m_pConstantBuffers[m_Pass], 0 ); // 定数バッファを設定 pD3DDeviceContext->VSSetConstantBuffers( 0, 1, &m_pConstantBuffers[m_Pass] ); pD3DDeviceContext->PSSetConstantBuffers( 0, 1, &m_pConstantBuffers[m_Pass] ); } break; case 1: { XMMATRIX matCameraWorldViewProj, matLightWorldViewProj; matCameraWorldViewProj = (*pMatWorld) * m_MatCameraViewProj; matCameraWorldViewProj = XMMatrixTranspose( matCameraWorldViewProj ); matLightWorldViewProj = (*pMatWorld) * m_MatLightViewProj; matLightWorldViewProj = XMMatrixTranspose( matLightWorldViewProj ); // メッシュ基準のローカル座標系上での平行光源の方向ベクトルを計算する XMMATRIX matInv = XMMatrixInverse( nullptr, *pMatWorld ); XMVECTOR v = XMVector4Transform( XMLoadFloat4( &m_VecLightPos ), matInv ); XMVECTOR nv = XMVector3Normalize( v ); XMFLOAT4 localLightPos; XMStoreFloat4( &localLightPos, nv ); XMFLOAT4 shadowMapSize = XMFLOAT4( (float)m_Width, (float)m_Height, 0, 0 ); // 定数バッファを作成する D3D11_MAPPED_SUBRESOURCE mappedResource; if( FAILED( hr = pD3DDeviceContext->Map( m_pConstantBuffers[m_Pass], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource ) ) ) throw( UException( -1, _T("ShadowMapping::SetConstantBuffers()でエラーが発生しました。Map()が失敗しました。") ) ); ShadowMapping::CBUFFER_PASS1* cbuffer = (ShadowMapping::CBUFFER_PASS1*)mappedResource.pData; ::CopyMemory( &cbuffer->matCameraWorldViewProj, &matCameraWorldViewProj, sizeof( XMMATRIX )); ::CopyMemory( &cbuffer->matLightWorldViewProj, &matLightWorldViewProj, sizeof( XMMATRIX )); ::CopyMemory( &cbuffer->vecLightDir, &localLightPos, sizeof( XMFLOAT4 )); ::CopyMemory( &cbuffer->vecShadowMapSize, &shadowMapSize, sizeof( XMFLOAT4 )); pD3DDeviceContext->Unmap( m_pConstantBuffers[m_Pass], 0 ); // 定数バッファを設定 pD3DDeviceContext->VSSetConstantBuffers( 0, 1, &m_pConstantBuffers[m_Pass] ); pD3DDeviceContext->PSSetConstantBuffers( 0, 1, &m_pConstantBuffers[m_Pass] ); } break; } } void ShadowMapping::EndPass( ID3D11DeviceContext* pD3DDeviceContext ) { switch( m_Pass ) { case 0: // レンダーターゲットビューと深度ステンシルビューとビューポートを戻す pD3DDeviceContext->OMSetRenderTargets( 1, &m_pOldRTView, m_pOldDSView ); SAFE_RELEASE( m_pOldRTView ); SAFE_RELEASE( m_pOldDSView ); pD3DDeviceContext->RSSetViewports( m_ViewportCount, m_pOldViewport ); break; case 1: ID3D11ShaderResourceView* pNull[1] = { nullptr }; pD3DDeviceContext->PSSetShaderResources( 1, _countof( pNull ), pNull ); break; } m_Pass = -1; }
#ifndef F14MESH_H #define F14MESH_H #include "../Common/UCommon.h" #include "../Common/UDirect3D11.h" #include "../Common/UException.h" #include "../Common/UD3DMeshDataCreater.h" class F14Mesh { private: // 頂点バッファ ID3D11Buffer* m_pVertexBuffer; // インデックスバッファ // 未使用 // シェーダーリソースビュー ID3D11ShaderResourceView* m_pSRView; // サンプラーステート ID3D11SamplerState* m_pSamplerState; UD3DMeshDataCreater m_MeshDataCreater; XMMATRIX m_MatWorld[4]; UD3DMeshDataCreater::VERTEX* m_pVertex; ULONG m_VertexCount; public: F14Mesh(); virtual ~F14Mesh(); void Invalidate(); void CreateMesh( ID3D11Device* pD3DDevice ); void NextFrame(); inline XMMATRIX* GetMatWorld( UINT Index ){ return &m_MatWorld[Index]; }; inline UINT GetMaxCount(){ return _countof( m_MatWorld ); }; void Render( ID3D11DeviceContext* pD3DDeviceContext ); }; #endif
#include "../../Header/Mesh/F14Mesh.h" F14Mesh::F14Mesh() { m_pVertexBuffer = nullptr; m_pSRView = nullptr; m_pSamplerState = nullptr; m_pVertex = nullptr; m_VertexCount = 0; } F14Mesh::~F14Mesh() { Invalidate(); } void F14Mesh::Invalidate() { m_VertexCount = 0; SAFE_DELETE_ARRAY( m_pVertex ); SAFE_RELEASE( m_pSamplerState ); SAFE_RELEASE( m_pSRView ); SAFE_RELEASE( m_pVertexBuffer ); } void F14Mesh::CreateMesh( ID3D11Device* pD3DDevice ) { // COLLADAデータを取得 m_MeshDataCreater.LoadMesh( _T("../Resource/f14.dae") ); UINT MeshIndex = 0; m_MeshDataCreater.GetVertexes( MeshIndex, &m_pVertex, &m_VertexCount ); // 頂点バッファを作成する m_pVertexBuffer = UBuffers::CreateVertexBuffer( pD3DDevice, m_pVertex, sizeof( UD3DMeshDataCreater::VERTEX ) * m_VertexCount, 0 ); // サンプラーステートを作成する m_pSamplerState = USamplers::CreateSamplerState( pD3DDevice, D3D11_TEXTURE_ADDRESS_WRAP ); // テクスチャーを作成する UMaps::CreateSRViewFromDDSFile( pD3DDevice, m_MeshDataCreater.GetTextureFileName( MeshIndex ).data(), &m_pSRView ); SAFE_DELETE_ARRAY( m_pVertex ); } void F14Mesh::NextFrame() { XMMATRIX matScaling, matXRotation, matTranslate; matScaling = XMMatrixScaling( 20, 20, 20 ); static float XRotation = 0; XRotation += 0.0005f; if( XRotation > 2 * XM_PI ) XRotation -= 2 * XM_PI; matXRotation = XMMatrixRotationX( XRotation ); for( int i=0; i<_countof( m_MatWorld ); i++ ) { matTranslate = XMMatrixTranslation( 0, 10.0f + 30.0f - (float)i * 10.0f, 80.0f - (float)i * 70.0f ); matXRotation = XMMatrixRotationX( XRotation + (float)i * 0.8f ); m_MatWorld[i] = matScaling * matXRotation * matTranslate; } } void F14Mesh::Render( ID3D11DeviceContext* pD3DDeviceContext ) { // 頂点バッファ設定 UINT stride = sizeof( UD3DMeshDataCreater::VERTEX ); UINT offset = 0; pD3DDeviceContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset ); // プリミティブ タイプおよびデータの順序に関する情報を設定 pD3DDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); // ピクセルシェーダーのサンプラーステートを設定する pD3DDeviceContext->PSSetSamplers( 0, 1, &m_pSamplerState ); // デカールマップを設定する pD3DDeviceContext->PSSetShaderResources( 0, 1, &m_pSRView ); // インデックスバッファを使用しない描画 pD3DDeviceContext->Draw( m_VertexCount, 0 ); }
#ifndef PLANEMESH_H #define PLANEMESH_H #include "../Common/UCommon.h" #include "../Common/UDirect3D11.h" #include "../Common/UException.h" #include "../Common/UD3DMeshDataCreater.h" class PlaneMesh { private: // 頂点バッファ ID3D11Buffer* m_pVertexBuffer; // インデックスバッファ ID3D11Buffer* m_pIndexBuffer; // シェーダーリソースビュー ID3D11ShaderResourceView* m_pSRView; // サンプラーステート ID3D11SamplerState* m_pSamplerState; XMMATRIX m_MatWorld; ULONG m_VertexCount, m_IndexCount; public: PlaneMesh(); virtual ~PlaneMesh(); void Invalidate(); void CreateMesh( ID3D11Device* pD3DDevice, UINT WidthNum = 0, UINT HeightNum = 0 ); void NextFrame(); inline XMMATRIX* GetMatWorld(){ return &m_MatWorld; }; void Render( ID3D11DeviceContext* pD3DDeviceContext, D3D_PRIMITIVE_TOPOLOGY PrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); }; #endif
#include "../../Header/Mesh/PlaneMesh.h" PlaneMesh::PlaneMesh() { m_pVertexBuffer = nullptr; m_pIndexBuffer = nullptr; m_pSRView = nullptr; m_pSamplerState = nullptr; m_VertexCount = 0; m_IndexCount = 0; } PlaneMesh::~PlaneMesh() { Invalidate(); } void PlaneMesh::Invalidate() { m_IndexCount = 0; m_VertexCount = 0; SAFE_RELEASE( m_pSamplerState ); SAFE_RELEASE( m_pSRView ); SAFE_RELEASE(m_pIndexBuffer); SAFE_RELEASE( m_pVertexBuffer ); } void PlaneMesh::CreateMesh( ID3D11Device* pD3DDevice, UINT WidthNum, UINT HeightNum ) { m_VertexCount = 0; m_IndexCount = 0; UINT widthNum = 1; if (WidthNum != 0) { widthNum = WidthNum; } UINT heightNum = 1; if (HeightNum != 0) { heightNum = HeightNum; } m_VertexCount = (widthNum + 1) * (heightNum + 1); UD3DMeshDataCreater::VERTEX* vertexes = NEW UD3DMeshDataCreater::VERTEX[m_VertexCount]; float OnePolyWidthSize = 2000.0f / (float)widthNum; float OnePolyOneHeightSize = 2000.0f / (float)heightNum; float OneTexelWidthSize = 10.0f / (float)widthNum; float OneTexelHeightSize = 10.0f / (float)heightNum; for (ULONG i = 0; i < heightNum + 1; i++) { for (ULONG j = 0; j < widthNum + 1; j++) { ULONG index = i * (widthNum + 1) + j; vertexes[index].Position = XMFLOAT3(-1000.0f + OnePolyWidthSize * (float)(j), 0.0f, 1000.0f - OnePolyOneHeightSize * (float)i); vertexes[index].Normal = XMFLOAT3(0.0f, 1.0f, 0.0f); vertexes[index].Texcoord = XMFLOAT2(0.0f + (float)(j)* OneTexelWidthSize, 0.0f + (float)(i)* OneTexelHeightSize); } } // 頂点バッファを作成する m_pVertexBuffer = UBuffers::CreateVertexBuffer( pD3DDevice, vertexes, sizeof( UD3DMeshDataCreater::VERTEX ) * m_VertexCount, 0 ); SAFE_DELETE_ARRAY(vertexes); m_IndexCount = widthNum * heightNum * 6; ULONG* indexes = NEW ULONG[m_IndexCount]; ULONG index = 0; for (ULONG i = 0; i < heightNum; i++) { for (ULONG j = 0; j < widthNum; j++) { indexes[index++] = (j + 1) + i * (widthNum + 1); // 右上 indexes[index++] = j + i * (widthNum + 1); // 左上 indexes[index++] = j + (i + 1) * (widthNum + 1); //左下 indexes[index++] = (j + 1) + i * (widthNum + 1); // 右上 indexes[index++] = j + (i + 1) * (widthNum + 1); //左下 indexes[index++] = (j + 1) + (i + 1) * (widthNum + 1); //右下 } } // インデックスバッファを作成する m_pIndexBuffer = UBuffers::CreateIndexBuffer(pD3DDevice, indexes, sizeof(ULONG) * m_IndexCount, 0); SAFE_DELETE_ARRAY(indexes); // サンプラーステートを作成する m_pSamplerState = USamplers::CreateSamplerState( pD3DDevice, D3D11_TEXTURE_ADDRESS_WRAP ); // テクスチャーを作成する UMaps::CreateSRViewFromDDSFile( pD3DDevice, _T("../Resource/Plane.dds"), &m_pSRView ); } void PlaneMesh::NextFrame() { XMMATRIX matTranslate; matTranslate = XMMatrixTranslation( 0.0f, -20.0f, 0.0f ); m_MatWorld = matTranslate; } void PlaneMesh::Render( ID3D11DeviceContext* pD3DDeviceContext, D3D_PRIMITIVE_TOPOLOGY PrimitiveTopology ) { // 頂点バッファ設定 UINT stride = sizeof( UD3DMeshDataCreater::VERTEX ); UINT offset = 0; pD3DDeviceContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset ); // インデックスバッファ設定 pD3DDeviceContext->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0); // プリミティブ タイプおよびデータの順序に関する情報を設定 pD3DDeviceContext->IASetPrimitiveTopology( PrimitiveTopology ); // ピクセルシェーダーのサンプラーステートを設定する pD3DDeviceContext->PSSetSamplers( 0, 1, &m_pSamplerState ); // デカールマップを設定する pD3DDeviceContext->PSSetShaderResources( 0, 1, &m_pSRView ); // インデックスバッファを使用する描画 pD3DDeviceContext->DrawIndexed(m_IndexCount, 0, 0); }
#include "../Header/Common/UCommon.h" #include "../Header/Common/UException.h" #include "../Header/Common/UDirect3D11.h" #include "../Header/Shader/ShadowMapping.h" #include "../Header/Common/UDebugFont.h" #if defined(DEBUG) || defined(_DEBUG) #include "../Header/Common/USRViewRenderer.h" #endif #include "../Header/Mesh/F14Mesh.h" #include "../Header/Mesh/PlaneMesh.h" // アプリケーション名 TCHAR* AppName = _T("Direct3D11 Shadow Mapping"); // Direct3D関連の自作クラス UDirect3D11* g_pDirect3D11 = nullptr; ShadowMapping* g_pShadowMapping = nullptr; F14Mesh* g_pF14Mesh = nullptr; PlaneMesh* g_pPlaneMesh = nullptr; UFPS* g_pFPS = nullptr; #if defined(DEBUG) || defined(_DEBUG) USRViewRenderer* g_pSRViewRenderer = nullptr; #endif DWORD g_Width = 640, g_Height = 480; // カメラビュー行列 XMMATRIX g_MatCameraView = XMMatrixIdentity(); // 射影行列 XMMATRIX g_MatCameraProj = XMMatrixPerspectiveFovLH( XM_PI / 5.0f, (float)g_Width / (float)g_Height, 0.01f, 500.0f ); // 正行列 XMMATRIX g_MatLightOrtho = XMMatrixOrthographicLH( (float)300, (float)300, 1.0f, 800.0f ); // 平行光源の位置ベクトル XMFLOAT4 g_VecLightPos = XMFLOAT4( 20.0f, 200.0f, 300.0f, 0 ); // メモリ解放 void Invalidate() { #if defined(DEBUG) || defined(_DEBUG) SAFE_DELETE( g_pSRViewRenderer ); #endif SAFE_DELETE( g_pFPS ); SAFE_DELETE( g_pShadowMapping ); SAFE_DELETE( g_pPlaneMesh ); SAFE_DELETE( g_pF14Mesh ); SAFE_DELETE( g_pDirect3D11 ); } // ウィンドウプロシージャ LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, UINT wParam, LONG lParam ) { switch( msg ) { case WM_KEYUP: // アプリ終了 if( wParam == VK_ESCAPE ) ::DestroyWindow( hWnd ); break; case WM_DESTROY: ::PostQuitMessage(0); break; default: return ::DefWindowProc( hWnd, msg, wParam, lParam ); } return 0L; } // Direct3Dの作成 void CreateDirect3D( HINSTANCE hInstance ) { DXGI_MODE_DESC* pModeDescArray = nullptr; __try { DXGI_MODE_DESC ModeDesc; UINT num; // ディスプレイモード一覧の数を取得する g_pDirect3D11->GetDisplayMode( nullptr, &num ); pModeDescArray = NEW DXGI_MODE_DESC[num]; // ディスプレイモード一覧を取得する g_pDirect3D11->GetDisplayMode( pModeDescArray, &num ); bool find = false; for( UINT i=0; i<num; i++ ) { // 適切な解像度のディスプレイモードを検索する if( pModeDescArray[i].Width == g_Width && pModeDescArray[i].Height == g_Height ) { find = true; ::CopyMemory( &ModeDesc, &pModeDescArray[i], sizeof( DXGI_MODE_DESC ) ); break; } } if( find == false ) throw( UException( -1, _T("InitDirect3D()でエラーが発生しました。適切なディスプレイモードの解像度を取得できません。") ) ); // ウィンドウの作成およびDirect3D の作成 g_pDirect3D11->CreateDirect3D11( AppName, hInstance, WndProc, &ModeDesc, TRUE, TRUE ); // FPS描画クラス g_pFPS->CreateMesh( g_pDirect3D11->m_pD3DDevice ); #if defined(DEBUG) || defined(_DEBUG) g_pSRViewRenderer->Create( g_pDirect3D11->m_pD3DDevice, 1.0f - 400.0f / (float)g_Width, 1.0f, 1.0f, 1.0f - 400.0f / (float)g_Height ); #endif } __finally { SAFE_DELETE_ARRAY( pModeDescArray ); } } void CreateGraphicePipeline() { g_pShadowMapping->Create( g_pDirect3D11->m_pD3DDevice, 1024, 1024 ); } // メッシュを作成する void CreateMesh() { g_pF14Mesh = NEW F14Mesh(); g_pF14Mesh->CreateMesh( g_pDirect3D11->m_pD3DDevice ); g_pPlaneMesh = NEW PlaneMesh(); g_pPlaneMesh->CreateMesh( g_pDirect3D11->m_pD3DDevice ); } void CreateResource( HINSTANCE hInstance ) { // Direct3D 関連自作クラスのインスタンスを作成 // CreateDirect3D()関数内でインスタンスの作成を行うと、C2712 エラーが発生するのでここで行う。 g_pDirect3D11 = NEW UDirect3D11(); g_pShadowMapping = NEW ShadowMapping(); g_pFPS = NEW UFPS(); #if defined(DEBUG) || defined(_DEBUG) g_pSRViewRenderer = NEW USRViewRenderer(); #endif // Direct3Dの作成 CreateDirect3D( hInstance ); // グラフィックパイプラインリソースの作成 CreateGraphicePipeline(); // リソースの作成 CreateMesh(); } void NextFrame() { // ビュー行列 if( GetKeyState( VK_UP ) & 0x8000 ) g_MatCameraView *= XMMatrixTranslation( 0, 0, -0.1f ); if( GetKeyState( VK_DOWN ) & 0x8000 ) g_MatCameraView *= XMMatrixTranslation( 0, 0, 0.1f ); if( GetKeyState( VK_RIGHT ) & 0x8000 ) g_MatCameraView *= XMMatrixRotationY( -0.002f ); if( GetKeyState( VK_LEFT ) & 0x8000 ) g_MatCameraView *= XMMatrixRotationY( 0.002f ); if( GetKeyState( 'Q' ) & 0x8000 ) g_MatCameraView *= XMMatrixRotationX( 0.002f ); if( GetKeyState( 'A' ) & 0x8000 ) g_MatCameraView *= XMMatrixRotationX( -0.002f ); g_pFPS->NextFrame(); g_pF14Mesh->NextFrame(); g_pPlaneMesh->NextFrame(); } // 描画処理 HRESULT Render() { HRESULT hr = E_FAIL; static float ClearColor[4] = { 0.3f, 0.3f, 1.0f, 1.0f }; // バックバッファをクリアする。 g_pDirect3D11->ClearBackBuffer( ClearColor ); // 深度バッファをクリアする。 g_pDirect3D11->ClearDepthStencilView( D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 ); for( UINT i=0; i<g_pShadowMapping->GetMaxPass(); i++ ) { g_pShadowMapping->BeginPass( g_pDirect3D11->m_pD3DDeviceContext, i, &g_VecLightPos, &g_MatLightOrtho, &g_MatCameraView, &g_MatCameraProj ); for( UINT j=0; j<g_pF14Mesh->GetMaxCount(); j++ ) { // 定数バッファを設定 g_pShadowMapping->SetConstantBuffers( g_pDirect3D11->m_pD3DDeviceContext, g_pF14Mesh->GetMatWorld(j) ); // レンダリング g_pF14Mesh->Render( g_pDirect3D11->m_pD3DDeviceContext ); } // 定数バッファを設定 g_pShadowMapping->SetConstantBuffers( g_pDirect3D11->m_pD3DDeviceContext, g_pPlaneMesh->GetMatWorld() ); // レンダリング g_pPlaneMesh->Render( g_pDirect3D11->m_pD3DDeviceContext ); g_pShadowMapping->EndPass( g_pDirect3D11->m_pD3DDeviceContext ); } #if defined(DEBUG) || defined(_DEBUG) int SrvRGB[] = { 0, 1, 2, 3 }; g_pSRViewRenderer->SetSRView( g_pShadowMapping->GetDepthMap(), SrvRGB ); g_pSRViewRenderer->Render( g_pDirect3D11->m_pD3DDeviceContext ); #endif g_pFPS->Render( g_pDirect3D11->m_pD3DDeviceContext ); // レンダリングされたイメージをユーザーに表示。 if( FAILED( hr = g_pDirect3D11->Present( 0, 0 ) ) ) throw( UException( hr, _T("IDXGISwapChain::Present()が失敗しました") ) ); return hr; } // メイン関数 int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR, INT ) { // メモリリーク検出 // _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | CRTDBG_CHECK_ALWAYS_DF ); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_EVERY_1024_DF ); MSG msg = {0}; try { CreateResource( hInstance ); ::ShowWindow( g_pDirect3D11->m_hWnd, SW_SHOW ); ::UpdateWindow( g_pDirect3D11->m_hWnd ); // メッセージループ do { if( ::PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) ) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } else { NextFrame(); Render(); } }while( msg.message != WM_QUIT ); } catch( UException ex ) { ::MessageBox( nullptr, ex.m_pErrorStr, _T("エラー"), MB_OK ); } Invalidate(); ::UnregisterClass( AppName, hInstance ); return msg.wParam; }