I'll post the whole working code, so that anyone who has the same problem can use this:
//-----------------------------------------------------------------------------// File: Vertices.cpp//// Desc: In this tutorial, we are rendering some Vertices. This introduces the// concept of the vertex buffer, a Direct3D object used to store// Vertices. Vertices can be defined any way we want by defining a// custom structure and a custom FVF (flexible vertex format). In this// tutorial, we are using Vertices that are transformed (meaning they// are already in 2D window coordinates) and lit (meaning we are not// using Direct3D lighting, but are supplying our own colors).//// Copyright (c) Microsoft Corporation. All rights reserved.//-----------------------------------------------------------------------------#include <d3d9.h>#include <d3dx9.h>#pragma warning( disable : 4996 ) // disable deprecated warning #pragma warning( default : 4996 )#include <stdexcept>#include <gdiplus.h>#include <atlimage.h>#include <strsafe.h>#include <Gdiplusimaging.h>#pragma comment( lib, "gdiplus.lib" )//-----------------------------------------------------------------------------// Global variables//-----------------------------------------------------------------------------LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDeviceLPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering deviceLPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // Buffer to hold VerticesLPDIRECT3DVERTEXBUFFER9 g_pVBTQ = NULL; // Buffer to hold Textured Quad verticesLPDIRECT3DTEXTURE9 g_pOORT = NULL; // TODO: Overlay offline render target// GDI+ stuffULONG_PTR gt;Gdiplus::GdiplusStartupInput gsi;void *g_pDIBData = NULL;// A structure for our custom vertex typestruct CUSTOMVERTEX{ FLOAT x, y, z, rhw; // The transformed position for the vertex DWORD color; // The vertex color};//Custom vertexstruct CUSTOMVERTEX2{ float x, y , z; float rhw; DWORD diffuse; float u, v;};// Our custom FVF, which describes our custom vertex structure#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)#define D3DFVF_CUSTOMVERTEX2 (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)//-----------------------------------------------------------------------------// Name: InitD3D()// Desc: Initializes Direct3D//-----------------------------------------------------------------------------HRESULT InitD3D( HWND hWnd ){ // Create the D3D object. if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; // Set up the structure used to create the D3DDevice D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof( d3dpp ) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // Create the D3DDevice if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ) { return E_FAIL; } // Device state would normally be set here g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); return S_OK;}//-----------------------------------------------------------------------------// Name: InitVB()// Desc: Creates a vertex buffer and fills it with our Vertices. The vertex// buffer is basically just a chuck of memory that holds Vertices. After// creating it, we must Lock()/Unlock() it to fill it. For indices, D3D// also uses index buffers. The special thing about vertex and index// buffers is that they can be created in device memory, allowing some// cards to process them in hardware, resulting in a dramatic// performance gain.//-----------------------------------------------------------------------------HRESULT InitVB(){ // Initialize three Vertices for rendering a triangle CUSTOMVERTEX Vertices[] = { { 300.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color { 400.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, }, { 200.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, }, }; CUSTOMVERTEX2 Vertices2[] = { {0, 0, 0, 1.0f, 0x00ffffff, 0, 0 }, //x, y, z, rhw, colour, u, v {256.0f, 0, 0, 1.0f, 0x00ffffff, 1.0f, 0 }, {256.0f, 256.0f, 0, 1.0f, 0x00ffffff, 1.0f, 1.0f }, {0, 256.0f, 0, 1.0f, 0x00ffffff, 0, 1.0f } }; // Create the vertex buffer. Here we are allocating enough memory // (from the default pool) to hold all our 3 custom Vertices. We also // specify the FVF, so the vertex buffer knows what data it contains. if( FAILED( g_pd3dDevice->CreateVertexBuffer(3 * sizeof( CUSTOMVERTEX ), D3DUSAGE_WRITEONLY, //TODO: Fixes D3D warning D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) ) { return E_FAIL; } if( FAILED( g_pd3dDevice->CreateVertexBuffer(4 * sizeof( CUSTOMVERTEX2 ), D3DUSAGE_WRITEONLY, //TODO: Fixes D3D warning D3DFVF_CUSTOMVERTEX2, D3DPOOL_DEFAULT, &g_pVBTQ, NULL ) ) ) { return E_FAIL; } // Now we fill the vertex buffer. To do this, we need to Lock() the VB to // gain access to the Vertices. This mechanism is required becuase vertex // buffers may be in device memory. VOID* pVertices; if( FAILED( g_pVB->Lock( 0, sizeof( Vertices ), ( void** )&pVertices, 0 ) ) ) return E_FAIL; memcpy( pVertices, Vertices, sizeof( Vertices ) ); g_pVB->Unlock(); VOID* pVertices2; if( FAILED( g_pVBTQ->Lock( 0, sizeof( Vertices2 ), ( void** )&pVertices2, 0 ) ) ) return E_FAIL; memcpy( pVertices2, Vertices2, sizeof( Vertices2 ) ); g_pVBTQ->Unlock(); return S_OK;}//-----------------------------------------------------------------------------// Name: InitOORT()// Desc: TODO//-----------------------------------------------------------------------------HRESULT InitOORT(){ // Create a blank texture if( FAILED( g_pd3dDevice->CreateTexture(512, 512, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_pOORT, NULL) ) ) { return E_FAIL; } // GDI+ stuff GdiplusStartup(>,&gsi,NULL); return S_OK;}//-----------------------------------------------------------------------------// Name: Cleanup()// Desc: Releases all previously initialized objects//-----------------------------------------------------------------------------VOID Cleanup(){ //GDI resources Gdiplus::GdiplusShutdown(gt); //D3D resources if( g_pVB != NULL ) g_pVB->Release(); if( g_pVBTQ != NULL ) g_pVBTQ->Release(); if ( g_pOORT != NULL ) g_pOORT->Release(); if( g_pd3dDevice != NULL ) g_pd3dDevice->Release(); if( g_pD3D != NULL ) g_pD3D->Release(); }void RenderOverlays(){ //Lock texture and render D3DLOCKED_RECT lockedRect; g_pOORT->LockRect(0, &lockedRect, NULL, 0); Gdiplus::Bitmap bitmap(512, 512, lockedRect.Pitch, PixelFormat32bppARGB , (BYTE*)lockedRect.pBits); Gdiplus::Graphics graphics( &bitmap ); graphics.Clear( Gdiplus::Color::Transparent ); Gdiplus::Pen pen( Gdiplus::Color::Red ); graphics.DrawLine(&pen, 10, 10, 120, 120); ::GdiFlush(); g_pOORT->UnlockRect(0);}//-----------------------------------------------------------------------------// Name: Render()// Desc: Draws the scene//-----------------------------------------------------------------------------VOID Render(){ // Clear the backbuffer to a blue color g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 ); // Render "offline" (outside render loop) RenderOverlays(); // Begin the scene if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Draw the triangles in the vertex buffer. This is broken into a few // steps. We are passing the Vertices down a "stream", so first we need // to specify the source of that stream, which is our vertex buffer. Then // we need to let D3D know what vertex shader to use. Full, custom vertex // shaders are an advanced topic, but in most cases the vertex shader is // just the FVF, so that D3D knows what type of Vertices we are dealing // with. Finally, we call DrawPrimitive() which does the actual rendering // of our geometry (in this case, just one triangle). g_pd3dDevice->SetTexture(0, NULL); g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) ); g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 ); // Set the texture on stage 0 g_pd3dDevice->SetTexture(0, g_pOORT); // Render a screen space quad g_pd3dDevice->SetStreamSource( 0, g_pVBTQ, 0, sizeof(CUSTOMVERTEX2) ); g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX2 ); g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 ); // End the scene g_pd3dDevice->EndScene(); } // Present the backbuffer contents to the display g_pd3dDevice->Present( NULL, NULL, NULL, NULL );}//-----------------------------------------------------------------------------// Name: MsgProc()// Desc: The window's message handler//-----------------------------------------------------------------------------LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){ switch( msg ) { case WM_DESTROY: Cleanup(); PostQuitMessage( 0 ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam );}//-----------------------------------------------------------------------------// Name: wWinMain()// Desc: The application's entry point//-----------------------------------------------------------------------------INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT ){ // Register the window class WNDCLASSEX wc = { sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle( NULL ), NULL, NULL, NULL, NULL, L"D3D Tutorial", NULL }; RegisterClassEx( &wc ); // Create the application's window HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial 02: Vertices", WS_OVERLAPPEDWINDOW, 128, 128, 512, 512, NULL, NULL, wc.hInstance, NULL ); // Initialize Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ) { // Create the vertex buffer and texture if( SUCCEEDED(InitVB()) && SUCCEEDED(InitOORT()) ) //TODO { // Show the window ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); // Enter the message loop MSG msg; ZeroMemory( &msg, sizeof( msg ) ); while( msg.message != WM_QUIT ) { if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else Render(); } } } DestroyWindow(hWnd); UnregisterClass( L"D3D Tutorial", wc.hInstance ); return 0;}
This is an altered version of the "Vertices.cpp" from the D3DSamples, Tutorial 02. Grab that sample from the SDK and replace Vertices.cpp's contents with what I pasted above.
As a final remark, this is just example code, to see how this works. Needless to say, when I add this functionality to my app, I won't use global variables, I'll respect OOP practices, encapsulate everything, etc. Hope that anyone who uses this code does the same, for the sake of anyone who will mantain his/her code in the future...