Sign in to follow this  
nlraley

DirectX9 - Having Problems Displaying Textures...

Recommended Posts

I hope I have this in the right forum.

I am trying to load a set of Map Tiles to fill up a background. Each tile is a 256x256 PNG image file with the same format.

I have 3 classes currently. A MapTile class that contains the file location of the png file for the tile as well as coordinate information for displaying the tile. A DXDirect3D class which handles my DX objects, and finally a DXTexture which maintains my DirectX Textures.

Currently my program searches through a specified set of directories and builds a MapTile for each PNG file located in there. The naming scheme of the tiles correlates to the X,Y screen position of my images. I maintain a complete list of each of these tile objects.

After creating these objects, I initialize my DXDirect3D class, then initialize my Direct3D as follows:

HRESULT TDXDirect3D::InitD3D (int resWidth, int resHeight, D3DFORMAT resFormat, HWND hWnd, BOOL bWindowedMode)
{
//-------------------
WinHandle = hWnd;
//------------------- Make Direct3D object
d3d = Direct3DCreate9(D3D_SDK_VERSION);
//------------------- Make sure NULL pointer was not returned
if (!d3d)
return false;
//------------------- Get device capabilities
ZeroMemory (&d3dCaps, sizeof(d3dCaps));
hr = d3d->GetDeviceCaps (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps);
if (FAILED(hr))
return hr;
//------------------- Setup present parameters
ZeroMemory(&d3dPresent,sizeof(d3dPresent));
d3dPresent.SwapEffect = D3DSWAPEFFECT_FLIP;
d3dPresent.hDeviceWindow = hWnd;
d3dPresent.BackBufferCount = 1;
//------------------- Check if windowed
if (bWindowedMode) // Windowed Mode
{
//-------------------
D3DDISPLAYMODE d3ddm;
RECT rWindow;
//------------------- Get display mode
d3d->GetAdapterDisplayMode (D3DADAPTER_DEFAULT, &d3ddm);
//------------------- Get window bounds
GetClientRect (hWnd, &rWindow);
//------------------- Setup screen dimensions
resWidth = rWindow.right - rWindow.left;
resHeight = rWindow.bottom - rWindow.top;
//------------------- Setup backbuffer
d3dPresent.Windowed = true;
d3dPresent.BackBufferFormat = d3ddm.Format;
d3dPresent.BackBufferWidth = rWindow.right - rWindow.left;
d3dPresent.BackBufferHeight = rWindow.bottom - rWindow.top;
//-------------------
format = d3ddm.Format;
//-------------------
} // if (bWindowedMode)
else // FullScreen
{
//-------------------
d3dPresent.Windowed = false;
d3dPresent.BackBufferWidth = resWidth;
d3dPresent.BackBufferHeight = resHeight;
d3dPresent.BackBufferFormat = resFormat;
//-------------------
} // End else
//------------------- Check if hardware vertex processing is available
if (d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
{
//------------------- Create device with hardware vertex processing
hr = d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dPresent, &d3dDevice);
//-------------------
}
else
{
//------------------- Create device with software vertex processing
hr = d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dPresent, &d3dDevice);
//-------------------
}
//------------------- Make sure device was created
if (FAILED(hr))
return hr;
//------------------- Set vertex shader
d3dDevice->SetVertexShader(NULL);
d3dDevice->SetFVF (D3DFVF_TLVERTEX);
//------------------- Create vertex buffer
hr = d3dDevice->CreateVertexBuffer(sizeof(textured_vertex) * 4, NULL, D3DFVF_TLVERTEX, D3DPOOL_MANAGED,
&vertexBuffer, NULL);
if (FAILED(hr))
return hr;
//------------------- Set as stream source
hr = d3dDevice->SetStreamSource (0, vertexBuffer, 0, sizeof(textured_vertex));
if (FAILED(hr))
return hr;
//------------------- Setup rendering states
d3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
d3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
d3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
//------------------- Setup the Sprite
hr = D3DXCreateSprite(d3dDevice, &d3dSprite);
if (FAILED(hr))
return hr;
//------------------- Successfully initalized Direct3D
return hr;
//-------------------
}


After that is done I make a call to:
IDirect3DDevice9->BeginScene()


Assuming that succeeds I then proceed to go through each of my MapTile objects. If the MapTileObject should be visible in the current viewport, I perform the following.

I call:
DXTexture Texture(&MainForm->Direct3D);

Which simply Initializes a Texture from my DXTexture class and sets its TDXDirect3D instance to that of my main form, the one I initialized above.

