Jump to content
  • Advertisement
Sign in to follow this  
Psychopathetica

Simple DirectX9 Rendering Issue

This topic is 2542 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm having a hard time getting a simple square to draw in DirectX9, yet my code seems right. It runs but it remains a black screen on both fullscreen and windowed mode. Am I doing something wrong?


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

struct TLVERTEX
{
float X, Y, Z, RHW;
DWORD Color;
};

#define FVF_TLVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)

const D3DFORMAT COLOR_DEPTH_16_BIT = D3DFMT_R5G6B5;
const D3DFORMAT COLOR_DEPTH_24_BIT = D3DFMT_A8R8G8B8;
const D3DFORMAT COLOR_DEPTH_32_BIT = D3DFMT_X8R8G8B8;

LPDIRECT3D9 Direct3D = NULL;
LPDIRECT3DDEVICE9 Direct3D_Device = NULL;
D3DDISPLAYMODE Display_Mode;
D3DPRESENT_PARAMETERS Direct3D_Window;
HWND hWnd;

bool Fullscreen_Enabled;
bool Running;

TLVERTEX Vertex_List[3];

TLVERTEX Create_TLVertex();
void Main();
void DirectX9_Initialize();
void Create_Polygon();
void Render();
void Shutdown();
LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmd, int nShow)
{
MSG msg;

WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_VREDRAW|CS_HREDRAW|CS_OWNDC, WndProc, 0, 0, hInstance,
NULL, NULL, NULL, NULL, "DIRECTX9_TUTORIAL", NULL};

RegisterClassEx(&amp;amp;wc);

if (MessageBox(hWnd, "Click Yes to go to full screen (Recommended)", "", MB_ICONINFORMATION | MB_YESNO) == IDYES)
Fullscreen_Enabled = true;

if (Fullscreen_Enabled == true)
hWnd = CreateWindow("DIRECTX9_TUTORIAL", "DirectX9 Tutorial", WS_VISIBLE | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 800, 600, NULL, NULL, hInstance, NULL);
else
hWnd = CreateWindow("DIRECTX9_TUTORIAL", "DirectX9 Tutorial", WS_OVERLAPPEDWINDOW, 0, 0, 800, 600, NULL, NULL, hInstance, NULL);

ShowWindow(hWnd, nShow);
UpdateWindow(hWnd);

Main();

while (Running == true)
{
while(GetMessage(&amp;amp;msg, NULL, 0, 0))
{
TranslateMessage(&amp;amp;msg);
DispatchMessage(&amp;amp;msg);
}
}
Shutdown();
return(0);
}

TLVERTEX Create_TLVertex(float X, float Y, float Z, float RHW, DWORD Color)
{
TLVERTEX Vertex;

Vertex.X = X;
Vertex.Y = Y;
Vertex.Z = Z;
Vertex.RHW = RHW;
Vertex.Color = Color;

return Vertex;
}

void DirectX9_Initialize()
{
Direct3D = Direct3DCreate9(D3D_SDK_VERSION);
memset(&amp;amp;Direct3D_Window, 0, sizeof(D3DPRESENT_PARAMETERS));

if (Fullscreen_Enabled == true)
{
Display_Mode.Width = 800;
Display_Mode.Height = 600;
Display_Mode.Format = COLOR_DEPTH_16_BIT;
Direct3D_Window.Windowed = FALSE;
Direct3D_Window.BackBufferCount = 1;
Direct3D_Window.BackBufferWidth = Display_Mode.Width;
Direct3D_Window.BackBufferHeight = Display_Mode.Height;
Direct3D_Window.hDeviceWindow = hWnd;
}
else
{
Direct3D-&amp;gt;GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &amp;amp;Display_Mode);
Direct3D_Window.Windowed = TRUE;
}
Direct3D_Window.SwapEffect = D3DSWAPEFFECT_COPY;
Direct3D_Window.BackBufferFormat = Display_Mode.Format;
Direct3D-&amp;gt;CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &amp;amp;Direct3D_Window, &amp;amp;Direct3D_Device);
}

