Sign in to follow this  

help with D3DXCreateTexture, emergency!

This topic is 3863 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

Hi, every body: I am a newbie in directX, but my project need it, I met a problem with D3DXCreateTexture I can not solve, please help me. my program is create a texture, then lock it's surface, import the data from outside, unlock it, render, because the outside data changes, so the screen will show the patern of the data changed. here is my program snips: (Visual C++ / DirectX 9.0 sdk / Windows xp pro) // omit the device create parts // set the texture status: if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ) { return E_FAIL; } // Turn off culling g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); // Turn on the zbuffer g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); // set texture stage g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); g_pd3dDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); g_pd3dDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); g_pd3dDevice->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_POINT); // create the texture D3DXCreateTexture(g_pd3dDevice, 160, 512, 0, // number of mip levels(0 - a complete mipmap chain is created) 0, // usage D3DFMT_L8, // format D3DPOOL_MANAGED, &g_pTexture); // because my outside data is 8 bits ilumination per pixel,so i used D3DFMT_L8 LPDIRECT3DSURFACE9 pRenderSurface = NULL; g_pTexture->GetSurfaceLevel(0, &pRenderSurface); D3DSURFACE_DESC surfaceDesc; pRenderSurface->GetDesc(&surfaceDesc); D3DLOCKED_RECT lockedRect; pRenderSurface->LockRect(&lockedRect, 0, 0); // entire surface BYTE* imageData = (BYTE*)lockedRect.pBits; for(int i = 0; i < surfaceDesc.Height; i++) { for(int j = 0; j < surfaceDesc.Width; j++) // trace here, found surfaceDesc.Width = 256,not 160 (I expected!) { int index = i * lockedRect.Pitch + j; // trace here, found lockedRect.Pitch = 256, not 160 (I expected) imageData[index] = DataTar[i+j*512 ]; // pour in outside data. which is one colum one colmn aligned. } } pRenderSurface->UnlockRect(); The program works, but the data on screen is not what I expected. becase the original data format is 8 bits/pixel, width = 160, height=512, i expected it show in that patern, but i found it show it about left 3/4 of the screen block the whole 160 data, and the right 1/4 repeat the right side data! so it shows a two patched blocks in one screen, but actually I need the whole screen show 160 width, 512 height. i traced it, found the width of the surface which i associated with the texture is also 256, not 160 ( please see the remark in the program) strangely enough, if I change the width = 128 or less in the following: D3DXCreateTexture(g_pd3dDevice, 160, // <----------------changed to 128 or less 512, 0, // number of mip levels(0 - a complete mipmap chain is created) 0, // usage D3DFMT_L8, // format D3DPOOL_MANAGED, &g_pTexture); then the whold screen show the data, but only 128 width of original data, but I want show the whole 160 width! when I change the width of D3DXCreateTexture to 128 or less, the surface width I retrieved also 128 or less, just as I wanted. any other number larger than 128 in D3DXCreateTexture, will result in surface width 256. What's wrong with my program? maybe I set some parameters wrong? please help me, I am in a emergent need for this program. thank you very much! winston.

Share this post


Link to post
Share on other sites
As an 'emergency' response, this question in some form or other is very common here. The D3DX load function will resize your texture to the next largest power of two size IF it isn't already a valid size. This is just one reason that using only power-of-two sized textures is recommended by so many. IF your hardware supports it (check D3DPTEXTURECAPS_NONPOW2CONDITIONAL), I think you can pass a parameter to the texture loader/creator (D3DX_DEFAULT_NONPOW2?) that says 'please don't resize my texture'. You might have to use the Ex version, I'm not sure...

Share this post


Link to post
Share on other sites
Thank you very much for your reply.

but I can not use the CreateTextureFromFile or Ex, because I have to create it from the memory, suppose I use

D3DXCreateTexture(g_pd3dDevice,
D3DX_DEFAULT_NONPOW2,//160
D3DX_DEFAULT_NONPOW2,//512
0,
0,
D3DFMT_L8,
D3DPOOL_MANAGED,
&g_pTexture);

