Sprites and D3D9

Started by
30 comments, last by falcon93 12 years, 7 months ago
[color="#1c2837"]
Graphics::Graphics(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);

ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));

d3dpp.Windowed = true;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = 1280;
d3dpp.BackBufferHeight = 800;

D3DXCreateSprite(d3ddev, &sprite);

HRESULT hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
}

You call D3DXCreateSprite with d3ddev as a parameter. Then in the line following it you create d2ddev, since this is your constructor and I don't see you setting d3ddev to NULL it would be logical to assume that they crash happens in D3DXCreateSprite since you pass it a invalid pointer (unless you are using VS in debug mode which I think sets all uninitialized variables to 0). Also you should error check these functions (d3d != NULL, d3d->CreateDevice(...) != S_OK).
Advertisement
Oh, thanks, it worked at and made sence too :) Thanks. I'll add error checking to, there's however a small problem more:

So, it builds fine, but the texture I try to draw on the screen isn't showing? Graphics.cpp code below:

[source lang="cpp"]

#include "Graphics.h"


Graphics::Graphics(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);

ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));

d3dpp.Windowed = true;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = 1280;
d3dpp.BackBufferHeight = 800;

HRESULT hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);

D3DXCreateSprite(d3ddev, &sprite);

D3DXCreateTextureFromFile(d3ddev, L"texture.jpg", &texture);

position.x = 100;
position.y = 100;
position.z = 0;
}


Graphics::~Graphics(void)
{
}


// --------------------------------------------------------------------------------
// Name: Begin
// Desc:
// Rtrn: None
// --------------------------------------------------------------------------------
void Graphics::Begin(void)
{
sprite->Begin(D3DXSPRITE_ALPHABLEND);
}


// --------------------------------------------------------------------------------
// Name: Draw
// Desc:
// Rtrn: None
// --------------------------------------------------------------------------------
void Graphics::Draw(void)
{
sprite->Draw(texture, NULL, NULL, &position, 0xFFFFFFFF);
}


// --------------------------------------------------------------------------------
// Name: End
// Desc:
// Rtrn: None
// --------------------------------------------------------------------------------
void Graphics::End(void)
{
sprite->End();
}
[/source]
It has been ages since I last looked at D3D9 but I think that you should check out the following.
1. Error check texture loading, make sure its loaded!
2. I don't know to what extend d3dxsprite sets its own rendering states (try searching the help files that come with the sdk) but you might want to try to turn of lighting (again its in the help files).
3. I don't see any d3ddev->Clear(...), d3ddev->BeginScene() d3ddev->EndScene() and d3ddev->Present(...). Do you call them somewhere else?

Maybe its a good idea to check out the tutorials in the help files, make your application mimic the the one that only draws a triangle and remove the triangle code and insert sprite begin, draw, end.
Do I have to use the clear, beginscene, endscene and present even with Sprite?

I started off by fixing the Clear method and choosing it to clear with black, but it gives me strange results. In fullscreen my application background is black, but when I run it windowed it is white? And I notice it gets really laggy when I run Clear?

Do I have to use the clear, beginscene, endscene and present even with Sprite?

I started off by fixing the Clear method and choosing it to clear with black, but it gives me strange results. In fullscreen my application background is black, but when I run it windowed it is white? And I notice it gets really laggy when I run Clear?


Yes they are essential. You should try to structure your program like this:


int WINAPI WinMain(...)
{
//create your window
...

//create graphics
Graphics g(hwnd);
//create a way to check if this was successful or better move the initialization into a separate method
if (!g.init(hwnd))
{
//FAIL, I can't stress it enough if you are serious about finding the problem you have to rule out bogus function calls with error checking
}

//maybe a separate method to load the texture(s)?

//your game loop
while (gameNotClosed)
{
//update window

//begin the scene
g.beginScene(); //which calls d3ddev->Clear d3ddev->BeginScene()

//draw sprite
g.begin(); //which calls sprite->begin(), and try turning of alpha blending for the moment
g.draw(); //which calls the drawing function on the sprite
g.end(); //which calls sprite->end();

//EDIT: and ofcourse EndScene()
g.endScene();
}

return 0;
}


And ofcourse do not use the standard updatewindow function to acquire window messages, try searching the forums for "game loop" I think on windows you should use PeekMessage to acquire the messages but I haven't been on a windows platform for a while so I can't say for sure.
Are you clearing the Z-Buffer? If you are clearing the z-buffer when you didn't create one you may run into some artifacts/problems! The sprite Draw(), Begin() and End() methods must be called between BeginScene() and EndScene() pair.

What header do I have to include to use TDWORD and wstring? Also, I've checked for null values with if statements but didin't find any.