If that succeeds I call:
Texture.Init(fileLoc.c_str())

Calling the Init function of my Texture class which is defined as follows:
bool DXTexture::Init(std::string sFilename)
{
//-------------------
D3DSURFACE_DESC surfaceDesc;
LOADEDTEXTURE* newTexture;
//-------------------
std::list<LOADEDTEXTURE*>::iterator itTextures;
//------------------- Make sure texture is not already loaded
if (bLoaded)
return FALSE;
//------------------- Convert filename to lowercase letters
sFilename = strlwr((char *)sFilename.c_str ());
//------------------- Check if texture is in the loaded list
for (itTextures = loadedTextures.begin (); itTextures != loadedTextures.end (); itTextures++)
if ((*itTextures)->sFilename == sFilename)
{
//------------------- Get LOADEDTEXTURE Object
texture = *itTextures;
//------------------- Increment Reference Counter
(*itTextures)->referenceCount++;
//------------------- Set Loaded Flag
bLoaded = TRUE;
//------------------- Successfully found texture
return TRUE;
//-------------------
}
//------------------- Texture was not in the list, make a new texture
newTexture = new LOADEDTEXTURE;
//------------------- Load texture from file
newTexture->texture = DXDirect3D->LoadTexture((char*)sFilename.c_str());
//------------------- Make sure texture was loaded
if (!newTexture->texture)
return FALSE;
//------------------- Get texture dimensions
newTexture->texture->GetLevelDesc(0, &surfaceDesc);
//------------------- Set new texture parameters
newTexture->referenceCount = 1;
newTexture->sFilename = sFilename;
newTexture->width = surfaceDesc.Width;
newTexture->height = surfaceDesc.Height;
//------------------- Push new texture onto list
loadedTextures.push_back (newTexture);
//------------------- Setup current texture instance
texture = loadedTextures.back();
bLoaded = TRUE;
//------------------- Successfully loaded texture
return TRUE;
//-------------------
}


What this does is check to see if the texture has already been created, if it hasn't it creates a new LOADEDTEXTURE and calls the DXDirect3D->LoadTexture((char*)sFilename.c_str()) function from my DXDirect3D class which is defined as:
IDirect3DTexture9 *TDXDirect3D::LoadTexture(char *fileName)
{
//-------------------
IDirect3DTexture9 *d3dTexture;
D3DXIMAGE_INFO SrcInfo;
//------------------- Use a magenta colourkey
D3DCOLOR colorkey = 0xFFFF00FF;
//------------------- Load image from file
if (FAILED(D3DXCreateTextureFromFileEx (d3dDevice, fileName, 0, 0, 1, 0,
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT,
colorkey, &SrcInfo, NULL, &d3dTexture)))
return NULL;
//------------------- Return the newly made texture
return d3dTexture;
//-------------------
}


As you can see, this calls D3DXCreateTextureFromFileEx loading the PNG's file location and setting the texture property of my LOADEDTEXTURE to this newly created Texture.

My next step calls:
Texture.Blit(xValue, yValue, vertexColour, 0)

Which calls this function:
HRESULT DXTexture::Blit (int X, int Y, D3DCOLOR vertexColour, float rotate)
{
//-------------------
RECT rDest;
//------------------- Setup destination rectangle
rDest.left = X;
rDest.right = X + texture->width;
rDest.top = Y;
rDest.bottom = Y + texture->height;
//------------------- Draw texture
hr = DXDirect3D->BlitD3D (texture->texture, &rDest, vertexColour, rotate);
//-------------------
}