g_pd3dDevice->SetTexture( 0, g_pTexture );

// Set the Data:
LPDIRECT3DSURFACE9 pRenderSurface = NULL;

g_pTexture->GetSurfaceLevel(0, &pRenderSurface);
D3DSURFACE_DESC surfaceDesc;
pRenderSurface->GetDesc(&surfaceDesc);

D3DLOCKED_RECT lockedRect;
pRenderSurface->LockRect(&lockedRect, 0, 0);

BYTE* imageData = (BYTE*)lockedRect.pBits;
for(int i = 0; i < surfaceDesc.Height; i++)
{
for(int j = 0; j < surfaceDesc.Width; j++)
{
int index = i * lockedRect.Pitch + j;

imageData[index] = // actuall data

}
}

pRenderSurface->UnlockRect();


then where can i set the actuall size?
I have to tell DirectX that my texture is 160*512 ? but how?

I am sorry, I am really new to DirectX here.

Thank you again.

winston

Share this post


Link to post
Share on other sites
just a try:

I use D3DxCrateTextureFromFileEx load a 160*512 file, indeed, it can show the whole thing,

if(FAILED( D3DXCreateTextureFromFileEx(
g_pd3dDevice,
"chess.bmp",
D3DX_DEFAULT_NONPOW2,
D3DX_DEFAULT_NONPOW2,
D3DX_FROM_FILE,
0,
D3DFMT_L8,
D3DPOOL_MANAGED,
D3DX_DEFAULT ,
D3DX_FILTER_NONE,
0,
NULL,
NULL,
&g_pTexture)))


// above I used D3DX_DEFAULT_NONPOW2, and D3DX_FROM_FILE with no mipmap to get
it.

// But I have to change the texture dynamically, so I used the following:

LPDIRECT3DSURFACE9 pRenderSurface = NULL;

g_pTexture->GetSurfaceLevel(0, &pRenderSurface);
D3DSURFACE_DESC surfaceDesc;
pRenderSurface->GetDesc(&surfaceDesc);

D3DLOCKED_RECT lockedRect;
pRenderSurface->LockRect(&lockedRect, 0, 0); // entire surface

BYTE* imageData = (BYTE*)lockedRect.pBits;
for(int i = 0; i < surfaceDesc.Height; i++)
{
for(int j = 0; j < surfaceDesc.Width; j++) // found still 256?why not 160 as the file size?
{
int index = i * lockedRect.Pitch + j; //Trace found Pitch 256,not 160 as I expected。

imageData[index] = // dynamic data
}
}


Why this happened?

I have to change the texture dynamically, and fast. how can i do it ?

Thank you very much!


Share this post


Link to post
Share on other sites

anybody can help me?

no matter how to set the parameter, as long as I want to set the data to the texture (with LPDIRECT3DSURFACE9 ), the surfaceDesc.Width and surfaceDesc.Pitch become 256 not 160

thank you, please give me some hints

winston

Share this post


Link to post
Share on other sites
Winston,

Are you sure your hardware supports this? (Did you check the caps bit as mentioned in previous post?) Not all hardware supports non power of two textures. I could be totally wrong on this, and it is just a suggestion; but there's no point in looking further if your hardware is against you.

Share this post


Link to post
Share on other sites
hi, MasterWorks:

thank you, I check it as following:

bool CViaBCDlg::ChekHardWare3DTexture()
{
D3DCAPS9 d3dcaps;
g_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,&d3dcaps);
bool bHardwareTexture;
if(d3dcaps.DevCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL){
bHardwareTexture=true;
AfxMessageBox(" display card DO support nonpow2 Texture");
}
else{
bHardwareTexture=false;
AfxMessageBox(" display card don't support nonpow2 Texture");
}

return bHardwareTexture;
}

Indeed, it say " display card don't support nonpow2 Texture"
that mean my display card don't support NONPOW2?