void Create_Polygon()
{
Vertex_List[0] = Create_TLVertex(0, 0, 0, 1, D3DCOLOR_RGBA(255, 255, 255, 255));
Vertex_List[1] = Create_TLVertex(100, 0, 0, 1, D3DCOLOR_RGBA(255, 255, 255, 255));
Vertex_List[2] = Create_TLVertex(0, 100, 0, 1, D3DCOLOR_RGBA(255, 255, 255, 255));
Vertex_List[3] = Create_TLVertex(100, 100, 0, 1, D3DCOLOR_RGBA(255, 255, 255, 255));
}

void Render()
{
Create_Polygon();
Direct3D_Device-&amp;gt;Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 1.0f, 0); // clear frame
Direct3D_Device-&amp;gt;BeginScene();
//Rendering code goes here
Direct3D_Device-&amp;gt;DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, Vertex_List, sizeof(TLVERTEX));
Direct3D_Device-&amp;gt;EndScene();
Direct3D_Device-&amp;gt;Present(NULL, NULL, NULL, NULL);
}

void Main()
{
DirectX9_Initialize();
Running = true;
}

void Shutdown()
{
Direct3D_Device-&amp;gt;Release();
Direct3D-&amp;gt;Release();
}

LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return(0);
case WM_PAINT:
Render();
ValidateRect(hWnd, NULL);
return(0);
case WM_KEYDOWN:
if(wParam == VK_ESCAPE)
Running = false;
DestroyWindow(hWnd);
return(0);
}
return(DefWindowProc(hWnd, msg, wParam, lParam));
}
</d3d9.h></windows.h>

Share this post


Link to post
Share on other sites
Advertisement
Have you stepped through your program to ensure that the methods are being called in the places that you expect them to be? It is also standard practice to always check the HRESULT from any API operations to see if they have failed. Similarly, you can see debug messages in the output window if there are errors detected by the runtime.

Finally, your best tool for debugging graphical errors is PIX. If you aren't familiar with it, spend a little time to read about it and try it out - you will learn lots about how your program is using the API by doing some inspection with PIX!

Share this post


Link to post
Share on other sites
As Jason Z mentioned, get to know, love and hate PIX smile.png

Some problems with your code:

You don't set an FVF or vertex declaration anywhere. Check this out for a guide on how to do that.
EDIT: I see that you declare the fvf, but don't actually set it. Just add this line

Direct3D_Device->SetFVF(FVF_TLVERTEX);

right before your DrawPrimitiveUP call.


You call Render() as a response to WM_PAINT messages. WM_PAINT is generally only sent when the window or a portion of it is invalidated (you resize the window, move another window over it, etc). Your program will usually be sitting around idling in the GetMessage function. In this case it won't matter, but as soon as you have any movement onscreen it will look like its not working because WM_PAINT isn't being sent, and thus Render() isn't being called. To draw frames even when there are no messages, use PeekMessage

It would look something like this:


