#include "vars.h" // 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) { HWND hWnd; WNDCLASSEX wc; ZeroMemory(&wc, sizeof(WNDCLASSEX)); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszClassName = L"WindowClass"; RegisterClassEx(&wc); RECT wr = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT}; AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); hWnd = CreateWindowEx(NULL, L"WindowClass", L"Our First Direct3D Program", WS_OVERLAPPEDWINDOW, 300, 300, wr.right - wr.left, wr.bottom - wr.top, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); // set up and initialize Direct3D InitD3D(hWnd); // enter the main loop: MSG msg; while(TRUE) { if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); if(msg.message == WM_QUIT) break; } RenderFrame(); } // clean up DirectX and COM CleanD3D(); return msg.wParam; } // this is the main message handler for the program LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_DESTROY: { PostQuitMessage(0); return 0; } break; } return DefWindowProc (hWnd, message, wParam, lParam); } // this function initializes and prepares Direct3D for use void InitD3D(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_R8G8B8A8_UNORM; // use 32-bit color scd.BufferDesc.Width = SCREEN_WIDTH; // set the back buffer width scd.BufferDesc.Height = SCREEN_HEIGHT; // set the back buffer height 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 = 4; // how many multisamples scd.Windowed = TRUE; // windowed/full-screen mode scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // allow full-screen switching // create a device, device context and swap chain using the information in the scd struct D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &scd, &swapchain, &dev, NULL, &devcon); // create the depth buffer texture D3D11_TEXTURE2D_DESC texd; ZeroMemory(&texd, sizeof(texd)); texd.Width = SCREEN_WIDTH; texd.Height = SCREEN_HEIGHT; texd.ArraySize = 1; texd.MipLevels = 1; texd.SampleDesc.Count = 4; texd.Format = DXGI_FORMAT_D32_FLOAT; texd.BindFlags = D3D11_BIND_DEPTH_STENCIL; ID3D11Texture2D *pDepthBuffer; dev->CreateTexture2D(&texd, NULL, &pDepthBuffer); // create the depth buffer D3D11_DEPTH_STENCIL_VIEW_DESC dsvd; ZeroMemory(&dsvd, sizeof(dsvd)); dsvd.Format = DXGI_FORMAT_D32_FLOAT; dsvd.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; dev->CreateDepthStencilView(pDepthBuffer, &dsvd, &zbuffer); pDepthBuffer->Release(); // get the address of the back buffer ID3D11Texture2D *pBackBuffer; swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); // use the back buffer address to create the render target dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer); pBackBuffer->Release(); // set the render target as the back buffer devcon->OMSetRenderTargets(1, &backbuffer, zbuffer); // Set the viewport D3D11_VIEWPORT viewport; ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT)); viewport.TopLeftX = 0; // set the left to 0 viewport.TopLeftY = 0; // set the top to 0 viewport.Width = SCREEN_WIDTH; // set the width to the window's width viewport.Height = SCREEN_HEIGHT; // set the height to the window's height viewport.MinDepth = 0; // the closest an object can be on the depth buffer is 0.0 viewport.MaxDepth = 1; // the farthest an object can be on the depth buffer is 1.0 devcon->RSSetViewports(1, &viewport); InitPipeline(); InitGraphics(); } // this is the function used to render a single frame void RenderFrame(void) { D3DXMATRIX matRotate, matView, matProjection; D3DXMATRIX matFinal; static float Time = 0.0f; Time += 0.0003f; // create a world matrices D3DXMatrixRotationY(&matRotate, Time); // create a view matrix D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0.0f, 7.0f, 5.0f), // the camera position &D3DXVECTOR3(0.0f, 0.0f, 0.0f), // the look-at position &D3DXVECTOR3(0.0f, 1.0f, 0.0f)); // the up direction // create a projection matrix D3DXMatrixPerspectiveFovLH(&matProjection, (FLOAT)D3DXToRadian(45), // field of view (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // aspect ratio 1.0f, // near view-plane 1000.0f); // far view-plane // load the matrices into the constant buffer matFinal = matRotate * matView * matProjection; // clear the back buffer to a deep blue devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f)); // clear the depth buffer devcon->ClearDepthStencilView(zbuffer, D3D11_CLEAR_DEPTH, 1.0f, 0); // select which vertex buffer to display UINT stride = sizeof(VertexType); UINT offset = 0; devcon->IASetVertexBuffers(0, 1, &pVBuffer, &stride, &offset); devcon->IASetIndexBuffer(pIBuffer, DXGI_FORMAT_R32_UINT, 0); // select which primtive type we are using devcon->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_LINELIST); //Draw devcon->DrawIndexed(m_indexCount, 0, 0); // switch the back buffer and the front buffer swapchain->Present(0, 0); } // this is the function that cleans up Direct3D and COM void CleanD3D(void) { swapchain->SetFullscreenState(FALSE, NULL); // switch to windowed mode // close and release all existing COM objects zbuffer->Release(); pLayout->Release(); pVS->Release(); pPS->Release(); pVBuffer->Release(); pIBuffer->Release(); swapchain->Release(); backbuffer->Release(); dev->Release(); devcon->Release(); } // this is the function that creates the shape to render void InitGraphics() { VertexType* vertices; unsigned long* indices; int i, j, index; float positionX, positionZ; // Calculate the number of vertices in the terrain mesh. m_vertexCount = (m_terrainWidth - 1) * (m_terrainHeight - 1) * 8; // Set the index count to the same as the vertex count. m_indexCount = m_vertexCount; vertices = new VertexType[m_vertexCount]; indices = new unsigned long[m_indexCount]; // Initialize the index to the vertex buffer. index = 0; // Load the vertex and index array with the terrain data. for(j=0; j<(m_terrainHeight-1); j++) { for(i=0; i<(m_terrainWidth-1); i++) { // LINE 1 // Upper left. positionX = (float)i; positionZ = (float)(j+1); vertices[index].position = D3DXVECTOR3(positionX, 0.0f, positionZ); vertices[index].color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f); indices[index] = index; index++; // Upper right. positionX = (float)(i+1); positionZ = (float)(j+1); vertices[index].position = D3DXVECTOR3(positionX, 0.0f, positionZ); vertices[index].color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f); indices[index] = index; index++; // LINE 2 // Upper right. positionX = (float)(i+1); positionZ = (float)(j+1); vertices[index].position = D3DXVECTOR3(positionX, 0.0f, positionZ); vertices[index].color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f); indices[index] = index; index++; // Bottom right. positionX = (float)(i+1); positionZ = (float)j; vertices[index].position = D3DXVECTOR3(positionX, 0.0f, positionZ); vertices[index].color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f); indices[index] = index; index++; // LINE 3 // Bottom right. positionX = (float)(i+1); positionZ = (float)j; vertices[index].position = D3DXVECTOR3(positionX, 0.0f, positionZ); vertices[index].color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f); indices[index] = index; index++; // Bottom left. positionX = (float)i; positionZ = (float)j; vertices[index].position = D3DXVECTOR3(positionX, 0.0f, positionZ); vertices[index].color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f); indices[index] = index; index++; // LINE 4 // Bottom left. positionX = (float)i; positionZ = (float)j; vertices[index].position = D3DXVECTOR3(positionX, 0.0f, positionZ); vertices[index].color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f); indices[index] = index; index++; // Upper left. positionX = (float)i; positionZ = (float)(j+1); vertices[index].position = D3DXVECTOR3(positionX, 0.0f, positionZ); vertices[index].color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f); indices[index] = index; index++; } } // create the vertex buffer D3D11_BUFFER_DESC bd; ZeroMemory(&bd, sizeof(bd)); bd.Usage = D3D11_USAGE_DYNAMIC; bd.ByteWidth = sizeof(VertexType) * m_vertexCount; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; dev->CreateBuffer(&bd, NULL, &pVBuffer); // copy the vertices into the buffer D3D11_MAPPED_SUBRESOURCE ms; devcon->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms); // map the buffer memcpy(ms.pData, vertices, sizeof(vertices)); // copy the data devcon->Unmap(pVBuffer, NULL); // create the index buffer bd.Usage = D3D11_USAGE_DYNAMIC; bd.ByteWidth = sizeof(unsigned long) * m_indexCount; bd.BindFlags = D3D11_BIND_INDEX_BUFFER; bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; bd.MiscFlags = 0; dev->CreateBuffer(&bd, NULL, &pIBuffer); devcon->Map(pIBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms); // map the buffer memcpy(ms.pData, indices, sizeof(indices)); // copy the data devcon->Unmap(pIBuffer, NULL); /* D3DX11CreateShaderResourceViewFromFile(dev, // the Direct3D device L"Wood.png", // load Wood.png in the local folder NULL, // no additional information NULL, // no multithreading &pTexture, // address of the shader-resource-view NULL); // no multithreading */ delete [] vertices; vertices = 0; delete [] indices; indices = 0; } // this function loads and prepares the shaders void InitPipeline() { // compile the shaders ID3D10Blob *VS, *PS; D3DX11CompileFromFile(L"shaders.hlsl", 0, 0, "VShader", "vs_5_0", 0, 0, 0, &VS, 0, 0); D3DX11CompileFromFile(L"shaders.hlsl", 0, 0, "PShader", "ps_5_0", 0, 0, 0, &PS, 0, 0); // create the shader objects dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS); dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS); // set the shader objects devcon->VSSetShader(pVS, 0, 0); devcon->PSSetShader(pPS, 0, 0); // create the input element object D3D11_INPUT_ELEMENT_DESC ied[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D10_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; // use the input element descriptions to create the input layout dev->CreateInputLayout(ied, 3, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout); devcon->IASetInputLayout(pLayout); }