WPFとDirect3D11の連携 --- テクスチャ貼り付け
下記記事にて三角形を描画するところまで記述しました。
WPFとDirect3D11の連携 --- 三角形描画 - 何でもプログラミング
今回はテクスチャを貼り付けて表示してみたいと思います。
Texture作成
Direct3D9側でD3DFMT_A8R8G8B8にてレンダリングターゲットを作成しているため、DXGI_FORMAT_B8G8R8A8_UNORMにて作成します。(反転しているのでややこしいです。)
TextureではなくResourceViewを返すよう実装してあります。
#define AssertHR(expr) { HRESULT hr = expr; if (FAILED(hr)) throw gcnew ComponentModel::Win32Exception(hr, #expr); } CComPtr<ID3D11ShaderResourceView> CreateTexture(ID3D11Device* device, int width, int height, const byte* pixels) { D3D11_TEXTURE2D_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Width = width; desc.Height = height; desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; desc.MipLevels = 1; desc.ArraySize = 1; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; D3D11_SUBRESOURCE_DATA data; ZeroMemory(&data, sizeof(data)); data.pSysMem = pixels; data.SysMemPitch = 4 * width; CComPtr<ID3D11Texture2D> texture; AssertHR(device->CreateTexture2D(&desc, &data, &texture.p)); CComPtr<ID3D11ShaderResourceView> resourceView; AssertHR(device->CreateShaderResourceView(texture, NULL, &resourceView.p)); return resourceView; }
Renderer作成
CliComPtr、D3D9Ex::CreateDeviceは下記記事を参照してください。
WPFとDirect3D9Exの連携 --- 導入 - 何でもプログラミング
CreateSharedRenderTarget、CreateDevice、OpenRenderTarget、Tie2は下記記事を参照してください。
WPFとDirect3D11の連携 --- 導入 - 何でもプログラミング
CreateVertexShader、CreatePixelShader、CreateVertexBufferは下記記事を参照してください。
WPFとDirect3D11の連携 --- 三角形描画 - 何でもプログラミング
struct Vertex { float X, Y, Z; float U, V; }; public ref class Renderer { public: property IntPtr Surface { IntPtr get() { return IntPtr(_surface9); } } Renderer(int width, int height, array<byte>^ pixels) { _device9 = D3D9Ex::CreateDevice(); HANDLE handle; Tie2(_surface9, handle, CreateSharedRenderTarget(_device9, width, height)); Tie2(_device, _context, CreateDevice()); _renderTarget = OpenRenderTarget(_device, handle); // Shader作成 std::string vertexCode = "struct VS_OUTPUT { \n" " float4 Position : SV_POSITION; \n" " float2 Texcoord : TEXCOORD0; \n" "}; \n" "VS_OUTPUT main( \n" " float4 position : POSITION, \n" " float2 texcoord : TEXCOORD0) { \n" " VS_OUTPUT output = (VS_OUTPUT)0; \n" " output.Position = position; \n" " output.Texcoord = texcoord; \n" " return output; \n" "} \n"; std::vector<D3D11_INPUT_ELEMENT_DESC> inputDesc = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 } }; Tie2(_vertexShader, _inputLayout, CreateVertexShader(_device, vertexCode, inputDesc)); std::string pixelCode = "Texture2D texture0 : register(t0); \n" "SamplerState texture0Sampler { \n" " Filter = MIN_MAG_MIP_POINT; \n" " AddressU = Clamp; \n" " AddressV = Clamp; \n" "}; \n" "float4 main( \n" " float4 position : SV_POSITION, \n" " float2 texcoord : TEXCOORD0) : SV_TARGET { \n" " return texture0.Sample(texture0Sampler, texcoord); \n" "} \n"; _pixelShader = CreatePixelShader(_device, pixelCode); // VertexBuffer作成 std::vector<Vertex3> vertices = { { -1.0f, 1.0f, 0.5f, 0.0f, 0.0f }, { 1.0f, 1.0f, 0.5f, 1.0f, 0.0f }, { -1.0f, -1.0f, 0.5f, 0.0f, 1.0f }, { 1.0f, -1.0f, 0.5f, 1.0f, 1.0f }, }; _vertexBuffer = CreateVertexBuffer(_device, vertices); // テクスチャ作成 pin_ptr<byte> pixelsPtr = &pixels[0]; _texture = CreateTexture(_device, width, height, pixelsPtr); // 描画準備 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(Vertex3); UINT offset = 0; ID3D11Buffer* vertexBuffers[1] = { _vertexBuffer }; _context->IASetVertexBuffers(0, 1, vertexBuffers, &stride, &offset); ID3D11ShaderResourceView* resourceViews[1] = { _texture }; _context->PSSetShaderResources(0, 1, resourceViews); 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); // 描画 _context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); _context->Draw(4, 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; CliComPtr<ID3D11ShaderResourceView> _texture; };