Regarding the Debug Runtimes. This is the window, but now I don't know what to change? Your path worked untill this window :P
hw0qcy.jpg



@Aerodactyl55:[color="#1c2837"] I'm calling it?
[color="#1c2837"]
Graphics::Graphics(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);

ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));

d3dpp.Windowed = true;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = 1280;
d3dpp.BackBufferHeight = 800;

D3DXCreateSprite(d3ddev, &sprite);

HRESULT hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
}



Thank you btoh for helping me appreciated :)


you need to select the "Use The Debug Version Of Direct3D 9"

Never say Never, Because Never comes too soon. - ryan20fun

Disclaimer: Each post of mine is intended as an attempt of helping and/or bringing some meaningfull insight to the topic at hand. Due to my nature, my good intentions will not always be plainly visible. I apologise in advance and assure you I mean no harm and do not intend to insult anyone.

Ok, I solved it by simply add the BeginScene, EndScene and Present methods. Everything works well now, my current code is below (some of the code in main.cpp is just temporary)



Main.cpp
[source lang="cpp"]

#include <Windows.h>
#include "Main.h"
#include "Graphics.h"
#include "Input.h"


Graphics* graphics;
Input* input;


LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY: PostQuitMessage(0); return 0;
}

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


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));

wc.cbSize = sizeof(WNDCLASSEX);
wc.hInstance = hInstance;
wc.lpfnWndProc = WindowProc;
wc.lpszClassName = L"AvoidBallClass";
wc.style = CS_VREDRAW | CS_HREDRAW;

RegisterClassEx(&wc);

HWND hWnd;
hWnd = CreateWindowEx(NULL, L"AvoidBallClass", L"AvoidBall", WS_OVERLAPPED, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);

MSG msg;

graphics = new Graphics(hWnd);
input = new Input();

// Temporary
LPDIRECT3DTEXTURE9 texture;
texture = graphics->LoadTexture(L"spitfire.png");
D3DXVECTOR3 pos;
pos.x = 0;
pos.y = 0;
pos.z = 0;
RECT rectangle;
rectangle.bottom = 400;
rectangle.top = 0;
rectangle.right = 100;
rectangle.left = 0;

while (true)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

graphics->Begin();
graphics->Draw(texture, pos, 0);
graphics->End();

if (input->ButtonDownOnce(VK_ESCAPE))
{
PostQuitMessage(0);
return 0;
}
}

// TODO: Clean up resources.

return msg.wParam;
}
[/source]



Graphics.cpp
[source lang="cpp"]

#include "Graphics.h"


Graphics::Graphics(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);

ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));

d3dpp.Windowed = true;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = 1280;
d3dpp.BackBufferHeight = 800;

d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);

D3DXCreateSprite(d3ddev, &sprite);
}


Graphics::~Graphics(void)
{
}


// --------------------------------------------------------------------------------
// Name: Begin
// Desc: Prepares a device for drawing
// Rtrn: None
// --------------------------------------------------------------------------------
void Graphics::Begin(void)
{
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 255, 255), 1, 0);
d3ddev->BeginScene();
sprite->Begin(D3DXSPRITE_ALPHABLEND);
}


// --------------------------------------------------------------------------------
// Name: Draw
// Desc: Draws a texture to the screen
// Rtrn: None
// --------------------------------------------------------------------------------
void Graphics::Draw(LPDIRECT3DTEXTURE9 texture, D3DXVECTOR3 position, int alpha)
{
color = D3DCOLOR_COLORVALUE(0, 0, 0, alpha);
sprite->Draw(texture, NULL, NULL, &position, 0xFFFFFFFF);
}


// --------------------------------------------------------------------------------
// Name: DrawSpriteSheet
// Desc: Draws a texture to the screen with enabled source rectangle
// Rtrn: None
// --------------------------------------------------------------------------------
void Graphics::DrawSpriteSheet(LPDIRECT3DTEXTURE9 texture, D3DXVECTOR3 position, RECT source_rectangle, int alpha)
{
color = D3DCOLOR_COLORVALUE(255, 255, 255, alpha);
sprite->Draw(texture, &source_rectangle, NULL, &position, 0xFFFFFFFF);
}


// --------------------------------------------------------------------------------
// Name: DrawEx
// Desc: Draws a texture to the screen with enabled rotation
// Rtrn: None
// --------------------------------------------------------------------------------
void Graphics::DrawEx(LPDIRECT3DTEXTURE9 texture, D3DXVECTOR3 position, RECT source_rectangle, int alpha, D3DXVECTOR3 rotation_orgin, float rotation)
{
}


// --------------------------------------------------------------------------------
// Name: End
// Desc: Restores the device state to how it was before Begin was called
// Rtrn: None
// --------------------------------------------------------------------------------
void Graphics::End(void)
{
sprite->End();
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
}