This sets up the Destination Rect before calling the DXDirect3D->BlitD3D which is defined as follows:
HRESULT TDXDirect3D::BlitD3D (IDirect3DTexture9 *texture, RECT *rDest, D3DCOLOR vertexColour, float rotate)
{
//-------------------
textured_vertex* vertices;
//------------------- Lock the vertex buffer
vertexBuffer->Lock(0, 0, (void **)&vertices, NULL);
//------------------- Setup vertices
// A -0.5f modifier is applied to vertex coordinates to match texture and screen coords
// Some drivers may compensate for this automatically, but on others texture alignment errors are introduced
// More information on this can be found in the Direct3D 9 documentation
//-------------------
vertices[0].colour = vertexColour;
vertices[0].x = (float) rDest->left - 0.5f;
vertices[0].y = (float) rDest->top - 0.5f;
vertices[0].z = 0.0f;
vertices[0].rhw = 1.0f;
vertices[0].u = 0.0f;
vertices[0].v = 0.0f;
//-------------------
vertices[1].colour = vertexColour;
vertices[1].x = (float) rDest->right - 0.5f;
vertices[1].y = (float) rDest->top - 0.5f;
vertices[1].z = 0.0f;
vertices[1].rhw = 1.0f;
vertices[1].u = 1.0f;
vertices[1].v = 0.0f;
//-------------------
vertices[2].colour = vertexColour;
vertices[2].x = (float) rDest->right - 0.5f;
vertices[2].y = (float) rDest->bottom - 0.5f;
vertices[2].z = 0.0f;
vertices[2].rhw = 1.0f;
vertices[2].u = 1.0f;
vertices[2].v = 1.0f;
//-------------------
vertices[3].colour = vertexColour;
vertices[3].x = (float) rDest->left - 0.5f;
vertices[3].y = (float) rDest->bottom - 0.5f;
vertices[3].z = 0.0f;
vertices[3].rhw = 1.0f;
vertices[3].u = 0.0f;
vertices[3].v = 1.0f;
/* OMITTED
//------------------- Handle rotation
if (rotate != 0)
{
//-------------------
RECT rOrigin;
float centerX, centerY;
//------------------- Find center of destination rectangle
centerX = (float)(rDest->left + rDest->right) / 2;
centerY = (float)(rDest->top + rDest->bottom) / 2;
//------------------- Translate destination rect to be centered on the origin
rOrigin.top = rDest->top - (int)(centerY);
rOrigin.bottom = rDest->bottom - (int)(centerY);
rOrigin.left = rDest->left - (int)(centerX);
rOrigin.right = rDest->right - (int)(centerX);
//------------------- Rotate vertices about the origin
bufferVertices[index].x = rOrigin.left * cosf(rotate) -
rOrigin.top * sinf(rotate);
bufferVertices[index].y = rOrigin.left * sinf(rotate) +
rOrigin.top * cosf(rotate);
//-------------------
bufferVertices[index + 1].x = rOrigin.right * cosf(rotate) -
rOrigin.top * sinf(rotate);
bufferVertices[index + 1].y = rOrigin.right * sinf(rotate) +
rOrigin.top * cosf(rotate);
//-------------------
bufferVertices[index + 2].x = rOrigin.right * cosf(rotate) -
rOrigin.bottom * sinf(rotate);
bufferVertices[index + 2].y = rOrigin.right * sinf(rotate) +
rOrigin.bottom * cosf(rotate);
//-------------------
bufferVertices[index + 3].x = rOrigin.left * cosf(rotate) -
rOrigin.bottom * sinf(rotate);
bufferVertices[index + 3].y = rOrigin.left * sinf(rotate) +
rOrigin.bottom * cosf(rotate);
//------------------- Translate vertices to proper position
bufferVertices[index].x += centerX;
bufferVertices[index].y += centerY;
bufferVertices[index + 1].x += centerX;
bufferVertices[index + 1].y += centerY;
bufferVertices[index + 2].x += centerX;
bufferVertices[index + 2].y += centerY;
bufferVertices[index + 3].x += centerX;
bufferVertices[index + 3].y += centerY;
//-------------------
}
*/
//------------------- Unlock the vertex buffer
vertexBuffer->Unlock();
//------------------- Set texture
hr = d3dDevice->SetTexture (0, texture);
if (FAILED(hr))
return hr;
//------------------- Draw image
hr = d3dDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);
//-------------------
return hr;
//-------------------
}


Which sets up the Vertices for the Texture, calls the SetTexture of my IDirect3DDevice9 followed by the DrawPrimitive of my IDirect3DDevice9.

I then call:

d3dDevice->EndScene();
d3dDevice->Present(NULL, NULL, NULL, NULL);


Yet I end up with absolutely nothing being displayed. I tried calling Sprite->Draw instead of Blitting; however, Draw always fails. What am I doing wrong here?

Share this post


Link to post
Share on other sites
First, take a look at the faq in the upper right-hand corner of this page and use [source] [/source] tags to help us out.
Quote:
What am I doing wrong here?

It appears that you've written hundreds of lines of code without testing it along the way. That's probably your worst error. A better practice would be to code a single function, or even just several lines of code in that function, and test it thoroughly. Compiling and running takes a few seconds. Debugging hundreds of lines of untested code takes hours.

With regard to what may be wrong, you need to provide some information about what you've tested, what you know works for sure (such as textures are loaded successfully, the vertex buffer shows okay in wireframe mode, etc.)
Quote:
Draw always fails.

