1 #include "pch.h"
2 #include "QuadRenderer.h"
3 
4 using namespace DirectX;
5 using namespace Microsoft::WRL;
6 using namespace Windows::Foundation;
7 using namespace Windows::UI::Core;
8 
QuadRenderer()9 QuadRenderer::QuadRenderer() :
10     m_loadingComplete(false),
11     m_indexCount(0)
12 {
13 }
14 
CreateTextureFromByte(byte * buffer,int width,int height)15 void QuadRenderer::CreateTextureFromByte(byte* buffer,int width,int height)
16 {
17     int pixelSize = 4;
18 
19     if (m_Texture.Get() == nullptr)
20     {
21         CD3D11_TEXTURE2D_DESC textureDesc(
22             DXGI_FORMAT_B8G8R8A8_UNORM,		// format
23             static_cast<UINT>(width),		// width
24             static_cast<UINT>(height),		// height
25             1,								// arraySize
26             1,								// mipLevels
27             D3D11_BIND_SHADER_RESOURCE,		// bindFlags
28             D3D11_USAGE_DYNAMIC,			// usage
29             D3D11_CPU_ACCESS_WRITE,			// cpuaccessFlags
30             1,								// sampleCount
31             0,								// sampleQuality
32             0								// miscFlags
33             );
34 
35         D3D11_SUBRESOURCE_DATA data;
36         data.pSysMem = buffer;
37         data.SysMemPitch = pixelSize*width;
38         data.SysMemSlicePitch = pixelSize*width*height;
39 
40         DX::ThrowIfFailed(
41             m_d3dDevice->CreateTexture2D(
42             &textureDesc,
43             &data,
44             m_Texture.ReleaseAndGetAddressOf()
45             )
46             );
47 
48         m_d3dDevice->CreateShaderResourceView(m_Texture.Get(), NULL, m_SRV.ReleaseAndGetAddressOf());
49         D3D11_SAMPLER_DESC sampDesc;
50         ZeroMemory(&sampDesc, sizeof(sampDesc));
51         sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
52         sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
53         sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
54         sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
55         sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
56         sampDesc.MinLOD = 0;
57         sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
58         m_d3dDevice->CreateSamplerState(&sampDesc, m_QuadsTexSamplerState.ReleaseAndGetAddressOf());
59     }
60     else
61     {
62         int nRowSpan = width * pixelSize;
63         D3D11_MAPPED_SUBRESOURCE mappedResource;
64         HRESULT hr = m_d3dContext->Map(m_Texture.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
65         BYTE* mappedData = static_cast<BYTE*>(mappedResource.pData);
66 
67         for (int i = 0; i < height; ++i)
68         {
69             memcpy(mappedData + (i*mappedResource.RowPitch), buffer + (i*nRowSpan), nRowSpan);
70         }
71 
72         m_d3dContext->Unmap(m_Texture.Get(), 0);
73     }
74 }
75 
CreateDeviceResources()76 void QuadRenderer::CreateDeviceResources()
77 {
78     Direct3DBase::CreateDeviceResources();
79     D3D11_BLEND_DESC blendDesc;
80     ZeroMemory( &blendDesc, sizeof(blendDesc) );
81 
82     D3D11_RENDER_TARGET_BLEND_DESC rtbd;
83     ZeroMemory( &rtbd, sizeof(rtbd) );
84 
85     rtbd.BlendEnable = TRUE;
86     rtbd.SrcBlend = D3D11_BLEND_SRC_ALPHA;
87     rtbd.DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
88     rtbd.BlendOp = D3D11_BLEND_OP_ADD;
89     rtbd.SrcBlendAlpha = D3D11_BLEND_ONE;
90     rtbd.DestBlendAlpha = D3D11_BLEND_ZERO;
91     rtbd.BlendOpAlpha = D3D11_BLEND_OP_ADD;
92     rtbd.RenderTargetWriteMask = 0x0f;
93 
94     blendDesc.AlphaToCoverageEnable = false;
95     blendDesc.RenderTarget[0] = rtbd;
96 
97     m_d3dDevice->CreateBlendState(&blendDesc, &m_Transparency);
98 
99     D3D11_RASTERIZER_DESC cmdesc;
100     ZeroMemory(&cmdesc, sizeof(D3D11_RASTERIZER_DESC));
101 
102     cmdesc.FillMode = D3D11_FILL_SOLID;
103     cmdesc.CullMode = D3D11_CULL_BACK;
104     cmdesc.DepthClipEnable = TRUE;
105 
106     cmdesc.FrontCounterClockwise = true;
107     m_d3dDevice->CreateRasterizerState(&cmdesc, &CCWcullMode);
108 
109     cmdesc.FrontCounterClockwise = false;
110     m_d3dDevice->CreateRasterizerState(&cmdesc, &CWcullMode);
111 
112     auto loadVSTask = DX::ReadDataAsync("SimpleVertexShader.cso");
113     auto loadPSTask = DX::ReadDataAsync("SimplePixelShader.cso");
114     auto createVSTask = loadVSTask.then([this](Platform::Array<byte>^ fileData)
115     {
116         DX::ThrowIfFailed(
117             m_d3dDevice->CreateVertexShader(
118             fileData->Data,
119             fileData->Length,
120             nullptr,
121             &m_vertexShader
122             )
123             );
124 
125         const D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
126         {
127             { "POSITION",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },
128             { "TEXCOORD",    0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
129         };
130 
131         DX::ThrowIfFailed(
132             m_d3dDevice->CreateInputLayout(
133             vertexDesc,
134             ARRAYSIZE(vertexDesc),
135             fileData->Data,
136             fileData->Length,
137             &m_inputLayout
138             )
139             );
140     });
141 
142     auto createPSTask = loadPSTask.then([this](Platform::Array<byte>^ fileData)
143     {
144         DX::ThrowIfFailed(
145             m_d3dDevice->CreatePixelShader(
146             fileData->Data,
147             fileData->Length,
148             nullptr,
149             &m_pixelShader
150             )
151             );
152 
153         CD3D11_BUFFER_DESC constantBufferDesc(sizeof(ModelViewProjectionConstantBuffer), D3D11_BIND_CONSTANT_BUFFER);
154         DX::ThrowIfFailed(
155             m_d3dDevice->CreateBuffer(
156             &constantBufferDesc,
157             nullptr,
158             &m_constantBuffer
159             )
160             );
161     });
162 
163     auto createCubeTask = (createPSTask && createVSTask).then([this] ()
164     {
165         Vertex v[] =
166         {
167             Vertex(-1.0f, -1.0f, 1.0f, 1.0f, 1.0f),
168             Vertex(1.0f, -1.0f, 1.0f, 0.0f, 1.0f),
169             Vertex(1.0f, 1.0f, 1.0f, 0.0f, 0.0f),
170             Vertex(-1.0f, 1.0f, 1.0f, 1.0f, 0.0f)
171         };
172 
173         D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
174         vertexBufferData.pSysMem = v;
175         vertexBufferData.SysMemPitch = 0;
176         vertexBufferData.SysMemSlicePitch = 0;
177         CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(v), D3D11_BIND_VERTEX_BUFFER);
178         DX::ThrowIfFailed(
179             m_d3dDevice->CreateBuffer(
180             &vertexBufferDesc,
181             &vertexBufferData,
182             &m_vertexBuffer
183             )
184             );
185 
186         DWORD indices[] =
187         {
188             // Front Face
189             0,  2,  1,
190             0,  3,  2,
191 
192         };
193 
194         m_indexCount = ARRAYSIZE(indices);
195 
196         D3D11_SUBRESOURCE_DATA indexBufferData = {0};
197         indexBufferData.pSysMem = indices;
198         indexBufferData.SysMemPitch = 0;
199         indexBufferData.SysMemSlicePitch = 0;
200         CD3D11_BUFFER_DESC indexBufferDesc(sizeof(indices), D3D11_BIND_INDEX_BUFFER);
201         DX::ThrowIfFailed(
202             m_d3dDevice->CreateBuffer(
203             &indexBufferDesc,
204             &indexBufferData,
205             &m_indexBuffer
206             )
207             );
208     });
209 
210     createCubeTask.then([this] ()
211     {
212         m_loadingComplete = true;
213     });
214 }
215 
CreateWindowSizeDependentResources()216 void QuadRenderer::CreateWindowSizeDependentResources()
217 {
218     Direct3DBase::CreateWindowSizeDependentResources();
219 
220     float aspectRatio = m_windowBounds.Width / m_windowBounds.Height;
221     float fovAngleY = 60.0f * (XM_PI / 180.0f);
222 
223     if (aspectRatio < 1.0f)
224     {
225         fovAngleY /= aspectRatio;
226     }
227 
228     XMStoreFloat4x4(
229         &m_constantBufferData.projection,
230         XMMatrixTranspose(
231         XMMatrixPerspectiveFovRH(
232         fovAngleY,
233         aspectRatio,
234         0.01f,
235         100.0f
236         )
237         )
238         );
239 }
240 
Update(float timeTotal,float timeDelta)241 void QuadRenderer::Update(float timeTotal, float timeDelta)
242 {
243     (void) timeDelta; // Unused parameter.
244 
245     XMVECTOR X = XMVectorSet(0.0f, 0.0f, .3f, 0.0f);
246     XMVECTOR Y = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
247     XMVECTOR Z = XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f);
248 
249     XMStoreFloat4x4(&m_constantBufferData.view, XMMatrixTranspose(XMMatrixLookAtLH(X, Y, Z)));
250     XMStoreFloat4x4(&m_constantBufferData.model, XMMatrixTranspose(XMMatrixRotationY(timeTotal * XM_PIDIV4)));
251 }
252 
Render()253 void QuadRenderer::Render()
254 {
255     Render(m_renderTargetView, m_depthStencilView);
256 }
257 
Render(Microsoft::WRL::ComPtr<ID3D11RenderTargetView> renderTargetView,Microsoft::WRL::ComPtr<ID3D11DepthStencilView> depthStencilView)258 void QuadRenderer::Render(Microsoft::WRL::ComPtr<ID3D11RenderTargetView> renderTargetView, Microsoft::WRL::ComPtr<ID3D11DepthStencilView> depthStencilView)
259 {
260     const float black[] = {0, 0, 0, 1.0 };
261 
262     m_d3dContext->ClearRenderTargetView(
263         renderTargetView.Get(),
264         black
265         );
266 
267     m_d3dContext->ClearDepthStencilView(
268         depthStencilView.Get(),
269         D3D11_CLEAR_DEPTH,
270         1.0f,
271         0
272         );
273 
274     if (m_SRV && m_loadingComplete)	// Only draw the cube once it is loaded (loading is asynchronous).
275     {
276         m_d3dContext->OMSetRenderTargets(
277             1,
278             renderTargetView.GetAddressOf(),
279             depthStencilView.Get()
280             );
281 
282         m_d3dContext->UpdateSubresource(
283             m_constantBuffer.Get(),
284             0,
285             NULL,
286             &m_constantBufferData,
287             0,
288             0
289             );
290 
291         UINT stride = sizeof(Vertex);
292         UINT offset = 0;
293 
294         m_d3dContext->IASetVertexBuffers(
295             0,
296             1,
297             m_vertexBuffer.GetAddressOf(),
298             &stride,
299             &offset
300             );
301 
302         m_d3dContext->IASetIndexBuffer(
303             m_indexBuffer.Get(),
304             DXGI_FORMAT_R32_UINT,
305             0
306             );
307 
308         m_d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
309         m_d3dContext->IASetInputLayout(m_inputLayout.Get());
310 
311         m_d3dContext->VSSetShader(
312             m_vertexShader.Get(),
313             nullptr,
314             0
315             );
316 
317         m_d3dContext->VSSetConstantBuffers(
318             0,
319             1,
320             m_constantBuffer.GetAddressOf()
321             );
322 
323         m_d3dContext->PSSetShader(
324             m_pixelShader.Get(),
325             nullptr,
326             0
327             );
328 
329         m_d3dContext->PSSetShaderResources(0, 1, m_SRV.GetAddressOf());
330         m_d3dContext->PSSetSamplers(0, 1, m_QuadsTexSamplerState.GetAddressOf());
331         m_d3dContext->OMSetBlendState(m_Transparency.Get(), nullptr, 0xffffffff);
332         m_d3dContext->RSSetState(CCWcullMode.Get());
333 
334         m_d3dContext->DrawIndexed(
335             m_indexCount,
336             0,
337             0
338             );
339     }
340 }