GraphGame gg001-Triangle Visual Studio, háromszög rajzolása Szécsi László
Direct3D11 SDK Win10 SDK része Visual Studio 2015
Könyvtár-hierarchia GraphGame – solution folder Projects – ide gyűjtjük a projecteket (csak forrás) gg001-Triangle – ez például egy project folder lesz Build – ide dolgozik majd a Visual Studio Debug – ide ha debugba fordítunk gg001-Triangle – minden projectnek lesz alkönyvtára Release – ide ha releasebe gg001-Triangle – itt is Bin – ide kerülnek a futtathatók (ugyanaz a hierarchia)
Könyvtár-hierarchia II. GraphGame – solution folder Media – ide kerülnek a projectek közös modell, textúra, stb filejai shaders – ide kerülnek a közös shaderek
Solution és project gyártása Visual Studio/Project/New Project… Templates/Visual C++/Win32/Win32 project project name: gg001-Triangle solution name: GraphGame Application settings empty project
Project áthelyezése solution explorerben jobb klikk a projectre remove filerendszerben új folder létrehozása: a solution folderben neve: Projects ide mozgassuk be a projectfolderünket solution explorer add new solution folder: Projects jobb klikk az új folderen: add existing project
64-bites platform jobb klikk, project properties Configuration manager... Active solution platform és project platform megváltoztatása x64-re Poject properties/Linker/Advances/Target machine beállítás ellenőrizhető
Folderek A GraphGame folderben hozzuk létre a következő foldereket Projects (már megcsináltuk) Media (projectek közös modelljei, textúrái) Shaders (projectek közös shader kódja) Bin (bináris exe, lib) Build (ideiglenes fileok)
Könyvtárbeállítások solution explorer/jobbklikk a projecten/project properties/general output directory $(ProjectDir.Replace($(SolutionDir),$(SolutionDir)Bin\$(Configuration)\)) intermediate directory $(ProjectDir.Replace($(SolutionDir),$(SolutionDir)Build\$(Configuration)\)) project properties/debugging/working dir $(SolutionDir)
Fordítás (majd ha lesz mit) A megfelelő könyvtárakba szemetel Így könnyű pl. csak a forrást összezippelni DE: duplaklikkel megnyitott solutionre nem működik!! helyette: studio indítása, solution drag&drop ha elfelejtjük, nincs nagy baj, csak esetleg újra lefordít már kész dolgokat, meg sokat szemetel
stdafx.h lérehozása header files/jobb klikk/add new item/C++ header file neve: stdafx.h
stdafx.h #pragma once #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #define NOMINMAX #include <wrl.h>
main.cpp lérehozása source files/jobb klikk/add new item/C++ file neve: main.cpp
main.cpp #include "stdafx.h" LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
main.cpp int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow) { // Register the window class. const wchar_t CLASS_NAME[] = L"D3D11 Window"; WNDCLASS wc = {}; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.lpszClassName = CLASS_NAME; RegisterClass(&wc);
main.cpp // Create the window. HWND hwnd = CreateWindowEx( 0, // Optional window styles. CLASS_NAME, // Window class L"GraphGame17",// Window text WS_OVERLAPPEDWINDOW, // Window style // Size and position CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, // Parent window NULL, // Menu hInstance, // Instance handle NULL // Additional application data );
main.cpp if (hwnd == NULL) { return 0; } ShowWindow(hwnd, nCmdShow);
main.cpp - hurok MSG msg = { 0 }; while (WM_QUIT != msg.message) { if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) TranslateMessage(&msg); DispatchMessage(&msg); } else // itt fogunk rajzolni return 0;
main.cpp LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, uMsg, wParam, lParam);
Fordítás, futtatás: üres ablak
Precompiled header main.cpp properties C/C++/precompiled headers/Precomiled header: Create később az összes cpp-ben az első sor az stdafx.h includeolása mindegyikre C/C++/precompiled headers/Precomiled header: Use
stdafx.h – D3D include #include <d3d11_2.h> #include <D3DCompiler.h>
main.cpp LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, uMsg, wParam, lParam);
SDK könyvtárak $(WindowsSDK_IncludePath);
Háromszög rajzolása erőforrás létrehozás/felszabadítás (vertex buffer), render target törlés, rajzolás
Ezekre lesz szükség vertex buffer = [x, y, z] [x, y, z] [x, y, z, 1] IA VS IA RS PS OM [x, y, z, 1] [x, y, z, 1] input layout vertex shader primitive topology marad default pixel shader marad default
main.cpp ShowWindow(hwnd, nCmdShow); UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; #if defined(_DEBUG) creationFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0 };
main.cpp using namespace Microsoft::WRL; // Create the Direct3D 11 API device object and a corresponding context. ComPtr<ID3D11Device> device; ComPtr<ID3D11DeviceContext> context; D3D_FEATURE_LEVEL d3dFeatureLevel;
ThrowOnFail.h class ThrowOnFail { std::string errorMessage; std::string filename; int lineNumber; public: ThrowOnFail(std::string errorMessage, std::string filename, int lineNumber) :errorMessage(errorMessage), filename(filename), lineNumber(lineNumber) { }
ThrowOnFail.h void operator^(HRESULT hr){ if (FAILED(hr)) std::stringstream errorMessage; errorMessage << this->filename << "(" << this->lineNumber << "): " << this->errorMessage; MessageBoxA(NULL, errorMessage.str().c_str(), "Error!", MB_ICONSTOP | MB_OK); exit(-1); } };
main.cpp ThrowOnFail("Failed to create D3D device.", __FILE__, __LINE__) ^ D3D11CreateDevice( nullptr,// Specify nullptr to use the default adapter. D3D_DRIVER_TYPE_HARDWARE,// Create a device using the hardware graphics driver. 0,// Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE. creationFlags,// Set debug and Direct2D compatibility flags. featureLevels,// List of feature levels this app can support. ARRAYSIZE(featureLevels),// Size of the list above. D3D11_SDK_VERSION,// Always set this to D3D11_SDK_VERSION for Windows Store apps. device.GetAddressOf(),// Returns the Direct3D device created. &d3dFeatureLevel,// Returns feature level of device created. context.GetAddressOf()// Returns the device immediate context. );
main.cpp ComPtr<IDXGIDevice3> dxgiDevice; ThrowOnFail("The device is not a DXGI device.", __FILE__, __LINE__) ^ device.As(&dxgiDevice); ComPtr<IDXGIAdapter> dxgiAdapter; ThrowOnFail("Failed to get adapter from device.", __FILE__, __LINE__) ^ dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf()); ComPtr<IDXGIFactory2> dxgiFactory; ThrowOnFail("Failed to get factory from adapter.", __FILE__, __LINE__) ^ dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.GetAddressOf()));
main.cpp ComPtr<IDXGISwapChain1> swapChain; RECT r; GetWindowRect(hwnd, &r); DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; swapChainDesc.Width = r.right - r.left; // Match the size of the window. swapChainDesc.Height = r.bottom - r.top; swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format. swapChainDesc.Stereo = false; swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling. swapChainDesc.SampleDesc.Quality = 0; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency. swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect. swapChainDesc.Flags = 0; swapChainDesc.Scaling = DXGI_SCALING_NONE; swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
main.cpp ThrowOnFail("Failed to create swap chain.", __FILE__, __LINE__) ^ dxgiFactory->CreateSwapChainForHwnd( device.Get(), hwnd, &swapChainDesc, nullptr, &swapChain );
main.cpp ComPtr<ID3D11Texture2D> backBuffer; ThrowOnFail("Failed to get swapchain backbuffer.", __FILE__, __LINE__) ^ swapChain->GetBuffer(0, IID_PPV_ARGS(backBuffer.GetAddressOf())); ComPtr<ID3D11RenderTargetView> renderTargetView; ThrowOnFail("Failed to create render target view.", __FILE__, __LINE__) ^ device->CreateRenderTargetView( backBuffer.Get(), nullptr, renderTargetView.GetAddressOf() );
main.cpp // Create a depth stencil view for use with 3D rendering if needed. CD3D11_TEXTURE2D_DESC depthStencilDesc( DXGI_FORMAT_D24_UNORM_S8_UINT, static_cast<UINT>(swapChainDesc.Width), static_cast<UINT>(swapChainDesc.Height), 1, // This depth stencil view has only one texture. 1, // Use a single mipmap level. D3D11_BIND_DEPTH_STENCIL );
main.cpp ComPtr<ID3D11Texture2D> depthStencil; GraphGame::ThrowOnFail("Failed to create depth stencil texture.", __FILE__, __LINE__) ^ device->CreateTexture2D( &depthStencilDesc, nullptr, &depthStencil );
main.cpp ComPtr<ID3D11DepthStencilView> depthStencilView; CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); GraphGame::ThrowOnFail("Failed to create depth stencil view.", __FILE__, __LINE__) ^ device->CreateDepthStencilView( depthStencil.Get(), &depthStencilViewDesc, depthStencilView.GetAddressOf() );
main.cpp // Set the 3D rendering viewport to target the entire window. CD3D11_VIEWPORT screenViewport( 0.0f, swapChainDesc.Width, swapChainDesc.Height ); context->RSSetViewports(1, &screenViewport);
Keret kész jöhet a háromszög erőforrások rajzolás vertex buffer input layout vertex shader pixel shader rajzolás erőforrások bekötése draw
main.cpp ComPtr<ID3D11Buffer> vertexBuffer; ComPtr<ID3D11InputLayout> inputLayout; ComPtr<ID3D11VertexShader> vertexShader; ComPtr<ID3D11PixelShader> pixelShader;
main.cpp struct float3 { float x, y, z; float3(float x, float y, float z) :x(x), y(y), z(z) {} };
main.cpp D3D11_BUFFER_DESC desc; desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.ByteWidth = sizeof(float3) * 3; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; desc.StructureByteStride = sizeof(float3); desc.Usage = D3D11_USAGE_IMMUTABLE;
main.cpp float3 vertexPositionArray[3] = { float3(0, 0, 0.5), D3D11_SUBRESOURCE_DATA initData; initData.pSysMem = vertexPositionArray; initData.SysMemPitch = 0; initData.SysMemSlicePitch = 0;
main.cpp ThrowOnFail("Failed to create vertex buffer.", __FILE__, __LINE__) ^ device->CreateBuffer(&desc, &initData, vertexBuffer.GetAddressOf());
main.cpp const char* vertexShaderCode = "float4 vsIdle(float4 pos :POSITION ) :SV_Position {return pos;}"; ID3DBlob* vertexShaderByteCode; ThrowOnFail("Failed to compile vertex shader source.", __FILE__, __LINE__) ^ D3DCompile(vertexShaderCode, strlen(vertexShaderCode), NULL, NULL, NULL, "vsIdle", "vs_5_0", 0, 0, &vertexShaderByteCode, NULL);
main.cpp GraphGame::ThrowOnFail("Failed to create vertex shader.", __FILE__, __LINE__) ^ device->CreateVertexShader( vertexShaderByteCode->GetBufferPointer(), vertexShaderByteCode->GetBufferSize(), NULL, vertexShader.GetAddressOf());
main.cpp D3D11_INPUT_ELEMENT_DESC positionElement; positionElement.AlignedByteOffset = 0; positionElement.Format = DXGI_FORMAT_R32G32B32_FLOAT; positionElement.InputSlot = 0; positionElement.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; positionElement.InstanceDataStepRate = 0; positionElement.SemanticIndex = 0; positionElement.SemanticName = "POSITION";
main.cpp ThrowOnFail("Failed to create input layout.", __FILE__, __LINE__) ^ device->CreateInputLayout( &positionElement, 1, vertexShaderByteCode ->GetBufferPointer(), vertexShaderByteCode ->GetBufferSize(), inputLayout.GetAddressOf());
main.cpp const char* pixelShaderCode = "float4 psIdle() : SV_Target {return float4(1, 0, 0, 1);}"; A PIXEL SHADER LEFORDíTÁSA, OBJEKTUM LÉTREHOZÁSA ÖNÁLLÓ FELADAT – VS ALAPJÁN
rajzolás a hurokban context->OMSetRenderTargets(1, renderTargetView.GetAddressOf(), depthStencilView.Get()); // idle: update, render float clearColor[4] = { 0.9f, 0.7f, 0.1f, 0.0f }; context->ClearRenderTargetView( renderTargetView.Get(), clearColor); context->ClearDepthStencilView(depthStencilView.Get(), D3D11_CLEAR_DEPTH, 1.0, 0);
rajzolás a hurokban unsigned int stride = sizeof(float3); unsigned int offset = 0; context->IASetVertexBuffers(0, 1, vertexBuffer.GetAddressOf(), &stride, &offset); context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); context->IASetInputLayout(inputLayout.Get()); context->VSSetShader(vertexShader.Get(), NULL, 0); context->PSSetShader(pixelShader.Get(), NULL, 0);
rajzolás a hurokban context->Draw(3, 0); ThrowOnFail("Failed to present swap chain.", __FILE__, __LINE__) ^ swapChain->Present(0, 0);
Háromszög kész
Honnan tudjuk mit kell csinálni? MSDN Direct3D 11 Graphics MSDN Direct3D 11 Reference
Visual Studio 2015 tippek bepastelt kódhoz: általában kódoláshoz formáz: kijelöl, Ctrl+K, Ctrl+F általában kódoláshoz kódieg.: eleje begépel, aztán Ctrl+space metódus paraméterlistája kurzor a zárójelek közé v. nyitó zárójel után ctrl+alt+space