#include "pch.h" #include "QuadRenderer.h" using namespace DirectX; using namespace Microsoft::WRL; using namespace Windows::Foundation; using namespace Windows::UI::Core; QuadRenderer::QuadRenderer() : m_loadingComplete(false), m_indexCount(0) { } void QuadRenderer::CreateTextureFromByte(byte* buffer,int width,int height) { int pixelSize = 4; if (m_Texture.Get() == nullptr) { CD3D11_TEXTURE2D_DESC textureDesc( DXGI_FORMAT_B8G8R8A8_UNORM, // format static_cast(width), // width static_cast(height), // height 1, // arraySize 1, // mipLevels D3D11_BIND_SHADER_RESOURCE, // bindFlags D3D11_USAGE_DYNAMIC, // usage D3D11_CPU_ACCESS_WRITE, // cpuaccessFlags 1, // sampleCount 0, // sampleQuality 0 // miscFlags ); D3D11_SUBRESOURCE_DATA data; data.pSysMem = buffer; data.SysMemPitch = pixelSize*width; data.SysMemSlicePitch = pixelSize*width*height; DX::ThrowIfFailed( m_d3dDevice->CreateTexture2D( &textureDesc, &data, m_Texture.ReleaseAndGetAddressOf() ) ); m_d3dDevice->CreateShaderResourceView(m_Texture.Get(), NULL, m_SRV.ReleaseAndGetAddressOf()); D3D11_SAMPLER_DESC sampDesc; ZeroMemory(&sampDesc, sizeof(sampDesc)); sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampDesc.MinLOD = 0; sampDesc.MaxLOD = D3D11_FLOAT32_MAX; m_d3dDevice->CreateSamplerState(&sampDesc, m_QuadsTexSamplerState.ReleaseAndGetAddressOf()); } else { int nRowSpan = width * pixelSize; D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT hr = m_d3dContext->Map(m_Texture.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); BYTE* mappedData = static_cast(mappedResource.pData); for (int i = 0; i < height; ++i) { memcpy(mappedData + (i*mappedResource.RowPitch), buffer + (i*nRowSpan), nRowSpan); } m_d3dContext->Unmap(m_Texture.Get(), 0); } } void QuadRenderer::CreateDeviceResources() { Direct3DBase::CreateDeviceResources(); D3D11_BLEND_DESC blendDesc; ZeroMemory( &blendDesc, sizeof(blendDesc) ); D3D11_RENDER_TARGET_BLEND_DESC rtbd; ZeroMemory( &rtbd, sizeof(rtbd) ); rtbd.BlendEnable = TRUE; rtbd.SrcBlend = D3D11_BLEND_SRC_ALPHA; rtbd.DestBlend = D3D11_BLEND_INV_SRC_ALPHA; rtbd.BlendOp = D3D11_BLEND_OP_ADD; rtbd.SrcBlendAlpha = D3D11_BLEND_ONE; rtbd.DestBlendAlpha = D3D11_BLEND_ZERO; rtbd.BlendOpAlpha = D3D11_BLEND_OP_ADD; rtbd.RenderTargetWriteMask = 0x0f; blendDesc.AlphaToCoverageEnable = false; blendDesc.RenderTarget[0] = rtbd; m_d3dDevice->CreateBlendState(&blendDesc, &m_Transparency); D3D11_RASTERIZER_DESC cmdesc; ZeroMemory(&cmdesc, sizeof(D3D11_RASTERIZER_DESC)); cmdesc.FillMode = D3D11_FILL_SOLID; cmdesc.CullMode = D3D11_CULL_BACK; cmdesc.DepthClipEnable = TRUE; cmdesc.FrontCounterClockwise = true; m_d3dDevice->CreateRasterizerState(&cmdesc, &CCWcullMode); cmdesc.FrontCounterClockwise = false; m_d3dDevice->CreateRasterizerState(&cmdesc, &CWcullMode); auto loadVSTask = DX::ReadDataAsync("SimpleVertexShader.cso"); auto loadPSTask = DX::ReadDataAsync("SimplePixelShader.cso"); auto createVSTask = loadVSTask.then([this](Platform::Array^ fileData) { DX::ThrowIfFailed( m_d3dDevice->CreateVertexShader( fileData->Data, fileData->Length, nullptr, &m_vertexShader ) ); const D3D11_INPUT_ELEMENT_DESC vertexDesc[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; DX::ThrowIfFailed( m_d3dDevice->CreateInputLayout( vertexDesc, ARRAYSIZE(vertexDesc), fileData->Data, fileData->Length, &m_inputLayout ) ); }); auto createPSTask = loadPSTask.then([this](Platform::Array^ fileData) { DX::ThrowIfFailed( m_d3dDevice->CreatePixelShader( fileData->Data, fileData->Length, nullptr, &m_pixelShader ) ); CD3D11_BUFFER_DESC constantBufferDesc(sizeof(ModelViewProjectionConstantBuffer), D3D11_BIND_CONSTANT_BUFFER); DX::ThrowIfFailed( m_d3dDevice->CreateBuffer( &constantBufferDesc, nullptr, &m_constantBuffer ) ); }); auto createCubeTask = (createPSTask && createVSTask).then([this] () { Vertex v[] = { Vertex(-1.0f, -1.0f, 1.0f, 1.0f, 1.0f), Vertex(1.0f, -1.0f, 1.0f, 0.0f, 1.0f), Vertex(1.0f, 1.0f, 1.0f, 0.0f, 0.0f), Vertex(-1.0f, 1.0f, 1.0f, 1.0f, 0.0f) }; D3D11_SUBRESOURCE_DATA vertexBufferData = {0}; vertexBufferData.pSysMem = v; vertexBufferData.SysMemPitch = 0; vertexBufferData.SysMemSlicePitch = 0; CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(v), D3D11_BIND_VERTEX_BUFFER); DX::ThrowIfFailed( m_d3dDevice->CreateBuffer( &vertexBufferDesc, &vertexBufferData, &m_vertexBuffer ) ); DWORD indices[] = { // Front Face 0, 2, 1, 0, 3, 2, }; m_indexCount = ARRAYSIZE(indices); D3D11_SUBRESOURCE_DATA indexBufferData = {0}; indexBufferData.pSysMem = indices; indexBufferData.SysMemPitch = 0; indexBufferData.SysMemSlicePitch = 0; CD3D11_BUFFER_DESC indexBufferDesc(sizeof(indices), D3D11_BIND_INDEX_BUFFER); DX::ThrowIfFailed( m_d3dDevice->CreateBuffer( &indexBufferDesc, &indexBufferData, &m_indexBuffer ) ); }); createCubeTask.then([this] () { m_loadingComplete = true; }); } void QuadRenderer::CreateWindowSizeDependentResources() { Direct3DBase::CreateWindowSizeDependentResources(); float aspectRatio = m_windowBounds.Width / m_windowBounds.Height; float fovAngleY = 60.0f * (XM_PI / 180.0f); if (aspectRatio < 1.0f) { fovAngleY /= aspectRatio; } XMStoreFloat4x4( &m_constantBufferData.projection, XMMatrixTranspose( XMMatrixPerspectiveFovRH( fovAngleY, aspectRatio, 0.01f, 100.0f ) ) ); } void QuadRenderer::Update(float timeTotal, float timeDelta) { (void) timeDelta; // Unused parameter. XMVECTOR X = XMVectorSet(0.0f, 0.0f, .3f, 0.0f); XMVECTOR Y = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f); XMVECTOR Z = XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f); XMStoreFloat4x4(&m_constantBufferData.view, XMMatrixTranspose(XMMatrixLookAtLH(X, Y, Z))); XMStoreFloat4x4(&m_constantBufferData.model, XMMatrixTranspose(XMMatrixRotationY(timeTotal * XM_PIDIV4))); } void QuadRenderer::Render() { Render(m_renderTargetView, m_depthStencilView); } void QuadRenderer::Render(Microsoft::WRL::ComPtr renderTargetView, Microsoft::WRL::ComPtr depthStencilView) { const float black[] = {0, 0, 0, 1.0 }; m_d3dContext->ClearRenderTargetView( renderTargetView.Get(), black ); m_d3dContext->ClearDepthStencilView( depthStencilView.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0 ); if (m_SRV && m_loadingComplete) // Only draw the cube once it is loaded (loading is asynchronous). { m_d3dContext->OMSetRenderTargets( 1, renderTargetView.GetAddressOf(), depthStencilView.Get() ); m_d3dContext->UpdateSubresource( m_constantBuffer.Get(), 0, NULL, &m_constantBufferData, 0, 0 ); UINT stride = sizeof(Vertex); UINT offset = 0; m_d3dContext->IASetVertexBuffers( 0, 1, m_vertexBuffer.GetAddressOf(), &stride, &offset ); m_d3dContext->IASetIndexBuffer( m_indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0 ); m_d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); m_d3dContext->IASetInputLayout(m_inputLayout.Get()); m_d3dContext->VSSetShader( m_vertexShader.Get(), nullptr, 0 ); m_d3dContext->VSSetConstantBuffers( 0, 1, m_constantBuffer.GetAddressOf() ); m_d3dContext->PSSetShader( m_pixelShader.Get(), nullptr, 0 ); m_d3dContext->PSSetShaderResources(0, 1, m_SRV.GetAddressOf()); m_d3dContext->PSSetSamplers(0, 1, m_QuadsTexSamplerState.GetAddressOf()); m_d3dContext->OMSetBlendState(m_Transparency.Get(), nullptr, 0xffffffff); m_d3dContext->RSSetState(CCWcullMode.Get()); m_d3dContext->DrawIndexed( m_indexCount, 0, 0 ); } }