Jump to content
  • Advertisement
Sign in to follow this  
nlraley

DirectX9 - Having Problems Displaying Textures...

This topic is 2833 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 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
Advertisement
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
What does debug runtime tell you?
Quote:
But I don't see it in your code.

And, did you set the viewport, view and projection matrices as mentioned above?

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!