WPFとDirect3D11の連携 --- 三角形描画
下記記事にてWPFとDirect3D11を連携してサーフェスを表示しました。
WPFとDirect3D11の連携 --- 導入 - 何でもプログラミング
今回は単純な三角形を描画してWPFで表示してみたいと思います。
Shader作成(csoから)
csoデータが存在する場合は、下記関数のみで作成できます。
VertexShaderではInputLayoutも併せて作成しています。
#define AssertHR(expr) { HRESULT hr = expr; if (FAILED(hr)) throw gcnew ComponentModel::Win32Exception(hr, #expr); } std::tuple<CComPtr<ID3D11VertexShader>, CComPtr<ID3D11InputLayout>> CreateVertexShader( ID3D11Device* device, const std::vector<byte>& cso, const std::vector<D3D11_INPUT_ELEMENT_DESC>& inputDesc) { CComPtr<ID3D11VertexShader> shader; AssertHR(device->CreateVertexShader(cso.data(), cso.size(), NULL, &shader.p)); CComPtr<ID3D11InputLayout> inputLayout; AssertHR(device->CreateInputLayout(inputDesc.data(), inputDesc.size(), cso.data(), cso.size(), &inputLayout.p)); return { shader, inputLayout }; } CComPtr<ID3D11PixelShader> CreatePixelShader(ID3D11Device* device, const std::vector<byte>& cso) { CComPtr<ID3D11PixelShader> shader; AssertHR(device->CreatePixelShader(cso.data(), cso.size(), NULL, &shader.p)); return shader; }
Shader作成(コードから)
実行時にコンパイルする場合は、下記関数を利用します。
ターゲット(vs_4_0_level_9_1、ps_4_0_level_9_1)は適宜変更してください。
Compile関数は下記記事を参照してください。
WPFとDirect3D9Exの連携 --- 三角形描画 - 何でもプログラミング
std::tuple<CComPtr<ID3D11VertexShader>, CComPtr<ID3D11InputLayout>> CreateVertexShader( ID3D11Device* device, std::string code, const std::vector<D3D11_INPUT_ELEMENT_DESC>& inputDesc) { auto blob = Compile(code, "vs_4_0_level_9_1"); auto p = (byte*)blob->GetBufferPointer(); std::vector<byte> cso(p, p + blob->GetBufferSize()); return CreateVertexShader(device, cso, inputDesc); } CComPtr<ID3D11PixelShader> CreatePixelShader(ID3D11Device* device, std::string code) { auto blob = Compile(code, "ps_4_0_level_9_1"); auto p = (byte*)blob->GetBufferPointer(); std::vector<byte> cso(p, p + blob->GetBufferSize()); return CreatePixelShader(device, cso); }
VertexBuffer作成
template <class T> CComPtr<ID3D11Buffer> CreateVertexBuffer(ID3D11Device* device, const std::vector<T>& vertices) { D3D11_BUFFER_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Usage = D3D11_USAGE_DEFAULT; desc.ByteWidth = vertices.size() * sizeof(T); desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = 0; D3D11_SUBRESOURCE_DATA data; ZeroMemory(&data, sizeof(data)); data.pSysMem = vertices.data(); CComPtr<ID3D11Buffer> buffer; AssertHR(device->CreateBuffer(&desc, &data, &buffer)); return buffer; }
Renderer作成
CliComPtr、D3D9Ex::CreateDeviceは下記記事を参照してください。
WPFとDirect3D9Exの連携 --- 導入 - 何でもプログラミング
CreateSharedRenderTarget、CreateDevice、OpenRenderTarget、Tie2は下記記事を参照してください。
WPFとDirect3D11の連携 --- 導入 - 何でもプログラミング
struct Vertex { float X, Y, Z; }; public ref class Renderer { public: property IntPtr Surface { IntPtr get() { return IntPtr(_surface9); } } Renderer(int width, int height) { _device9 = D3D9Ex::CreateDevice(); HANDLE handle; Tie2(_surface9, handle, CreateSharedRenderTarget(_device9, width, height)); Tie2(_device, _context, CreateDevice()); _renderTarget = OpenRenderTarget(_device, handle); // Shader作成 std::string vertexCode = "float4 main(float4 position : POSITION) : SV_POSITION { \n" " return position; \n" "} \n"; std::vector<D3D11_INPUT_ELEMENT_DESC> inputDesc = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 } }; Tie2(_vertexShader, _inputLayout, CreateVertexShader(_device, vertexCode, inputDesc)); std::string pixelCode = "float4 main() : SV_TARGET { \n" " return float4(1.0f, 0.0f, 0.0f, 1.0f); \n" "} \n"; _pixelShader = CreatePixelShader(_device, pixelCode); // VertexBuffer作成 std::vector<Vertex> vertices = { { 0.0f, 1.0f, 0.5f }, { 1.0f, -1.0f, 0.5f }, { -1.0f, -1.0f, 0.5f }, }; _vertexBuffer = CreateVertexBuffer(_device, vertices); // 描画準備 ID3D11RenderTargetView* renderTargets[1] = { _renderTarget }; _context->OMSetRenderTargets(1, renderTargets, NULL); _context->VSSetShader(_vertexShader, NULL, 0); _context->PSSetShader(_pixelShader, NULL, 0); _context->IASetInputLayout(_inputLayout); UINT stride = sizeof(Vertex); UINT offset = 0; ID3D11Buffer* vertexBuffers[1] = { _vertexBuffer }; _context->IASetVertexBuffers(0, 1, vertexBuffers, &stride, &offset); D3D11_VIEWPORT viewport; viewport.Width = (float)width; viewport.Height = (float)height; viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; viewport.TopLeftX = 0.0f; viewport.TopLeftY = 0.0f; _context->RSSetViewports(1, &viewport); // 描画 float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; _context->ClearRenderTargetView(_renderTarget, clearColor); _context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); _context->Draw(3, 0); _context->Flush(); }; private: CliComPtr<IDirect3DDevice9Ex> _device9; CliComPtr<IDirect3DSurface9> _surface9; CliComPtr<ID3D11Device> _device; CliComPtr<ID3D11DeviceContext> _context; CliComPtr<ID3D11RenderTargetView> _renderTarget; CliComPtr<ID3D11VertexShader> _vertexShader; CliComPtr<ID3D11InputLayout> _inputLayout; CliComPtr<ID3D11PixelShader> _pixelShader; CliComPtr<ID3D11Buffer> _vertexBuffer; };