while (running)
{
if (Peekmessage(msg, NULL, 0, 0, PM_REMOVE)
// process message

Render()
}

Share this post


Link to post
Share on other sites
Whoh thanks turch. I forgot one line of code biggrin.png

Direct3D_Device->SetFVF(FVF_TLVERTEX);


And yes I researched PeekMessage. Turns out it's best used in games. So I'm gonna stick with that.

Share this post


Link to post
Share on other sites
One other thing. How come in fullscreen mode my mouse icon constantly loads, yet in windowed mode it doesn't? Does it have something to do with me compiling in debug mode? Also my C++ IDE in windowed mode ends up getting in front of my app after playing, which is annoying. Would prefer my app to have focus when running. Im using Visual C++ 2008 Express Edition. Another thing is when I exit out of my app's exe, it remains in the process list.

Share this post


Link to post
Share on other sites
You need to set the cursor like so

wc.hCursor = LoadCursor(NULL, IDC_ARROW);


It actually doesn't work in windowed mode either, the cursor stays as whatever it was was when the mouse was moved over the window. There just happens to be a 1 pixel padding just inside the resize border which switches it to the pointer. If you move the mouse into the window quickly, the padding is skipped, and the cursor stays as the resizing one.

One more quick note, in your message handler, on a WM_KEYDOWN you test if the key is escape, but the if doesn't have braces. Because of this, you destroy the window on any keydown, but only exit the main loop when the key is escape (so the application continues to run with no window). However, even if you put the two lines in braces, the window can still be closed by hitting the X, in which case the window is destroyed but the loop continues running since no WM_KEYDOWN is sent. You can move the Running = false into the WM_DESTROY case, ensuring that if there is no window the application quits.


switch(msg)
{
case WM_DESTROY:
// move this here
Running = false;
////////////////
PostQuitMessage(0);
return(0);
case WM_PAINT:
Render();
ValidateRect(hWnd, NULL);
return(0);
case WM_KEYDOWN:
////////////////
//if(wParam == VK_ESCAPE)
//Running = false;
/////////////
DestroyWindow(hWnd);
return(0);
}

Share this post


Link to post
Share on other sites
Oh ok thanks for the tip. I redone the win32 window entirely and found a way to end the process with the help of 3 lines of code. So I'm gonna splice this in with my DX code. It also has focus rather than the IDE:


#include <windows.h>

LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
HWND hWnd;
MSG msg;
WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_VREDRAW|CS_HREDRAW|CS_OWNDC, WindowProcedure, 0, 0, hInstance, NULL, NULL, NULL, NULL, "DX_TUT", NULL};
RegisterClassEx(&wc);
hWnd = CreateWindowEx (0, "DX_TUT", "DirectX9 Tutorial", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 544, 375, HWND_DESKTOP, NULL, hInstance, NULL);
ShowWindow (hWnd, nCmdShow);
while (true)
{
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
if (WM_QUIT == msg.message) break;
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
return msg.wParam;
}

LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage (0);
HANDLE Process;
Process = OpenProcess(PROCESS_ALL_ACCESS , true , GetCurrentProcessId());
TerminateProcess(Process , 0);
break;
default:
return DefWindowProc (hWnd, msg, wParam, lParam);
}
return 0;
}

Share this post


Link to post
Share on other sites
I found out why my window wasn't havent focus. It's the messagebox prior to opening the window. And when my window opens, its there for a split second and ends up behind the IDE. Does anyone have a clue how to fix that? Sorry for all the questions I'm a little bit new to C++, yet have many years experience in VB and VB.Net.


#include <windows.h>

bool Fullscreen_Enabled;

LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
MSG msg;
WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_VREDRAW|CS_HREDRAW|CS_OWNDC, WindowProcedure, 0, 0, hInstance, NULL, NULL, NULL, NULL, "DX_TUT", NULL};
RegisterClassEx(&wc);

if (MessageBox(hWnd, "Click Yes to go to full screen (Recommended)", "", MB_ICONINFORMATION | MB_YESNO) == IDYES)
Fullscreen_Enabled = true;

if (Fullscreen_Enabled == true)
hWnd = CreateWindowEx (0, "DX_TUT", "DirectX9 Tutorial", WS_VISIBLE | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, 544, 375, HWND_DESKTOP, NULL, hInstance, NULL);
else
hWnd = CreateWindowEx (0, "DX_TUT", "DirectX9 Tutorial", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 544, 375, HWND_DESKTOP, NULL, hInstance, NULL);

ShowWindow (hWnd, nCmdShow);
while (true)
{
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
if (WM_QUIT == msg.message) break;
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
return msg.wParam;
}

LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage (0);
HANDLE Process;
Process = OpenProcess(PROCESS_ALL_ACCESS , true , GetCurrentProcessId());
TerminateProcess(Process , 0);
break;
default:
return DefWindowProc (hWnd, msg, wParam, lParam);
}
return 0;
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!