Problems drawing with DirectX

Started by
4 comments, last by MJP 15 years, 11 months ago
Right. So I've been trying to get my head around DirectX. I created a wrapper class for a Win32 Window and DirectX view, named WindowManager. Furthermore, I have a class named GraphicsManager used to handle rendering states and setup the projection. Then I have a namespace Shapes2D, that contains the function RectSolid to draw a solid rectangle. Now in main, I put it all together and nothing draws. So, I was wondering if anyone has any idea what I am doing wrong. WindowManager.h

/*
 * WindowManager.h
 * Manages the Window used by the Engine.
 *
 * Julius Parishy
 * http://iamjunkie.net/
 * Copyright (C) 2008
 *
 * zLib License
 */

#ifndef __WINDOWMANAGER__
#define __WINDOWMANAGER__

#include <windows.h>
#include <d3d9.h>
#include <iostream>

#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")

class WindowManager
{
private:
	HWND m_windowRef;
	MSG m_windowMsg;
	HINSTANCE m_hInstance;

	std::string m_windowTitle;

	int m_width;
	int m_height;

	IDirect3D9* m_d3dObject;
	IDirect3DDevice9* m_d3dDevice;

public:
	WindowManager(void);
	WindowManager(HINSTANCE instance, int width, int height, std::string title);
	~WindowManager(void);

	bool SetupWindow(HINSTANCE instance);
	bool DestroyWindow();
	bool Update();

	bool SetTitle(std::string newTitle);
	std::string Title() const;

	IDirect3DDevice9* GraphicsDevice() const { return m_d3dDevice; }

	int width() const { return m_width; }
	int height() const { return m_height; }
};

#endif /* __WINDOWMANAGER__ */

WindowManager.cpp

#include "WindowManager.h"

bool WindowDidQuit = false;

WindowManager::WindowManager(void)
{
	m_width = 100;
	m_height = 100;
	m_windowTitle = "DustyEngine";
}

WindowManager::WindowManager(HINSTANCE instance, int width, int height, std::string title)
{
	m_width = width;
	m_height = height;
	m_windowTitle = title;

	SetupWindow(instance);
}

WindowManager::~WindowManager(void)
{
	DestroyWindow();
	
	if(m_d3dObject)
		m_d3dObject->Release();

	if(m_d3dDevice)
		m_d3dDevice->Release();
}

#include <fstream>

LRESULT CALLBACK HandleMessages(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	if(msg == WM_DESTROY)
	{
		std::cout << "Window Manager received Destroy signal.\n";
		WindowDidQuit = true;

		std::fstream quit("./quit.txt", std::fstream::out);
		quit << "Quitting...\n";
		quit.close();
	}

	return ::DefWindowProc(hWnd, msg, wParam, lParam);
}

bool WindowManager::SetupWindow(HINSTANCE instance)
{
	WNDCLASS windowClass;
	windowClass.style = CS_HREDRAW|CS_VREDRAW;	
	windowClass.lpfnWndProc = HandleMessages;
	windowClass.cbClsExtra = 0;
	windowClass.cbWndExtra = 0;
	windowClass.hInstance = instance;
	windowClass.hIcon = ::LoadIcon(0, IDI_APPLICATION);
	windowClass.hCursor = ::LoadCursor(0, IDC_ARROW);
	windowClass.hbrBackground = static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH));
	windowClass.lpszMenuName = 0;
	windowClass.lpszClassName = m_windowTitle.c_str();

	if(!::RegisterClass(&windowClass))
	{
		std::cout << "Failed to register window class.\n";
		return false;
	}
	
	m_windowRef = ::CreateWindow(m_windowTitle.c_str(), m_windowTitle.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, instance, 0);
	if(!m_windowRef)
	{
		std::cout << "Failed to create window.\n";
		return false;
	}

	::ShowWindow(m_windowRef, 1);
	::UpdateWindow(m_windowRef);

	m_d3dObject = ::Direct3DCreate9(D3D_SDK_VERSION);
	if(!m_d3dObject)
	{
		std::cout << "Failed to create Direct3D Handle\n";
		return false;
	}
	
	D3DPRESENT_PARAMETERS d3dParams;
	::ZeroMemory(&d3dParams, sizeof(D3DPRESENT_PARAMETERS));

	d3dParams.Windowed = true;
	d3dParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dParams.BackBufferFormat = D3DFMT_UNKNOWN;

	if(FAILED(m_d3dObject->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_windowRef, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dParams, &m_d3dDevice)))
	{
		std::cout << "Failed to create Direct3D Device\n";
	}

	return true;
}

