Help! Trying to render a triangle!

Started by
14 comments, last by DanoruX 18 years, 4 months ago
I've just started directx, and am trying to get one, yes ONE, triangle to show up on the screen. Apparently my code fails to do so, but doesn't crash! Please help me :)
/* WinMain */
#include <windows.h>
#include <stdio.h>
#include <stdarg.h>
#include <d3d9.h>
#include <d3dx9.h>

HINSTANCE g_hInst; // global instance handle
HWND g_hWnd; // global window handle

#define WNDHEIGHT 480
#define WNDWIDTH 640
#define WNDTYPE WS_OVERLAPPEDWINDOW
#define CUSTOMFVF (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
const char g_szClass[] = "FrameClass";
const char g_szCaption[] = "DirectX 9 Demo";

// prototypes
HRESULT setupvb();

// entry point
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow);

// Function to display an error message
void AppError(BOOL Fatal, char *Text, ...);

// Message procedure
long FAR PASCAL WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lparam);

// Functions to register and unregister windows classes
BOOL RegisterWindowClasses(HINSTANCE hInst);
BOOL UnregisterWindowClasses(HINSTANCE hInst);

// Function to create the application window
HWND CreateMainWindow(HINSTANCE hInst);

// Functions to init, shutdown, and handle per-frame functions
BOOL DoInit();
BOOL DoShutdown();
BOOL DoPreFrame();
BOOL DoFrame();
BOOL DoPostFrame();

IDirect3D9 *g_D3D; // global IDirect3D9 object
IDirect3DDevice9 *g_D3DDevice;
D3DDISPLAYMODE d3ddm;
D3DPRESENT_PARAMETERS d3dpp;
HWND hWnd;

// Stuff for the triangle to be drawn
struct _vertex
{
    float x, y, z, rhw;
	DWORD color;
};

typedef struct _vertex vertex;

IDirect3DVertexBuffer9 *g_VB;

// Functions
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
{

	MSG Msg;

	// Save application instance
	g_hInst = hInst;

	// Register window classes - return on FALSE
	if(RegisterWindowClasses(hInst) == FALSE)
	{
		return FALSE;
	}

	// create window - return on FALSE
	if((g_hWnd = CreateMainWindow(hInst)) == NULL)
	{
		return FALSE;
	}

	// Do application initialization - return on false
	if(DoInit() == TRUE)
	{
		setupvb();

        // Enter the message pump
		ZeroMemory(&Msg, sizeof(MSG));
		while(Msg.message != WM_QUIT)
		{
			//handle windows messages if any
			if(PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
			{
				TranslateMessage(&Msg);
				DispatchMessage(&Msg);
			}
			else
			{
				// do pre-frame processing, break on FALSE return value
				if(DoPreFrame() == FALSE){ break; }

				// do per-frame processing, break on FALSE return value
				if(DoFrame() == FALSE){ break; }

				// do post-frame processing, break on FALSE...
				if(DoPostFrame() == FALSE){ break; }

			}
		}
	}

	// do shutdown functions
	DoShutdown();

	// unregister window
	UnregisterWindowClasses(hInst);

	return TRUE;
}

BOOL RegisterWindowClasses(HINSTANCE hInst)
{
	WNDCLASSEX wcex;

	// Create the window class here and register it
	wcex.cbSize = sizeof(wcex);
	wcex.style = CS_CLASSDC;
	wcex.lpfnWndProc = WindowProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = hInst;
	wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+2);
	wcex.lpszMenuName = NULL;
	wcex.lpszClassName = g_szClass;
	wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

	if(!RegisterClassEx(&wcex)) { return FALSE; }

	return TRUE;
}

BOOL UnregisterWindowClasses(HINSTANCE hInst)
{
	// Unregister the window class
	UnregisterClass(g_szClass, hInst);
	return TRUE;
}

HWND CreateMainWindow(HINSTANCE hInst)
{
	// create main window
	hWnd = CreateWindow(g_szClass, 
						g_szCaption, 
						WNDTYPE, 
						0, 
						0, 
						WNDWIDTH, 
						WNDHEIGHT, 
						NULL, 
						NULL, 
						hInst, 
						NULL);

	if(!hWnd) { return NULL; }

	// show and update window
	ShowWindow(hWnd, SW_SHOW);
	UpdateWindow(hWnd);

	// return handle
	return hWnd;
}