What error do you get? Does the Debug Runtime output give you any information? Have you stepped through your code in debug mode and confirmed that variable values are what you expect?

Share this post


Link to post
Share on other sites
So far, all of my HRESULTS for everything with the exception of the Present work.

It appears that the Direct3D is initialized properly along with the devive. My textures appear to be created properly. However, nothing is displayed.

I am not getting any errors, the images just are never displayed. So not sure where to go from here.

I'll not that I wasn't coding all of this blindly. I was following a tutorial located here:
http://www.gamedev.net/reference/articles/article1972.asp

And I have everything okay, or at least as far as I can tell, up to where I try to blit the images. Again, HRESULT returns okay, but nothing is ever displayed. So I'm stuck at what to check for now and what would be causing it.

Share this post


Link to post
Share on other sites
Review the documenation and SDK examples for DrawPrimitive. You need to set a streamsource and FVF, at a minimum.

EDIT: you do set the FVF. Sorry about that.

EDIT2: well, pfui. You set the stream source, also. Double-sorry.

If you haven't tried the Debug Runtime, do so now. Are you using the Debug Version of Direct3D (through your control panel)?

Share this post


Link to post
Share on other sites
Didn't I do that correctly?


HRESULT DrawPrimitive(
[in] D3DPRIMITIVETYPE PrimitiveType,
[in] UINT StartVertex,
[in] UINT PrimitiveCount
);

I called
hr = d3dDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);

Start Vertex is 0, Primitve Count is 2 right? Draws 2 triangles to create a single quad right?

Share this post


Link to post
Share on other sites
I was looking at another example and they called IDirect3DDevice9.Clear(...) before calling BeginScene(). This does fail for one reason or another. Could that be part of my issue?

Share this post


Link to post
Share on other sites
Quote:
they called IDirect3DDevice9.Clear(...) before calling BeginScene(). This does fail for one reason or another.

That definitely indicates a problem. What's the error code tell you?

You can use DXGetErrorDescription9(hr) to get a bit more detail.

Add #include "dxerr9.h" and link to dxerr9.lib for that.

Also, use the debug runtime!

EDIT: that tutorial lacks in a couple details - like setting a viewport, view matrix and projection matrix. Oops. Looks like it does setup those matrices. But I don't see it in your code.

Share this post


Link to post
Share on other sites
It appears this may be your first DirectX project. Even if not, I'd strongly suggest you work through some of the examples in the SDK. There's one that draws a simple triangle (untextured but similar to what you're trying) that would've provided you with a good basis for the basics (setting up the device, etc.).

Share this post


Link to post
Share on other sites
Yea, it's my first one in DirectX 9, and to add further complications I'm doing this in Borland Builder 6. If I don't get this ironed out by the end of the day I'll spend some time this weekend trying to get one up and running in Visual Studio at home.

)I'm just having a hard time finding anything that goes into decent detail about what is doing what and what needs to be done, and I could find which SDK examples I needed to look into b/c I wasn't exactly sure on the terminology for what I was trying to do.

Share this post


Link to post
Share on other sites
Yeah, starting out can be difficult. Not sure about newer SDKs, but there should be a Samples folder. If so, then go into the C++ examples, Direct3D folder, Tutorials folder and look through there. Should be a simple progression of "Create Device," "Vertices," "Matrices," etc., to get you started. It'd be well worth your time.

And.. get the debug runtime running! That'll give you quite detailed error descriptions in the IDE output window of Visual Studio.

Share this post


Link to post
Share on other sites
1. I'd highly recommend Visual Studio over Borland Builder - VS2010 Express is free, officially supported with the DirectX SDK (Unlike Borland Builder), and is an industry standard.

2. I'd also highly recommend using ID3DXSprite instead of managing a vertex buffer yourself - ID3DXSprite is going to be easier to handle, more efficient, and has less to go wrong.

3. You should get output similar to the following if the debug runtimes are set up correctly and a function fails:
.
If you don't get any relevant output, try running DebugView and see if that records any output (In case Borland Builder is failing in some way)

Share this post


Link to post
Share on other sites
Well, the reason I was running it in Borland was b/c I was asked to attempt to create a DirectX based offline mapping system for our program, which is written in Borland. The company hasn't decided to move over to a newer Builder or Visual Studio yet due to the time it would take to convert our 2 main programs that we develop for.

But I'm building a project from scratch in VS 2010 right now and trying to get things up and running there. Once I have everything there loaded, I'll try and port it over to Borland.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this