// --------------------------------------------------------------------------------
// Name: LoadTexture
// Desc: Creates a texture from a file
// Rtrn: Returns the created texture
// --------------------------------------------------------------------------------
LPDIRECT3DTEXTURE9 Graphics::LoadTexture(LPCWSTR path)
{
D3DXCreateTextureFromFile(d3ddev, path, &texture);
return texture;
}
[/source]


Graphics.h
[source lang="cpp"]

#pragma once


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


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


class Graphics
{

public:
Graphics(HWND hWnd);
~Graphics(void);
// --------------------------------------------------------------------------------
// Name: Begin
// Desc: Prepares a device for drawing
// Rtrn: None
// --------------------------------------------------------------------------------
void Begin(void);
// --------------------------------------------------------------------------------
// Name: Draw
// Desc: Draws a texture to the screen
// Rtrn: None
// --------------------------------------------------------------------------------
void Draw(LPDIRECT3DTEXTURE9 texture, D3DXVECTOR3 position, int alpha);
// --------------------------------------------------------------------------------
// Name: DrawSpriteSheet
// Desc: Draws a texture to the screen with enabled source rectangle
// Rtrn: None
// --------------------------------------------------------------------------------
void DrawSpriteSheet(LPDIRECT3DTEXTURE9 texture, D3DXVECTOR3 position, RECT source_rectangle, int alpha);
// --------------------------------------------------------------------------------
// Name: DrawEx
// Desc: Draws a texture to the screen with enabled rotation
// Rtrn: None
// --------------------------------------------------------------------------------
void DrawEx(LPDIRECT3DTEXTURE9 texture, D3DXVECTOR3 position, RECT source_rectangle, int alpha, D3DXVECTOR3 rotation_orgin, float rotation);
// --------------------------------------------------------------------------------
// Name: End
// Desc: Restores the device state to how it was before Begin was called
// Rtrn: None
// --------------------------------------------------------------------------------
void End(void);
// --------------------------------------------------------------------------------
// Name: LoadTexture
// Desc: Creates a texture from a file
// Rtrn: Returns the created texture
// --------------------------------------------------------------------------------
LPDIRECT3DTEXTURE9 LoadTexture(LPCWSTR path);

private:
LPDIRECT3D9 d3d;
D3DPRESENT_PARAMETERS d3dpp;
LPDIRECT3DDEVICE9 d3ddev;
LPD3DXSPRITE sprite;
LPDIRECT3DTEXTURE9 texture;
D3DCOLOR color;

};
[/source]

Does this seem correct, or should you have changed anything? (I'll also add the error checking)

Then I also have 2 more questions:

1. I've noticed that the texture is scaling to the closest 64x64, 128x128, 256x256, 512x512, 1024x1024 etc. If my texture is 300 in height, it's going to be scaled to 512 in height. Can I disable this somehow?

2. What do you think is better? Using Sprites or setting up vertices?


@ryan20fun: Ok, I've checked the Debug Runtime Version. Should I do anything with the Debug Output Level? Where will I find this debug help in Visual Studio when I work?


Thanks for helping! :)

1. I've noticed that the texture is scaling to the closest 64x64, 128x128, 256x256, 512x512, 1024x1024 etc. If my texture is 300 in height, it's going to be scaled to 512 in height. Can I disable this somehow?


it depends, does the card support non power of two textures ?
if so you can manually specify the x and y size, its what i do.


2. What do you think is better? Using Sprites or setting up vertices?


i would vote sprites for now, i think if you are going to upgrade to D3D10 / 11, it might be easier to use vertices and rotate them manually etc.
because from D3D10, Microsoft dropped the fixed function pipeline.


@ryan20fun: Ok, I've checked the Debug Runtime Version. Should I do anything with the Debug Output Level?


the more debug out put D3D will Do.
if you select the highest out put, you will get mesages for everything you did wtong, and forgot to do.


Where will I find this debug help in Visual Studio when I work?


D3D will output the info to the "Output" Window, the one that tells you X has been compiled.

Never say Never, Because Never comes too soon. - ryan20fun

Disclaimer: Each post of mine is intended as an attempt of helping and/or bringing some meaningfull insight to the topic at hand. Due to my nature, my good intentions will not always be plainly visible. I apologise in advance and assure you I mean no harm and do not intend to insult anyone.


1. I've noticed that the texture is scaling to the closest 64x64, 128x128, 256x256, 512x512, 1024x1024 etc. If my texture is 300 in height, it's going to be scaled to 512 in height. Can I disable this somehow?
[/quote]
Try using D3DXCreateTextureFromFileEx() instead of the D3DXCreateTextureFromFile().

This topic is closed to new replies.

Advertisement