bool WindowManager::DestroyWindow()
{
	if(m_windowRef)
	{
	}

	return true;
}

bool WindowManager::Update()
{
	if(WindowDidQuit)
		::PostQuitMessage(0);

	::ZeroMemory(&m_windowMsg, sizeof(MSG));
	if(::PeekMessage(&m_windowMsg, 0, 0, 0, PM_REMOVE))
	{
		if(m_windowMsg.message == WM_QUIT)
		{
			std::fstream quit("./quit.txt", std::fstream::out);
			quit << "Quitting2...\n";
			quit.close();
			return false;
		}

		::TranslateMessage(&m_windowMsg);
		::DispatchMessage(&m_windowMsg);
	}

	return true;
}

GraphicsManager.h

/*
 * GraphicsManager.h
 * Defines the entry point for the engine.
 *
 * Julius Parishy
 * http://iamjunkie.net/
 * Copyright (C) 2008
 *
 * zLib License
 */

#ifndef __GRAPHICSMANAGER__
#define __GRAPHICSMANAGER__

#include <d3d9.h>
#include <d3dx9.h>

#include <iostream>

class GraphicsManager
{
private:
	IDirect3DDevice9* m_device;

	D3DXMATRIX m_viewMatrix;
	D3DXMATRIX m_projMatrix;

public:
	GraphicsManager(void);
	~GraphicsManager(void);

	void SetDevice(IDirect3DDevice9* device);

	void SetupProjection(int width, int height);

	void Clear();

	void StartScene();
	void EndScene();

	void Update();
};

#endif /* __GRAPHICSMANAGER__ */

GraphicsManager.cpp

#include "GraphicsManager.h"

GraphicsManager::GraphicsManager(void)
{
}

GraphicsManager::~GraphicsManager(void)
{
}

void GraphicsManager::SetDevice(IDirect3DDevice9* device)
{
	if(!device)
	{
		std::cout << "Failed to set graphics device.\n";
		return;
	}

	m_device = device;
}

void GraphicsManager::SetupProjection(int width, int height)
{
	D3DXVECTOR3 eye(0.0f, 0.0f, -5.0f);
	D3DXVECTOR3 look(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);

	D3DXMatrixLookAtLH(&m_viewMatrix, &eye, &look, &up);
	D3DXMatrixPerspectiveFovLH(&m_projMatrix, D3DX_PI / 2.0f, (float)width/(float)height, 1.0f, 100.0f);

	m_device->SetTransform(D3DTS_VIEW, &m_viewMatrix);
	m_device->SetTransform(D3DTS_PROJECTION, &m_projMatrix);
}

void GraphicsManager::Clear()
{
	m_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);
}

void GraphicsManager::StartScene()
{
	m_device->BeginScene();
}

void GraphicsManager::EndScene()
{
	m_device->EndScene();
}

void GraphicsManager::Update()
{
	m_device->Present(NULL, NULL, NULL, NULL);
}

Shapes2D.h

/*
 * Shapes2D.h
 * Defines 2D drawing of basic shapes
 *
 * Julius Parishy
 * http://iamjunkie.net/
 * Copyright (C) 2008
 *
 * zLib License
 */

#ifndef __SHAPES2D__
#define __SHAPES2D__

#include "DustyTypes.h"

#include <d3d9.h>

namespace Shapes2D
{
	enum DrawMethod
	{
		DM_SOLID,
		DM_OUTLINE,
	};

	::IDirect3DDevice9* s2dDevice;

	static void SetDevice(::IDirect3DDevice9* device)
	{
		if(!device)
		{
			::MessageBox(NULL, "Unable to set device!", "Error", 0);
			return;
		}

		::MessageBox(NULL, "Device has been set!", "Notice", 0);
		s2dDevice = device;
	}