but why if I use D3DXCreateTextureFromFileEx to show a 160*512 bmp file, which is not a pow2 size, it can show the whole thing? the only problem is I can not change the texture pixel because I don't know the size inside.

also , somebody say,

"
for create a 200*200 texture:
use D3DXCreateTexture to crate texture then GetLevelDesc check the size,it can be readjusted to 56×256,Pitch also is 256

but if LPDIRECT3DDEVICE8::CreateTexture is used instead,then using GetLevelDesc to check,you will find texture is 200×200,Pitch is also 200

"
it that true?

but I used LPDIRECT3DDEVICE8::CreateTexture , it failed:

HRESULT hRet = g_pd3dDevice->CreateTexture(160,
512,
0, // truncated until 1;
0, // usage or D3DUSAGE_RENDERTARGET
D3DFMT_L8,
D3DPOOL_MANAGED,
&g_pTexture,
NULL);

switch(hRet)
{
case D3D_OK:
AfxMessageBox(" ok");
break;
case D3DERR_INVALIDCALL:
AfxMessageBox(" invalidated calling createtexture");
break;
case D3DERR_OUTOFVIDEOMEMORY:
AfxMessageBox(" outof video memory in calling createtexture");
break;
case E_OUTOFMEMORY:
AfxMessageBox(" outof memory in calling createtexture");
break;
}

I get "invalidated calling createtexture"!
why?

thank you
winston

Share this post


Link to post
Share on other sites
D3DXCreateTextureFrom*() will always round the dimensions up to the nearest power of 2, unless you explicitly tell it not to.
IDirect3DDevice9::CreateTexture() will try to create the exact size you pass it.

If you're loading a 56x160px texture with D3DXCreateTextureFrom*(), D3DX will create a texture that's 64x256. So GetLevelDesc() will tell you the texture is 64x256.
If you're loading a 56x160px texture with IDirect3DDevice9::CreateTexture(), D3D will create a texture that's 56x160 if it can. So GetLevelDesc() will tell you the texture is 56x160.

However, the pitch will probably not be 56, since the card is likely to add some padding, and some cards might even allocate a 64x256 chunk of memory internally.

Using non-power-of-2 textures comes with a few restrictions in most cases, and many cards don't support them at all (Like your card).

Most people will tile several smaller power-of-2 textures instead of creating one larger non-power-of-2 texture (E.g. instead of creating a 800x600 texture to cover the screen, create a 3x2 area of 256x256 textures, then fill in the borders will smaller quads), or put several smaller non-power-of-2 textures on one larger power-of-2 texture (E.g. having several non-power-of-2 sprites on one sprite sheet).


Quote:
Original post by winston123
Indeed, it say " display card don't support nonpow2 Texture"
that mean my display card don't support NONPOW2?
Yes

Quote:
Original post by winston123
but why if I use D3DXCreateTextureFromFileEx to show a 160*512 bmp file, which is not a pow2 size, it can show the whole thing?
D3DX is creating a 256x512 texture, and loading the image into the upper 160x512 area. The rest will be filled with black.

Quote:
Original post by winston123
"for create a 200*200 texture:
use D3DXCreateTexture to crate texture then GetLevelDesc check the size,it can be readjusted to 56×256,Pitch also is 256

but if LPDIRECT3DDEVICE8::CreateTexture is used instead,then using GetLevelDesc to check,you will find texture is 200×200,Pitch is also 200"
it that true?
Yes and no. If your card supports non-power-of-2 textures, that's half correct. The pitch isn't guaranteed to be anything. If your card doesn't support non-power-of-2 textures, CreateTexture will fail.

Quote:
Original post by winston123but I used LPDIRECT3DDEVICE8::CreateTexture , it failed:

[snip]

I get "invalidated calling createtexture"!
why?
Your card doesn't support non-power-of-2 textures. You should really be using the debug runtimes, then D3D will tell you why the call failed (Probably something like "(D3D) ERROR: Non power of 2 texture size specified but device does not support non power of two textures. CreateTexture fails.")

Share this post


Link to post
Share on other sites

This topic is 3863 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.

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