diff --git a/17-D3D12_Assimp_Animation/17-D3D12_Assimp_Animation.cpp b/17-D3D12_Assimp_Animation/17-D3D12_Assimp_Animation.cpp index cd606176deb16992cde6e63dbd7cc82ce3f227c9..46573213797d99ff3b72c78734ce987f5c13e049 100644 --- a/17-D3D12_Assimp_Animation/17-D3D12_Assimp_Animation.cpp +++ b/17-D3D12_Assimp_Animation/17-D3D12_Assimp_Animation.cpp @@ -78,17 +78,17 @@ LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ) { - int iWidth = 1024; - int iHeight = 768; + int iWidth = 1280; + int iHeight = 800; HWND hWnd = nullptr; MSG msg = {}; const UINT nFrameBackBufCount = 3u; UINT nFrameIndex = 0; DXGI_FORMAT emRenderTargetFormat = DXGI_FORMAT_R8G8B8A8_UNORM; + DXGI_FORMAT emDepthStencilFormat = DXGI_FORMAT_D32_FLOAT; const float faClearColor[] = { 0.17647f, 0.549f, 0.941176f, 1.0f }; - UINT nRTVDescriptorSize = 0U; UINT nSamplerDescriptorSize = 0; UINT nCBVSRVDescriptorSize = 0; @@ -98,9 +98,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR D3D_FEATURE_LEVEL emFeatureLevel = D3D_FEATURE_LEVEL_12_1; - ComPtr pIDXGIFactory5; ComPtr pIDXGIFactory6; - ComPtr pIAdapter1; ComPtr pID3D12Device4; ComPtr pIMainCMDQueue; @@ -117,7 +115,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR D3D12_RESOURCE_BARRIER stBeginResBarrier = {}; D3D12_RESOURCE_BARRIER stEneResBarrier = {}; - ComPtr pISwapChain1; + ComPtr pISwapChain3; ComPtr pIRTVHeap; ComPtr pIARenderTargets[nFrameBackBufCount]; @@ -164,9 +162,43 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR ST_GRS_CB_MVP* pstCBMVP = nullptr; ST_GRS_CB_BONES* pstBones = nullptr; + // 纹理数组,一般模型中会关联多个纹理,本示例中目前仅使用基本的纹理 CAtlArray> arTexture; CAtlArray> arTextureUp; + USES_CONVERSION; + + D3D12_HEAP_PROPERTIES stDefautHeapProps = {}; + stDefautHeapProps.Type = D3D12_HEAP_TYPE_DEFAULT; + stDefautHeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + stDefautHeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + stDefautHeapProps.CreationNodeMask = 0; + stDefautHeapProps.VisibleNodeMask = 0; + + D3D12_HEAP_PROPERTIES stUploadHeapProps = {}; + stUploadHeapProps.Type = D3D12_HEAP_TYPE_UPLOAD; + stUploadHeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + stUploadHeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + stUploadHeapProps.CreationNodeMask = 0; + stUploadHeapProps.VisibleNodeMask = 0; + + D3D12_RESOURCE_DESC stBufferResSesc = {}; + stBufferResSesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + stBufferResSesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + stBufferResSesc.Flags = D3D12_RESOURCE_FLAG_NONE; + stBufferResSesc.Format = DXGI_FORMAT_UNKNOWN; + stBufferResSesc.Width = 0; + stBufferResSesc.Height = 1; + stBufferResSesc.DepthOrArraySize = 1; + stBufferResSesc.MipLevels = 1; + stBufferResSesc.SampleDesc.Count = 1; + stBufferResSesc.SampleDesc.Quality = 0; + + D3D12_RESOURCE_BARRIER stResStateTransBarrier = {}; + stResStateTransBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + stResStateTransBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + stResStateTransBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + try { ::CoInitialize( nullptr ); //for WIC & COM @@ -200,18 +232,11 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR StringCchCopyA( g_pszAppPathA, MAX_PATH, T2A( g_pszAppPath ) ); } - // 1、载入默认的模型 + // 1、载入模型 { - g_stMeshData.m_strFileName = CString( g_pszAppPathA ) + "Assets\\The3DModel\\hero.x"; - - CHAR pszAppPathA[MAX_PATH] = {}; - StringCchCopyA( pszAppPathA, MAX_PATH, T2A( g_pszAppPath ) ); + g_stMeshData.m_strFileName.Format( "%Assets\\The3DModel\\hero.x", g_pszAppPathA ); - //CHAR pXFile[MAX_PATH] = {}; - //StringCchPrintfA( pXFile, MAX_PATH, "%Assets\\The3DModel\\hero.x", pszAppPathA ); - g_stMeshData.m_strFileName.Format( "%Assets\\The3DModel\\hero.x", pszAppPathA ); - OPENFILENAMEA ofn; - RtlZeroMemory( &ofn, sizeof( ofn ) ); + OPENFILENAMEA ofn = {}; ofn.lStructSize = sizeof( ofn ); ofn.hwndOwner = ::GetConsoleWindow(); ofn.lpstrFilter = "x 文件\0*.x;*.X\0OBJ文件\0*.obj\0FBX文件\0*.fbx\0所有文件\0*.*\0"; @@ -222,7 +247,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR if ( !GetOpenFileNameA( &ofn ) ) { - g_stMeshData.m_strFileName.Format( "%Assets\\The3DModel\\hero.x", pszAppPathA ); + g_stMeshData.m_strFileName.Format( "%Assets\\The3DModel\\hero.x", g_pszAppPathA ); } if ( !LoadMesh( g_stMeshData.m_strFileName, g_stMeshData ) ) @@ -284,6 +309,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR nDXGIFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG; } #endif + ComPtr pIDXGIFactory5; GRS_THROW_IF_FAILED( CreateDXGIFactory2( nDXGIFactoryFlags, IID_PPV_ARGS( &pIDXGIFactory5 ) ) ); GRS_SET_DXGI_DEBUGNAME_COMPTR( pIDXGIFactory5 ); @@ -294,6 +320,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR // 4、枚举适配器创建设备 {//选择NUMA架构的独显来创建3D设备对象,暂时先不支持集显了,当然你可以修改这些行为 + ComPtr pIAdapter1; GRS_THROW_IF_FAILED( pIDXGIFactory6->EnumAdapterByGpuPreference( 0 , DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE , IID_PPV_ARGS( &pIAdapter1 ) ) ); @@ -344,6 +371,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR GRS_SET_D3D12_DEBUGNAME_COMPTR( pIMainCMDList ); + // 创建Copy命令队列 stQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_COPY; GRS_THROW_IF_FAILED( pID3D12Device4->CreateCommandQueue( &stQueueDesc, IID_PPV_ARGS( &pICopyCMDQueue ) ) ); GRS_SET_D3D12_DEBUGNAME_COMPTR( pICopyCMDQueue ); @@ -354,7 +382,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR GRS_SET_D3D12_DEBUGNAME_COMPTR( pICopyCMDAlloc ); - // 创建图形命令列表 + // 创建Copy命令列表 GRS_THROW_IF_FAILED( pID3D12Device4->CreateCommandList( 0 , D3D12_COMMAND_LIST_TYPE_COPY @@ -378,6 +406,8 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR stSwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; stSwapChainDesc.Scaling = DXGI_SCALING_NONE; + ComPtr pISwapChain1; + GRS_THROW_IF_FAILED( pIDXGIFactory6->CreateSwapChainForHwnd( pIMainCMDQueue.Get(), // 交换链需要命令队列,Present命令要执行 hWnd, @@ -388,9 +418,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR ) ); GRS_SET_DXGI_DEBUGNAME_COMPTR( pISwapChain1 ); - GRS_THROW_IF_FAILED( pISwapChain1.As( &pISwapChain3 ) ); - GRS_SET_DXGI_DEBUGNAME_COMPTR( pISwapChain3 ); //得到当前后缓冲区的序号,也就是下一个将要呈送显示的缓冲区的序号 @@ -412,7 +440,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR } - //创建RTV的描述符 + //创建RTV的描述符 { D3D12_CPU_DESCRIPTOR_HANDLE stRTVHandle = pIRTVHeap->GetCPUDescriptorHandleForHeapStart(); @@ -440,22 +468,15 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR // 7、创建深度缓冲及深度缓冲描述符堆 { D3D12_DEPTH_STENCIL_VIEW_DESC stDepthStencilDesc = {}; - stDepthStencilDesc.Format = DXGI_FORMAT_D32_FLOAT; + stDepthStencilDesc.Format = emDepthStencilFormat; stDepthStencilDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; stDepthStencilDesc.Flags = D3D12_DSV_FLAG_NONE; D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; - depthOptimizedClearValue.Format = DXGI_FORMAT_D32_FLOAT; + depthOptimizedClearValue.Format = emDepthStencilFormat; depthOptimizedClearValue.DepthStencil.Depth = 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; - D3D12_HEAP_PROPERTIES stDSHeapProp = { }; - stDSHeapProp.Type = D3D12_HEAP_TYPE_DEFAULT; - stDSHeapProp.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; - stDSHeapProp.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; - stDSHeapProp.CreationNodeMask = 0; - stDSHeapProp.VisibleNodeMask = 0; - D3D12_RESOURCE_DESC stDSTex2DDesc = {}; stDSTex2DDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; stDSTex2DDesc.Alignment = 0; @@ -463,7 +484,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR stDSTex2DDesc.Height = iHeight; stDSTex2DDesc.DepthOrArraySize = 1; stDSTex2DDesc.MipLevels = 0; - stDSTex2DDesc.Format = DXGI_FORMAT_D32_FLOAT; + stDSTex2DDesc.Format = emDepthStencilFormat; stDSTex2DDesc.SampleDesc.Count = 1; stDSTex2DDesc.SampleDesc.Quality = 0; stDSTex2DDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; @@ -472,7 +493,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR //使用隐式默认堆创建一个深度蜡板缓冲区, //因为基本上深度缓冲区会一直被使用,重用的意义不大,所以直接使用隐式堆,图方便 GRS_THROW_IF_FAILED( pID3D12Device4->CreateCommittedResource( - &stDSHeapProp + &stDefautHeapProps , D3D12_HEAP_FLAG_NONE , &stDSTex2DDesc , D3D12_RESOURCE_STATE_DEPTH_WRITE @@ -673,14 +694,14 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR GRS_THROW_IF_FAILED( hr ); } - // 我们多添加了一个法线的定义,但目前Shader中我们并没有使用 + // 定义传入管线的数据结构,这里使用了多Slot方式,注意Slot的用法 D3D12_INPUT_ELEMENT_DESC stIALayoutSphere[] = { - { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, - { "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 2, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, - { "BLENDINDICES", 0, DXGI_FORMAT_R32G32B32A32_UINT, 3, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, - { "BLENDWEIGHT", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 3, 16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } + { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 2, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "BLENDINDICES", 0, DXGI_FORMAT_R32G32B32A32_UINT, 3, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "BLENDWEIGHT", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 3, 16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } }; // 创建 graphics pipeline state object (PSO)对象 @@ -702,7 +723,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR stPSODesc.BlendState.IndependentBlendEnable = FALSE; stPSODesc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; - stPSODesc.DSVFormat = DXGI_FORMAT_D32_FLOAT; + stPSODesc.DSVFormat = emDepthStencilFormat; stPSODesc.DepthStencilState.DepthEnable = TRUE; stPSODesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;//启用深度缓存写入功能 stPSODesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS; //深度测试函数(该值为普通的深度测试) @@ -726,6 +747,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR } // 10、创建 SRV CBV Sample堆 + if( TRUE ) { //将纹理视图描述符和CBV描述符放在一个描述符堆上 D3D12_DESCRIPTOR_HEAP_DESC stSRVHeapDesc = {}; @@ -750,54 +772,42 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR // 11、创建D3D12的模型资源,并复制数据 { + size_t szAlign = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; // 计算所有的缓冲大小 - size_t szPositions = g_stMeshData.m_arPositions.GetCount() * sizeof( g_stMeshData.m_arPositions[0] ); - size_t szNormals = g_stMeshData.m_arNormals.GetCount() * sizeof( g_stMeshData.m_arNormals[0] ); - size_t szTexCoords = g_stMeshData.m_arTexCoords.GetCount() * sizeof( g_stMeshData.m_arTexCoords[0] ); + size_t szPositions = g_stMeshData.m_arPositions.GetCount() * sizeof( g_stMeshData.m_arPositions[0] ); + size_t szNormals = g_stMeshData.m_arNormals.GetCount() * sizeof( g_stMeshData.m_arNormals[0] ); + size_t szTexCoords = g_stMeshData.m_arTexCoords.GetCount() * sizeof( g_stMeshData.m_arTexCoords[0] ); size_t szBoneIndices = g_stMeshData.m_arBoneIndices.GetCount() * sizeof( g_stMeshData.m_arBoneIndices[0] ); - size_t szIndices = g_stMeshData.m_arIndices.GetCount() * sizeof( g_stMeshData.m_arIndices[0] ); - // 需要的缓冲大小+64k-1 使得刚好是64k边界大小时,可以多分配64k出来,防止CreatePlacedResource报错 - size_t szVBBuffer = szPositions + szNormals + szTexCoords + szBoneIndices + D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT - 1; - // 注意对齐边界必须是4的倍数,比5大4的倍数是8 - size_t szAlign = 4 * D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; + size_t szIndices = g_stMeshData.m_arIndices.GetCount() * sizeof( g_stMeshData.m_arIndices[0] ); - // 创建上传堆 + // 需要的缓冲大小+64k-1 使得刚好是64k边界大小时,可以多分配64k出来,防止CreatePlacedResource报错 + size_t szVBBuffer = GRS_UPPER( szPositions, szAlign ) + + GRS_UPPER( szNormals, szAlign ) + + GRS_UPPER( szTexCoords, szAlign ) + + GRS_UPPER( szBoneIndices, szAlign ) + + szAlign - 1; + D3D12_HEAP_DESC stUploadHeapDesc = { }; + // 上传堆类型就是普通的缓冲,可以摆放任意数据 + stUploadHeapDesc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; // 实际数据大小的5*64K边界对齐大小,因为有5个Buffer stUploadHeapDesc.SizeInBytes = GRS_UPPER( szVBBuffer, szAlign ); // 注意上传堆肯定是Buffer类型,可以不指定对齐方式,其默认是64k边界对齐 stUploadHeapDesc.Alignment = 0; - stUploadHeapDesc.Properties.Type = D3D12_HEAP_TYPE_UPLOAD; //上传堆类型 - stUploadHeapDesc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; - stUploadHeapDesc.Properties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; - // 上传堆就是缓冲,可以摆放任意数据 - stUploadHeapDesc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; - + stUploadHeapDesc.Properties = stUploadHeapProps; + + // 创建顶点数据的上传堆 GRS_THROW_IF_FAILED( pID3D12Device4->CreateHeap( &stUploadHeapDesc, IID_PPV_ARGS( &pIUploadHeapModel ) ) ); GRS_SET_D3D12_DEBUGNAME_COMPTR( pIUploadHeapModel ); - size_t szOffset = 0; BYTE* pData = nullptr; - D3D12_RESOURCE_DESC stUploadBufferDesc = {}; - - stUploadBufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - stUploadBufferDesc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; - stUploadBufferDesc.Width = GRS_UPPER( szPositions, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ); - stUploadBufferDesc.Height = 1; - stUploadBufferDesc.DepthOrArraySize = 1; - stUploadBufferDesc.MipLevels = 1; - stUploadBufferDesc.Format = DXGI_FORMAT_UNKNOWN; - stUploadBufferDesc.SampleDesc.Count = 1; - stUploadBufferDesc.SampleDesc.Quality = 0; - stUploadBufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - stUploadBufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE; - // Positions Upload Buffer + stBufferResSesc.Width = GRS_UPPER( szPositions, szAlign ); GRS_THROW_IF_FAILED( pID3D12Device4->CreatePlacedResource( pIUploadHeapModel.Get() , szOffset - , &stUploadBufferDesc + , &stBufferResSesc , D3D12_RESOURCE_STATE_GENERIC_READ , nullptr , IID_PPV_ARGS( &pIVBPositionsUp ) ) ); @@ -812,13 +822,13 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR pData = nullptr; // Normals Upload Buffer - szOffset += stUploadBufferDesc.Width; - stUploadBufferDesc.Width = GRS_UPPER( szNormals, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ); + szOffset += stBufferResSesc.Width; + stBufferResSesc.Width = GRS_UPPER( szNormals, szAlign ); GRS_THROW_IF_FAILED( pID3D12Device4->CreatePlacedResource( pIUploadHeapModel.Get() , szOffset - , &stUploadBufferDesc + , &stBufferResSesc , D3D12_RESOURCE_STATE_GENERIC_READ , nullptr , IID_PPV_ARGS( &pIVBNormalsUp ) ) ); @@ -833,13 +843,13 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR pData = nullptr; // TexCoords Upload Buffer - szOffset += stUploadBufferDesc.Width; - stUploadBufferDesc.Width = GRS_UPPER( szTexCoords, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ); + szOffset += stBufferResSesc.Width; + stBufferResSesc.Width = GRS_UPPER( szTexCoords, szAlign ); GRS_THROW_IF_FAILED( pID3D12Device4->CreatePlacedResource( pIUploadHeapModel.Get() , szOffset - , &stUploadBufferDesc + , &stBufferResSesc , D3D12_RESOURCE_STATE_GENERIC_READ , nullptr , IID_PPV_ARGS( &pIVBTexCoordsUp ) ) ); @@ -854,13 +864,13 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR pData = nullptr; // Bone Indices Upload Buffer - szOffset += stUploadBufferDesc.Width; - stUploadBufferDesc.Width = GRS_UPPER( szBoneIndices, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ); + szOffset += stBufferResSesc.Width; + stBufferResSesc.Width = GRS_UPPER( szBoneIndices, szAlign ); GRS_THROW_IF_FAILED( pID3D12Device4->CreatePlacedResource( pIUploadHeapModel.Get() , szOffset - , &stUploadBufferDesc + , &stBufferResSesc , D3D12_RESOURCE_STATE_GENERIC_READ , nullptr , IID_PPV_ARGS( &pIVBBoneIndicesUp ) ) ); @@ -874,52 +884,26 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR pIVBBoneIndicesUp->Unmap( 0, nullptr ); pData = nullptr; - // 创建默认堆(显存中的堆) D3D12_HEAP_DESC stDefaultHeapDesc = {}; // 大小跟上传堆一样 - stDefaultHeapDesc.SizeInBytes = GRS_UPPER( szVBBuffer, szAlign ); - // 指定堆的对齐方式,这里使用了默认的64K边界对齐,因为这里实际放的是顶点数据 - stDefaultHeapDesc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; - stDefaultHeapDesc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT; //默认堆类型 - stDefaultHeapDesc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; - stDefaultHeapDesc.Properties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; - // 只是用来摆放普通的缓冲 + stDefaultHeapDesc.SizeInBytes = stUploadHeapDesc.SizeInBytes; stDefaultHeapDesc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; + // 指定堆的对齐方式,这里使用了默认的64K边界对齐,因为这里实际放的是顶点数据 + stDefaultHeapDesc.Alignment = szAlign; + stDefaultHeapDesc.Properties = stDefautHeapProps; // Vertex Data Default Heap GRS_THROW_IF_FAILED( pID3D12Device4->CreateHeap( &stDefaultHeapDesc, IID_PPV_ARGS( &pIDefaultHeapModel ) ) ); GRS_SET_D3D12_DEBUGNAME_COMPTR( pIDefaultHeapModel ); - - D3D12_RESOURCE_DESC stDefaultBufferDesc = {}; - szOffset = 0; - - stDefaultBufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - stDefaultBufferDesc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; - stDefaultBufferDesc.Width = GRS_UPPER( szPositions, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ); - stDefaultBufferDesc.Height = 1; - stDefaultBufferDesc.DepthOrArraySize = 1; - stDefaultBufferDesc.MipLevels = 1; - stDefaultBufferDesc.Format = DXGI_FORMAT_UNKNOWN; - stDefaultBufferDesc.SampleDesc.Count = 1; - stDefaultBufferDesc.SampleDesc.Quality = 0; - stDefaultBufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - stDefaultBufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE; - - D3D12_RESOURCE_BARRIER stBufferBarrier = {}; - stBufferBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - stBufferBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - stBufferBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; - stBufferBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; - stBufferBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - // Positions Default Buffer szOffset = 0; + stBufferResSesc.Width = GRS_UPPER( szPositions, szAlign ); GRS_THROW_IF_FAILED( pID3D12Device4->CreatePlacedResource( pIDefaultHeapModel.Get() , szOffset - , &stDefaultBufferDesc + , &stBufferResSesc , D3D12_RESOURCE_STATE_COPY_DEST , nullptr , IID_PPV_ARGS( &pIVBPositions ) ) ); @@ -929,17 +913,19 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR // 第二次Copy!独显的时候:Share Memory -> Video Memory // 这里只是记录个复制命令,之后会在Copy Engine上Excute pICopyCMDList->CopyBufferRegion( pIVBPositions.Get(), 0, pIVBPositionsUp.Get(), 0, szPositions ); - // 然后加入个资源屏障,同步! 并确认复制操作完成 - stBufferBarrier.Transition.pResource = pIVBPositions.Get(); - pICopyCMDList->ResourceBarrier( 1, &stBufferBarrier ); + // 然后加入个资源屏障,同步! 并确认复制操作完成 + stResStateTransBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + stResStateTransBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + stResStateTransBarrier.Transition.pResource = pIVBPositions.Get(); + pICopyCMDList->ResourceBarrier( 1, &stResStateTransBarrier ); // Normals Default Buffer - szOffset += stDefaultBufferDesc.Width; - stDefaultBufferDesc.Width = GRS_UPPER( szNormals, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ); + szOffset += stBufferResSesc.Width; + stBufferResSesc.Width = GRS_UPPER( szNormals, szAlign ); GRS_THROW_IF_FAILED( pID3D12Device4->CreatePlacedResource( pIDefaultHeapModel.Get() , szOffset - , &stDefaultBufferDesc + , &stBufferResSesc , D3D12_RESOURCE_STATE_COPY_DEST , nullptr , IID_PPV_ARGS( &pIVBNormals ) ) ); @@ -950,16 +936,16 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR // 这里只是记录个复制命令,之后会在Copy Engine上Excute pICopyCMDList->CopyBufferRegion( pIVBNormals.Get(), 0, pIVBNormalsUp.Get(), 0, szNormals ); // 然后加入个资源屏障,同步! 并确认复制操作完成 - stBufferBarrier.Transition.pResource = pIVBNormals.Get(); - pICopyCMDList->ResourceBarrier( 1, &stBufferBarrier ); + stResStateTransBarrier.Transition.pResource = pIVBNormals.Get(); + pICopyCMDList->ResourceBarrier( 1, &stResStateTransBarrier ); // TexCoords Default Buffer - szOffset += stDefaultBufferDesc.Width; - stDefaultBufferDesc.Width = GRS_UPPER( szTexCoords, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ); + szOffset += stBufferResSesc.Width; + stBufferResSesc.Width = GRS_UPPER( szTexCoords, szAlign ); GRS_THROW_IF_FAILED( pID3D12Device4->CreatePlacedResource( pIDefaultHeapModel.Get() , szOffset - , &stDefaultBufferDesc + , &stBufferResSesc , D3D12_RESOURCE_STATE_COPY_DEST , nullptr , IID_PPV_ARGS( &pIVBTexCoords ) ) ); @@ -970,16 +956,16 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR // 这里只是记录个复制命令,之后会在Copy Engine上Excute pICopyCMDList->CopyBufferRegion( pIVBTexCoords.Get(), 0, pIVBTexCoordsUp.Get(), 0, szTexCoords ); // 然后加入个资源屏障,同步! 并确认复制操作完成 - stBufferBarrier.Transition.pResource = pIVBTexCoords.Get(); - pICopyCMDList->ResourceBarrier( 1, &stBufferBarrier ); + stResStateTransBarrier.Transition.pResource = pIVBTexCoords.Get(); + pICopyCMDList->ResourceBarrier( 1, &stResStateTransBarrier ); // Bone Indices Default Buffer - szOffset += stDefaultBufferDesc.Width; - stDefaultBufferDesc.Width = GRS_UPPER( szBoneIndices, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ); + szOffset += stBufferResSesc.Width; + stBufferResSesc.Width = GRS_UPPER( szBoneIndices, szAlign ); GRS_THROW_IF_FAILED( pID3D12Device4->CreatePlacedResource( pIDefaultHeapModel.Get() , szOffset - , &stDefaultBufferDesc + , &stBufferResSesc , D3D12_RESOURCE_STATE_COPY_DEST , nullptr , IID_PPV_ARGS( &pIVBBoneIndices ) ) ); @@ -990,8 +976,9 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR // 这里只是记录个复制命令,之后会在Copy Engine上Excute pICopyCMDList->CopyBufferRegion( pIVBBoneIndices.Get(), 0, pIVBBoneIndicesUp.Get(), 0, szBoneIndices ); // 然后加入个资源屏障,同步! 并确认复制操作完成 - stBufferBarrier.Transition.pResource = pIVBBoneIndices.Get(); - pICopyCMDList->ResourceBarrier( 1, &stBufferBarrier ); + stResStateTransBarrier.Transition.pResource = pIVBBoneIndices.Get(); + pICopyCMDList->ResourceBarrier( 1, &stResStateTransBarrier ); + // Positions Buffer View staVBV[0].BufferLocation = pIVBPositions->GetGPUVirtualAddress(); @@ -1015,17 +1002,17 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR // Indices Upload Buffer // Indices 上传堆 - stUploadHeapDesc.SizeInBytes = GRS_UPPER( szIndices, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ); + stUploadHeapDesc.SizeInBytes = GRS_UPPER( szIndices, szAlign ); GRS_THROW_IF_FAILED( pID3D12Device4->CreateHeap( &stUploadHeapDesc, IID_PPV_ARGS( &pIUploadHeapIndices ) ) ); GRS_SET_D3D12_DEBUGNAME_COMPTR( pIUploadHeapIndices ); - stUploadBufferDesc.Width = GRS_UPPER( szIndices, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ); + stBufferResSesc.Width = GRS_UPPER( szIndices, szAlign ); GRS_THROW_IF_FAILED( pID3D12Device4->CreatePlacedResource( pIUploadHeapIndices.Get() , 0 - , &stUploadBufferDesc + , &stBufferResSesc , D3D12_RESOURCE_STATE_GENERIC_READ , nullptr , IID_PPV_ARGS( &pIIBIndicesUp ) ) ); @@ -1039,19 +1026,18 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR pIIBIndicesUp->Unmap( 0, nullptr ); pData = nullptr; - // Indices Default Buffer // Indices Data Default Heap - stDefaultHeapDesc.SizeInBytes = GRS_UPPER( szIndices, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ); + stDefaultHeapDesc.SizeInBytes = GRS_UPPER( szIndices, szAlign ); GRS_THROW_IF_FAILED( pID3D12Device4->CreateHeap( &stDefaultHeapDesc, IID_PPV_ARGS( &pIDefaultHeapIndices ) ) ); GRS_SET_D3D12_DEBUGNAME_COMPTR( pIDefaultHeapIndices ); - stDefaultBufferDesc.Width = GRS_UPPER( szIndices, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ); + stBufferResSesc.Width = GRS_UPPER( szIndices, szAlign ); GRS_THROW_IF_FAILED( pID3D12Device4->CreatePlacedResource( pIDefaultHeapIndices.Get() , 0 - , &stDefaultBufferDesc + , &stBufferResSesc , D3D12_RESOURCE_STATE_COPY_DEST , nullptr , IID_PPV_ARGS( &pIIBIndices ) ) ); @@ -1062,16 +1048,14 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR // 这里只是记录个复制命令,之后会在Copy Engine上Excute pICopyCMDList->CopyBufferRegion( pIIBIndices.Get(), 0, pIIBIndicesUp.Get(), 0, szIndices ); // 然后加入个资源屏障,同步! 并确认复制操作完成 - stBufferBarrier.Transition.pResource = pIIBIndices.Get(); - pICopyCMDList->ResourceBarrier( 1, &stBufferBarrier ); - + stResStateTransBarrier.Transition.pResource = pIIBIndices.Get(); + pICopyCMDList->ResourceBarrier( 1, &stResStateTransBarrier ); // Indices Buffer View stIBV.BufferLocation = pIIBIndices->GetGPUVirtualAddress(); stIBV.SizeInBytes = (UINT) szIndices; // 32bit ? 16bit Index stIBV.Format = ( sizeof( g_stMeshData.m_arIndices[0] ) > 2 ) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT; - // Const Buffers D3D12_HEAP_PROPERTIES stUploadHeapProp = { }; @@ -1084,8 +1068,8 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR D3D12_RESOURCE_DESC stConstBufferDesc = {}; stConstBufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - stConstBufferDesc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; - stConstBufferDesc.Width = GRS_UPPER( sizeof( ST_GRS_CB_MVP ), D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ); + stConstBufferDesc.Alignment = szAlign; + stConstBufferDesc.Width = GRS_UPPER( sizeof( ST_GRS_CB_MVP ), szAlign ); stConstBufferDesc.Height = 1; stConstBufferDesc.DepthOrArraySize = 1; stConstBufferDesc.MipLevels = 1; @@ -1109,7 +1093,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR GRS_THROW_IF_FAILED( pICBMVP->Map( 0, nullptr, reinterpret_cast( &pstCBMVP ) ) ); // Bones Const Buffer - stConstBufferDesc.Width = GRS_UPPER( sizeof( ST_GRS_CB_BONES ), D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ); + stConstBufferDesc.Width = GRS_UPPER( sizeof( ST_GRS_CB_BONES ), szAlign ); GRS_THROW_IF_FAILED( pID3D12Device4->CreateCommittedResource( &stUploadHeapProp @@ -1123,8 +1107,6 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR // Map 之后就不再Unmap了 直接复制数据进去 这样每帧都不用map-copy-unmap浪费时间了 GRS_THROW_IF_FAILED( pICBBones->Map( 0, nullptr, reinterpret_cast( &pstBones ) ) ); - - // Create Const Buffer View D3D12_CPU_DESCRIPTOR_HANDLE stCBVHandle = { pICBVSRVHeap->GetCPUDescriptorHandleForHeapStart() }; @@ -1148,17 +1130,16 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR // 12、加载纹理 { - // 从模型文件所在路径计算纹理文件 + // 从模型文件所在路径计算纹理文件路径 WCHAR pszModelPath[MAX_PATH] = {}; StringCchCopyW( pszModelPath, MAX_PATH, A2W( g_stMeshData.m_strFileName ) ); WCHAR* lastSlash = _tcsrchr( pszModelPath, _T( '\\' ) ); if ( lastSlash ) - {//删除Exe文件名 + {// 删除模型文件名 *( lastSlash ) = _T( '\0' ); } - //使用WIC类厂对象接口加载纹理图片,并得到一个WIC解码器对象接口,图片信息就在这个接口代表的对象中了 WCHAR pszTexcuteFileName[MAX_PATH] = {}; ID3D12Resource* pITex = nullptr; ID3D12Resource* pITexUp = nullptr; @@ -1168,7 +1149,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR stSRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; stSRVDesc.Texture2D.MipLevels = 1; - D3D12_CPU_DESCRIPTOR_HANDLE stSRVHandle = { pICBVSRVHeap->GetCPUDescriptorHandleForHeapStart() }; + D3D12_CPU_DESCRIPTOR_HANDLE stSRVHandle = pICBVSRVHeap->GetCPUDescriptorHandleForHeapStart() ; // 堆上第三个开始是纹理的SRV stSRVHandle.ptr += (size_t) 2 * nCBVSRVDescriptorSize; @@ -1243,7 +1224,6 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR stSamplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; pID3D12Device4->CreateSampler( &stSamplerDesc, hSamplerHeap ); - } // 13、上传 @@ -1269,7 +1249,6 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR stBeginResBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; stBeginResBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - stEneResBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; stEneResBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; stEneResBarrier.Transition.pResource = pIARenderTargets[nFrameIndex].Get(); @@ -1518,19 +1497,19 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam if ( VK_TAB == n16KeyCode ) {// 按Tab键切换选择模型文件 - OPENFILENAMEA ofn = {}; - ofn.lStructSize = sizeof( ofn ); - ofn.hwndOwner = hWnd; - ofn.lpstrFilter = "x 文件\0*.x;*.X\0OBJ文件\0*.obj\0FBX文件\0*.fbx\0所有文件\0*.*\0"; - ofn.lpstrFile = g_pszModelFile; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrTitle = "请选择一个要显示的3D模型文件..."; - ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; - - if ( !GetOpenFileNameA( &ofn ) ) - { - StringCchPrintfA( g_pszModelFile, MAX_PATH, "%sasset\\rgbgame\\hero.x", g_pszAppPathA ); - } + //OPENFILENAMEA ofn = {}; + //ofn.lStructSize = sizeof( ofn ); + //ofn.hwndOwner = hWnd; + //ofn.lpstrFilter = "x 文件\0*.x;*.X\0OBJ文件\0*.obj\0FBX文件\0*.fbx\0所有文件\0*.*\0"; + //ofn.lpstrFile = g_pszModelFile; + //ofn.nMaxFile = MAX_PATH; + //ofn.lpstrTitle = "请选择一个要显示的3D模型文件..."; + //ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; + + //if ( !GetOpenFileNameA( &ofn ) ) + //{ + // StringCchPrintfA( g_pszModelFile, MAX_PATH, "%sasset\\rgbgame\\hero.x", g_pszAppPathA ); + //} } if ( VK_SPACE == n16KeyCode ) @@ -1549,7 +1528,9 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam g_bWireFrame = !g_bWireFrame; } - XMVECTOR vDelta = { 0.0f,0.0f,1.0f,0.0f }; + float fDelta = 0.2f; + + XMVECTOR vDelta = { 0.0f,0.0f,fDelta,0.0f }; // Z-轴 if ( VK_UP == n16KeyCode || 'w' == n16KeyCode || 'W' == n16KeyCode ) { @@ -1564,7 +1545,7 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam } // X-轴 - vDelta = { 1.0f,0.0f,0.0f,0.0f }; + vDelta = { fDelta,0.0f,0.0f,0.0f }; if ( VK_LEFT == n16KeyCode || 'a' == n16KeyCode || 'A' == n16KeyCode ) { g_v4EyePos = XMVectorAdd( g_v4EyePos, vDelta ); @@ -1578,7 +1559,7 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam } // Y-轴 - vDelta = { 0.0f,1.0f,0.0f,0.0f }; + vDelta = { 0.0f,fDelta,0.0f,0.0f }; if ( VK_PRIOR == n16KeyCode || 'r' == n16KeyCode || 'R' == n16KeyCode ) { g_v4EyePos = XMVectorAdd( g_v4EyePos, vDelta ); @@ -1592,15 +1573,16 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam } // 缩放 + fDelta = 0.2f; if ( VK_ADD == n16KeyCode || VK_OEM_PLUS == n16KeyCode ) { - g_fScaling += 1.0f; + g_fScaling += fDelta; } if ( VK_SUBTRACT == n16KeyCode || VK_OEM_MINUS == n16KeyCode ) { - g_fScaling -= 1.0f; - if ( g_fScaling <= 1.0f ) + g_fScaling -= fDelta; + if ( g_fScaling <= 0.0f ) { g_fScaling = 1.0f; } diff --git a/18-PBR-Base-Point-Lights/18-PBR-Base-Point-Lights.cpp b/18-PBR-Base-Point-Lights/18-PBR-Base-Point-Lights.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2bea063d1f7f2a86bbaba5450b70cd9331183bd --- /dev/null +++ b/18-PBR-Base-Point-Lights/18-PBR-Base-Point-Lights.cpp @@ -0,0 +1,1164 @@ +#include +#define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料 +#include +#include +#include +#include //添加WTL支持 方便使用COM +#include +#include //for ifstream + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include //for d3d12 +#include +#if defined(_DEBUG) +#include +#endif + +#include "../Commons/GRS_Mem.h" +#include "../Commons/GRS_D3D12_Utility.h" + +using namespace std; +using namespace DirectX; +using namespace Microsoft; +using namespace Microsoft::WRL; + +#pragma comment(lib, "dxguid.lib") +#pragma comment(lib, "dxgi.lib") +#pragma comment(lib, "d3d12.lib") +#pragma comment(lib, "d3dcompiler.lib") + +#define GRS_SLEEP(dwMilliseconds) WaitForSingleObject(GetCurrentThread(),dwMilliseconds) +#define GRS_THROW_IF_FAILED(hr) {HRESULT _hr = (hr);if (FAILED(_hr)){ ATLTRACE("Error: 0x%08x\n",_hr); AtlThrow(_hr); }} +#define GRS_SAFE_RELEASE(p) if(nullptr != (p)){(p)->Release();(p)=nullptr;} +//更简洁的向上边界对齐算法 内存管理中常用 请记住 +#define GRS_UPPER(A,B) ((size_t)(((A)+((B)-1))&~((B) - 1))) +//上取整除法 +#define GRS_UPPER_DIV(A,B) ((UINT)(((A)+((B)-1))/(B))) + +#define GRS_WND_CLASS _T("GRS Game Window Class") +#define GRS_WND_TITLE _T("GRS DirectX12 PBR Base With Point Light Sample") + +struct ST_GRS_CB_MVP +{ + XMFLOAT4X4 mxWorld; //世界矩阵,这里其实是Model->World的转换矩阵 + XMFLOAT4X4 mxView; //视矩阵 + XMFLOAT4X4 mxProjection; //投影矩阵 + XMFLOAT4X4 mxViewProj; //视矩阵*投影 + XMFLOAT4X4 mxMVP; //世界*视矩阵*投影 +}; + +// Camera +struct ST_CB_CAMERA //: register( b1 ) +{ + XMFLOAT4 m_v4CameraPos; +}; + +#define GRS_LIGHT_COUNT 8 +// lights +struct ST_CB_LIGHTS //: register( b2 ) +{ + XMFLOAT4 m_v4LightPos[GRS_LIGHT_COUNT]; + XMFLOAT4 m_v4LightClr[GRS_LIGHT_COUNT]; +}; + +// PBR material parameters +struct ST_CB_PBR_MATERIAL //: register( b3 ) +{ + XMFLOAT3 m_v3Albedo; // 反射率 + float m_fMetallic; // 金属度 + float m_fRoughness; // 粗糙度 + float m_fAO; // 环境光遮蔽 +}; + +struct ST_GRS_VERTEX +{ + XMFLOAT4 m_v4Position; //Position + XMFLOAT4 m_v4Normal; //Normal + XMFLOAT2 m_v2UV; //Texcoord +}; + +TCHAR g_pszAppPath[MAX_PATH] = {}; + +XMVECTOR g_v4EyePos = XMVectorSet( 0.0f, 0.0f, -3.0f, 0.0f ); //眼睛位置 +XMVECTOR g_v4LookAt = XMVectorSet( 0.0f, 0.0f, 2.0f, 0.0f ); //眼睛所盯的位置 +XMVECTOR g_v4UpDir = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f ); //头部正上方位置 + +// 缩放系数 +float g_fScaling = 1.0f; + +// 材质参数 +float g_fMetallic = 0.01f; // q-a 键增减 +float g_fRoughness = 0.01f; // w-s 键增减 +float g_fAO = 0.03f; // e-d 键增减 + +UINT g_nCurAlbedo = 0; // Tab键切换 +XMFLOAT3 g_pv3Albedo[] = +{ + {0.97f,0.96f,0.91f} // 银 Silver + ,{0.91f,0.92f,0.92f} // 铝 Aluminum + ,{0.76f,0.73f,0.69f} // 钛 Titanium + ,{0.77f,0.78f,0.78f} // 铁 Iron + ,{0.83f,0.81f,0.78f} // 铂 Platinum + ,{1.00f,0.85f,0.57f} // 金 Gold + ,{0.98f,0.90f,0.59f} // 黄铜 Brass + ,{0.97f,0.74f,0.62f} // 铜 Copper +}; +const UINT g_nAlbedoCount = _countof( g_pv3Albedo ); + +// 物体旋转的角速度,单位:弧度/秒 +double g_fPalstance = 10.0f * XM_PI / 180.0f; + +BOOL LoadMeshVertex( const CHAR* pszMeshFileName, UINT& nVertexCnt, ST_GRS_VERTEX*& ppVertex, UINT*& ppIndices ); +LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); + +int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ) +{ + int iWidth = 1280; + int iHeight = 800; + HWND hWnd = nullptr; + MSG msg = {}; + + const UINT nFrameBackBufCount = 3u; + UINT nFrameIndex = 0; + DXGI_FORMAT emRenderTargetFormat = DXGI_FORMAT_R8G8B8A8_UNORM; + DXGI_FORMAT emDepthStencilFormat = DXGI_FORMAT_D32_FLOAT; + const float faClearColor[] = { 0.17647f, 0.549f, 0.941176f, 1.0f }; + + UINT nRTVDescriptorSize = 0U; + UINT nCBVSRVDescriptorSize = 0; + UINT nSamplerDescriptorSize = 0; + + D3D12_VIEWPORT stViewPort = { 0.0f, 0.0f, static_cast( iWidth ), static_cast( iHeight ), D3D12_MIN_DEPTH, D3D12_MAX_DEPTH }; + D3D12_RECT stScissorRect = { 0, 0, static_cast( iWidth ), static_cast( iHeight ) }; + + D3D_FEATURE_LEVEL emFeatureLevel = D3D_FEATURE_LEVEL_12_1; + + ComPtr pIDXGIFactory6; + ComPtr pID3D12Device4; + + ComPtr pIMainCMDQueue; + ComPtr pIMainCMDAlloc; + ComPtr pIMainCMDList; + + ComPtr pIFence; + UINT64 n64FenceValue = 0ui64; + HANDLE hEventFence = nullptr; + + ComPtr pISwapChain3; + ComPtr pIRTVHeap; + ComPtr pIARenderTargets[nFrameBackBufCount]; + ComPtr pIDSVHeap; + ComPtr pIDepthStencilBuffer; + + const UINT nConstBufferCount = 4; // 本示例中需要4个Const Buffer + + ComPtr pIRootSignature; + ComPtr pIPSOModel; + + ComPtr pICBVSRVHeap; + + UINT nIndexCnt = 0; + ComPtr pIVB; + ComPtr pIIB; + + D3D12_VERTEX_BUFFER_VIEW stVBV = {}; + D3D12_INDEX_BUFFER_VIEW stIBV = {}; + + ComPtr pICBMVP; + ST_GRS_CB_MVP* pstCBMVP = nullptr; + ComPtr pICBCameraPos; + ST_CB_CAMERA* pstCBCameraPos = nullptr; + ComPtr pICBLights; + ST_CB_LIGHTS* pstCBLights = nullptr; + ComPtr pICBPBRMaterial; + ST_CB_PBR_MATERIAL* pstCBPBRMaterial = nullptr; + + D3D12_HEAP_PROPERTIES stDefaultHeapProps = {}; + stDefaultHeapProps.Type = D3D12_HEAP_TYPE_DEFAULT; + stDefaultHeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + stDefaultHeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + stDefaultHeapProps.CreationNodeMask = 0; + stDefaultHeapProps.VisibleNodeMask = 0; + + D3D12_HEAP_PROPERTIES stUploadHeapProps = {}; + stUploadHeapProps.Type = D3D12_HEAP_TYPE_UPLOAD; + stUploadHeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + stUploadHeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + stUploadHeapProps.CreationNodeMask = 0; + stUploadHeapProps.VisibleNodeMask = 0; + + D3D12_RESOURCE_DESC stBufferResSesc = {}; + stBufferResSesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + stBufferResSesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + stBufferResSesc.Flags = D3D12_RESOURCE_FLAG_NONE; + stBufferResSesc.Format = DXGI_FORMAT_UNKNOWN; + stBufferResSesc.Width = 0; + stBufferResSesc.Height = 1; + stBufferResSesc.DepthOrArraySize = 1; + stBufferResSesc.MipLevels = 1; + stBufferResSesc.SampleDesc.Count = 1; + stBufferResSesc.SampleDesc.Quality = 0; + + D3D12_RESOURCE_BARRIER stResStateTransBarrier = {}; + stResStateTransBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + stResStateTransBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + stResStateTransBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + + USES_CONVERSION; + try + { + ::CoInitialize( nullptr ); //for WIC & COM + + // 0、得到当前的工作目录,方便我们使用相对路径来访问各种资源文件 + { + if ( 0 == ::GetModuleFileName( nullptr, g_pszAppPath, MAX_PATH ) ) + { + GRS_THROW_IF_FAILED( HRESULT_FROM_WIN32( GetLastError() ) ); + } + + WCHAR* lastSlash = _tcsrchr( g_pszAppPath, _T( '\\' ) ); + if ( lastSlash ) + {//删除Exe文件名 + *( lastSlash ) = _T( '\0' ); + } + + lastSlash = _tcsrchr( g_pszAppPath, _T( '\\' ) ); + if ( lastSlash ) + {//删除x64路径 + *( lastSlash ) = _T( '\0' ); + } + + lastSlash = _tcsrchr( g_pszAppPath, _T( '\\' ) ); + if ( lastSlash ) + {//删除Debug 或 Release路径 + *( lastSlash + 1 ) = _T( '\0' ); + } + } + + // 1、创建窗口 + { + WNDCLASSEX wcex = {}; + wcex.cbSize = sizeof( WNDCLASSEX ); + wcex.style = CS_GLOBALCLASS; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hCursor = LoadCursor( nullptr, IDC_ARROW ); + wcex.hbrBackground = (HBRUSH) GetStockObject( NULL_BRUSH ); //防止无聊的背景重绘 + wcex.lpszClassName = GRS_WND_CLASS; + RegisterClassEx( &wcex ); + + DWORD dwWndStyle = WS_OVERLAPPED | WS_SYSMENU; + RECT rtWnd = { 0, 0, iWidth, iHeight }; + AdjustWindowRect( &rtWnd, dwWndStyle, FALSE ); + + // 计算窗口居中的屏幕坐标 + INT posX = ( GetSystemMetrics( SM_CXSCREEN ) - rtWnd.right - rtWnd.left ) / 2; + INT posY = ( GetSystemMetrics( SM_CYSCREEN ) - rtWnd.bottom - rtWnd.top ) / 2; + + hWnd = CreateWindowW( GRS_WND_CLASS + , GRS_WND_TITLE + , dwWndStyle + , posX + , posY + , rtWnd.right - rtWnd.left + , rtWnd.bottom - rtWnd.top + , nullptr + , nullptr + , hInstance + , nullptr ); + + if ( !hWnd ) + { + GRS_THROW_IF_FAILED( HRESULT_FROM_WIN32( GetLastError() ) ); + } + } + + // 2、创建DXGI Factory对象 + { + UINT nDXGIFactoryFlags = 0U; + +#if defined(_DEBUG) + // 打开显示子系统的调试支持 + ComPtr debugController; + if ( SUCCEEDED( D3D12GetDebugInterface( IID_PPV_ARGS( &debugController ) ) ) ) + { + debugController->EnableDebugLayer(); + // 打开附加的调试支持 + nDXGIFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG; + } +#endif + ComPtr pIDXGIFactory5; + GRS_THROW_IF_FAILED( CreateDXGIFactory2( nDXGIFactoryFlags, IID_PPV_ARGS( &pIDXGIFactory5 ) ) ); + GRS_SET_DXGI_DEBUGNAME_COMPTR( pIDXGIFactory5 ); + + //获取IDXGIFactory6接口 + GRS_THROW_IF_FAILED( pIDXGIFactory5.As( &pIDXGIFactory6 ) ); + GRS_SET_DXGI_DEBUGNAME_COMPTR( pIDXGIFactory6 ); + } + + // 3、枚举适配器创建设备 + { // 直接枚举最高性能的显卡来运行示例 + ComPtr pIAdapter1; + GRS_THROW_IF_FAILED( pIDXGIFactory6->EnumAdapterByGpuPreference( 0, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IID_PPV_ARGS( &pIAdapter1 ) ) ); + GRS_SET_DXGI_DEBUGNAME_COMPTR( pIAdapter1 ); + + // 创建D3D12.1的设备 + GRS_THROW_IF_FAILED( D3D12CreateDevice( pIAdapter1.Get(), emFeatureLevel, IID_PPV_ARGS( &pID3D12Device4 ) ) ); + GRS_SET_D3D12_DEBUGNAME_COMPTR( pID3D12Device4 ); + + DXGI_ADAPTER_DESC1 stAdapterDesc = {}; + TCHAR pszWndTitle[MAX_PATH] = {}; + GRS_THROW_IF_FAILED( pIAdapter1->GetDesc1( &stAdapterDesc ) ); + ::GetWindowText( hWnd, pszWndTitle, MAX_PATH ); + StringCchPrintf( pszWndTitle, MAX_PATH, _T( "%s (GPU[0]:%s)" ), pszWndTitle, stAdapterDesc.Description ); + ::SetWindowText( hWnd, pszWndTitle ); + + // 得到每个描述符元素的大小 + nRTVDescriptorSize = pID3D12Device4->GetDescriptorHandleIncrementSize( D3D12_DESCRIPTOR_HEAP_TYPE_RTV ); + nSamplerDescriptorSize = pID3D12Device4->GetDescriptorHandleIncrementSize( D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER ); + nCBVSRVDescriptorSize = pID3D12Device4->GetDescriptorHandleIncrementSize( D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ); + } + + // 4、创建命令队列&命令列表 + { + D3D12_COMMAND_QUEUE_DESC stQueueDesc = {}; + stQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + GRS_THROW_IF_FAILED( pID3D12Device4->CreateCommandQueue( &stQueueDesc, IID_PPV_ARGS( &pIMainCMDQueue ) ) ); + GRS_SET_D3D12_DEBUGNAME_COMPTR( pIMainCMDQueue ); + + GRS_THROW_IF_FAILED( pID3D12Device4->CreateCommandAllocator( D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS( &pIMainCMDAlloc ) ) ); + GRS_SET_D3D12_DEBUGNAME_COMPTR( pIMainCMDAlloc ); + + // 创建图形命令列表 + GRS_THROW_IF_FAILED( pID3D12Device4->CreateCommandList( + 0, D3D12_COMMAND_LIST_TYPE_DIRECT, pIMainCMDAlloc.Get(), nullptr, IID_PPV_ARGS( &pIMainCMDList ) ) ); + GRS_SET_D3D12_DEBUGNAME_COMPTR( pIMainCMDList ); + } + + // 5、创建交换链、深度缓冲、描述符堆、描述符 + { + DXGI_SWAP_CHAIN_DESC1 stSwapChainDesc = {}; + stSwapChainDesc.BufferCount = nFrameBackBufCount; + stSwapChainDesc.Width = 0;//iWidth; + stSwapChainDesc.Height = 0;// iHeight; + stSwapChainDesc.Format = emRenderTargetFormat; + stSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + stSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + stSwapChainDesc.SampleDesc.Count = 1; + stSwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + stSwapChainDesc.Scaling = DXGI_SCALING_NONE; + + // 交换链需要命令队列,Present命令要执行 + ComPtr pISwapChain1; + GRS_THROW_IF_FAILED( pIDXGIFactory6->CreateSwapChainForHwnd( + pIMainCMDQueue.Get(), hWnd, &stSwapChainDesc, nullptr, nullptr, &pISwapChain1 ) ); + + GRS_SET_DXGI_DEBUGNAME_COMPTR( pISwapChain1 ); + + GRS_THROW_IF_FAILED( pISwapChain1.As( &pISwapChain3 ) ); + + GRS_SET_DXGI_DEBUGNAME_COMPTR( pISwapChain3 ); + + //得到当前后缓冲区的序号,也就是下一个将要呈送显示的缓冲区的序号 + //注意此处使用了高版本的SwapChain接口的函数 + nFrameIndex = pISwapChain3->GetCurrentBackBufferIndex(); + + //创建RTV(渲染目标视图)描述符堆(这里堆的含义应当理解为数组或者固定大小元素的固定大小显存池) + { + D3D12_DESCRIPTOR_HEAP_DESC stRTVHeapDesc = {}; + stRTVHeapDesc.NumDescriptors = nFrameBackBufCount; + stRTVHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + stRTVHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + + GRS_THROW_IF_FAILED( pID3D12Device4->CreateDescriptorHeap( &stRTVHeapDesc, IID_PPV_ARGS( &pIRTVHeap ) ) ); + GRS_SET_D3D12_DEBUGNAME_COMPTR( pIRTVHeap ); + } + + //创建RTV的描述符 + { + D3D12_CPU_DESCRIPTOR_HANDLE stRTVHandle + = pIRTVHeap->GetCPUDescriptorHandleForHeapStart(); + for ( UINT i = 0; i < nFrameBackBufCount; i++ ) + { + GRS_THROW_IF_FAILED( pISwapChain3->GetBuffer( i, IID_PPV_ARGS( &pIARenderTargets[i] ) ) ); + GRS_SET_D3D12_DEBUGNAME_INDEXED_COMPTR( pIARenderTargets, i ); + pID3D12Device4->CreateRenderTargetView( pIARenderTargets[i].Get(), nullptr, stRTVHandle ); + stRTVHandle.ptr += nRTVDescriptorSize; + } + } + + // 关闭ALT+ENTER键切换全屏的功能,因为我们没有实现OnSize处理,所以先关闭 + // 注意将这个屏蔽Alt+Enter组合键的动作放到了这里,是因为直到这个时候DXGI Factory通过Create Swapchain动作才知道了HWND是哪个窗口 + // 因为组合键的处理在Windows中都是基于窗口过程的,没有窗口句柄就不知道是哪个窗口以及窗口过程,之前的屏蔽就没有意义了 + GRS_THROW_IF_FAILED( pIDXGIFactory6->MakeWindowAssociation( hWnd, DXGI_MWA_NO_ALT_ENTER ) ); + + + // 创建深度缓冲、深度缓冲描述符堆 + D3D12_DEPTH_STENCIL_VIEW_DESC stDepthStencilDesc = {}; + stDepthStencilDesc.Format = emDepthStencilFormat; + stDepthStencilDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + stDepthStencilDesc.Flags = D3D12_DSV_FLAG_NONE; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = emDepthStencilFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + D3D12_RESOURCE_DESC stDSTex2DDesc = {}; + stDSTex2DDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + stDSTex2DDesc.Alignment = 0; + stDSTex2DDesc.Width = iWidth; + stDSTex2DDesc.Height = iHeight; + stDSTex2DDesc.DepthOrArraySize = 1; + stDSTex2DDesc.MipLevels = 0; + stDSTex2DDesc.Format = emDepthStencilFormat; + stDSTex2DDesc.SampleDesc.Count = 1; + stDSTex2DDesc.SampleDesc.Quality = 0; + stDSTex2DDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + stDSTex2DDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + //使用隐式默认堆创建一个深度蜡板缓冲区, + //因为基本上深度缓冲区会一直被使用,重用的意义不大,所以直接使用隐式堆,图方便 + GRS_THROW_IF_FAILED( pID3D12Device4->CreateCommittedResource( + &stDefaultHeapProps + , D3D12_HEAP_FLAG_NONE + , &stDSTex2DDesc + , D3D12_RESOURCE_STATE_DEPTH_WRITE + , &depthOptimizedClearValue + , IID_PPV_ARGS( &pIDepthStencilBuffer ) + ) ); + + //============================================================================================== + D3D12_DESCRIPTOR_HEAP_DESC stDSVHeapDesc = {}; + stDSVHeapDesc.NumDescriptors = 1; + stDSVHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + stDSVHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + GRS_THROW_IF_FAILED( pID3D12Device4->CreateDescriptorHeap( &stDSVHeapDesc, IID_PPV_ARGS( &pIDSVHeap ) ) ); + + pID3D12Device4->CreateDepthStencilView( pIDepthStencilBuffer.Get(), &stDepthStencilDesc, pIDSVHeap->GetCPUDescriptorHandleForHeapStart() ); + } + + // 6、创建围栏 + if ( TRUE ) + { + GRS_THROW_IF_FAILED( pID3D12Device4->CreateFence( 0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS( &pIFence ) ) ); + GRS_SET_D3D12_DEBUGNAME_COMPTR( pIFence ); + + n64FenceValue = 1; + + // 创建一个Event同步对象,用于等待围栏事件通知 + hEventFence = CreateEvent( nullptr, FALSE, FALSE, nullptr ); + if ( hEventFence == nullptr ) + { + GRS_THROW_IF_FAILED( HRESULT_FROM_WIN32( GetLastError() ) ); + } + } + + // 7、编译Shader创建渲染管线状态对象 + { + // 先创建根签名 + D3D12_FEATURE_DATA_ROOT_SIGNATURE stFeatureData = {}; + // 检测是否支持V1.1版本的根签名 + stFeatureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1; + if ( FAILED( pID3D12Device4->CheckFeatureSupport( D3D12_FEATURE_ROOT_SIGNATURE, &stFeatureData, sizeof( stFeatureData ) ) ) ) + {// 1.0版 直接丢异常退出了 + GRS_THROW_IF_FAILED( E_NOTIMPL ); + } + + D3D12_DESCRIPTOR_RANGE1 stDSPRanges1[1] = {}; + stDSPRanges1[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; + stDSPRanges1[0].NumDescriptors = nConstBufferCount; + stDSPRanges1[0].BaseShaderRegister = 0; + stDSPRanges1[0].RegisterSpace = 0; + stDSPRanges1[0].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE; + stDSPRanges1[0].OffsetInDescriptorsFromTableStart = 0; + + D3D12_ROOT_PARAMETER1 stRootParameters1[1] = {}; + stRootParameters1[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + stRootParameters1[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + stRootParameters1[0].DescriptorTable.NumDescriptorRanges = 1; + stRootParameters1[0].DescriptorTable.pDescriptorRanges = &stDSPRanges1[0]; + + D3D12_VERSIONED_ROOT_SIGNATURE_DESC stRootSignatureDesc = {}; + stRootSignatureDesc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1; + stRootSignatureDesc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; + stRootSignatureDesc.Desc_1_1.NumParameters = _countof( stRootParameters1 ); + stRootSignatureDesc.Desc_1_1.pParameters = stRootParameters1; + stRootSignatureDesc.Desc_1_1.NumStaticSamplers = 0; + stRootSignatureDesc.Desc_1_1.pStaticSamplers = nullptr; + + ComPtr pISignatureBlob; + ComPtr pIErrorBlob; + + HRESULT _hr = D3D12SerializeVersionedRootSignature( &stRootSignatureDesc, &pISignatureBlob, &pIErrorBlob ); + + if ( FAILED( _hr ) ) + { + ATLTRACE( "Create Root Signature Error:%s\n", (CHAR*) ( pIErrorBlob ? pIErrorBlob->GetBufferPointer() : "未知错误" ) ); + AtlThrow( _hr ); + } + + GRS_THROW_IF_FAILED( pID3D12Device4->CreateRootSignature( 0, pISignatureBlob->GetBufferPointer() + , pISignatureBlob->GetBufferSize(), IID_PPV_ARGS( &pIRootSignature ) ) ); + GRS_SET_D3D12_DEBUGNAME_COMPTR( pIRootSignature ); + + // 接着以函数方式编译Shader + UINT compileFlags = 0; +#if defined(_DEBUG) + // Enable better shader debugging with the graphics debugging tools. + compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + //编译为行矩阵形式 + compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR; + + TCHAR pszShaderFileName[MAX_PATH] = {}; + ComPtr pIVSModel; + ComPtr pIPSModel; + pIErrorBlob.Reset(); + StringCchPrintf( pszShaderFileName, MAX_PATH, _T( "%s18-PBR-Base-Point-Lights\\Shader\\VS.hlsl" ), g_pszAppPath ); + HRESULT hr = D3DCompileFromFile( pszShaderFileName, nullptr, nullptr, "VSMain", "vs_5_1", compileFlags, 0, &pIVSModel, &pIErrorBlob ); + + if ( FAILED( hr ) ) + { + ATLTRACE( "编译 Vertex Shader:\"%s\" 发生错误:%s\n" + , T2A( pszShaderFileName ) + , pIErrorBlob ? pIErrorBlob->GetBufferPointer() : "无法读取文件!" ); + GRS_THROW_IF_FAILED( hr ); + } + pIErrorBlob.Reset(); + StringCchPrintf( pszShaderFileName, MAX_PATH, _T( "%s18-PBR-Base-Point-Lights\\Shader\\PS_PBR_Base_Point_Lights.hlsl" ), g_pszAppPath ); + hr = D3DCompileFromFile( pszShaderFileName, nullptr, nullptr, "PSMain", "ps_5_1", compileFlags, 0, &pIPSModel, &pIErrorBlob ); + if ( FAILED( hr ) ) + { + ATLTRACE( "编译 Pixel Shader:\"%s\" 发生错误:%s\n" + , T2A( pszShaderFileName ) + , pIErrorBlob ? pIErrorBlob->GetBufferPointer() : "无法读取文件!" ); + GRS_THROW_IF_FAILED( hr ); + } + + D3D12_INPUT_ELEMENT_DESC stIALayoutSphere[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + + // 创建 graphics pipeline state object (PSO)对象 + D3D12_GRAPHICS_PIPELINE_STATE_DESC stPSODesc = {}; + stPSODesc.InputLayout = { stIALayoutSphere, _countof( stIALayoutSphere ) }; + + stPSODesc.pRootSignature = pIRootSignature.Get(); + stPSODesc.VS.pShaderBytecode = pIVSModel->GetBufferPointer(); + stPSODesc.VS.BytecodeLength = pIVSModel->GetBufferSize(); + stPSODesc.PS.pShaderBytecode = pIPSModel->GetBufferPointer(); + stPSODesc.PS.BytecodeLength = pIPSModel->GetBufferSize(); + + stPSODesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; + stPSODesc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK; + + stPSODesc.BlendState.AlphaToCoverageEnable = FALSE; + stPSODesc.BlendState.IndependentBlendEnable = FALSE; + stPSODesc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + + stPSODesc.DSVFormat = emDepthStencilFormat; + stPSODesc.DepthStencilState.DepthEnable = TRUE; + stPSODesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;//启用深度缓存写入功能 + stPSODesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS; //深度测试函数(该值为普通的深度测试) + stPSODesc.DepthStencilState.StencilEnable = FALSE; + + stPSODesc.SampleMask = UINT_MAX; + stPSODesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + stPSODesc.NumRenderTargets = 1; + stPSODesc.RTVFormats[0] = emRenderTargetFormat; + stPSODesc.SampleDesc.Count = 1; + + GRS_THROW_IF_FAILED( pID3D12Device4->CreateGraphicsPipelineState( &stPSODesc, IID_PPV_ARGS( &pIPSOModel ) ) ); + GRS_SET_D3D12_DEBUGNAME_COMPTR( pIPSOModel ); + } + + // 8、创建 SRV CBV Sample堆 + if ( TRUE ) + { + //将纹理视图描述符和CBV描述符放在一个描述符堆上 + D3D12_DESCRIPTOR_HEAP_DESC stSRVHeapDesc = {}; + + stSRVHeapDesc.NumDescriptors = nConstBufferCount; // nConstBufferCount * CBV + nTextureCount * SRV + stSRVHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + stSRVHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + + GRS_THROW_IF_FAILED( pID3D12Device4->CreateDescriptorHeap( &stSRVHeapDesc, IID_PPV_ARGS( &pICBVSRVHeap ) ) ); + + GRS_SET_D3D12_DEBUGNAME_COMPTR( pICBVSRVHeap ); + } + + // 9、创建常量缓冲和对应描述符 + { + // MVP Const Buffer + stBufferResSesc.Width = GRS_UPPER( sizeof( ST_GRS_CB_MVP ), D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT ); + GRS_THROW_IF_FAILED( pID3D12Device4->CreateCommittedResource( + &stUploadHeapProps + , D3D12_HEAP_FLAG_NONE + , &stBufferResSesc //注意缓冲尺寸设置为256边界对齐大小 + , D3D12_RESOURCE_STATE_GENERIC_READ + , nullptr + , IID_PPV_ARGS( &pICBMVP ) ) ); + GRS_SET_D3D12_DEBUGNAME_COMPTR( pICBMVP ); + + // Map 之后就不再Unmap了 直接复制数据进去 这样每帧都不用map-copy-unmap浪费时间了 + GRS_THROW_IF_FAILED( pICBMVP->Map( 0, nullptr, reinterpret_cast( &pstCBMVP ) ) ); + + stBufferResSesc.Width = GRS_UPPER( sizeof( ST_CB_CAMERA ), D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT ); + GRS_THROW_IF_FAILED( pID3D12Device4->CreateCommittedResource( + &stUploadHeapProps + , D3D12_HEAP_FLAG_NONE + , &stBufferResSesc //注意缓冲尺寸设置为256边界对齐大小 + , D3D12_RESOURCE_STATE_GENERIC_READ + , nullptr + , IID_PPV_ARGS( &pICBCameraPos ) ) ); + GRS_SET_D3D12_DEBUGNAME_COMPTR( pICBCameraPos ); + + // Map 之后就不再Unmap了 直接复制数据进去 这样每帧都不用map-copy-unmap浪费时间了 + GRS_THROW_IF_FAILED( pICBCameraPos->Map( 0, nullptr, reinterpret_cast( &pstCBCameraPos ) ) ); + + stBufferResSesc.Width = GRS_UPPER( sizeof( ST_CB_LIGHTS ), D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT ); + GRS_THROW_IF_FAILED( pID3D12Device4->CreateCommittedResource( + &stUploadHeapProps + , D3D12_HEAP_FLAG_NONE + , &stBufferResSesc //注意缓冲尺寸设置为256边界对齐大小 + , D3D12_RESOURCE_STATE_GENERIC_READ + , nullptr + , IID_PPV_ARGS( &pICBLights ) ) ); + GRS_SET_D3D12_DEBUGNAME_COMPTR( pICBLights ); + + // Map 之后就不再Unmap了 直接复制数据进去 这样每帧都不用map-copy-unmap浪费时间了 + GRS_THROW_IF_FAILED( pICBLights->Map( 0, nullptr, reinterpret_cast( &pstCBLights ) ) ); + + stBufferResSesc.Width = GRS_UPPER( sizeof( ST_CB_PBR_MATERIAL ), D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT ); + GRS_THROW_IF_FAILED( pID3D12Device4->CreateCommittedResource( + &stUploadHeapProps + , D3D12_HEAP_FLAG_NONE + , &stBufferResSesc //注意缓冲尺寸设置为256边界对齐大小 + , D3D12_RESOURCE_STATE_GENERIC_READ + , nullptr + , IID_PPV_ARGS( &pICBPBRMaterial ) ) ); + GRS_SET_D3D12_DEBUGNAME_COMPTR( pICBPBRMaterial ); + + // Map 之后就不再Unmap了 直接复制数据进去 这样每帧都不用map-copy-unmap浪费时间了 + GRS_THROW_IF_FAILED( pICBPBRMaterial->Map( 0, nullptr, reinterpret_cast( &pstCBPBRMaterial ) ) ); + + // Create Const Buffer View + D3D12_CPU_DESCRIPTOR_HANDLE stCBVHandle = pICBVSRVHeap->GetCPUDescriptorHandleForHeapStart(); + + // 创建第一个CBV 世界矩阵 视矩阵 透视矩阵 + D3D12_CONSTANT_BUFFER_VIEW_DESC stCBVDesc = {}; + stCBVDesc.BufferLocation = pICBMVP->GetGPUVirtualAddress(); + stCBVDesc.SizeInBytes = (UINT) GRS_UPPER( sizeof( ST_GRS_CB_MVP ), D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT ); + pID3D12Device4->CreateConstantBufferView( &stCBVDesc, stCBVHandle ); + + stCBVHandle.ptr += nCBVSRVDescriptorSize; + stCBVDesc.BufferLocation = pICBCameraPos->GetGPUVirtualAddress(); + stCBVDesc.SizeInBytes = (UINT) GRS_UPPER( sizeof( ST_CB_CAMERA ), D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT ); + pID3D12Device4->CreateConstantBufferView( &stCBVDesc, stCBVHandle ); + + stCBVHandle.ptr += nCBVSRVDescriptorSize; + stCBVDesc.BufferLocation = pICBLights->GetGPUVirtualAddress(); + stCBVDesc.SizeInBytes = (UINT) GRS_UPPER( sizeof( ST_CB_LIGHTS ), D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT ); + pID3D12Device4->CreateConstantBufferView( &stCBVDesc, stCBVHandle ); + + stCBVHandle.ptr += nCBVSRVDescriptorSize; + stCBVDesc.BufferLocation = pICBPBRMaterial->GetGPUVirtualAddress(); + stCBVDesc.SizeInBytes = (UINT) GRS_UPPER( sizeof( ST_CB_PBR_MATERIAL ), D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT ); + pID3D12Device4->CreateConstantBufferView( &stCBVDesc, stCBVHandle ); + } + + // 10、创建D3D12的模型资源,并复制数据 + { + CHAR pszMeshFile[MAX_PATH] = {}; + StringCchPrintfA( pszMeshFile, MAX_PATH, "%sAssets\\sphere.txt", T2A( g_pszAppPath ) ); + + ST_GRS_VERTEX* pstVertices = nullptr; + UINT* pnIndices = nullptr; + UINT nVertexCnt = 0; + LoadMeshVertex( pszMeshFile, nVertexCnt, pstVertices, pnIndices ); + nIndexCnt = nVertexCnt; + + stBufferResSesc.Width = nVertexCnt * sizeof( ST_GRS_VERTEX ); + //创建 Vertex Buffer 仅使用Upload隐式堆 + GRS_THROW_IF_FAILED( pID3D12Device4->CreateCommittedResource( + &stUploadHeapProps + , D3D12_HEAP_FLAG_NONE + , &stBufferResSesc + , D3D12_RESOURCE_STATE_GENERIC_READ + , nullptr + , IID_PPV_ARGS( &pIVB ) ) ); + GRS_SET_D3D12_DEBUGNAME_COMPTR( pIVB ); + + //使用map-memcpy-unmap大法将数据传至顶点缓冲对象 + UINT8* pVertexDataBegin = nullptr; + D3D12_RANGE stReadRange = { 0, 0 }; // We do not intend to read from this resource on the CPU. + + GRS_THROW_IF_FAILED( pIVB->Map( 0, &stReadRange, reinterpret_cast( &pVertexDataBegin ) ) ); + memcpy( pVertexDataBegin, pstVertices, nVertexCnt * sizeof( ST_GRS_VERTEX ) ); + pIVB->Unmap( 0, nullptr ); + + //创建 Index Buffer 仅使用Upload隐式堆 + stBufferResSesc.Width = nIndexCnt * sizeof( UINT ); + GRS_THROW_IF_FAILED( pID3D12Device4->CreateCommittedResource( + &stUploadHeapProps + , D3D12_HEAP_FLAG_NONE + , &stBufferResSesc + , D3D12_RESOURCE_STATE_GENERIC_READ + , nullptr + , IID_PPV_ARGS( &pIIB ) ) ); + GRS_SET_D3D12_DEBUGNAME_COMPTR( pIIB ); + + UINT8* pIndexDataBegin = nullptr; + GRS_THROW_IF_FAILED( pIIB->Map( 0, &stReadRange, reinterpret_cast( &pIndexDataBegin ) ) ); + memcpy( pIndexDataBegin, pnIndices, nIndexCnt * sizeof( UINT ) ); + pIIB->Unmap( 0, nullptr ); + + //创建Vertex Buffer View + stVBV.BufferLocation = pIVB->GetGPUVirtualAddress(); + stVBV.StrideInBytes = sizeof( ST_GRS_VERTEX ); + stVBV.SizeInBytes = nVertexCnt * sizeof( ST_GRS_VERTEX ); + + //创建Index Buffer View + stIBV.BufferLocation = pIIB->GetGPUVirtualAddress(); + stIBV.Format = DXGI_FORMAT_R32_UINT; + stIBV.SizeInBytes = nIndexCnt * sizeof( UINT ); + + GRS_SAFE_FREE( pstVertices ); + GRS_SAFE_FREE( pnIndices ); + } + + DWORD dwRet = 0; + BOOL bExit = FALSE; + D3D12_CPU_DESCRIPTOR_HANDLE stRTVHandle = pIRTVHeap->GetCPUDescriptorHandleForHeapStart(); + D3D12_CPU_DESCRIPTOR_HANDLE stDSVHandle = pIDSVHeap->GetCPUDescriptorHandleForHeapStart(); + + GRS_THROW_IF_FAILED( pIMainCMDList->Close() ); + ::SetEvent( hEventFence ); + + FLOAT fStartTime = ( FLOAT )::GetTickCount64(); + FLOAT fCurrentTime = fStartTime; + //计算旋转角度需要的变量 + double dModelRotationYAngle = 0.0f; + + ShowWindow( hWnd, nCmdShow ); + UpdateWindow( hWnd ); + + // 16、消息循环 + while ( !bExit ) + { + dwRet = ::MsgWaitForMultipleObjects( 1, &hEventFence, FALSE, INFINITE, QS_ALLINPUT ); + switch ( dwRet - WAIT_OBJECT_0 ) + { + case 0: + { + //----------------------------------------------------------------------------------------------------- + // OnUpdate() + // Model Matrix + // ----- + // 缩放 + XMMATRIX mxModel = XMMatrixScaling( g_fScaling, g_fScaling, g_fScaling ); + // ----- + // 旋转 + fCurrentTime = ( float )::GetTickCount64(); + //计算旋转的角度:旋转角度(弧度) = 时间(秒) * 角速度(弧度/秒) + //下面这句代码相当于经典游戏消息循环中的OnUpdate函数中需要做的事情 + dModelRotationYAngle += ( ( fCurrentTime - fStartTime ) / 1000.0f ) * g_fPalstance; + fStartTime = fCurrentTime; + //旋转角度是2PI周期的倍数,去掉周期数,只留下相对0弧度开始的小于2PI的弧度即可 + if ( dModelRotationYAngle > XM_2PI ) + { + dModelRotationYAngle = fmod( dModelRotationYAngle, XM_2PI ); + } + //计算 World 矩阵 这里是个旋转矩阵 + mxModel = XMMatrixMultiply( mxModel, XMMatrixRotationY( static_cast( dModelRotationYAngle ) ) ); + + // ----- + // 位移 + mxModel = XMMatrixMultiply( mxModel, XMMatrixTranslation( 0.0f, 0.0f, 0.0f ) ); + + // World Matrix + XMMATRIX mxWorld = XMMatrixIdentity(); + mxWorld = XMMatrixMultiply( mxModel, mxWorld ); + XMStoreFloat4x4( &pstCBMVP->mxWorld, mxWorld ); + + // View Matrix + XMMATRIX mxView = XMMatrixLookAtLH( g_v4EyePos, g_v4LookAt, g_v4UpDir ); + XMStoreFloat4x4( &pstCBMVP->mxView, mxView ); + + // Projection Matrix + XMMATRIX mxProjection = XMMatrixPerspectiveFovLH( XM_PIDIV4, (FLOAT) iWidth / (FLOAT) iHeight, 0.1f, 10000.0f ); + XMStoreFloat4x4( &pstCBMVP->mxProjection, mxProjection ); + + // View Matrix * Projection Matrix + XMMATRIX mxViewProj = XMMatrixMultiply( mxView, mxProjection ); + XMStoreFloat4x4( &pstCBMVP->mxViewProj, mxViewProj ); + + // World Matrix * View Matrix * Projection Matrix + XMMATRIX mxMVP = XMMatrixMultiply( mxWorld, mxViewProj ); + XMStoreFloat4x4( &pstCBMVP->mxMVP, mxMVP ); + + // Camera Position + XMStoreFloat4( &pstCBCameraPos->m_v4CameraPos, g_v4EyePos ); + + // Lights + { + float fZ = -3.0f; + // 4个前置灯 + pstCBLights->m_v4LightPos[0] = { 0.0f,0.0f,fZ,1.0f }; + pstCBLights->m_v4LightClr[0] = { 23.47f,21.31f,20.79f, 1.0f }; + + pstCBLights->m_v4LightPos[1] = { 0.0f,3.0f,fZ,1.0f }; + pstCBLights->m_v4LightClr[1] = { 53.47f,41.31f,40.79f, 1.0f }; + + pstCBLights->m_v4LightPos[2] = { 3.0f,-3.0f,fZ,1.0f }; + pstCBLights->m_v4LightClr[2] = { 23.47f,21.31f,20.79f, 1.0f }; + + pstCBLights->m_v4LightPos[3] = { -3.0f,-3.0f,fZ,1.0f }; + pstCBLights->m_v4LightClr[3] = { 23.47f,21.31f,20.79f, 1.0f }; + + // 其它方位灯 + fZ = 0.0f; + float fY = 5.0f; + pstCBLights->m_v4LightPos[4] = { 0.0f,0.0f,fZ,1.0f }; + pstCBLights->m_v4LightClr[4] = { 23.47f,21.31f,20.79f, 1.0f }; + + pstCBLights->m_v4LightPos[5] = { 0.0f,-fY,fZ,1.0f }; + pstCBLights->m_v4LightClr[5] = { 53.47f,41.31f,40.79f, 1.0f }; + + pstCBLights->m_v4LightPos[6] = { fY,fY,fZ,1.0f }; + pstCBLights->m_v4LightClr[6] = { 23.47f,21.31f,20.79f, 1.0f }; + + pstCBLights->m_v4LightPos[7] = { -fY,fY,fZ,1.0f }; + pstCBLights->m_v4LightClr[7] = { 23.47f,21.31f,20.79f, 1.0f }; + } + + // PBR Material + pstCBPBRMaterial->m_v3Albedo = g_pv3Albedo[g_nCurAlbedo]; + pstCBPBRMaterial->m_fMetallic = g_fMetallic; // 0.04 - 1.0 之间 + pstCBPBRMaterial->m_fRoughness = g_fRoughness; + pstCBPBRMaterial->m_fAO = g_fAO; + //----------------------------------------------------------------------------------------------------- + + //----------------------------------------------------------------------------------------------------- + // OnRender() + //----------------------------------------------------------------------------------------------------- + //命令分配器先Reset一下 + GRS_THROW_IF_FAILED( pIMainCMDAlloc->Reset() ); + //Reset命令列表,并重新指定命令分配器和PSO对象 + GRS_THROW_IF_FAILED( pIMainCMDList->Reset( pIMainCMDAlloc.Get(), pIPSOModel.Get() ) ); + + nFrameIndex = pISwapChain3->GetCurrentBackBufferIndex(); + + pIMainCMDList->RSSetViewports( 1, &stViewPort ); + pIMainCMDList->RSSetScissorRects( 1, &stScissorRect ); + + // 通过资源屏障判定后缓冲已经切换完毕可以开始渲染了 + stResStateTransBarrier.Transition.pResource = pIARenderTargets[nFrameIndex].Get(); + stResStateTransBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; + stResStateTransBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; + pIMainCMDList->ResourceBarrier( 1, &stResStateTransBarrier ); + + //开始记录命令 + stRTVHandle = pIRTVHeap->GetCPUDescriptorHandleForHeapStart(); + stRTVHandle.ptr += (size_t) nFrameIndex * nRTVDescriptorSize; + + //设置渲染目标 + pIMainCMDList->OMSetRenderTargets( 1, &stRTVHandle, FALSE, &stDSVHandle ); + + // 继续记录命令,并真正开始新一帧的渲染 + pIMainCMDList->ClearRenderTargetView( stRTVHandle, faClearColor, 0, nullptr ); + pIMainCMDList->ClearDepthStencilView( pIDSVHeap->GetCPUDescriptorHandleForHeapStart() + , D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr ); + + // 渲染物体 + pIMainCMDList->SetGraphicsRootSignature( pIRootSignature.Get() ); + + // 注意我们使用的渲染手法是三角形列表,也就是通常的Mesh网格 + pIMainCMDList->IASetPrimitiveTopology( D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); + + pIMainCMDList->IASetVertexBuffers( 0, 1, &stVBV ); + pIMainCMDList->IASetIndexBuffer( &stIBV ); + + ID3D12DescriptorHeap* ppHeaps[] = { pICBVSRVHeap.Get() }; + pIMainCMDList->SetDescriptorHeaps( _countof( ppHeaps ), ppHeaps ); + + D3D12_GPU_DESCRIPTOR_HANDLE stGPUSRVHandle = { pICBVSRVHeap->GetGPUDescriptorHandleForHeapStart() }; + // 设置CBV + pIMainCMDList->SetGraphicsRootDescriptorTable( 0, stGPUSRVHandle ); + + // Draw Call + pIMainCMDList->DrawIndexedInstanced( nIndexCnt, 1, 0, 0, 0 ); + + //又一个资源屏障,用于确定渲染已经结束可以提交画面去显示了 + stResStateTransBarrier.Transition.pResource = pIARenderTargets[nFrameIndex].Get(); + stResStateTransBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + stResStateTransBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; + pIMainCMDList->ResourceBarrier( 1, &stResStateTransBarrier ); + + //关闭命令列表,可以去执行了 + GRS_THROW_IF_FAILED( pIMainCMDList->Close() ); + + //执行命令列表 + ID3D12CommandList* ppCommandLists[] = { pIMainCMDList.Get() }; + pIMainCMDQueue->ExecuteCommandLists( _countof( ppCommandLists ), ppCommandLists ); + + //提交画面 + GRS_THROW_IF_FAILED( pISwapChain3->Present( 1, 0 ) ); + + //开始同步GPU与CPU的执行,先记录围栏标记值 + const UINT64 n64CurrentFenceValue = n64FenceValue; + GRS_THROW_IF_FAILED( pIMainCMDQueue->Signal( pIFence.Get(), n64CurrentFenceValue ) ); + n64FenceValue++; + GRS_THROW_IF_FAILED( pIFence->SetEventOnCompletion( n64CurrentFenceValue, hEventFence ) ); + //----------------------------------------------------------------------------------------------------- + } + break; + case 1: + { + while ( ::PeekMessage( &msg, nullptr, 0, 0, PM_REMOVE ) ) + { + if ( WM_QUIT != msg.message ) + { + ::TranslateMessage( &msg ); + ::DispatchMessage( &msg ); + } + else + { + bExit = TRUE; + } + } + } + default: + break; + } + } + } + catch ( CAtlException& e ) + {//发生了COM异常 + e; + } + catch ( ... ) + { + + } + return 0; +} + +BOOL LoadMeshVertex( const CHAR* pszMeshFileName, UINT& nVertexCnt, ST_GRS_VERTEX*& ppVertex, UINT*& ppIndices ) +{ + ifstream fin; + char input; + BOOL bRet = TRUE; + try + { + fin.open( pszMeshFileName ); + if ( fin.fail() ) + { + AtlThrow( E_FAIL ); + } + fin.get( input ); + while ( input != ':' ) + { + fin.get( input ); + } + fin >> nVertexCnt; + + fin.get( input ); + while ( input != ':' ) + { + fin.get( input ); + } + fin.get( input ); + fin.get( input ); + + ppVertex = (ST_GRS_VERTEX*) GRS_CALLOC( nVertexCnt * sizeof( ST_GRS_VERTEX ) ); + ppIndices = (UINT*) GRS_CALLOC( nVertexCnt * sizeof( UINT ) ); + + for ( UINT i = 0; i < nVertexCnt; i++ ) + { + fin >> ppVertex[i].m_v4Position.x >> ppVertex[i].m_v4Position.y >> ppVertex[i].m_v4Position.z; + ppVertex[i].m_v4Position.w = 1.0f; //点的第4维坐标设为1 + fin >> ppVertex[i].m_v2UV.x >> ppVertex[i].m_v2UV.y; + fin >> ppVertex[i].m_v4Normal.x >> ppVertex[i].m_v4Normal.y >> ppVertex[i].m_v4Normal.z; + ppVertex[i].m_v4Normal.w = 0.0f; //纯向量的第4维坐标设为0 + ppIndices[i] = i; + } + } + catch ( CAtlException& e ) + { + e; + bRet = FALSE; + } + return bRet; +} + +LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) +{ + switch ( message ) + { + case WM_DESTROY: + { + PostQuitMessage( 0 ); + } + break; + case WM_KEYDOWN: + { + USHORT n16KeyCode = ( wParam & 0xFF ); + + if ( VK_TAB == n16KeyCode ) + {// 按Tab键 + g_nCurAlbedo += 1; + if ( g_nCurAlbedo >= g_nAlbedoCount ) + { + g_nCurAlbedo = 0; + } + } + + float fDelta = 0.2f; + XMVECTOR vDelta = { 0.0f,0.0f,fDelta,0.0f }; + // Z-轴 + if ( VK_UP == n16KeyCode ) + { + g_v4EyePos = XMVectorAdd( g_v4EyePos, vDelta ); + g_v4LookAt = XMVectorAdd( g_v4LookAt, vDelta ); + } + + if ( VK_DOWN == n16KeyCode ) + { + g_v4EyePos = XMVectorSubtract( g_v4EyePos, vDelta ); + g_v4LookAt = XMVectorSubtract( g_v4LookAt, vDelta ); + } + // X-轴 + vDelta = { fDelta,0.0f,0.0f,0.0f }; + if ( VK_LEFT == n16KeyCode ) + { + g_v4EyePos = XMVectorAdd( g_v4EyePos, vDelta ); + g_v4LookAt = XMVectorAdd( g_v4LookAt, vDelta ); + } + + if ( VK_RIGHT == n16KeyCode ) + { + g_v4EyePos = XMVectorSubtract( g_v4EyePos, vDelta ); + g_v4LookAt = XMVectorSubtract( g_v4LookAt, vDelta ); + } + + // Y-轴 + vDelta = { 0.0f,fDelta,0.0f,0.0f }; + if ( VK_PRIOR == n16KeyCode ) + { + g_v4EyePos = XMVectorAdd( g_v4EyePos, vDelta ); + g_v4LookAt = XMVectorAdd( g_v4LookAt, vDelta ); + } + + if ( VK_NEXT == n16KeyCode ) + { + g_v4EyePos = XMVectorSubtract( g_v4EyePos, vDelta ); + g_v4LookAt = XMVectorSubtract( g_v4LookAt, vDelta ); + } + + // 缩放 + fDelta = 0.2f; + if ( VK_ADD == n16KeyCode || VK_OEM_PLUS == n16KeyCode ) + { + g_fScaling += fDelta; + } + + if ( VK_SUBTRACT == n16KeyCode || VK_OEM_MINUS == n16KeyCode ) + { + g_fScaling -= fDelta; + if ( g_fScaling <= fDelta ) + { + g_fScaling = fDelta; + } + } + + // 金属度 + fDelta = 0.04f; + if ( 'q' == n16KeyCode || 'Q' == n16KeyCode ) + { + g_fMetallic += fDelta; + if ( g_fMetallic > 1.0f ) + { + g_fMetallic = 1.0f; + } + ATLTRACE( L"Metallic = %11.6f\n", g_fMetallic ); + } + + if ( 'a' == n16KeyCode || 'A' == n16KeyCode ) + { + g_fMetallic -= fDelta; + if ( g_fMetallic < fDelta ) + { + g_fMetallic = fDelta; + } + ATLTRACE( L"Metallic = %11.6f\n", g_fMetallic ); + } + + // 粗糙度 + fDelta = 0.05f; + if ( 'w' == n16KeyCode || 'W' == n16KeyCode ) + { + g_fRoughness += fDelta; + if ( g_fRoughness > 1.0f ) + { + g_fRoughness = 1.0f; + } + ATLTRACE( L"Roughness = %11.6f\n", g_fRoughness ); + } + + if ( 's' == n16KeyCode || 'S' == n16KeyCode ) + { + g_fRoughness -= fDelta; + if ( g_fRoughness < 0.0f ) + { + g_fRoughness = 0.0f; + } + ATLTRACE( L"Roughness = %11.6f\n", g_fRoughness ); + } + + // 环境遮挡 + fDelta = 0.1f; + if ( 'e' == n16KeyCode || 'E' == n16KeyCode ) + { + g_fAO += fDelta; + if ( g_fAO > 1.0f ) + { + g_fAO = 1.0f; + } + ATLTRACE( L"Ambient Occlusion = %11.6f\n", g_fAO ); + } + + if ( 'd' == n16KeyCode || 'D' == n16KeyCode ) + { + g_fAO -= fDelta; + if ( g_fAO < 0.0f ) + { + g_fAO = 0.0f; + } + ATLTRACE( L"Ambient Occlusion = %11.6f\n", g_fAO ); + } + + } + break; + + default: + return DefWindowProc( hWnd, message, wParam, lParam ); + } + + return DefWindowProc( hWnd, message, wParam, lParam ); +} diff --git a/18-PBR-Base-Point-Lights/18-PBR-Base-Point-Lights.vcxproj b/18-PBR-Base-Point-Lights/18-PBR-Base-Point-Lights.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..6b324bf5e87f2b6632b6faf46aab0f671f79237f --- /dev/null +++ b/18-PBR-Base-Point-Lights/18-PBR-Base-Point-Lights.vcxproj @@ -0,0 +1,157 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {c537ac94-2f18-4ab5-84ef-16b584566923} + My18PBRBasePointLights + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + true + true + + + true + true + + + + + + \ No newline at end of file diff --git a/18-PBR-Base-Point-Lights/18-PBR-Base-Point-Lights.vcxproj.filters b/18-PBR-Base-Point-Lights/18-PBR-Base-Point-Lights.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..6bb23dffbd99a36fa149bfd27061530a9fb969eb --- /dev/null +++ b/18-PBR-Base-Point-Lights/18-PBR-Base-Point-Lights.vcxproj.filters @@ -0,0 +1,33 @@ +锘 + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {d8d991aa-df75-4486-94c8-387fb1221b64} + + + + + 婧愭枃浠 + + + + + Shader + + + Shader + + + \ No newline at end of file diff --git a/18-PBR-Base-Point-Lights/18-PBR-Base-Point-Lights.vcxproj.user b/18-PBR-Base-Point-Lights/18-PBR-Base-Point-Lights.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..88a550947edbc3c5003a41726f0749201fdb6822 --- /dev/null +++ b/18-PBR-Base-Point-Lights/18-PBR-Base-Point-Lights.vcxproj.user @@ -0,0 +1,4 @@ +锘 + + + \ No newline at end of file diff --git a/18-PBR-Base-Point-Lights/Shader/PS_PBR_Base_Point_Lights.hlsl b/18-PBR-Base-Point-Lights/Shader/PS_PBR_Base_Point_Lights.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..aeb16d503fce2c1c5484ea156c3f5ab48dffa606 --- /dev/null +++ b/18-PBR-Base-Point-Lights/Shader/PS_PBR_Base_Point_Lights.hlsl @@ -0,0 +1,146 @@ +// Simplified PBR HLSL + + + +static const float PI = 3.14159265359; + +cbuffer MVPBuffer : register( b0 ) +{ + float4x4 mxWorld; //世界矩阵,这里其实是Model->World的转换矩阵 + float4x4 mxView; //视矩阵 + float4x4 mxProjection; //投影矩阵 + float4x4 mxViewProj; //视矩阵*投影 + float4x4 mxMVP; //世界*视矩阵*投影 +}; + +// Camera +cbuffer ST_CB_CAMERA: register( b1 ) +{ + float4 g_v4CameraPos; +}; + +#define GRS_LIGHT_COUNT 8 +// lights +cbuffer ST_CB_LIGHTS : register( b2 ) +{ + float4 g_v4LightPos[GRS_LIGHT_COUNT]; + float4 g_v4LightClr[GRS_LIGHT_COUNT]; +}; + +// PBR material parameters +cbuffer ST_CB_PBR_MATERIAL : register( b3 ) +{ + float3 g_v3Albedo; // 反射率 + float g_fMetallic; // 金属度 + float g_fRoughness; // 粗糙度 + float g_fAO; // 环境光遮蔽 +}; + +struct PSInput +{ + float4 g_v4PosWVP : SV_POSITION; + float4 g_v4PosWorld : POSITION; + float4 g_v4Normal : NORMAL; + float2 g_v2UV : TEXCOORD; +}; + +float3 Fresnel_Schlick( float cosTheta, float3 F0 ) +{ + return F0 + ( 1.0 - F0 ) * pow( 1.0 - cosTheta, 5.0 ); +} + +float Distribution_GGX( float3 N, float3 H, float fRoughness ) +{ + float a = fRoughness * fRoughness; + float a2 = a * a; + float NdotH = max( dot( N, H ), 0.0 ); + float NdotH2 = NdotH * NdotH; + + float num = a2; + float denom = ( NdotH2 * ( a2 - 1.0 ) + 1.0 ); + denom = PI * denom * denom; + + return num / denom; +} + +float Geometry_Schlick_GGX( float NdotV, float fRoughness ) +{ + float r = ( fRoughness + 1.0 ); + float k = ( r * r ) / 8.0; + + float num = NdotV; + float denom = NdotV * ( 1.0 - k ) + k; + + return num / denom; +} + +float Geometry_Smith( float3 N, float3 V, float3 L, float fRoughness ) +{ + float NdotV = max( dot( N, V ), 0.0 ); + float NdotL = max( dot( N, L ), 0.0 ); + float ggx2 = Geometry_Schlick_GGX( NdotV, fRoughness ); + float ggx1 = Geometry_Schlick_GGX( NdotL, fRoughness ); + + return ggx1 * ggx2; +} + +float4 PSMain( PSInput stPSInput ) : SV_TARGET +{ + // 使用插值生成的光滑法线 + float3 N = normalize( stPSInput.g_v4Normal.xyz ); + // 视向量 + float3 V = normalize( g_v4CameraPos.xyz - stPSInput.g_v4PosWorld.xyz ); + + float3 F0 = float3( 0.04f, 0.04f, 0.04f ); + + // Gamma矫正颜色 + float3 v3Albedo = pow( g_v3Albedo, 2.2f ); + + F0 = lerp( F0, v3Albedo, g_fMetallic ); + + // 出射辐射度 + float3 Lo = float3( 0.0f, 0.0f, 0.0f ); + + // 粗糙度 + float fRoughness = g_fRoughness; + + for ( int i = 0; i < GRS_LIGHT_COUNT; ++i ) + {// 对每一个光源求解光照积分方程 + // 点光源的情况 + // 入射光向量 + float3 L = normalize( g_v4LightPos[i].xyz - stPSInput.g_v4PosWorld.xyz ); + // 中间向量(入射光与法线的角平分线) + float3 H = normalize( V + L ); + float distance = length( g_v4LightPos[i].xyz - stPSInput.g_v4PosWorld.xyz ); + float attenuation = 1.0 / ( distance * distance ); + float3 radiance = g_v4LightClr[i].xyz * attenuation; + + // Cook-Torrance光照模型 BRDF + float NDF = Distribution_GGX( N, H, fRoughness ); + float G = Geometry_Smith( N, V, L, fRoughness ); + float3 F = Fresnel_Schlick( max( dot( H, V ), 0.0 ), F0 ); + + float3 kS = F; + float3 kD = float3( 1.0f,1.0f,1.0f ) - kS; + kD *= 1.0 - g_fMetallic; + + float3 numerator = NDF * G * F; + float denominator = 4.0 * max( dot( N, V ), 0.0 ) * max( dot( N, L ), 0.0 ); + float3 specular = numerator / max( denominator, 0.001 ); + + // add to outgoing radiance Lo + float NdotL = max( dot( N, L ), 0.0 ); + Lo += ( kD * v3Albedo / PI + specular ) * radiance * NdotL; + } + + float fAO = g_fAO; + // 环境光项 + float3 ambient = float3( 0.03f, 0.03f, 0.03f ) * v3Albedo * fAO; + float3 color = ambient + Lo; + + color = color / ( color + float3( 1.0f,1.0f,1.0f ) ); + // Gamma 矫正 + color = pow( color, 1.0f / 2.2f ); + return float4( color, 1.0 ); +} + diff --git a/18-PBR-Base-Point-Lights/Shader/VS.hlsl b/18-PBR-Base-Point-Lights/Shader/VS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..7fca8ee36d5e113b6269c48ca64fef1168f55627 --- /dev/null +++ b/18-PBR-Base-Point-Lights/Shader/VS.hlsl @@ -0,0 +1,30 @@ +// Simplified PBR HLSL Vertex Shader + +cbuffer MVPBuffer : register( b0 ) +{ + float4x4 mxWorld; //世界矩阵,这里其实是Model->World的转换矩阵 + float4x4 mxView; //视矩阵 + float4x4 mxProjection; //投影矩阵 + float4x4 mxViewProj; //视矩阵*投影 + float4x4 mxMVP; //世界*视矩阵*投影 +}; + +struct PSInput +{ + float4 m_v4PosWVP : SV_POSITION; + float4 m_v4PosWorld : POSITION; + float4 m_v4Normal: NORMAL; + float2 m_v2UV: TEXCOORD; +}; + +PSInput VSMain( float4 v4LocalPos : POSITION, float4 v4LocalNormal:NORMAL, float2 v2UV : TEXCOORD ) +{ + PSInput stOutput; + + stOutput.m_v4PosWVP = mul( v4LocalPos, mxMVP ); + stOutput.m_v4PosWorld = mul( v4LocalPos, mxWorld); + v4LocalNormal.w = 0.0f; + stOutput.m_v4Normal = mul( v4LocalNormal, mxWorld); + stOutput.m_v2UV = v2UV; + return stOutput; +} \ No newline at end of file diff --git a/Commons/GRS_Assimp_Loader.h b/Commons/GRS_Assimp_Loader.h index a3a00c64053067512b74fbad57e9c5178bfc0edf..7ce11c4616f8546d1e2943f25b08dcf2ce48866e 100644 --- a/Commons/GRS_Assimp_Loader.h +++ b/Commons/GRS_Assimp_Loader.h @@ -95,26 +95,26 @@ typedef CAtlArray CGRSSubMesh; const UINT g_ncSlotCnt = 4; // 用4个插槽上传顶点数据 struct ST_GRS_MESH_DATA { - XMMATRIX m_mxModel; - CStringA m_strFileName; - const aiScene* m_paiModel; - - CGRSSubMesh m_arSubMeshInfo; - - CGRSARPositions m_arPositions; - CGRSARNormals m_arNormals; - CGRSARTexCoords m_arTexCoords; - CGRSARVertexBones m_arBoneIndices; - CGRSARIndices m_arIndices; - //CGRSARTTextureName m_arTextureName; + const aiScene* m_paiModel; + CStringA m_strFileName; + XMMATRIX m_mxModel; + + CGRSSubMesh m_arSubMeshInfo; + + CGRSARPositions m_arPositions; + CGRSARNormals m_arNormals; + CGRSARTexCoords m_arTexCoords; + CGRSARVertexBones m_arBoneIndices; + CGRSARIndices m_arIndices; + CGRSMapString2UINT m_mapTextrueName2Index; - CGRSMapUINT2UINT m_mapTextureIndex2HeapIndex; + CGRSMapUINT2UINT m_mapTextureIndex2HeapIndex; - CGRSARBoneDatas m_arBoneDatas; + CGRSARBoneDatas m_arBoneDatas; CGRSMapString2UINT m_mapName2Bone; //名称->骨骼的索引 CGRSMapString2UINT m_mapAnimName2Index; //名称->动画的索引 - UINT m_nCurrentAnimIndex; // 当前播放的动画序列索引 + UINT m_nCurrentAnimIndex; // 当前播放的动画序列索引(当前动作) }; __inline const XMMATRIX& MXEqual(XMMATRIX& mxDX, const aiMatrix4x4& mxAI) diff --git a/D3D12 Tutorials.sln b/D3D12 Tutorials.sln index aa0026396bc9d42923d0030b013e242a17afbc49..22de54691e4032b28481d1966b30cde73f3ee680 100644 --- a/D3D12 Tutorials.sln +++ b/D3D12 Tutorials.sln @@ -37,6 +37,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "16-Assimp_Data_Display", "1 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "17-D3D12_Assimp_Animation", "17-D3D12_Assimp_Animation\17-D3D12_Assimp_Animation.vcxproj", "{6BFFBD6C-B171-4C22-8878-4BCAFBE4CF0F}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "18-PBR-Base-Point-Lights", "18-PBR-Base-Point-Lights\18-PBR-Base-Point-Lights.vcxproj", "{C537AC94-2F18-4AB5-84EF-16B584566923}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -251,6 +253,18 @@ Global {6BFFBD6C-B171-4C22-8878-4BCAFBE4CF0F}.Release|x64.Build.0 = Release|x64 {6BFFBD6C-B171-4C22-8878-4BCAFBE4CF0F}.Release|x86.ActiveCfg = Release|Win32 {6BFFBD6C-B171-4C22-8878-4BCAFBE4CF0F}.Release|x86.Build.0 = Release|Win32 + {C537AC94-2F18-4AB5-84EF-16B584566923}.Debug|x64.ActiveCfg = Debug|x64 + {C537AC94-2F18-4AB5-84EF-16B584566923}.Debug|x64.Build.0 = Debug|x64 + {C537AC94-2F18-4AB5-84EF-16B584566923}.Debug|x86.ActiveCfg = Debug|Win32 + {C537AC94-2F18-4AB5-84EF-16B584566923}.Debug|x86.Build.0 = Debug|Win32 + {C537AC94-2F18-4AB5-84EF-16B584566923}.Profile|x64.ActiveCfg = Debug|x64 + {C537AC94-2F18-4AB5-84EF-16B584566923}.Profile|x64.Build.0 = Debug|x64 + {C537AC94-2F18-4AB5-84EF-16B584566923}.Profile|x86.ActiveCfg = Debug|Win32 + {C537AC94-2F18-4AB5-84EF-16B584566923}.Profile|x86.Build.0 = Debug|Win32 + {C537AC94-2F18-4AB5-84EF-16B584566923}.Release|x64.ActiveCfg = Release|x64 + {C537AC94-2F18-4AB5-84EF-16B584566923}.Release|x64.Build.0 = Release|x64 + {C537AC94-2F18-4AB5-84EF-16B584566923}.Release|x86.ActiveCfg = Release|Win32 + {C537AC94-2F18-4AB5-84EF-16B584566923}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Revision.md b/Revision.md index b7590b6adae1396baa48545672ad02e614c57964..fe31d9c8c95938994f724fed180b8bbadf965b37 100644 --- a/Revision.md +++ b/Revision.md @@ -82,3 +82,15 @@ D3D12 ERROR: ID3D12CommandQueue::Present: Resource state (0x800: D3D12_RESOURCE_ 2021-6-16 1銆佽皟鏁翠簡16鍙蜂緥瀛愪腑鐨勮緭鍑烘牸寮忥紝骞朵笖杩藉姞浜嗘樉绀簃etadata鐨勪唬鐮侊紱 + +2021-6-18 + +1銆佸幓闄17鍙风ず渚嬩腑鐨勫啑浣欎唬鐮侊紝淇浜嗛儴鍒嗘敞閲婏紱 + +2021-6-19 + +1銆佷慨姝17鍙风ず渚嬩腑锛岃绠楃紦鍐插ぇ灏忛敊璇殑BUG锛屼箣鍓嶇殑璁$畻鍦ㄩ《鐐规暟鎹皬鏃朵笉浼氭湁闂锛屽綋椤剁偣鏁版嵁杩囧ぇ鏃跺氨鎶ラ敊浜嗭紝鍘熷洜鏄瘡涓紦鍐查兘鎸夌収杈圭晫瀵归綈鍒嗛厤浜嗭紝浣嗘槸缂撳啿鏄暣浣撴寜杈圭晫瀵归綈澶у皬鍒嗛厤鐨勶紝鎵浠ュ湪鏌愪釜缂撳啿杈冨ぇ鏃跺氨浼氬嚭閿欎簡锛屽疄闄呭垎閰嶇殑缂撳啿澶у皬浼氬皬浜庨渶瑕佺殑缂撳啿澶у皬锛 + +2021-6-22 + +1銆佹坊鍔犵18涓ず渚嬶紝18-PBR-Base-Point-Lights锛屽紑鍚珮绾у厜鐓т箣鏃咃紝鐩存帴鐣ヨ繃鏃犺亰鐨勪紶缁熷厜鐓э紱