// include the basic windows header file #include #include #include #pragma comment (lib, "d3d11.lib") #include #pragma comment (lib, "d3dcompiler.lib") #include #include namespace dx = DirectX; #include // to usd std::size #include // to use std::sin and std::cos #include "Timer.h" // to use timer Timer timer; #include "Graphics.h" #include #include "Triangle.h" #include "Box.h" #include "Logger.h" Logger logger("log.txt"); #include #include "Ground.h" /************************************ * 1.1 CreateDeviceAndSwapChain ************************************/ // global declarations Microsoft::WRL::ComPtr swapchain; // the pointer to the swap chain interface Microsoft::WRL::ComPtr dev; // the pointer to our Direct3D device interface Microsoft::WRL::ComPtr devcon; // the pointer to our Direct3D device context /************************************ * 1.2 DefineRenderTargetView ************************************/ Microsoft::WRL::ComPtr pBackBuffer; // 定义Targe View Microsoft::WRL::ComPtr targetView; /************************************ * 1.3 DefineDepthStencilView ************************************/ // Define depth stencil buffer Microsoft::WRL::ComPtr pDepthStencilState; // Define depth stencil texture Microsoft::WRL::ComPtr depthStencilTexture; // Define depth stencil view Microsoft::WRL::ComPtr pDSView; /************************************ * 2.3 DefineVertexBuffer ************************************/ // Define vertex buffer Microsoft::WRL::ComPtr pVertexBuffer; // Create buffer description struct Vertex { float x; float y; float z; float r; float g; float b; }; // create vertex buffer (8 vertices for one cube) const Vertex vertices[] = { // left bottom back { -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f }, // right bottom back { 1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f }, // left top back { -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f }, // right top back { 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f }, // left bottom front { -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, // right bottom front { 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f }, // left top front { -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f }, // right top front { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, }; /************************************ * 2.4 DefineIndexBuffer ************************************/ // Define index buffer Microsoft::WRL::ComPtr pIndexBuffer; // Create index buffer const unsigned short indices[] = { // back surface 0, 2, 1, 2, 3, 1, // right surface 1, 3, 5, 3, 7, 5, // top surface 2, 6, 3, 3, 6, 7, // front surface 4, 5, 7, 4, 7, 6, // left surface 0, 4, 2, 2, 4, 6, // bottom surface 0, 1, 4, 1, 5, 4, }; /************************************ * 2.5 DefineTransConstBuffer ************************************/ // Define transformation constant buffer Microsoft::WRL::ComPtr pTransConstBuffer; // Create transformation constant buffer struct struct TransConstBuffer { dx::XMMATRIX transform; }; // create constant buffer const float heightWidthRatio = 0.3f / 0.4f; float angle = 0.0f; TransConstBuffer tcb = { // transpose the matrix to change from row_major to column_major dx::XMMatrixTranspose( // rotate Z axis dx::XMMatrixRotationZ(-angle) // rotate X axis * dx::XMMatrixRotationX(-angle) // scaling //* dx::XMMatrixScaling(heightWidthRatio, 1.0f, 1.0f) // translation * dx::XMMatrixTranslation(0.0f, 0.0f, 4.0f) // projection * dx::XMMatrixPerspectiveLH(1.0f, heightWidthRatio, 0.1f, 10.0f) ) }; /************************************ * 2.6 DefineColorConstBuffer ************************************/ // Define color constant buffer Microsoft::WRL::ComPtr pColorConstBuffer; // Create constant buffer for color struct ColorConstantBuffer { struct { float r; float g; float b; float a; } face_colors[6]; }; const ColorConstantBuffer ccb = { { { 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 1.0f }, } }; /************************************ * 2.7 DefineVertexShader ************************************/ // Define Vertex Shader Microsoft::WRL::ComPtr pCompiledVertexBlob; Microsoft::WRL::ComPtr pVertexShader; /************************************ * 2.8 DefinePixelShader ************************************/ // Define Pixel Shader Microsoft::WRL::ComPtr pCompiledPixelBlob; Microsoft::WRL::ComPtr pPixelShader; /************************************ * 2.9 DefineInputLayout ************************************/ // Define input layout ID3D11InputLayout* pInputLayout; /************************************ * 2.3 DefineVertexBuffer ************************************/ void DefineVertexBuffer() { D3D11_BUFFER_DESC bd = {}; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; bd.Usage = D3D11_USAGE_DEFAULT; bd.CPUAccessFlags = 0u; bd.MiscFlags = 0u; bd.ByteWidth = sizeof(vertices); bd.StructureByteStride = sizeof(Vertex); logger.PutLog("DefineVertexBuffer", "ByteWidth: " + std::to_string(sizeof(vertices))); logger.PutLog("DefineVertexBuffer", "StructureByteStride: " + std::to_string(sizeof(Vertex))); D3D11_SUBRESOURCE_DATA sd = {}; sd.pSysMem = vertices; // Create vertex buffer dev->CreateBuffer(&bd, &sd, &pVertexBuffer); // Bind vertex buffer to pipeline const UINT stride = sizeof(Vertex); const UINT offset = 0u; devcon->IASetVertexBuffers(0u, 1u, pVertexBuffer.GetAddressOf(), &stride, &offset); } /************************************ * 2.4 DefineIndexBuffer ************************************/ void DefineIndexBuffer() { D3D11_BUFFER_DESC ibd = {}; ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; ibd.Usage = D3D11_USAGE_DEFAULT; ibd.CPUAccessFlags = 0u; ibd.MiscFlags = 0u; ibd.ByteWidth = sizeof(indices); ibd.StructureByteStride = sizeof(unsigned short); logger.PutLog("DefineIndexBuffer", "size of ByteWidth: " + std::to_string(ibd.ByteWidth)); logger.PutLog("DefineIndexBuffer", "size of StructureByteStride: " + std::to_string(ibd.StructureByteStride)); D3D11_SUBRESOURCE_DATA isd = {}; isd.pSysMem = indices; // Create index buffer dev->CreateBuffer(&ibd, &isd, &pIndexBuffer); // Bind index buffer to pipeline devcon->IASetIndexBuffer(pIndexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0u); } /************************************ * 2.5 DefineTransConstBuffer ************************************/ void DefineTransConstBuffer(float angle, float z) { tcb = { // transpose the matrix to change from row_major to column_major dx::XMMatrixTranspose( // rotate Z axis //dx::XMMatrixRotationZ(-angle) // rotate X axis //* dx::XMMatrixRotationX(-angle) // scaling //* dx::XMMatrixScaling(heightWidthRatio, 1.0f, 1.0f) // translation dx::XMMatrixTranslation(0.0f, 0.0f, z) // projection * dx::XMMatrixPerspectiveLH(1.0f, heightWidthRatio, 0.5f, 10.0f) ) }; D3D11_BUFFER_DESC cbd = {}; cbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; cbd.Usage = D3D11_USAGE_DYNAMIC; cbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; cbd.MiscFlags = 0u; cbd.ByteWidth = sizeof(tcb); cbd.StructureByteStride = 0u; D3D11_SUBRESOURCE_DATA csd = {}; csd.pSysMem = &tcb; // Create constant buffer dev->CreateBuffer(&cbd, &csd, &pTransConstBuffer); // Bind constant buffer to vertex buffer devcon->VSSetConstantBuffers(0u, 1u, pTransConstBuffer.GetAddressOf()); } /************************************ * 2.6 DefineColorConstBuffer ************************************/ void DefineColorConstBuffer() { D3D11_BUFFER_DESC ccbd = {}; ccbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; ccbd.Usage = D3D11_USAGE_DEFAULT; ccbd.CPUAccessFlags = 0u; ccbd.MiscFlags = 0u; ccbd.ByteWidth = sizeof(ccb); ccbd.StructureByteStride = 0u; D3D11_SUBRESOURCE_DATA ccsd = {}; ccsd.pSysMem = &ccb; dev->CreateBuffer(&ccbd, &ccsd, &pColorConstBuffer); // Bind constant buffer to vertex devcon->PSSetConstantBuffers(0u, 1u, pColorConstBuffer.GetAddressOf()); } /************************************ * 2.7 DefineVertexShader ************************************/ void DefineVertexShader() { // Load pixel shader file into BLOB, and create COM object of vertex shader D3DReadFileToBlob(L"VertexShader.cso", &pCompiledVertexBlob); dev->CreateVertexShader(pCompiledVertexBlob->GetBufferPointer(), pCompiledVertexBlob->GetBufferSize(), nullptr, &pVertexShader); // bind vertex shader devcon->VSSetShader(pVertexShader.Get(), nullptr, 0u); } /************************************ * 2.8 DefinePixelShader ************************************/ void DefinePixelShader() { // Load vertex shader file into BLOB, and create COM object of pixel shader D3DReadFileToBlob(L"PixelShader.cso", &pCompiledPixelBlob); dev->CreatePixelShader(pCompiledPixelBlob->GetBufferPointer(), pCompiledPixelBlob->GetBufferSize(), nullptr, &pPixelShader); // bind pixel shader devcon->PSSetShader(pPixelShader.Get(), nullptr, 0u); } /************************************ * 2.9 DefineInputLayout ************************************/ void DefineInputLayout() { // Create input elements description, choosing whatever need to send to GPU const D3D11_INPUT_ELEMENT_DESC ied[] = { //{ "Position",0,DXGI_FORMAT_R32G32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0 }, { "Position",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0 }, //{ "Color",0,DXGI_FORMAT_R32G32B32_FLOAT,0,8,D3D11_INPUT_PER_VERTEX_DATA,0 }, //{ "Color",0,DXGI_FORMAT_R32G32B32_FLOAT,0,12,D3D11_INPUT_PER_VERTEX_DATA,0 }, }; // Create input layout, using the description Defined above dev->CreateInputLayout ( ied, (UINT)std::size(ied), pCompiledVertexBlob->GetBufferPointer(), pCompiledVertexBlob->GetBufferSize(), &pInputLayout ); // Bind layout to pipeline // bind vertex layout devcon->IASetInputLayout(pInputLayout); } /************************************ * 2.10 DefinePrimitiveTopology ************************************/ void DefinePrimitiveTopology() { // Set the primitive type to use // Set primitive topology to triangle list (groups of 3 vertices) devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); } /************************************ * 2.11 DefineViewPorts ************************************/ void DefineViewPorts() { // 指定View Port D3D11_VIEWPORT viewport; ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT)); // 控制View port的位置 viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = 800; viewport.Height = 600; viewport.MinDepth = 0; viewport.MaxDepth = 1; devcon->RSSetViewports(1, &viewport); } /************************************ * 2.11 DrawPrimitive ************************************/ void DrawPrimitive() { // Draw the triangle. // devcon->Draw((UINT)sizeof(vertices), 0u); devcon->DrawIndexed((UINT)std::size(indices), 0u, 0u); } void drawSingleTriangle(float angle, float z) { /************************************ * 2.3 DefineVertexBuffer ************************************/ DefineVertexBuffer(); /************************************ * 2.4 DefineIndexBuffer ************************************/ DefineIndexBuffer(); /************************************ * 2.5 DefineTransConstBuffer ************************************/ DefineTransConstBuffer(angle, z); /************************************ * 2.6 DefineColorConstBuffer ************************************/ DefineColorConstBuffer(); /************************************ * 2.7 DefineVertexShader ************************************/ DefineVertexShader(); /************************************ * 2.8 DefinePixelShader ************************************/ DefinePixelShader(); /************************************ * 2.9 DefineInputLayout ************************************/ DefineInputLayout(); /************************************ * 2.10 DefinePrimitiveTopology ************************************/ DefinePrimitiveTopology(); /************************************ * 2.11 DefineViewPorts ************************************/ DefineViewPorts(); /************************************ * 2.12 DrawPrimitive ************************************/ DrawPrimitive(); } void drawTriangle() { drawSingleTriangle(timer.Peek(), 4.0f); //drawSingleTriangle(-timer.Peek(), 4.5f); } /************************************ * 1.1 CreateDeviceAndSwapChain ************************************/ void CreateDeviceAndSwapChain(HWND hWnd) { // create a struct to hold information about the swap chain DXGI_SWAP_CHAIN_DESC scd; // clear out the struct for use ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC)); // fill the swap chain description struct scd.BufferCount = 1; // one back buffer scd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // use 32-bit color scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used scd.OutputWindow = hWnd; // the window to be used scd.SampleDesc.Count = 1; // how many multisamples scd.Windowed = TRUE; // windowed/full-screen mode // create a device, device context and swap chain using the information in the scd struct D3D11CreateDeviceAndSwapChain(NULL, // IDXGIAdapter *pAdapter - Let DXGI take care of what adapter to use (default adapter) D3D_DRIVER_TYPE_HARDWARE, // D3D_DRIVER_TYPE DriverType - hardware or software, or others NULL, // HMODULE Software NULL, // UINT Flags NULL, // D3D_FEATURE_LEVEL *pFeatureLevels NULL, // UINT FeatureLevels D3D11_SDK_VERSION, // UINT SDKVersion &scd, // DXGI_SWAP_CHAIN_DESC *pSwapChainDesc &swapchain, // IDXGISwapChain **ppSwapChain &dev, // ID3D11Device **ppDevice NULL, // D3D_FEATURE_LEVEL *FeatureLevel &devcon); // ID3D11DeviceContext **ppImmediateContext } /************************************ * 1.2 DefineRenderTargetView ************************************/ void DefineRenderTargetView() { // 从SwapChain中取得back buffer swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); // 根据back buffer,创建新的View Target dev->CreateRenderTargetView(pBackBuffer.Get(), NULL, &targetView); } /************************************ * 1.3 DefineDepthStencilView ************************************/ void DefineDepthStencilView() { // Create depth stencil state D3D11_DEPTH_STENCIL_DESC depthStencilDesc = {}; depthStencilDesc.DepthEnable = TRUE; depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; // Create depth stencil state dev->CreateDepthStencilState(&depthStencilDesc, &pDepthStencilState); // bind depth state devcon->OMSetDepthStencilState(pDepthStencilState.Get(), 1u); // Create the depth stencil texture D3D11_TEXTURE2D_DESC depthStencilTextureDesc = {}; depthStencilTextureDesc.Width = 800; depthStencilTextureDesc.Height = 600; depthStencilTextureDesc.MipLevels = 1u; depthStencilTextureDesc.ArraySize = 1u; depthStencilTextureDesc.Format = DXGI_FORMAT_D32_FLOAT; depthStencilTextureDesc.SampleDesc.Count = 1u; depthStencilTextureDesc.SampleDesc.Quality = 0u; depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT; depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; // Create texture dev->CreateTexture2D(&depthStencilTextureDesc, nullptr, &depthStencilTexture); // Create the depth stencil view D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc = {}; depthStencilViewDesc.Format = DXGI_FORMAT_D32_FLOAT; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilViewDesc.Texture2D.MipSlice = 0u; dev->CreateDepthStencilView(depthStencilTexture.Get(), &depthStencilViewDesc, &pDSView); } /************************************ * 1.4 DefineRenderTarget ************************************/ void DefineRenderTarget() { // 将渲染目标设置成我们新创建的View Target //devcon->OMSetRenderTargets(1u, targetView.GetAddressOf(), NULL); devcon->OMSetRenderTargets(1u, targetView.GetAddressOf(), pDSView.Get()); } // this function initializes and prepares Direct3D for use void InitD3D(HWND hWnd) { /************************************ * 1.1 CreateDeviceAndSwapChain ************************************/ CreateDeviceAndSwapChain(hWnd); /************************************ * 1.2 DefineRenderTargetView ************************************/ DefineRenderTargetView(); /************************************ * 1.3 DefineDepthStencilView ************************************/ DefineDepthStencilView(); /************************************ * 1.4 DefineRenderTarget ************************************/ DefineRenderTarget(); } // this is the function used to render a single frame void RenderFrame(void) { /************************************ * 2.1 ClearRenderTargetView ************************************/ // clear the back buffer to a deep blue const float color[] = { 0.0f, 0.2f, 0.4f, 1.0f }; devcon->ClearRenderTargetView(targetView.Get(), color); /************************************ * 2.2 ClearDepthStencilView ************************************/ // clear the depth stencil view devcon->ClearDepthStencilView(pDSView.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0u); /************************************ * 2.3 - 2.12 Repeat graphic objects ************************************/ // do 3D rendering on the back buffer here drawTriangle(); /************************************ * 3 DrawPrimitive ************************************/ // switch the back buffer and the front buffer // 切换显示,将back buffer的内容交换到front buffer swapchain->Present(0, 0); } // this is the function that cleans up Direct3D and COM void CleanD3D() { // close and release all existing COM objects // changed to use smart pointer, do NOT need to manually release // pPixelShader->Release(); // pCompiledPixelBlob->Release(); // pVertexShader->Release(); // pCompiledVertexBlob->Release(); // pVertexBuffer->Release(); // pInputLayout->Release(); // swapchain->Release(); // targetView->Release(); // dev->Release(); // devcon->Release(); } // the WindowProc function prototype LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); // the entry point for any Windows program int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { logger.start(); // the handle for the window, filled by a function HWND hWnd; // this struct holds information for the window class WNDCLASSEX wc; // clear out the window class for use ZeroMemory(&wc, sizeof(WNDCLASSEX)); // fill in the struct with the needed information wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)COLOR_WINDOW; wc.lpszClassName = "WindowClass"; // register the window class RegisterClassEx(&wc); // create rectangle for client area RECT wr = { 0, 0, 800, 600 }; // set the size only, but not the position AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // adjust the size // create the window and use the result as the handle hWnd = CreateWindowEx( NULL, "WindowClass", // name of the window class "Oasis Demo", // title of the window WS_OVERLAPPEDWINDOW, // window style 300, // x-position of the window 200, // y-position of the window 800, // width of the window 600, // height of the window NULL, // we have no parent window, NULL NULL, // we aren't using menus, NULL hInstance, // application handle NULL); // used with multiple windows, NULL // display the window on the screen ShowWindow(hWnd, nCmdShow); // set up and initialize Direct3D //InitD3D(hWnd); //std::unique_ptr pGfx = std::make_unique(hWnd); Graphics gfx(hWnd); gfx.SetProjection(DirectX::XMMatrixPerspectiveLH(1.0f, 3.0f / 4.0f, 0.5f, 40.0f)); std::vector> boxes; for (int i = -5; i < 6; i++) { for (int j = -5; j < 6; j++) { float boxPos[8][3] = { // left bottom back { -1.0f + i, -1.0f, -1.0f + j }, // right bottom back { 1.0f + i, -1.0f, -1.0f + j }, // left top back { -1.0f + i, 1.0f, -1.0f + j }, // right top back { 1.0f + i, 1.0f, -1.0f + j }, // left bottom front { -1.0f + i, -1.0f, 1.0f + j }, // right bottom front { 1.0f + i, -1.0f, 1.0f + j }, // left top front { -1.0f + i, 1.0f, 1.0f + j }, // right top front { 1.0f + i, 1.0f, 1.0f + j }, }; float boxCol[6][3] = { { 0.0f, 1.0f, 0.0f }, // Green { 1.0f, 1.0f, 0.0f }, // Yellow { 1.0f, 0.0f, 0.0f }, // Red { 0.0f, 0.0f, 1.0f }, // Blue { 0.0f, 1.0f, 1.0f }, // Cyan { 1.0f, 0.0f, 1.0f }, // Magenta }; boxes.push_back(std::make_unique(gfx, boxPos, boxCol, logger)); } } Ground ground(gfx, logger); double seed = 0; seed = int(seed) % 10000; // enter the main loop: // this struct holds Windows event messages MSG msg; // wait for the next message in the queue, store the result in 'msg' while (true) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // translate keystroke messages into the right format TranslateMessage(&msg); // send the message to the WindowProc function DispatchMessage(&msg); // check if message to quit if (msg.message == WM_QUIT) { break; } } else { //RenderFrame(); gfx.RendorFrame(); seed++; auto dt = sin(seed / 1000); logger.PutLog("seed", std::to_string(seed)); logger.PutLog("dt", std::to_string(dt)); auto sinValue = sin(seed / 1000); auto cosValue = cos(seed / 1000); // Set camera DirectX::XMVECTOR eyePosition = DirectX::XMVectorSet(20.0f * sinValue, 10.0f, -20.0f * cosValue, 1.0f); DirectX::XMVECTOR focusPosition = DirectX::XMVectorZero(); DirectX::XMVECTOR upDirection = DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f); ground.SetCamera(logger, eyePosition, focusPosition, upDirection); ground.DrawShapes(gfx, logger); gfx.EndFrame(); } } // clean up DirectX and COM CleanD3D(); logger.end(); // return this part of the WM_QUIT message to Windows return msg.wParam; } // this is the main message handler for the program LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { // sort through and find what code to run for the message given switch (message) { // this message is read when the window is closed case WM_DESTROY: { // close the application entirely PostQuitMessage(0); return 0; } break; } // Handle any messages the switch statement didn't return DefWindowProc(hWnd, message, wParam, lParam); }