|
|
|
#pragma comment(lib, "user32") |
|
#pragma comment(lib, "d3d11") |
|
#pragma comment(lib, "d3dcompiler") |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
#include <windows.h> |
|
#include <d3d11.h> |
|
#include <d3dcompiler.h> |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
#define TEXTURE_WIDTH 17 |
|
#define TEXTURE_HEIGHT 25 |
|
|
|
unsigned long long texturedata[] = // skull texture. 17 x 25 pixels, 8 bits per pixel (grayscale) for compactness |
|
{ |
|
0x0000000000000000, 0x0000000000000000, 0xdd00000000000000, 0x00000000b2e0dede, 0xe1dc000000000000, 0x00afaeaeaec8c8c8, |
|
0xc7e3000000000000, 0x89b09999c3ddddc3, 0xc7dd0000000000ae, 0x9b99afb0c6dbddc6, 0xc400000000af899b, 0xb0aeaec6c6dedcc6, |
|
0xdd0000008a9c99af, 0xadadaec4dedcdcc4, 0x0000599b9aaeafaf, 0xadadc6c6ddddc6c6, 0x005c9a9aafafadae, 0xadacc6c3e0ddc600, |
|
0x5c9d5ab0b0aeadad, 0xaddedcdcc6ae0000, 0x9f5ac4c4c7c6adad, 0x895e89ae5d00005c, 0x5b56578dc6aeaeb0, 0x18185c3300005a5a, |
|
0x1818198cae8c1716, 0x195a330000305b31, 0x171617af5a331718, 0x8ec60000315a5b30, 0x165b8b8a58321718, 0xe000005b8c5a3132, |
|
0x8a17dd8d5c188db1, 0x000089ad8a5a1658, 0x3219da888eaf8b5b, 0x00323034898b8d5b, 0x16aeae1719590000, 0x00301717af8d3089, |
|
0xad5a32dc00000000, 0x005a1959ad8c8bb0, 0x8d198a0000000000, 0x58318b17e217dc5a, 0x8a8a000000000000, 0x5b3230185a5b2f18, |
|
0xae00000000000033, 0xb02fdc30de18ddaf, 0x000000000000335a, 0xb0e1aeb1afafae00, 0x0000000000005daf, 0xadafb1afb0000000, |
|
0x0000000000005b5c, 0x898b8b0000000000, 0x0000000000005a5c, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, |
|
}; |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) |
|
{ |
|
WNDCLASSA wndclass = { 0, DefWindowProcA, 0, 0, 0, 0, 0, 0, 0, "d7" }; |
|
|
|
RegisterClassA(&wndclass); |
|
|
|
HWND window = CreateWindowExA(0, "d7", 0, 0x91000000, 0, 0, 0, 0, 0, 0, 0, 0); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
D3D_FEATURE_LEVEL featurelevels[] = { D3D_FEATURE_LEVEL_11_0 }; |
|
|
|
DXGI_SWAP_CHAIN_DESC swapchaindesc = {}; |
|
swapchaindesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // non-srgb for simplicity here. see other minimal gists for srgb setup |
|
swapchaindesc.SampleDesc.Count = 1; |
|
swapchaindesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; |
|
swapchaindesc.BufferCount = 2; |
|
swapchaindesc.OutputWindow = window; |
|
swapchaindesc.Windowed = TRUE; |
|
swapchaindesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; |
|
|
|
IDXGISwapChain* swapchain; |
|
|
|
ID3D11Device* device; |
|
ID3D11DeviceContext* devicecontext; |
|
|
|
D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT, featurelevels, ARRAYSIZE(featurelevels), D3D11_SDK_VERSION, &swapchaindesc, &swapchain, &device, nullptr, &devicecontext); |
|
|
|
swapchain->GetDesc(&swapchaindesc); // get actual dimensions |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
ID3D11Texture2D* framebuffer; |
|
|
|
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&framebuffer); // get the swapchain's buffer |
|
|
|
ID3D11RenderTargetView* framebufferRTV; |
|
|
|
device->CreateRenderTargetView(framebuffer, nullptr, &framebufferRTV); // and make it a render target [view] |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
ID3DBlob* vertexshaderCSO; |
|
|
|
D3DCompileFromFile(L"gpu.hlsl", 0, 0, "VsMain", "vs_5_0", 0, 0, &vertexshaderCSO, 0); |
|
|
|
ID3D11VertexShader* vertexshader; |
|
|
|
device->CreateVertexShader(vertexshaderCSO->GetBufferPointer(), vertexshaderCSO->GetBufferSize(), 0, &vertexshader); |
|
|
|
D3D11_INPUT_ELEMENT_DESC inputelementdesc[] = // maps to vertexdesc struct in gpu.hlsl via semantic names ("POS", "TEX", "COL") |
|
{ |
|
{ "POS", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, // float2 position (x, y) |
|
{ "TEX", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, // float2 texcoord (u, v) |
|
{ "COL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, // float4 color (r, g, b, a) |
|
}; |
|
|
|
ID3D11InputLayout* inputlayout; |
|
|
|
device->CreateInputLayout(inputelementdesc, ARRAYSIZE(inputelementdesc), vertexshaderCSO->GetBufferPointer(), vertexshaderCSO->GetBufferSize(), &inputlayout); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
ID3DBlob* pixelshaderCSO; |
|
|
|
D3DCompileFromFile(L"gpu.hlsl", 0, 0, "PsMain", "ps_5_0", 0, 0, &pixelshaderCSO, 0); |
|
|
|
ID3D11PixelShader* pixelshader; |
|
|
|
device->CreatePixelShader(pixelshaderCSO->GetBufferPointer(), pixelshaderCSO->GetBufferSize(), 0, &pixelshader); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
D3D11_RASTERIZER_DESC rasterizerdesc = { D3D11_FILL_SOLID, D3D11_CULL_NONE }; |
|
|
|
ID3D11RasterizerState* rasterizerstate; |
|
|
|
device->CreateRasterizerState(&rasterizerdesc, &rasterizerstate); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
D3D11_SAMPLER_DESC samplerdesc = { D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_TEXTURE_ADDRESS_WRAP, D3D11_TEXTURE_ADDRESS_WRAP, D3D11_TEXTURE_ADDRESS_WRAP }; |
|
|
|
ID3D11SamplerState* samplerstate; |
|
|
|
device->CreateSamplerState(&samplerdesc, &samplerstate); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
D3D11_BLEND_DESC blenddesc = { FALSE, FALSE, { TRUE, D3D11_BLEND_SRC_ALPHA , D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL } }; |
|
|
|
ID3D11BlendState* blendstate; |
|
|
|
device->CreateBlendState(&blenddesc, &blendstate); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
float constants[2] = { 2.0f / swapchaindesc.BufferDesc.Width, -2.0f / swapchaindesc.BufferDesc.Height }; // precalc for simple screen coordinate transform in shader (instead of full-on projection matrix) |
|
|
|
D3D11_BUFFER_DESC constantbufferdesc = {}; |
|
constantbufferdesc.ByteWidth = sizeof(constants) + 0xf & 0xfffffff0; |
|
constantbufferdesc.Usage = D3D11_USAGE_IMMUTABLE; |
|
constantbufferdesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; |
|
|
|
D3D11_SUBRESOURCE_DATA constantbufferSRD = { constants }; |
|
|
|
ID3D11Buffer* constantbuffer; |
|
|
|
device->CreateBuffer(&constantbufferdesc, &constantbufferSRD, &constantbuffer); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
D3D11_TEXTURE2D_DESC texturedesc = {}; |
|
texturedesc.Width = TEXTURE_WIDTH; |
|
texturedesc.Height = TEXTURE_HEIGHT; |
|
texturedesc.MipLevels = 1; |
|
texturedesc.ArraySize = 1; |
|
texturedesc.Format = DXGI_FORMAT_R8_UNORM; // 8 bits per pixel |
|
texturedesc.SampleDesc.Count = 1; |
|
texturedesc.Usage = D3D11_USAGE_IMMUTABLE; |
|
texturedesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; |
|
|
|
D3D11_SUBRESOURCE_DATA textureSRD = {}; |
|
textureSRD.pSysMem = texturedata; |
|
textureSRD.SysMemPitch = TEXTURE_WIDTH * 1; // 1 byte per pixel (R8) |
|
|
|
ID3D11Texture2D* texture; |
|
|
|
device->CreateTexture2D(&texturedesc, &textureSRD, &texture); |
|
|
|
ID3D11ShaderResourceView* textureSRV; |
|
|
|
device->CreateShaderResourceView(texture, nullptr, &textureSRV); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
#define MAX_VERTICES 1024 // arbitrary limit |
|
|
|
struct vertexdesc { float x, y, u, v, r, g, b, a; }; // float2 position, float2 texcoord, float4 color |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
D3D11_BUFFER_DESC vertexbufferdesc = {}; |
|
vertexbufferdesc.ByteWidth = sizeof(vertexdesc) * MAX_VERTICES; |
|
vertexbufferdesc.Usage = D3D11_USAGE_DYNAMIC; // updated every frame |
|
vertexbufferdesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; |
|
vertexbufferdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; |
|
|
|
ID3D11Buffer* vertexbuffer; |
|
|
|
device->CreateBuffer(&vertexbufferdesc, nullptr, &vertexbuffer); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
FLOAT clearcolor[4] = { 0.1725f, 0.1725f, 0.1725f, 1.0f }; // RGBA |
|
|
|
D3D11_VIEWPORT viewport = { 0, 0, (float)swapchaindesc.BufferDesc.Width, (float)swapchaindesc.BufferDesc.Height, 0, 1 }; |
|
|
|
UINT stride = sizeof(vertexdesc); |
|
UINT offset = 0; |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
vertexdesc* vertexbatch = (vertexdesc*)HeapAlloc(GetProcessHeap(), 0, sizeof(vertexdesc) * MAX_VERTICES); // per frame vertex batch (cpu-local buffer) |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
while (true) |
|
{ |
|
MSG msg; |
|
|
|
while (PeekMessageA(&msg, nullptr, 0, 0, PM_REMOVE)) |
|
{ |
|
if (msg.message == WM_KEYDOWN) return 0; // PRESS ANY KEY TO EXIT |
|
DispatchMessageA(&msg); |
|
} |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
int vertexcount = 0; // start a new vertex batch every frame |
|
|
|
// triangle 1: |
|
{ |
|
// vertex 1 |
|
vertexdesc vertex; |
|
vertex.x = 100; // screen coordinates in pixels (xy) |
|
vertex.y = 100; |
|
vertex.u = 0.0f; // texture coordinates (uv) |
|
vertex.v = 0.0f; |
|
vertex.r = 1.0f; // color (rgba) |
|
vertex.g = 1.0f; |
|
vertex.b = 1.0f; |
|
vertex.a = 1.0f; |
|
|
|
vertexbatch[vertexcount++] = vertex; // add vertex to batch |
|
|
|
// vertex 2 |
|
vertexbatch[vertexcount++] = { 252, 300, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; // x, y, u, v, r, g, b, a |
|
|
|
// vertex 3 |
|
vertexbatch[vertexcount++] = { 100, 300, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; |
|
} |
|
|
|
// triangle 2: |
|
vertexbatch[vertexcount++] = { 100, 100, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f }; |
|
vertexbatch[vertexcount++] = { 252, 100, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f }; |
|
vertexbatch[vertexcount++] = { 252, 300, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; |
|
|
|
// triangle 3: |
|
vertexbatch[vertexcount++] = { 296, 104, 0.0f, 0.0f, 0.803f, 0.000f, 0.290f, 1.0f }; |
|
vertexbatch[vertexcount++] = { 448, 304, 1.0f, 1.0f, 0.952f, 0.439f, 0.105f, 1.0f }; |
|
vertexbatch[vertexcount++] = { 296, 304, 0.0f, 1.0f, 0.988f, 0.721f, 0.023f, 1.0f }; |
|
|
|
// triangle 4: |
|
vertexbatch[vertexcount++] = { 304, 96, 0.0f, 0.0f, 0.011f, 0.698f, 0.286f, 1.0f }; |
|
vertexbatch[vertexcount++] = { 456, 96, 1.0f, 0.0f, 0.000f, 0.541f, 0.819f, 1.0f }; |
|
vertexbatch[vertexcount++] = { 456, 296, 1.0f, 1.0f, 0.392f, 0.376f, 0.670f, 1.0f }; |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
D3D11_MAPPED_SUBRESOURCE vertexbufferMSR; |
|
|
|
devicecontext->Map(vertexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &vertexbufferMSR); |
|
{ |
|
memcpy(vertexbufferMSR.pData, vertexbatch, sizeof(vertexdesc) * vertexcount); // send vertex batch to gpu |
|
} |
|
devicecontext->Unmap(vertexbuffer, 0); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
devicecontext->ClearRenderTargetView(framebufferRTV, clearcolor); |
|
|
|
devicecontext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // 3 vertices per triangle |
|
devicecontext->IASetInputLayout(inputlayout); |
|
devicecontext->IASetVertexBuffers(0, 1, &vertexbuffer, &stride, &offset); |
|
|
|
devicecontext->VSSetShader(vertexshader, nullptr, 0); |
|
devicecontext->VSSetConstantBuffers(0, 1, &constantbuffer); |
|
|
|
devicecontext->RSSetViewports(1, &viewport); |
|
devicecontext->RSSetState(rasterizerstate); |
|
|
|
devicecontext->PSSetShader(pixelshader, nullptr, 0); |
|
devicecontext->PSSetShaderResources(0, 1, &textureSRV); |
|
devicecontext->PSSetSamplers(0, 1, &samplerstate); |
|
|
|
devicecontext->OMSetRenderTargets(1, &framebufferRTV, nullptr); |
|
devicecontext->OMSetBlendState(blendstate, nullptr, 0xffffffff); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
devicecontext->Draw(vertexcount, 0); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
swapchain->Present(1, 0); |
|
} |
|
} |