void AppError(BOOL Fatal, char *Text, ...)
{
	char CaptionText[12];
	char ErrorText[2048];
	va_list valist;

	// Build the message box caption based on fatal flag
	if(Fatal == FALSE){ strcpy(CaptionText, "Error"); }
	else			  { strcpy(CaptionText, "Fatal Error"); }

	// build variable text buffer
	va_start(valist, Text);
	vsprintf(ErrorText, Text, valist);

	va_end(valist);

	// display the message box
	MessageBox(NULL, ErrorText, CaptionText, MB_OK | MB_ICONEXCLAMATION);

	// Post a quite message if errorwas fatal
	if(Fatal == TRUE)
	{
		PostQuitMessage(0);
	}
}

long FAR PASCAL WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uMsg)
	{
		case WM_DESTROY: PostQuitMessage(0); return 0; 
	}

	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

BOOL DoInit()
{
	// perform application initialization functions here such as those
	// that set up gfx, sound, network, etc.
	// return true for success, false otherwise
	g_D3D = NULL;
	g_D3DDevice = NULL;
	D3DDISPLAYMODE d3ddm;
	D3DPRESENT_PARAMETERS d3dpp;

	if((g_D3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
	{
		return FALSE;
	}
	
	d3ddm.Width = WNDWIDTH;
	d3ddm.Height = WNDHEIGHT;
	d3ddm.RefreshRate = 0;
	d3ddm.Format = D3DFMT_A8R8G8B8;

	if(FAILED(g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
	{
		return FALSE;
	}

	ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));

	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferWidth = WNDWIDTH;
	d3dpp.BackBufferCount = WNDHEIGHT;
	d3dpp.BackBufferFormat = d3ddm.Format;
	d3dpp.BackBufferCount = 1;
	d3dpp.hDeviceWindow = hWnd;

	if (FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT,
									D3DDEVTYPE_HAL, 
									g_hWnd,
									D3DCREATE_SOFTWARE_VERTEXPROCESSING,
									&d3dpp,
									&g_D3DDevice)))
	{
		AppError(true, "Something crashed while creating a DX9 device");
		return FALSE;
	}

	return TRUE;
}

BOOL DoShutdown()
{
	// perform application shutdown functions
	if(g_D3DDevice != NULL)
	{
		g_D3DDevice->Release();
	}
	if(g_D3D != NULL)
	{
		g_D3D->Release();
	}
	return TRUE;
}

BOOL DoPreFrame()
{
	// perform preframe processing
	return TRUE;
}

BOOL DoFrame()
{
	// perform per-frame processing
	if (g_D3DDevice == NULL)
	{
		return FALSE;
	}
	g_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET,
						D3DCOLOR_XRGB(0,0,0), 1.0f, 0);

	g_D3DDevice->BeginScene();

	g_D3DDevice->SetStreamSource(0, g_VB, 0, sizeof(g_VB));
	g_D3DDevice->SetFVF(CUSTOMFVF);
	g_D3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 1);

	g_D3DDevice->EndScene();

	g_D3DDevice->Present(NULL,NULL,NULL,NULL);

	return TRUE;
}

BOOL DoPostFrame()
{
	// perform post-frame processing
	return TRUE;
}

HRESULT setupvb()
{
    vertex v[3] = {{0.0f, 100.0f, 0.5f, 1.0f, D3DCOLOR_ARGB(0,255,10,110)},
				{000.0f, 0.0f, 0.5f, 1.0f, D3DCOLOR_ARGB(0,100,10,255)},
				{100.0f, 0.0f, 0.5f, 1.0f, D3DCOLOR_ARGB(0,110,255,110)}};

	g_D3DDevice->CreateVertexBuffer(3*sizeof(vertex), D3DUSAGE_WRITEONLY, (D3DFVF_XYZRHW|D3DFVF_DIFFUSE), D3DPOOL_MANAGED, &g_VB, NULL);

	VOID *ptr;

	g_VB->Lock(0,0,(void**)&ptr, 0);
	
	memcpy(ptr, v, sizeof(v));

	g_VB->Unlock();

	return S_OK;
}
Advertisement
Hi, I can't see that you've called setupvb() anywhere? otherwise it seems to look ok.
Quote:Original post by Stevieboy
Hi, I can't see that you've called setupvb() anywhere? otherwise it seems to look ok.


I called it right after I initialize directx in the winmain()
Does your screen clear to the background colour?
Quote:Original post by Stevieboy
Does your screen clear to the background colour?


Only before beginscene(), as far as I understand:

BOOL DoFrame()
{
// perform per-frame processing
if (g_D3DDevice == NULL)
{
return FALSE;
}
g_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET,
D3DCOLOR_XRGB(0,0,0), 1.0f, 0);