	static void RectSolid(float x, float y, float w, float h, unsigned int color)
	{
		::IDirect3DVertexBuffer9* vBuf;
		if(FAILED(s2dDevice->CreateVertexBuffer(sizeof(VertexFC) * 6, D3DUSAGE_WRITEONLY, VERTEX_FC_MODE, D3DPOOL_DEFAULT, &vBuf, NULL)))
		{
			::MessageBox(NULL, "VertexBuffer Creation Failed.", "ERROR", MB_OK);
		}
		
		VertexFC verts[6] = {
			{ x, y, 10.0f, color },
			{ x + w, y, 10.0f, color },
			{ x + w, y + h, 10.0f, color },

			{ x, y, 10.0f, color },
			{ x + w, y + h, 10.0f, color },
			{ x, y + h, 10.0f, color },
		};

		vBuf->Lock(0, 0, (void**)&verts, 0);
		vBuf->Unlock();

		s2dDevice->SetStreamSource(0, vBuf, 0, sizeof(VertexFC));
		s2dDevice->SetFVF(VERTEX_FC_MODE);
		
		s2dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

		vBuf->Release();
	}
}

#endif

main.cpp

/*
 * main.cpp
 * Main game code setup and execution.
 *
 * Julius Parishy
 * http://iamjunkie.net/
 * Copyright (C) 2008
 *
 * zLib License
 */

#include "DustyEngineEntry.h"
#include "WindowManager.h"
#include "GraphicsManager.h"
#include "Shapes2D.h"

#include <iostream>
#include <vector>
#include <fstream>

int DustyMain()
{
	WindowManager* wm = new WindowManager(DUSTY_GET_HINSTANCE(), 640, 480, "DustyEngine");

	GraphicsManager* gm = new GraphicsManager();
	gm->SetDevice(wm->GraphicsDevice());

	Shapes2D::SetDevice(wm->GraphicsDevice());

	gm->SetupProjection(wm->width(), wm->height());

	while(wm->Update())
	{
		gm->Clear();
		gm->StartScene();

		Shapes2D::RectSolid(100, 100, 100, 100, D3DCOLOR_XRGB(0, 255, 0));

		gm->EndScene();

		gm->Update();
	}
	
	delete wm;
	delete gm;
	return 0;
}

Thanks guys!
Advertisement
Okay a few things here...

1. Your code for creating a vertex buffer looks pretty strange. Normally you don't want to be creating a vertex buffer every frame, it's a very expensive thing to do. Instead you can create it once, fill it with values, then leave those values alone until you really need to change them (which in most cases is never). Also you don't want to create your vertex buffer in D3DPOOL_DEFAULT in most cases. Resources in the DEFAULT pool are essentially locked into video memory and can't be moved off, and need to be re-created when the device is reset. You should use D3DPOOL_MANAGED for any resources that aren't dynamic.

2. You're filling the vertex buffer wrong. The Lock method doesn't actually fill the buffer...basically calling it is like saying "I want to get or set some values in the vertex buffer, so lock it so that only I can access it and give me a pointer to the data". That "ppbData" parameter is where you send a pointer that gets set to an area of memory, which is where you want to set your vertex values. So you want to do soemthing like this:

VertexFC verts[6] = {			{ x, y, 10.0f, color },			{ x + w, y, 10.0f, color },			{ x + w, y + h, 10.0f, color },			{ x, y, 10.0f, color },			{ x + w, y + h, 10.0f, color },			{ x, y + h, 10.0f, color },		};void* vbPointer;vBuf->Lock(0, 0, vbPointer, 0);memcpy(vbPointer, verts, sizeof(VertexFC) * 6);vBuf->Unlock();

Hey MJP, thanks for the help. Unfortunately, I tried doing the memcpy as you suggested and that did not seem to fix anything. I think something may be wrong else where, like my WindowManager. As for calling the CreateVertexBuffer function every frame, I am aware of the consequences, but I did not see a reason to optimize code that didn't work as of now. It shouldn't pose a problem, as far as I am aware.

Anyway, thanks a lot for the response. I'm new to DirectX and it hasn't been playing very nicely.
It may be as simple as looking from the wrong point.

Try changing your eye point from z=-15 to z=+15.

Triangles are "culled" ( not rendered ) if they are constructed counter-clockwise when viewed.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Thank you so much. I had not thought of that, but you were right. All that time and the vertex order was wrong. :|

Well, thanks a ton.
Back-face culling is enabled by default, but you can turn it off or set it to cull front-faces. Use IDirect3DDevice9::SetRenderState with D3DRS_CULLMODE and specify D3DCULL_NONE, D3DCULL_CW, or D3DCULL_CCW.

This topic is closed to new replies.

Advertisement