Movatterモバイル変換


[0]ホーム

URL:


Skip to content
Search Gists
Sign in Sign up

Instantly share code, notes, and snippets.

@d7samurai
Last activeAugust 24, 2025 05:57
    • Star(4)You must be signed in to star a gist
    • Fork(0)You must be signed in to fork a gist

    Select an option

    Save d7samurai/032c63fd91c400bc33fb79c9e74adc46 to your computer and use it in GitHub Desktop.
    Minimal D3D11 bonus material: even simpler 2D

    image

    Plain 2D rendering in D3D11, without the distracting feature set of acomplete sprite renderer and allowingarbitrarily placed triangle vertices with absolute pixel coordinate positioning (there's reallyno need for the sometimes confusing complication of a full-on projection matrix pipeline for UI and 2D games). Like theoriginal Minimal D3D11, this one uses a canonical 1:1TRIANGLELIST vertex buffer with input layout, so no fancy manual custom buffer fetching and in-shader instanced quad expansion here. As usual: complete, runnable single-function app. ~100 LOC. No modern C++, OOP or (other) obscuring cruft.

    This 'even simpler' variant renders solid color triangles; no texturing or alpha blending. For line drawing, changethis line to:

    devicecontext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
    #pragma comment(lib, "user32")
    #pragma comment(lib, "d3d11")
    #pragma comment(lib, "d3dcompiler")
    ///////////////////////////////////////////////////////////////////////////////////////////////////
    #include<windows.h>
    #include<d3d11.h>
    #include<d3dcompiler.h>
    ///////////////////////////////////////////////////////////////////////////////////////////////////
    int WINAPIWinMain(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 (see lines 94, 98)
    ///////////////////////////////////////////////////////////////////////////////////////////////
    ID3D11Texture2D* framebuffer;
    swapchain->GetBuffer(0,__uuidof(ID3D11Texture2D), (void**)&framebuffer);// get the swapchain's frame buffer
    ID3D11RenderTargetView* framebufferRTV;
    device->CreateRenderTargetView(framebuffer,nullptr, &framebufferRTV);// make a render target [view] from it
    FLOAT clearcolor[4] = {0.1725f,0.1725f,0.1725f,1.0f };// RGBA
    ///////////////////////////////////////////////////////////////////////////////////////////////
    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", "COL")
    {
    {"POS",0, DXGI_FORMAT_R32G32_FLOAT,0,0, D3D11_INPUT_PER_VERTEX_DATA,0 },// float2 position (x, y)
    {"COL",0, DXGI_FORMAT_R32G32B32_FLOAT,0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA,0 },// float3 color (r, g, b)
    };
    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 };// CULL_NONE to be agnostic of triangle winding order
    ID3D11RasterizerState* rasterizerstate;
    device->CreateRasterizerState(&rasterizerdesc, &rasterizerstate);
    D3D11_VIEWPORT viewport = {0,0, (float)swapchaindesc.BufferDesc.Width, (float)swapchaindesc.BufferDesc.Height,0,1 };
    ///////////////////////////////////////////////////////////////////////////////////////////////
    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;// constant buffer size must be multiple of 16
    constantbufferdesc.Usage = D3D11_USAGE_IMMUTABLE;// never updated
    constantbufferdesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    D3D11_SUBRESOURCE_DATA constantbufferSRD = { constants };
    ID3D11Buffer* constantbuffer;
    device->CreateBuffer(&constantbufferdesc, &constantbufferSRD, &constantbuffer);
    ///////////////////////////////////////////////////////////////////////////////////////////////
    #defineMAX_VERTICES1024// arbitrary limit
    structvertexdesc {float x, y, r, g, b; };// float2 position, float3 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);
    UINT stride =sizeof(vertexdesc);
    UINT offset =0;
    ///////////////////////////////////////////////////////////////////////////////////////////////
    while (true)
    {
    MSG msg;
    while (PeekMessageA(&msg,nullptr,0,0, PM_REMOVE))
    {
    if (msg.message == WM_KEYDOWN)return0;// PRESS ANY KEY TO EXIT
    DispatchMessageA(&msg);
    }
    ///////////////////////////////////////////////////////////////////////////////////////////
    D3D11_MAPPED_SUBRESOURCE vertexbufferMSR;
    devicecontext->Map(vertexbuffer,0, D3D11_MAP_WRITE_DISCARD,0, &vertexbufferMSR);
    {
    vertexdesc* vertex = (vertexdesc*)vertexbufferMSR.pData;
    vertex[0] = {150,100,1.0f,0.0f,0.0f };// vertex x, y, r, g, b
    vertex[1] = {200,250,0.0f,1.0f,0.0f };
    vertex[2] = {100,200,0.0f,0.0f,1.0f };
    }
    devicecontext->Unmap(vertexbuffer,0);
    ///////////////////////////////////////////////////////////////////////////////////////////
    devicecontext->ClearRenderTargetView(framebufferRTV, clearcolor);
    devicecontext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    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->OMSetRenderTargets(1, &framebufferRTV,nullptr);
    ///////////////////////////////////////////////////////////////////////////////////////////
    devicecontext->Draw(3,0);// draw 3 vertices
    ///////////////////////////////////////////////////////////////////////////////////////////
    swapchain->Present(1,0);
    }
    }
    cbuffer constants :register(b0)
    {
    float2 rn_screensize;// 2 / width, -2 / height
    }
    struct vertexdesc
    {
    float2 position : POS;
    float3 color : COL;
    };
    struct pixeldesc
    {
    float4 position :SV_POSITION;
    float4 color : COL;
    };
    pixeldescVsMain(vertexdesc vertex)
    {
    pixeldesc output;
    output.position =float4(vertex.position * rn_screensize -float2(1, -1),0,1);
    output.color =float4(vertex.color,1);
    return output;
    }
    float4PsMain(pixeldesc pixel) :SV_TARGET
    {
    return pixel.color;
    }
    Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

    [8]ページ先頭

    ©2009-2025 Movatter.jp