• Advertisement
Sign in to follow this  

dds Alpha channel not working on mesh

This topic is 2173 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 have a DXT3 dds image loaded in a LPDIRECT3DTEXTURE9. Drawing it as a sprite will make the "black pixels/alpha" transparent. However if I use it on a mesh it will show black edges along the texture where it should be transparent.

What should I do to make it transparent ( fixed pipeline atm ) ?

Share this post


Link to post
Share on other sites
Advertisement
I suppose you're referring to the D3DX sprite class. I've never used it so this post is mere speculation.
I suppose the sprite class internally sets up alpha blending and your code does not.
You need to enable [color=#000000][font=Consolas, Courier, monospace]

D3DRS_ALPHABLENDENABLE [/font](default: false). I suggest to take the chance to also consider [color=#000000][font=Consolas, Courier, monospace]

D3DRS_SRCBLEND[/font], [color=#000000][font=Consolas, Courier, monospace]

D3DRS_DESTBLEND[/font]. There are more advanced alpha blending settings as well.
For this specific application however, you might just be interested in alpha testing: see [color=#000000][font=Consolas, Courier, monospace]

D3DRS_ALPHATESTENABLE, [/font][color=#000000][font=Consolas, Courier, monospace]

D3DRS_ALPHAREF, [/font][color=#000000][font=Consolas, Courier, monospace]

D3DRS_ALPHAFUNC[/font].

Share this post


Link to post
Share on other sites
Ok, I got the effect I wanted but with a bug.

Places like some corners or edges there are small specks of black being visible. This is not shown in the game I "borrow" the asset from.

What are tyical sources for corner and edges specks?

Share this post


Link to post
Share on other sites
That sounds like you've only got alpha test on, so the pixel is either opaque or transparant, and not actually blended properly. What render states are you setting?

Share this post


Link to post
Share on other sites

SetRenderState(D3DRS_ZENABLE, TRUE);
SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(50, 50, 50));
SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);


What else is needed?

Share this post


Link to post
Share on other sites
I have recoded this 4 times now and still no go. Tried even with just a pure vertex buffer, with and without indices.

specks.png

Share this post


Link to post
Share on other sites
Another thing that is occuring is that if I have a sphere where a spot on the sphere surface is made transparent with alpha blending, the back/opposite side through the "spot hole" of the sphere also becomes transparent but is not supposed to.

It might be that my faces are two-sided. One interesting observation I have is that a strip of triangles are black on one side(alpha black) and have a texture on the other side, but with ALPHABLENDENABLE set to true both sides are invisble, while I want the other side visible.

So if the same "subset" is curled ontop of itself it like a sphere or ring, it will make invisible faces behind it that should not be.

Share this post


Link to post
Share on other sites
lol fixed it:

SetRenderState(D3DRS_ALPHAREF , 0x80);
SetRenderState(D3DRS_ALPHAFUNC , D3DCMP_GREATER);

Share this post


Link to post
Share on other sites
What DireCt version and what compiler and windows version are you using? I have problem finding AlphaBlend myself

Share this post


Link to post
Share on other sites
Always a new bug to figure out for me :(

Now, if the Mesh is barely 5+ units away from the camera the mesh will have many faces start becoming fully transparent.

Turning off D3DRS_ALPHATESTENABLE corrects this but that messes up my textures... And it seems the further away my Mesh gets from the camera the darker it gets..

What is going on? I have messed around with these states without any results


SetRenderState(D3DRS_LIGHTING, false);
SetRenderState(D3DRS_ZENABLE, true);
SetRenderState(D3DRS_ALPHAREF, 0x50);
SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(50, 50, 50));
SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
SetRenderState(D3DRS_NORMALIZENORMALS, true);
SetRenderState(D3DRS_ALPHABLENDENABLE, true);
SetRenderState(D3DRS_ALPHATESTENABLE, true);
SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

Share this post


Link to post
Share on other sites
Does anyone have any idea why my alphas are getting darker the further away the mesh is from the camera?

Share this post


Link to post
Share on other sites
Finally I have traced the problem down to

SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);


Turning this off makes everything fine. But I want to know what it messed it up. Why would a DXT3 dds manually loaded mess this up?


Here is the loading code, I tried with software vertex processing also but nothing good came out of it:

D3DLOCKED_RECT rc;
if( *(DWORD*)(pTextureData) == 'DXT3' ){
hr = pGraphicsDevice->GetDevice()->CreateTexture(width, height, NULL, NULL, D3DFMT_DXT3, D3DPOOL_MANAGED, &pTex, NULL);
if( hr!=D3D_OK ) return NULL;
hr = pTex->LockRect(0,&rc,NULL,0);
if(hr==D3D_OK){
CopyMemory(rc.pBits,pTextureData+4,(width/4) * (height/4) * 16 );
pTex->UnlockRect(0);
}
pTex->GenerateMipSubLevels(); //on or off makes no diff
return pTex;
}

Share this post


Link to post
Share on other sites
The 3rd parameter to CreateTexture() is the number of mip levels to generate, with 0 meaning "All, down to 1x1". NULL evaluates to 0, so you're generating a texture with a full mip chain. I'm not sure what the texture contains when it's created, but I'd assume that it's either undefined or all 0 bytes. If you have 0 bytes, then you'll end up with the alpha channel being set to 0 in the lower mips. If you generate the lower mips with a call to GenerateMipSubLevels, then you may end up with the texture getting blurred and the alpha channel messed up - especially if the texture has a lot of alpha in it.

In either case, you ned up with a texture that has a lot of alpha in the lower mips, and the lower mips are displayed when the texture is further away. Setting the mip filter to linear means the two closest mip levels are linearly interpolated to give the output colour, and not setting it means it stays at point (I.e. no mip filtering).
I can only assume that your particular setup makes the linear interpolation go screwy somehow.

What happens if you use D3DXSaveTextureToFile, save as .dds and then use the DirectX texture tool to look at the lower mip levels?

Also, slightly off topic, your code won't work correctly if the texture is not a multiple of 4 in width and height. It should be:
CopyMemory(rc.pBits, pTextureData+4, ((width+3)/4) * ((height+3)/4) * 16);

Share this post


Link to post
Share on other sites
I suspect GenerateMipSubLevels() is failing - check the return code. You probably won't be able to get it to work either because I don't know of any cards which support that function for DXT compressed textures as that would require them to decompress and then recompress the texture. It's intended for use on render targets.

I'm guessing you probably want to load the mipmaps from the texture file. The simplest option is to create a .dds file with the texture tool that comes with the SDK and load that with D3DXCreateTextureFromFile().

Share this post


Link to post
Share on other sites
Thanks a lot for the comments. I think Evil Steve is right, the mipmap alphas are getting messed up by the filter. But without the filter are the mipmaps even made? Does the pTex->UnlockRect(0); generate them? Is the filter just making them "worse" afterwards? Maybe pTex->GenerateMipSubLevels(); is called in UnLockRect().. who knows :P

All I know is that there are no mipmap levels saved in the file beforehand, and the Game which I take the assets from do support Mipmaps, so the should be post generated, but how....

Maybe I need to decompress the DXT3, generate mipmaps and then compress it back to DXT3 or just leave it uncompressed... What do you think?

Share this post


Link to post
Share on other sites
Using D3DXSaveTextureToFile I can now see that all the mipmaps are all solid black in the DirectX Texture Tool when viewing the alpha channel and they remain solid black with any mipmap filter applied, even D3DTEXF_NONE. Also, the color channels are clear, no mipmaps are actually generated.... Just a blank space. pTex->GenerateMipSubLevels(); Does nothing!!


also CopyMemory(rc.pBits, pTextureData+4, ((width+3)/4) * ((height+3)/4) * 16); breaks my app, my code works for this...

Share this post


Link to post
Share on other sites
Hmm, still have no clue:

if(FAILED(d3d->CheckDeviceFormat(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
D3DFMT_X8R8G8B8,
D3DUSAGE_AUTOGENMIPMAP,
D3DRTYPE_TEXTURE,
D3DFMT_DXT3)))
{
MessageBox(NULL, L"Can't D3DUSAGE_AUTOGENMIPMAP", L"Error", MB_OK);
PostQuitMessage(0);
}


This does not fail atleast. But D3DUSAGE_AUTOGENMIPMAP does not do anything anyway....

Share this post


Link to post
Share on other sites
As Adam_42 said, now I think about it, I wouldn't expect GenerateMipSubLevels() to work for DXT compressed textures, since it would require uncompressing the DXT texture (Which is easy), resizing it (Which is also easy), and then re-compressing it (Which is hard - that's why art packages that save DXT compressed textures often have various settings like perceptual and so on to decide how it compresses).
This is also why there's no cards I know of that can use DXT compressed formats as render target formats.

You'd be better off making the mip levels yourself manually, and loading each mip level into the texture instead of getting D3D / the driver to try and do it itself. Or, pass 1 for the 3rd parameter to CreateTexture to create a texture with a single mip level, and don't bother calling GenerateMipSubLevels().

Share this post


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

  • Advertisement