DX11: How do you draw a triangle?

Started by
6 comments, last by manders 14 years, 2 months ago
Due to the lack of easy-to-understand tutorials on the net, I am currently stuck trying to draw a triangle with DirectX 11. So far I've successfully managed to initialize these objects: - DX11 device - Swap-chain - A render target for rendering to the swap-chain's back-buffer - Device context (this is what you use to draw things, I presume) - A vertex buffer filled with three vertices (for the triangle) I've already set the render target and viewport for the device context. What is the next step to drawing the triangle? i.e. How to make DirectX read from my vertex buffer and draw it? Any help would be appreciated, Thanks
Advertisement
Quote:Original post by dadads
Due to the lack of easy-to-understand tutorials on the net, I am currently stuck trying to draw a triangle with DirectX 11.

So far I've successfully managed to initialize these objects:
- DX11 device
- Swap-chain
- A render target for rendering to the swap-chain's back-buffer
- Device context (this is what you use to draw things, I presume)
- A vertex buffer filled with three vertices (for the triangle)

I've already set the render target and viewport for the device context.

What is the next step to drawing the triangle?
i.e. How to make DirectX read from my vertex buffer and draw it?

Any help would be appreciated,
Thanks

Same way as in DX10, IIRC. You're just using the immediate context object (you got that from the CreateDevice through one of the parameters) instead of the device object itself.
clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.
From what I understand you need to create a vertex- and possibly (though I'm not entirely sure) a pixelshader and an input layout in order to draw your triangle. You can look up the BasicHLSL11 example under "Samples\C++\Direct3D11\BasicHLSL1". You can basically copy their example to render a simple triangle.

Assuming you've created the shaders. You will need to call:
-ID3D11DeviceContext::IASetInputLayout in order to tell D3D what vertex-data is must expect
-ID3D11DeviceContext::IASetVertexBuffers
-ID3D11DeviceContext::VSSetShader
(-ID3D11DeviceContext::PSSetShader)
-ID3D11DeviceContext::DrawIndexed

However I might be wrong with this, as I'm just starting with D3D11 myself (moving from D3D9) and currently struggling with the effects framework.
he does't have index buffer for triangle
so i suggest him to use just ID3D11DeviceContext::Draw or ID3D11DeviceContext::DrawAuto if possible
and to not hurt yourself with setting different VS/PS states he can use ID3DXEffect(but u have to compile it first)
Crazy dude smoking D3D11, AngelScript, PhysX, 3D Sound, Network, DB, FBX, and some other weird things, doing that on Visual Studio 2010 + Visual Assist X on Overclocked CPU
The D3D10 Basic Tutorials are pretty easy to follow. D3D11 is almost exactly the same, most of the time just renamed from 10 to 11.

EDIT: With 11 it might be easier to skip the effect framework in the beginning though, as others have said there are problems with it.
JollyJeffers posted a very simple starter application in his journal nearly a year ago now...

Keep in mind that it was developed when DX11 was still in beta form, but the basic drawing sequence should still be the same. I hope that helps!
*vomits

So much to do for a triangle!

Thanks for the info, I'll check them out.
Hi,

Here's source code for a pretty minimal app to draw a triangle in D3D11:

//--------------------------------------------------------------------------------------// File: Tutorial01.cpp//// This application displays a triangle rendered using Direct3D 11.//// Concepts introduced in this tutorial://     Creating a device and swap chain//     Compiling and creating shaders//     Setting up the render target and viewport//     Setting up a simple vertex buffer and its input layout//     Clearing the render target//     Drawing a triangle//     Presenting the rendered frame to the display//// Copyright (c) Microsoft Corporation. All rights reserved.//--------------------------------------------------------------------------------------#include <windows.h>#include <d3d11.h>#include <d3dcompiler.h>//--------------------------------------------------------------------------------------// Structures//--------------------------------------------------------------------------------------struct SimpleVertex{    FLOAT Pos[3]; // (X, Y, Z) coordinates of each vertex};//--------------------------------------------------------------------------------------// Global Variables//--------------------------------------------------------------------------------------HINSTANCE                   g_hInst = NULL;HWND                        g_hWnd = NULL;IDXGISwapChain*             g_pSwapChain = NULL;ID3D11Device*               g_pDevice = NULL;ID3D11DeviceContext*        g_pContext = NULL;ID3D11RenderTargetView*     g_pRenderTargetView = NULL;ID3D11InputLayout*          g_pInputLayout = NULL;ID3D11Buffer*               g_pVertexBuffer = NULL;ID3D11VertexShader*         g_pVertexShader = NULL;ID3D11PixelShader*          g_pPixelShader = NULL;//--------------------------------------------------------------------------------------// Vertex shader and pixel shader source code//--------------------------------------------------------------------------------------CHAR* g_strVS =     "void VS( in float4 posIn : POSITION,\n"    "         out float4 posOut : SV_Position )\n"    "{\n"    "    // Output the vertex position, unchanged\n"    "    posOut = posIn;\n"    "}\n";CHAR* g_strPS =     "void PS( out float4 colorOut : SV_Target )\n"    "{\n"    "    // Make each pixel yellow, with alpha = 1\n"    "    colorOut = float4( 1.0f, 1.0f, 0.0f, 1.0f );\n"    "}\n";//--------------------------------------------------------------------------------------// Forward declarations//--------------------------------------------------------------------------------------HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow );HRESULT InitDeviceAndSwapChain();HRESULT InitDeviceObjects();void InitDeviceContext();LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );void Render();void CleanupDevice();//--------------------------------------------------------------------------------------// Entry point to the program. Initializes everything and goes into a message processing // loop. Idle time is used to render the scene.//--------------------------------------------------------------------------------------int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ){    if( FAILED( InitWindow( hInstance, nCmdShow ) ) )        return 0;    if( FAILED( InitDeviceAndSwapChain() ) )        return 0;    if( FAILED( InitDeviceObjects() ) )    {        CleanupDevice();        return 0;    }    InitDeviceContext();    // Main message loop    MSG msg = { 0 };    while( WM_QUIT != msg.message )    {        if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )        {            TranslateMessage( &msg );            DispatchMessage( &msg );        }        else        {            Render();        }    }    CleanupDevice();    return (int)msg.wParam;}//--------------------------------------------------------------------------------------// Register class and create window//--------------------------------------------------------------------------------------HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ){    // Register class    WNDCLASSEX wcex;    wcex.cbSize = sizeof( WNDCLASSEX );    wcex.style = CS_HREDRAW | CS_VREDRAW;    wcex.lpfnWndProc = WndProc;    wcex.cbClsExtra = 0;    wcex.cbWndExtra = 0;    wcex.hInstance = hInstance;    wcex.hIcon = NULL;    wcex.hCursor = LoadCursor( NULL, IDC_ARROW );    wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );    wcex.lpszMenuName = NULL;    wcex.lpszClassName = L"TutorialWindowClass";    wcex.hIconSm = NULL;    if( !RegisterClassEx( &wcex ) )        return E_FAIL;    // Create window    g_hInst = hInstance;    RECT rc = { 0, 0, 640, 480 };    AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );    g_hWnd = CreateWindow( L"TutorialWindowClass", L"Direct3D 11 Tutorial 1: Triangle",                           WS_OVERLAPPEDWINDOW | WS_VISIBLE,                           CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top,                            NULL, NULL, hInstance, NULL );    if( !g_hWnd )        return E_FAIL;    return S_OK;}//--------------------------------------------------------------------------------------// Create the Direct3D device and DXGI swap chain//--------------------------------------------------------------------------------------HRESULT InitDeviceAndSwapChain(){    HRESULT hr = S_OK;    RECT rc;    GetClientRect( g_hWnd, &rc );    UINT width = rc.right - rc.left;    UINT height = rc.bottom - rc.top;    UINT createDeviceFlags = 0;#ifdef _DEBUG    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;#endif    D3D_DRIVER_TYPE driverTypes[] =    {        D3D_DRIVER_TYPE_HARDWARE,        D3D_DRIVER_TYPE_REFERENCE,    };    UINT numDriverTypes = _countof( driverTypes );    D3D_FEATURE_LEVEL featureLevels[] =     {        D3D_FEATURE_LEVEL_11_0,        D3D_FEATURE_LEVEL_10_1,        D3D_FEATURE_LEVEL_10_0,    };    UINT numFeatureLevels = _countof(featureLevels);    D3D_FEATURE_LEVEL featureLevelOut;    DXGI_SWAP_CHAIN_DESC sd;    ZeroMemory( &sd, sizeof( sd ) );    sd.BufferCount = 1;    sd.BufferDesc.Width = width;    sd.BufferDesc.Height = height;    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;    sd.BufferDesc.RefreshRate.Numerator = 60;    sd.BufferDesc.RefreshRate.Denominator = 1;    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;    sd.OutputWindow = g_hWnd;    sd.SampleDesc.Count = 1;    sd.SampleDesc.Quality = 0;    sd.Windowed = TRUE;    D3D_DRIVER_TYPE driverType;    for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )    {        driverType = driverTypes[driverTypeIndex];        hr = D3D11CreateDeviceAndSwapChain( NULL, driverType, NULL, createDeviceFlags,                                            featureLevels, numFeatureLevels, D3D11_SDK_VERSION,                                             &sd, &g_pSwapChain, &g_pDevice, &featureLevelOut,                                             &g_pContext );        if( SUCCEEDED( hr ) )            break;    }    return hr;}//--------------------------------------------------------------------------------------// Use the Direct3D device to create additional objects needed for rendering//--------------------------------------------------------------------------------------HRESULT InitDeviceObjects(){    HRESULT hr = S_OK;        // Create the render target view    ID3D11Texture2D* pRenderTargetTexture;    hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID*)&pRenderTargetTexture );    if( FAILED( hr ) )        return hr;    hr = g_pDevice->CreateRenderTargetView( pRenderTargetTexture, NULL, &g_pRenderTargetView );    pRenderTargetTexture->Release();    if( FAILED( hr ) )        return hr;    // Compile and create the vertex shader    DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS;#ifdef _DEBUG    dwShaderFlags |= D3D10_SHADER_DEBUG;#endif    ID3D10Blob* pBlobVS = NULL;    ID3D10Blob* pBlobError = NULL;    hr = D3DCompile( g_strVS, lstrlenA( g_strVS ) + 1, "VS", NULL, NULL, "VS",                      "vs_4_0", dwShaderFlags, 0, &pBlobVS, &pBlobError );    if( FAILED( hr ) )    {        if( pBlobError != NULL )        {            OutputDebugStringA( (CHAR*)pBlobError->GetBufferPointer() );            pBlobError->Release();        }        return hr;    }    hr = g_pDevice->CreateVertexShader( pBlobVS->GetBufferPointer(), pBlobVS->GetBufferSize(),                                         NULL, &g_pVertexShader );    if( FAILED( hr ) )        return hr;    // Compile and create the pixel shader    ID3D10Blob* pBlobPS = NULL;    hr = D3DCompile( g_strPS, lstrlenA( g_strPS ) + 1, "PS", NULL, NULL, "PS",                      "ps_4_0", dwShaderFlags, 0, &pBlobPS, &pBlobError );    if( FAILED( hr ) )    {        if( pBlobError != NULL )        {            OutputDebugStringA( (CHAR*)pBlobError->GetBufferPointer() );            pBlobError->Release();        }        return hr;    }    hr = g_pDevice->CreatePixelShader( pBlobPS->GetBufferPointer(), pBlobPS->GetBufferSize(),                                        NULL, &g_pPixelShader );    if( FAILED( hr ) )        return hr;    pBlobPS->Release();    // Create the input layout    D3D11_INPUT_ELEMENT_DESC elements[] =    {        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },    };    UINT numElements = _countof( elements );    hr = g_pDevice->CreateInputLayout( elements, numElements, pBlobVS->GetBufferPointer(),                                       pBlobVS->GetBufferSize(), &g_pInputLayout );    if( FAILED( hr ) )        return hr;    pBlobVS->Release();    // Create the vertex buffer    SimpleVertex vertices[] =    {        0.0f, 0.5f, 0.5f,        0.5f, -0.5f, 0.5f,        -0.5f, -0.5f, 0.5f,    };    D3D11_BUFFER_DESC bd;    bd.Usage = D3D11_USAGE_DEFAULT;    bd.ByteWidth = sizeof( vertices );    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;    bd.CPUAccessFlags = 0;    bd.MiscFlags = 0;    bd.StructureByteStride = 0;    D3D11_SUBRESOURCE_DATA initData;    initData.pSysMem = vertices;    hr = g_pDevice->CreateBuffer( &bd, &initData, &g_pVertexBuffer );    if( FAILED( hr ) )        return hr;    return hr;}//--------------------------------------------------------------------------------------// Set up the device context//--------------------------------------------------------------------------------------void InitDeviceContext(){    g_pContext->IASetInputLayout( g_pInputLayout );    UINT stride = sizeof( SimpleVertex );    UINT offset = 0;    g_pContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );    g_pContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );    g_pContext->VSSetShader( g_pVertexShader, NULL, 0 );    g_pContext->PSSetShader( g_pPixelShader, NULL, 0 );    RECT rc;    GetClientRect( g_hWnd, &rc );    D3D11_VIEWPORT vp;    vp.Width = (FLOAT)(rc.right - rc.left);    vp.Height = (FLOAT)(rc.bottom - rc.top);    vp.MinDepth = 0.0f;    vp.MaxDepth = 1.0f;    vp.TopLeftX = 0;    vp.TopLeftY = 0;    g_pContext->RSSetViewports( 1, &vp );    g_pContext->OMSetRenderTargets( 1, &g_pRenderTargetView, NULL );}//--------------------------------------------------------------------------------------// Called every time the application receives a message//--------------------------------------------------------------------------------------LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ){    PAINTSTRUCT ps;    HDC hdc;    switch( message )    {        case WM_PAINT:            hdc = BeginPaint( hWnd, &ps );            EndPaint( hWnd, &ps );            break;        case WM_CHAR:            if( wParam == VK_ESCAPE )                DestroyWindow( hWnd );            break;        case WM_DESTROY:            PostQuitMessage( 0 );            break;        default:            return DefWindowProc( hWnd, message, wParam, lParam );    }    return 0;}//--------------------------------------------------------------------------------------// Render a frame//--------------------------------------------------------------------------------------void Render(){    // Clear the render target to dark blue    float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // red, green, blue, alpha    g_pContext->ClearRenderTargetView( g_pRenderTargetView, ClearColor );    // Render a triangle    g_pContext->Draw( 3, 0 );    // Show the rendered frame on the screen    g_pSwapChain->Present( 0, 0 );}//--------------------------------------------------------------------------------------// Destroy the objects we've created//--------------------------------------------------------------------------------------void CleanupDevice(){    if( g_pVertexShader != NULL )        g_pVertexShader->Release();    if( g_pPixelShader != NULL )        g_pPixelShader->Release();    if( g_pVertexBuffer != NULL )        g_pVertexBuffer->Release();    if( g_pInputLayout != NULL )        g_pInputLayout->Release();    if( g_pRenderTargetView != NULL )        g_pRenderTargetView->Release();    if( g_pContext != NULL )        g_pContext->Release();    if( g_pSwapChain != NULL )        g_pSwapChain->Release();    if( g_pDevice != NULL )        g_pDevice->Release();}


Hope that helps.

-Mike

This topic is closed to new replies.

Advertisement