#include "dxlib_bishamon_dx11.h" #include "DxLib.h" #include #include #include // VisualStudioは必要になるライブラリが多岐に渡るので, // できるだけコンパイル時に対象ライブラリを解決する. #if _MSC_VER >= 1800 // vs2013 # define ML_LIBNAME_MSC_VER "v120" #elif _MSC_VER >= 1700 // vs2012 # define ML_LIBNAME_MSC_VER "v110" #elif _MSC_VER >= 1600 // vs2010 # define ML_LIBNAME_MSC_VER "v100" #elif _MSC_VER >= 1500 // vs2008 # define ML_LIBNAME_MSC_VER "v90" #endif #if defined(_DLL) # if defined(_DEBUG) # define ML_LIBNAME_SUFFIX "mdd" # else # define ML_LIBNAME_SUFFIX "md" # endif #else # if defined(_DEBUG) # define ML_LIBNAME_SUFFIX "mtd" # else # define ML_LIBNAME_SUFFIX "mt" # endif #endif #pragma comment(lib, "ml_bmfw_dx11_" ML_LIBNAME_MSC_VER ML_LIBNAME_SUFFIX ".lib") namespace bmfw = ml::bmfw; static ID3D11Texture2D* BackBufferTextureCopy = 0; static ID3D11ShaderResourceView* BackBufferResourceViewCopy = 0; static ID3D11Texture2D* DepthStencilTextureCopy = 0; static ID3D11ShaderResourceView* DepthStencilResourceViewCopy = 0; // // ヒープメモリ確保, 解放 // void* Alloc( const uint32_t size ) { return new char[ size ]; } void Free( void* p ) { delete[] reinterpret_cast(p); } /** ヒープメモリ確保リクエストのコールバック */ void requestHeapMemory( bmfw::ReqHeapMemory& req ) { // bmfw::ReqHeapMemory // size -- ヒープメモリのサイズ // alignment -- ヒープメモリのメモリアライメント // const uint32_t size = (req.size + (req.alignment-1)) & ~(req.alignment-1); // bmfw::ReqHeapMemory::Result // dataHead -- 確保したメモリの先頭アドレス(NULLを設定すると確保失敗とみなす) // req.result.dataHead = Alloc( size ); } /** ヒープメモリの解放可能タイミングで呼び出されるコールバック */ void discardHeapMemory( bmfw::DisHeapMemory& dis ) { // bmfw::DisHeapMemory // dataHead -- 確保したメモリの先頭アドレス // Free( dis.dataHead ); } // // 外部ファイル読み込み実装 // struct BinResult { void* head; uint32_t size; }; BinResult LoadBinary(const char* path) { BinResult result = { NULL, 0 }; std::ifstream ifs(path, std::ios::in | std::ios::binary | std::ios::ate ); if(!ifs.fail()) { const uint32_t size = static_cast(ifs.tellg()); if(char* data = reinterpret_cast(Alloc(size+1))) { ifs.seekg(0); ifs.read(data, size); data[size] = '\0'; result.head = data; result.size = size; } } return result; } static const char* sample_data_dirpath = "../data"; /** ShaderPackageバイナリリクエストのコールバック */ void requestShaderPackageBinary( bmfw::ReqShaderPackageBinary& req ) { std::ostringstream path; path << sample_data_dirpath << "/bmshaderpack.bin"; BinResult bin = LoadBinary( path.str().c_str() ); req.result.dataHead = bin.head; req.result.dataSize = bin.size; } /** ShaderPackageバイナリの削除可能タイミングで呼び出されるコールバック */ void discardShaderPackageBinary( bmfw::DisShaderPackageBinary& dis ) { Free( dis.dataHead ); } /** bmbバイナリリクエストのコールバック */ void requestBMBBinary( bmfw::ReqBMBBinary& req ) { // bmfw::ReqBMBBinary // name -- bmbファイル名 // std::ostringstream path; path << sample_data_dirpath << "/bmsln/" << req.name << ".bmb"; BinResult bin = LoadBinary( path.str().c_str() ); req.result.dataHead = bin.head; req.result.dataSize = bin.size; } /** bmbバイナリの削除可能タイミングで呼び出されるコールバック */ void discardBMBBinary( bmfw::DisBMBBinary& dis ) { Free( dis.dataHead ); } /** m3rバイナリリクエストのコールバック */ void requestM3RBinary( bmfw::ReqM3RBinary& req ) { // bmfw::ReqM3RBinary // name -- bmbファイル名 // std::ostringstream path; path << sample_data_dirpath << "/model/" << req.name << ".m3r"; BinResult bin = LoadBinary( path.str().c_str() ); req.result.dataHead = bin.head; req.result.dataSize = bin.size; } /** m3rバイナリの削除可能タイミングで呼び出されるコールバック */ void discardM3RBinary( bmfw::DisM3RBinary& dis ) { Free( dis.dataHead ); } // // グラフィックスリソース生成実装 // struct DDS_PIXELFORMAT { uint32_t size; uint32_t flags; uint32_t fourCC; uint32_t RGBBitCount; uint32_t RBitMask; uint32_t GBitMask; uint32_t BBitMask; uint32_t ABitMask; }; struct DDS_HEADER { uint32_t magic; uint32_t size; uint32_t flags; uint32_t height; uint32_t width; uint32_t pitchOrLinearSize; uint32_t depth; uint32_t mipMapCount; uint32_t reserved1[11]; DDS_PIXELFORMAT ddspf; uint32_t caps; uint32_t caps2; uint32_t caps3; uint32_t caps4; uint32_t reserved2; }; /** DDSからのテクスチャ生成(サンプル向け簡易版) * * 対応するDDSフォーマットは DXT5とA8B8G8R8 のみ. */ ID3D11ShaderResourceView* CreateTextureFromDDS(BinResult& bin) { if(bin.head == NULL) return NULL; const uint8_t* texture_data = reinterpret_cast(bin.head); const DDS_HEADER* dds_header = reinterpret_cast(texture_data); const uint32_t DDS_MAGIC = 0x20534444; // "DDS " const uint32_t DDS_DX10 = 0x30315844; // "DX10" if(DDS_MAGIC != dds_header->magic) return NULL; // Not DDS if(dds_header->flags & 0x00800000) return NULL; // 3D TEXTURE if(dds_header->caps2 & 0x00000200) return NULL; // CUBE MAP if(dds_header->ddspf.fourCC == DDS_DX10) return NULL; // DX10 DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; const uint32_t DDS_DXT5 = 0x35545844; // "DXT5" const uint32_t DDS_FOURCC = 0x00000004; const uint32_t DDS_RGB = 0x00000040; if( (dds_header->ddspf.flags & DDS_RGB) && (dds_header->ddspf.RGBBitCount == 32) ) { if( dds_header->ddspf.RBitMask == 0x000000ff && dds_header->ddspf.GBitMask == 0x0000ff00 && dds_header->ddspf.BBitMask == 0x00ff0000 && dds_header->ddspf.ABitMask == 0xff000000 ) format = DXGI_FORMAT_R8G8B8A8_UNORM; } if( (dds_header->ddspf.flags & DDS_FOURCC) && (dds_header->ddspf.fourCC == DDS_DXT5) ) { format = DXGI_FORMAT_BC3_UNORM; } if(format == DXGI_FORMAT_UNKNOWN) return NULL; // 未対応フォーマット uint32_t mip_count = min(9u, max(1u, dds_header->mipMapCount)); D3D11_SUBRESOURCE_DATA init_data[9]; const uint8_t* src = texture_data + sizeof(DDS_HEADER); const uint8_t* end = texture_data + bin.size; uint32_t w = dds_header->width; uint32_t h = dds_header->height; for(uint32_t i = 0; i < mip_count; ++i) { uint32_t row_bytes = 0, row_count = 0; switch(format) { case DXGI_FORMAT_R8G8B8A8_UNORM: row_bytes = (w * 32 + 7) / 8; row_count = h; break; case DXGI_FORMAT_BC3_UNORM: row_bytes = ((w + 3) / 4) * 16; row_count = (h + 3) / 4; break; default: __assume(0); } const uint32_t size = row_bytes * row_count; init_data[i].pSysMem = reinterpret_cast(src); init_data[i].SysMemPitch = row_bytes; init_data[i].SysMemSlicePitch = size; if(src + size > end) break; src += size; w = 1u > ( w >> 1 ) ? 1u : ( w >> 1 ) ; h = 1u > ( h >> 1 ) ? 1u : ( h >> 1 ) ; } D3D11_TEXTURE2D_DESC tex_desc; ZeroMemory( &tex_desc, sizeof(tex_desc) ); tex_desc.Width = dds_header->width; tex_desc.Height = dds_header->height; tex_desc.MipLevels = mip_count; tex_desc.ArraySize = 1; tex_desc.Format = format; tex_desc.SampleDesc.Count = 1; tex_desc.SampleDesc.Quality = 0; tex_desc.Usage = D3D11_USAGE_IMMUTABLE; tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; tex_desc.CPUAccessFlags = 0; tex_desc.MiscFlags = 0; ID3D11Texture2D* d3d_texture = NULL; HRESULT hr = (( ID3D11Device * )GetUseDirect3D11Device())->CreateTexture2D( &tex_desc, init_data, &d3d_texture ); if SUCCEEDED(hr) { D3D11_SHADER_RESOURCE_VIEW_DESC resource_desc; ZeroMemory( &resource_desc, sizeof(resource_desc) ); resource_desc.Format = format; resource_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; resource_desc.Texture2D.MostDetailedMip = 0; resource_desc.Texture2D.MipLevels = mip_count; ID3D11ShaderResourceView* resource_view = NULL; hr = (( ID3D11Device * )GetUseDirect3D11Device())->CreateShaderResourceView( d3d_texture, &resource_desc, &resource_view ); d3d_texture->Release(); return resource_view; } return NULL; } void requestGFXTexture( bmfw::ReqGFXTexture& req ) { std::ostringstream path; if( req.isModelTexture ) { path << sample_data_dirpath << "/model/" << req.name << ".dds"; } else { path << sample_data_dirpath << "/texture/" << req.name << ".dds"; } BinResult bin = LoadBinary( path.str().c_str() ); if( bin.head != NULL ) { bmfw::GFXDeviceTextureType texture = CreateTextureFromDDS( bin ); req.result.texture = texture; delete[] reinterpret_cast(bin.head); } } void discardGFXTexture( bmfw::DisGFXTexture& dis ) { if( dis.texture != NULL ) { dis.texture->Release(); } } // DXライブラリの行列をBISHAMONの行列に変換する void ConvertMatrix( MATRIX DxMat, bmfw::Mat44 *BmMat ) { BmMat->m00 = DxMat.m[ 0 ][ 0 ] ; BmMat->m01 = DxMat.m[ 0 ][ 1 ] ; BmMat->m02 = DxMat.m[ 0 ][ 2 ] ; BmMat->m03 = DxMat.m[ 0 ][ 3 ] ; BmMat->m10 = DxMat.m[ 1 ][ 0 ] ; BmMat->m11 = DxMat.m[ 1 ][ 1 ] ; BmMat->m12 = DxMat.m[ 1 ][ 2 ] ; BmMat->m13 = DxMat.m[ 1 ][ 3 ] ; BmMat->m20 = DxMat.m[ 2 ][ 0 ] ; BmMat->m21 = DxMat.m[ 2 ][ 1 ] ; BmMat->m22 = DxMat.m[ 2 ][ 2 ] ; BmMat->m23 = DxMat.m[ 2 ][ 3 ] ; BmMat->m30 = DxMat.m[ 3 ][ 0 ] ; BmMat->m31 = DxMat.m[ 3 ][ 1 ] ; BmMat->m32 = DxMat.m[ 3 ][ 2 ] ; BmMat->m33 = DxMat.m[ 3 ][ 3 ] ; } // BISHAMON の初期化を行う bool DxLib_Bishamon_DX11_Init() { int screenWidth, screenHeight ; ID3D11Texture2D *BackBufferTexture2D ; ID3D11Texture2D *DepthStencilTexture2D ; D3D11_TEXTURE2D_DESC BackBufferTexture2DDesc ; D3D11_TEXTURE2D_DESC DepthStencilTexture2DDesc ; ID3D11Device *D3D11Device ; // BISHAMONフレームワークにコールバックを設定. bmfw::SetResourceCallback( requestHeapMemory ); bmfw::SetResourceCallback( discardHeapMemory ); bmfw::SetResourceCallback( requestShaderPackageBinary ); bmfw::SetResourceCallback( discardShaderPackageBinary ); bmfw::SetResourceCallback( requestBMBBinary ); bmfw::SetResourceCallback( discardBMBBinary ); bmfw::SetResourceCallback( requestM3RBinary ); bmfw::SetResourceCallback( discardM3RBinary ); bmfw::SetResourceCallback( requestGFXTexture ); bmfw::SetResourceCallback( discardGFXTexture ); // BISHAMONフレームワークの初期化. bmfw::InitParam initParam; initParam.depend.dxDevice = ( ID3D11Device * )GetUseDirect3D11Device() ; initParam.depend.dxImmediateContext = ( ID3D11DeviceContext * )GetUseDirect3D11DeviceContext(); initParam.depend.dxDeferredContext = NULL; if( !bmfw::Init( initParam ) ) { return false; } // BISHAMONのシーンの情報を設定 bmfw::Scene().lightDirection = bmfw::Vec3( 1.0f, 1.0f, 0.0f ); bmfw::Scene().lightDiffuseColor = bmfw::Vec3( 0.6f, 0.6f, 0.2f ); bmfw::Scene().lightAmbientColor = bmfw::Vec3( 0.2f, 0.2f, 0.2f ); bmfw::Scene().fogColor = bmfw::Vec3( 0.0f, 0.5f, 1.0f ); bmfw::Scene().fogStartRangeRate = 0.0f; bmfw::Scene().fogEndRangeRate = 1.0f; // 画面のサイズを取得 GetDrawScreenSize( &screenWidth, &screenHeight ) ; // バックバッファと深度バッファの Texture2D を取得 BackBufferTexture2D = ( ID3D11Texture2D * )GetUseDirect3D11BackBufferTexture2D() ; DepthStencilTexture2D = ( ID3D11Texture2D * )GetUseDirect3D11DepthStencilTexture2D() ; // バックバッファと深度バッファの情報を取得 BackBufferTexture2D->GetDesc( &BackBufferTexture2DDesc ) ; DepthStencilTexture2D->GetDesc( &DepthStencilTexture2DDesc ) ; // ID3D11Device を取得 D3D11Device = ( ID3D11Device * )GetUseDirect3D11Device() ; // 描画ターゲット(シェーダー参照用のコピー) { D3D11_TEXTURE2D_DESC tex_desc; ZeroMemory(&tex_desc, sizeof(tex_desc)); tex_desc.Width = ( UINT )screenWidth; tex_desc.Height = ( UINT )screenHeight; tex_desc.MipLevels = 1; tex_desc.ArraySize = 1; tex_desc.Format = BackBufferTexture2DDesc.Format; tex_desc.SampleDesc.Count = 1; tex_desc.SampleDesc.Quality = 0; tex_desc.Usage = D3D11_USAGE_DEFAULT; tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; tex_desc.CPUAccessFlags = 0; tex_desc.MiscFlags = 0; D3D11Device->CreateTexture2D(&tex_desc, 0, &BackBufferTextureCopy); D3D11_SHADER_RESOURCE_VIEW_DESC shader_desc; ZeroMemory( &shader_desc, sizeof(shader_desc) ); shader_desc.Format = BackBufferTexture2DDesc.Format; shader_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; shader_desc.Texture2D.MipLevels = 1; shader_desc.Texture2D.MostDetailedMip = 0; D3D11Device->CreateShaderResourceView(BackBufferTextureCopy, &shader_desc, &BackBufferResourceViewCopy); } // 深度/ステンシルバッファ生成(シェーダー参照用のコピー) { D3D11_TEXTURE2D_DESC depth_desc; ZeroMemory(&depth_desc, sizeof(depth_desc)); depth_desc.Width = ( UINT )screenWidth; depth_desc.Height = ( UINT )screenHeight; depth_desc.MipLevels = 1; depth_desc.ArraySize = 1; depth_desc.Format = DepthStencilTexture2DDesc.Format; depth_desc.SampleDesc.Count = 1; depth_desc.SampleDesc.Quality = 0; depth_desc.Usage = D3D11_USAGE_DEFAULT; depth_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; depth_desc.CPUAccessFlags = 0; depth_desc.MiscFlags = 0; D3D11Device->CreateTexture2D(&depth_desc, 0, &DepthStencilTextureCopy); D3D11_SHADER_RESOURCE_VIEW_DESC shader_desc; ZeroMemory( &shader_desc, sizeof(shader_desc) ); shader_desc.Format = DXGI_FORMAT_R32_FLOAT; shader_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; shader_desc.Texture2D.MipLevels = 1; shader_desc.Texture2D.MostDetailedMip = 0; D3D11Device->CreateShaderResourceView(DepthStencilTextureCopy, &shader_desc, &DepthStencilResourceViewCopy); } return true; } // BISHAMONの描画の準備を行う void DxLib_Bishamon_DX11_DrawSetup() { int XSize, YSize ; ID3D11DeviceContext *D3D11DeviceContext ; // 画面のサイズをセット GetDrawScreenSize( &XSize, &YSize ) ; bmfw::Scene().screenWidth = ( unsigned int )XSize ; bmfw::Scene().screenHeight = ( unsigned int )YSize ; // カメラの設定をセット bmfw::Scene().nearClip = GetCameraNear() ; bmfw::Scene().farClip = GetCameraFar() ; bmfw::Scene().FoV = GetCameraFov() * 180.0f / DX_PI_F ; ConvertMatrix( GetCameraViewMatrix(), &bmfw::Scene().viewMatrix ) ; ConvertMatrix( GetCameraProjectionMatrix(), &bmfw::Scene().projectionMatrix ) ; // ID3D11DeviceContext を取得 D3D11DeviceContext = ( ID3D11DeviceContext * )GetUseDirect3D11DeviceContext() ; // バックバッファと深度バッファのコピーを作成 D3D11DeviceContext->CopyResource( BackBufferTextureCopy, ( ID3D11Texture2D * )GetUseDirect3D11BackBufferTexture2D() ); D3D11DeviceContext->CopyResource( DepthStencilTextureCopy, ( ID3D11Texture2D * )GetUseDirect3D11DepthStencilTexture2D() ) ; // バックバッファと深度バッファのコピーをセット bmfw::Scene().renderTargetTexture = BackBufferResourceViewCopy ; bmfw::Scene().depthBufferTexture = DepthStencilResourceViewCopy ; }