【DirectX12】2.示例三角形绘制
生活随笔
收集整理的這篇文章主要介紹了
【DirectX12】2.示例三角形绘制
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
示例三角形繪制
1.效果
下面只貼出關(guān)于dx的代碼,有時間再詳細說明。
2.標頭.h
#pragma once#include "pch.h" #include "LVEDebug.h" #include "LVESystem.h"#include <d3d12.h> #include "d3dx12.h" #include <dxgi1_6.h> #include <D3DCompiler.h> #include <DirectXMath.h> using namespace DirectX;typedef IDXGIFactory7 _IDXGIFactory; typedef IDXGIAdapter4 _IDXGIAdapter; typedef IDXGISwapChain4 _IDXGISwapChain; namespace LVE {void GetHardwareAdapter(_IDXGIFactory* pFactory, _IDXGIAdapter** ppAdapter);const int SWAP_CHAIN_BUFFER_COUNT = 2;//此值不能小于2class DirectX{public://pipelinecom_ptr<_IDXGIFactory> _factory;com_ptr<_IDXGIAdapter> _adapter;com_ptr<ID3D12Device> _device;com_ptr<ID3D12CommandQueue> _commandQueue;com_ptr<_IDXGISwapChain> _swapChain;com_ptr<ID3D12DescriptorHeap> _rtvHeap;UINT _rtvDescriptorSize;com_ptr<ID3D12Resource> _renderTargets[SWAP_CHAIN_BUFFER_COUNT];com_ptr<ID3D12CommandAllocator> _commandAllocator;//assetscom_ptr<ID3D12RootSignature> _rootSignature;com_ptr<ID3D12PipelineState> _pipelineState;com_ptr<ID3D12GraphicsCommandList> _commandList;com_ptr<ID3D12Resource> _vertexBuffer;D3D12_VERTEX_BUFFER_VIEW _vertexBufferView;//Synchronization objects.UINT _frameIndex;HANDLE _fenceEvent;com_ptr<ID3D12Fence> _fence;UINT64 _fenceValue;D3D12_VIEWPORT _viewport;D3D12_RECT _scissorRect;void Init();void Update();void Render();void Release();private:struct Vertex{XMFLOAT3 position;XMFLOAT4 color;};void _init_pre(){if (!XMVerifyCPUSupport()){g_debug.Line(L"DirectXMath does not support the current platform!");return;}}void _init_pipeline(){ #if defined(_DEBUG)_init_debug_layer(); #endif_init_dxgi();_init_device();_init_command_queue();_init_swap_chain();_init_descriptor_heap();_init_render_target_view();_init_command_allocator();}void _init_debug_layer();void _init_dxgi();void _init_device();void _init_command_queue();void _init_swap_chain();void _init_descriptor_heap();void _init_render_target_view();void _init_command_allocator();//void _init_assets(){_init_root_signature();_init_graphics_pipeline_state();_init_command_list();_init_vertex_buffer();_init_fence();}void _init_root_signature();void _init_graphics_pipeline_state();void _init_command_list();void _init_vertex_buffer();void _init_fence();void WaitForPreviousFrame();void PopulateCommandList();};extern DirectX g_dx; }3.源.cpp
#include "LVEDirectX.h"namespace LVE {DirectX g_dx;void DirectX::Init(){_init_pre();//load pipeline_init_pipeline();//load assets_init_assets();_viewport.Height = 600;_viewport.MaxDepth = 1.0f;_viewport.MinDepth = 0;_viewport.TopLeftX = 0;_viewport.TopLeftY = 0;_viewport.Width = 800;_scissorRect.bottom = 600;_scissorRect.left = 0;_scissorRect.right = 800;_scissorRect.top = 0;}void DirectX::Update(){}void DirectX::Render(){// Record all the commands we need to render the scene into the command list.PopulateCommandList();// Execute the command list.ID3D12CommandList* ppCommandLists[] = { _commandList.get() };_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);// Present the frame.HRESULT hr = _swapChain->Present(1, 0);if (FAILED(hr)){g_debug.Line(L"Failed to present frame!");return;}WaitForPreviousFrame();}void DirectX::Release(){// Wait for the GPU to be done with all resources.WaitForPreviousFrame();CloseHandle(_fenceEvent);}void DirectX::_init_debug_layer(){// Enable the D3D12 debug layer.com_ptr<ID3D12Debug> debugController;HRESULT hr = D3D12GetDebugInterface(IID_PPV_ARGS(&debugController));if (FAILED(hr)){g_debug.Line(L"Failed to create debug layer!");return;}debugController->EnableDebugLayer();}void DirectX::_init_dxgi(){HRESULT hr = CreateDXGIFactory1(__uuidof(_IDXGIFactory), (void**)(&_factory));if (FAILED(hr)){g_debug.Line(L"Failed to create DXGI factory!");return;}}void DirectX::_init_device(){_IDXGIAdapter* adapter;GetHardwareAdapter(_factory.get(), &adapter);if (adapter == nullptr){g_debug.Line(L"Failed to enumerate hardware adapter!");return;}_adapter.attach(adapter);HRESULT hr = D3D12CreateDevice(_adapter.get(),D3D_FEATURE_LEVEL_11_0,IID_PPV_ARGS(&_device));if (FAILED(hr)){g_debug.Line(L"Failed to create device!");return;}}void DirectX::_init_command_queue(){D3D12_COMMAND_QUEUE_DESC desc;desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;desc.NodeMask = 0;desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;HRESULT hr = _device->CreateCommandQueue(&desc, IID_PPV_ARGS(&_commandQueue));if (FAILED(hr)){g_debug.Line(L"Failed to create command queue!");return;}}void DirectX::_init_swap_chain(){com_ptr<IDXGISwapChain> swapChain;DXGI_SWAP_CHAIN_DESC desc;desc.BufferCount = SWAP_CHAIN_BUFFER_COUNT;desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;desc.BufferDesc.Height = 600;desc.BufferDesc.RefreshRate.Denominator = 0;desc.BufferDesc.RefreshRate.Numerator = 0;desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;desc.BufferDesc.Width = 800;desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;desc.Flags = 0;desc.OutputWindow = g_system.GetHwnd();desc.SampleDesc.Count = 1;desc.SampleDesc.Quality = 0;desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;desc.Windowed = TRUE;HRESULT hr = _factory->CreateSwapChain(_commandQueue.get(),&desc,swapChain.put());/*DXGI_SWAP_CHAIN_DESC1 desc;desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;desc.BufferCount = SWAP_CHAIN_BUFFER_COUNT;desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;desc.Flags = 0;desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.Height = 600;desc.SampleDesc.Count = 1;desc.SampleDesc.Quality = 0;desc.Scaling = DXGI_SCALING_NONE;desc.Stereo = FALSE;desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;desc.Width = 800;//DXGI_SWAP_CHAIN_FULLSCREEN_DESC desc_full;HRESULT hr = _factory->CreateSwapChainForHwnd(_commandQueue.get(),// For Direct3D 12, this is a pointer to a direct command queue, and not to the device.g_system.GetHwnd(),&desc,nullptr,nullptr,swapChain.put());*/if (FAILED(hr)){g_debug.Line(L"Failed to create swap chain!");return;}swapChain.as(_swapChain);}void DirectX::_init_descriptor_heap(){D3D12_DESCRIPTOR_HEAP_DESC desc;desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;desc.NodeMask = 0;desc.NumDescriptors = SWAP_CHAIN_BUFFER_COUNT;//desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;HRESULT hr = _device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&_rtvHeap));if (FAILED(hr)){g_debug.Line(L"Failed to create descriptor heap!");return;}_rtvDescriptorSize = _device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);}void DirectX::_init_render_target_view(){UINT m_rtvDescriptorSize = _device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);// Create frame resources.//D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = _rtvHeap->GetCPUDescriptorHandleForHeapStart();CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(_rtvHeap->GetCPUDescriptorHandleForHeapStart());// Create a RTV for each frame.for (UINT n = 0; n < SWAP_CHAIN_BUFFER_COUNT; n++){HRESULT hr = _swapChain->GetBuffer(n, IID_PPV_ARGS(&_renderTargets[n]));if (FAILED(hr)){g_debug.Line(L"Failed to get buffer from the swap chain!");continue;}_device->CreateRenderTargetView(_renderTargets[n].get(), nullptr, rtvHandle);rtvHandle.Offset(1, m_rtvDescriptorSize);}}void DirectX::_init_command_allocator(){HRESULT hr = _device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&_commandAllocator));if (FAILED(hr)){g_debug.Line(L"Failed to create command allocator!");return;}}void DirectX::_init_root_signature(){CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc;rootSignatureDesc.Init(0, nullptr, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);ID3DBlob* signature;ID3DBlob* error;HRESULT hr = D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error);if (FAILED(hr)){g_debug.Line(L"Failed to serialize root signature!");return;}hr = _device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&_rootSignature));if (FAILED(hr)){g_debug.Line(L"Failed to serialize root signature!");return;}}void DirectX::_init_graphics_pipeline_state(){com_ptr<ID3DBlob> vertexShader;com_ptr<ID3DBlob> pixelShader;#if defined(_DEBUG)// Enable better shader debugging with the graphics debugging tools.UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; #elseUINT compileFlags = 0; #endifHRESULT hr = D3DCompileFromFile(L"shaders.hlsl", nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, vertexShader.put(), nullptr);if (FAILED(hr)){g_debug.Line(L"Failed to compile vertex shader!");return;}hr = D3DCompileFromFile(L"shaders.hlsl", nullptr, nullptr, "PSMain", "ps_5_0", compileFlags, 0, pixelShader.put(), nullptr);if (FAILED(hr)){g_debug.Line(L"Failed to compile pixel shader!");return;}// Define the vertex input layout.D3D12_INPUT_ELEMENT_DESC inputElementDescs[] ={{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }};// Describe and create the graphics pipeline state object (PSO).D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) };psoDesc.pRootSignature = _rootSignature.get();psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()), vertexShader->GetBufferSize() };psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()), pixelShader->GetBufferSize() };psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);psoDesc.DepthStencilState.DepthEnable = FALSE;psoDesc.DepthStencilState.StencilEnable = FALSE;psoDesc.SampleMask = UINT_MAX;psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;psoDesc.NumRenderTargets = 1;psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;psoDesc.SampleDesc.Count = 1;hr = _device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&_pipelineState));if (FAILED(hr)){g_debug.Line(L"Failed to create graphics pipeline state!");return;}}void DirectX::_init_command_list(){HRESULT hr = _device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, _commandAllocator.get(), _pipelineState.get(), IID_PPV_ARGS(&_commandList));if (FAILED(hr)){g_debug.Line(L"Failed to create command list!");return;}_commandList->Close();}void DirectX::_init_vertex_buffer(){// Define the geometry for a triangle.Vertex triangleVertices[] ={{ { 0.0f, 0.25f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },{ { 0.25f, -0.25f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },{ { -0.25f, -0.25f, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }};const UINT vertexBufferSize = sizeof(triangleVertices);// Note: using upload heaps to transfer static data like vert buffers is not // recommended. Every time the GPU needs it, the upload heap will be marshalled // over. Please read up on Default Heap usage. An upload heap is used here for // code simplicity and because there are very few verts to actually transfer.CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_UPLOAD);auto desc = CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize);HRESULT hr = _device->CreateCommittedResource(&heapProps,D3D12_HEAP_FLAG_NONE,&desc,D3D12_RESOURCE_STATE_GENERIC_READ,nullptr,IID_PPV_ARGS(&_vertexBuffer));if (FAILED(hr)){g_debug.Line(L"Failed to create vertex buffer!");return;}// Copy the triangle data to the vertex buffer.UINT8* pVertexDataBegin;CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU.hr = _vertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin));memcpy(pVertexDataBegin, triangleVertices, sizeof(triangleVertices));_vertexBuffer->Unmap(0, nullptr);// Initialize the vertex buffer view._vertexBufferView.BufferLocation = _vertexBuffer->GetGPUVirtualAddress();_vertexBufferView.StrideInBytes = sizeof(Vertex);_vertexBufferView.SizeInBytes = vertexBufferSize;}void DirectX::_init_fence(){HRESULT hr = _device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&_fence));_fenceValue = 1;// Create an event handle to use for frame synchronization._fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);if (_fenceEvent == nullptr){hr = HRESULT_FROM_WIN32(GetLastError());if (FAILED(hr)){g_debug.Line(L"Failed to create fence!");return;}}// Wait for the command list to execute; we are reusing the same command // list in our main loop but for now, we just want to wait for setup to // complete before continuing.WaitForPreviousFrame();}void DirectX::WaitForPreviousFrame(){// WAITING FOR THE FRAME TO COMPLETE BEFORE CONTINUING IS NOT BEST PRACTICE.// This is code implemented as such for simplicity. More advanced samples // illustrate how to use fences for efficient resource usage.// Signal and increment the fence value.const UINT64 fence = _fenceValue;HRESULT hr = _commandQueue->Signal(_fence.get(), fence);if (FAILED(hr)){g_debug.Line(L"Failed to signal and increment fence!");return;}_fenceValue++;// Wait until the previous frame is finished.if (_fence->GetCompletedValue() < fence){hr = _fence->SetEventOnCompletion(fence, _fenceEvent);if (FAILED(hr)){g_debug.Line(L"Failed to set event on completion!");return;}WaitForSingleObject(_fenceEvent, INFINITE);}_frameIndex = _swapChain->GetCurrentBackBufferIndex();}void DirectX::PopulateCommandList(){// Command list allocators can only be reset when the associated // command lists have finished execution on the GPU; apps should use // fences to determine GPU execution progress.HRESULT hr = _commandAllocator->Reset();if (FAILED(hr)){g_debug.Line(L"Failed to reset command allocator!");return;}// However, when ExecuteCommandList() is called on a particular command // list, that command list can then be reset at any time and must be before // re-recording.hr = _commandList->Reset(_commandAllocator.get(), _pipelineState.get());if (FAILED(hr)){g_debug.Line(L"Failed to reset command list!");return;}// Set necessary state._commandList->SetGraphicsRootSignature(_rootSignature.get());_commandList->RSSetViewports(1, &_viewport);_commandList->RSSetScissorRects(1, &_scissorRect);// Indicate that the back buffer will be used as a render target.auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(_renderTargets[_frameIndex].get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);_commandList->ResourceBarrier(1, &barrier);CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(_rtvHeap->GetCPUDescriptorHandleForHeapStart(), _frameIndex, _rtvDescriptorSize);_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);// Record commands.const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);_commandList->IASetVertexBuffers(0, 1, &_vertexBufferView);_commandList->DrawInstanced(3, 1, 0, 0);// Indicate that the back buffer will now be used to present.barrier = CD3DX12_RESOURCE_BARRIER::Transition(_renderTargets[_frameIndex].get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);_commandList->ResourceBarrier(1, &barrier);hr = _commandList->Close();if (FAILED(hr)){g_debug.Line(L"Failed to close command list!");return;}}void GetHardwareAdapter(_IDXGIFactory* pFactory, _IDXGIAdapter** ppAdapter){*ppAdapter = nullptr;for (UINT adapterIndex = 0; ; ++adapterIndex){_IDXGIAdapter* pAdapter = nullptr;if (DXGI_ERROR_NOT_FOUND == pFactory->EnumAdapterByGpuPreference(adapterIndex,DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, _uuidof(_IDXGIAdapter), (void**)&pAdapter)){// No more adapters to enumerate.break;}// Check to see if the adapter supports Direct3D 12, but don't create the// actual device yet.if (SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))){*ppAdapter = pAdapter;return;}pAdapter->Release();}}}?
總結(jié)
以上是生活随笔為你收集整理的【DirectX12】2.示例三角形绘制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【XAuido2】播放wav和ogg格式
- 下一篇: 【DirectX12】3.配置FBX_S