g_D3DDevice->BeginScene();

g_D3DDevice->SetStreamSource(0, g_VB, 0, sizeof(g_VB));
g_D3DDevice->SetFVF(CUSTOMFVF);
g_D3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 1);

g_D3DDevice->EndScene();

g_D3DDevice->Present(NULL,NULL,NULL,NULL);

return TRUE;
}
There you go,

g_VB->Lock(0,0,(void**)&ptr, 0);

should be

g_VB->Lock(0, sizeof(v), (void**)&ptr, 0);



quote;
Only before beginscene(), as far as I understand:

Yeah thats alright, I was just checking to see if the d3d device was working, if the screen doesn't cleasr then you'd know you'd forgotten somethng with the device.
Quote:Original post by Stevieboy
There you go,

g_VB->Lock(0,0,(void**)&ptr, 0);

should be

g_VB->Lock(0, sizeof(v), (void**)&ptr, 0);


I changed setupvb() to:

HRESULT setupvb()
{
vertex v[3] = {{0.0f, 100.0f, 0.5f, 1.0f, D3DCOLOR_ARGB(0,255,10,110)},
{000.0f, 0.0f, 0.5f, 1.0f, D3DCOLOR_ARGB(0,100,10,255)},
{100.0f, 0.0f, 0.5f, 1.0f, D3DCOLOR_ARGB(0,110,255,110)}};

g_D3DDevice->CreateVertexBuffer(sizeof(v), D3DUSAGE_WRITEONLY, CUSTOMFVF, D3DPOOL_DEFAULT, &g_VB, NULL);

VOID *ptr;

g_VB->Lock(0, sizeof(v), (void**)&ptr, 0);

memcpy(ptr, v, sizeof(v));

g_VB->Unlock();

return S_OK;
}


....and it still shows black. The fix you provided makes sense though... *goes on looking for things he overlooked*
lol this is getting to be fun..



g_D3DDevice->CreateVertexBuffer(sizeof(v), D3DUSAGE_WRITEONLY, CUSTOMFVF, D3DPOOL_DEFAULT, &g_VB, NULL);

That should be 3*sizeof(v), lol, its funny how it changes around, what should go where.
Edit: actually that should be 3 times the size of your custom vertex fvf.

This is the init vb code from the "vertices" tutorial.

 HRESULT InitVB(){    // Initialize three vertices for rendering a triangle    CUSTOMVERTEX vertices[] =    {        { 150.0f,  50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color        { 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },        {  50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, },    };    // 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),                                                  0, D3DFVF_CUSTOMVERTEX,                                                  D3DPOOL_DEFAULT, &g_pVB, 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();    return S_OK;} 



Have you checked out the sdk tutorials, they have exactly what you are trying to do.
Here's what I have after adjusting my code to the sample:

HRESULT setupvb()
{
cvertex v[] = {{0.0f, 100.0f, 0.5f, 1.0f, D3DCOLOR_ARGB(0,255,10,110)},
{000.0f, 0.0f, 0.5f, 1.0f, D3DCOLOR_ARGB(0,100,10,255)},
{100.0f, 0.0f, 0.5f, 1.0f, D3DCOLOR_ARGB(0,110,255,110)}};

if( FAILED(g_D3DDevice->CreateVertexBuffer(3*sizeof(cvertex), 0, CUSTOMFVF, D3DPOOL_DEFAULT, &g_VB, NULL)))
{
return E_FAIL;
}

VOID *ptr;

g_VB->Lock(0, sizeof(v), (void**)&ptr, 0);

memcpy(ptr, v, sizeof(v));

g_VB->Unlock();

return S_OK;
}

Still doesn't work. It makes no sense! Is there a way to check if the vertices are being drawn at all in any form or shape?
ok, ive been looking at this code for what seems like 2 hours, and i came to this, you need to disable culling and disable lighting. You should also clear the backbuffer to another color that isnt black or white (like red or green, some good looking mix)

to disable lighting and culling:
BOOL DoPreFrame(){	g_D3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);	g_D3DDevice->SetRenderState(D3DRS_LIGHTING, false);	// perform preframe processing	return TRUE;}


but with that ive got a triangle up, its just its in the upper left corner and ive been trying like every combination to move around the triangles, and nothing works, i swear, sometimes i do some simple stuff and the triangle disapears, rhw is stupid! use orthagonal matrixes instead, its so much easier

This topic is closed to new replies.

Advertisement