🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Draw a rectangle with DX11

Started by
13 comments, last by Aerodactyl55 1 year, 10 months ago

Hi,

I need to draw a simple rectangle (not a filled box) with directx 11.

I have found this code:

    const float x = 0.1;
    const float y = 0.1;
    const float height = 0.9;
    const float width = 0.9;
    
   VERTEX OurVertices[] =
    {
        { x, y, 0, col },
        { x + width, y, 0, col },
        { x, y + height, 0, col },
        { x + width, y, 0, col },
        { x + width, y + height, 0 , col },
        { x, y + height, 0, col }
    };

    static const XMVECTORF32 col = { 1.f, 2.f, 3.f, 4.f };

    // this is the function used to render a single frame
    void RenderFrameTest(void)
    {
        // float color[4] = { 0.0f, 0.2f, 0.4f, 1.0f };
        float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
    
        // clear the back buffer to a deep blue
        devcon->ClearRenderTargetView(backbuffer, color);
    
        // select which vertex buffer to display
        UINT stride = sizeof(VERTEX);
        UINT offset = 0;
    
         devcon->IASetVertexBuffers(0, 1, &pVBuffer, &stride, &offset);
        // select which primtive type we are using
      //   draw the vertex buffer to the back buffer
        devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
        devcon->Draw(sizeof(OurVertices) / sizeof(VERTEX), 0);
      
        swapchain->Present(0, 0);
    
    }
    
    

   
    void DrawRectangle(float x, float y, float width, float height, XMVECTORF32 col)
    {
        D3D11_BUFFER_DESC bd;
        ZeroMemory(&bd, sizeof(bd));
        bd.Usage = D3D11_USAGE_DYNAMIC;
        bd.ByteWidth = sizeof(OurVertices);
        bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
        bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
        HRESULT val = dev->CreateBuffer(&bd, NULL, &pVBuffer);                   // create the buffer
        D3D11_MAPPED_SUBRESOURCE ms;
        val = devcon->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);   // map the buffer
        memcpy(ms.pData, OurVertices, sizeof(OurVertices));                      // copy the data
        devcon->Unmap(pVBuffer, NULL);
    }

but the result is not what I expected:

I suspect the problem is OurVertices array and "D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP" but I don't have have experience with DirectX in general.

Can you help me please ?

Advertisement

Can you try TRIANGLE LIST and see what that does? The enum options are faily easy to find / Google

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

@cozzie Thank you if I set:

D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST

don't draw nothing, the window is empy.

I think you need to post more code. A think that the order of your vertices should not produce that triangle. The fact that nothing shows when you use triangle list suggests that there is something odd about how you set up the scene.

Edit: I realized that you are not using the typical 2D coords, so you can ignore my comments about the order of vertices.

I would recommend downloading https://github.com/walbourn/directx-sdk-samples

Inside you will find a folder called Direct3D11Tutorials and there you will find a file called Readme.docx.

It will have several links to msdn for basic tuts, for instance this is the second one…
https://docs.microsoft.com/en-us/previous-versions//ff729719(v=vs.85)

🙂🙂🙂🙂🙂<←The tone posse, ready for action.

@Aerodactyl55 Thank you here most of code:

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(WS_EX_LAYERED, L"WindowClass", L"Our First Direct3D Program", WS_POPUP, 300, 300, wr.right - wr.left, wr.bottom - wr.top, NULL, NULL, hInstance, NULL);
SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), RGB(255, 255, 255), LWA_COLORKEY);

ShowWindow(hWnd, nCmdShow);

// set up and initialize Direct3D
InitD3D(hWnd);

// enter the main loop:

MSG msg;

// RenderFrame();


while (TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);

if (msg.message == WM_QUIT)
break;
}


// RenderFrame();
RenderFrameTest();
}

// clean up DirectX and COM
CleanD3D();

return msg.wParam;
}




// 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);


// 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, NULL);


// Set the viewport
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = SCREEN_WIDTH;
viewport.Height = SCREEN_HEIGHT;

devcon->RSSetViewports(1, &viewport);

InitPipeline();
static const XMVECTORF32 s_MyValue = { 1.f, 2.f, 3.f, 4.f };

DrawRectangle(0.1, 0.1, 0.9, 0.9, s_MyValue);
}




// this is the function used to render a single frame
void RenderFrameTest(void)
{
// float color[4] = { 0.0f, 0.2f, 0.4f, 1.0f };
float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };

// clear the back buffer to a deep blue
devcon->ClearRenderTargetView(backbuffer, color);

// select which vertex buffer to display
UINT stride = sizeof(VERTEX);
UINT offset = 0;

devcon->IASetVertexBuffers(0, 1, &pVBuffer, &stride, &offset);
// select which primtive type we are using
// draw the vertex buffer to the back buffer
devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
devcon->Draw(sizeof(OurVertices) / sizeof(VERTEX), 0);


swapchain->Present(0, 0);

}



void DrawRectangle(float x, float y, float width, float height, XMVECTORF32 col)
{
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = sizeof(OurVertices);
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
HRESULT val = dev->CreateBuffer(&bd, NULL, &pVBuffer); // create the buffer
D3D11_MAPPED_SUBRESOURCE ms;
val = devcon->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms); // map the buffer
memcpy(ms.pData, OurVertices, sizeof(OurVertices)); // copy the data
devcon->Unmap(pVBuffer, NULL);
}


I don't see where you setup the rasterizer state, so I recommend you use triangle list and check the winding order of your vertices.

@undefined You have right just uppdated the code:

void DrawRectangle(float x, float y, float width, float height, XMVECTORF32 col)
{

   rasterDesc.AntialiasedLineEnable = false;
   rasterDesc.CullMode = D3D11_CULL_BACK;
   rasterDesc.DepthBias = 0;
   rasterDesc.DepthBiasClamp = 0.0f;
   rasterDesc.DepthClipEnable = false;
   rasterDesc.FillMode = D3D11_FILL_WIREFRAME;
   rasterDesc.FrontCounterClockwise = true;
   rasterDesc.MultisampleEnable = false;
   rasterDesc.ScissorEnable = false;
   rasterDesc.SlopeScaledDepthBias = 0.0f;

   HRESULT result = dev->CreateRasterizerState(&rasterDesc, &m_rasterState);
   if (FAILED(result)) return;
   devcon->RSSetState(m_rasterState);

   D3D11_BUFFER_DESC bd;
   ZeroMemory(&bd, sizeof(bd));
   bd.Usage = D3D11_USAGE_DYNAMIC;
   bd.ByteWidth = sizeof(OurVertices);
   bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
   bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
   HRESULT val = dev->CreateBuffer(&bd, NULL, &pVBuffer);                   // create the buffer
   D3D11_MAPPED_SUBRESOURCE ms;
   val = devcon->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);   // map the buffer
   memcpy(ms.pData, OurVertices, sizeof(OurVertices));                      // copy the data
   devcon->Unmap(pVBuffer, NULL);
}

and now draw a filled box but I need a rectangle. If I change to "D3D11_FILL_WIREFRAME" show 3 sides good but the 4° side is diagonal.

My inpression is that I need to use "DrawIndexed" and not "Draw". What you think ?

So what you want is a rectangle outline. DrawIndexed is recommended but it is not what is preventing you from achieving what you want.

You can draw the outline buy drawing 4 rectangles (one for each side of the outline).

Edit: You can also use 4 trapezoids to draw the outline, but you can stick to rectangles if you find that hard.

@Aerodactyl55 Thank you now work !! last question there is a way to set the rectangle coordinate in pixel ?

This topic is closed to new replies.

Advertisement