Jump to content

  • Log In with Google      Sign In   
  • Create Account


dds Alpha channel not working on mesh


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
17 replies to this topic

#1 Tispe   Members   -  Reputation: 978

Like
0Likes
Like

Posted 02 February 2012 - 03:30 AM

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 ) ?

Sponsor:

#2 Krohm   Crossbones+   -  Reputation: 2916

Like
0Likes
Like

Posted 02 February 2012 - 04:02 AM

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 D3DRS_ALPHABLENDENABLE (default: false). I suggest to take the chance to also consider D3DRS_SRCBLEND, D3DRS_DESTBLEND. There are more advanced alpha blending settings as well.
For this specific application however, you might just be interested in alpha testing: see D3DRS_ALPHATESTENABLE, D3DRS_ALPHAREF, D3DRS_ALPHAFUNC.

#3 Tispe   Members   -  Reputation: 978

Like
0Likes
Like

Posted 03 February 2012 - 02:21 AM

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?

#4 Evil Steve   Members   -  Reputation: 1955

Like
0Likes
Like

Posted 03 February 2012 - 04:14 AM

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?

Steve Macpherson
Senior programmer, Firebrand Games


#5 Tispe   Members   -  Reputation: 978

Like
0Likes
Like

Posted 04 February 2012 - 07:30 AM

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?

#6 Tispe   Members   -  Reputation: 978

Like
0Likes
Like

Posted 04 February 2012 - 01:26 PM

I have recoded this 4 times now and still no go. Tried even with just a pure vertex buffer, with and without indices.

Posted Image

#7 Tispe   Members   -  Reputation: 978

Like
0Likes
Like

Posted 04 February 2012 - 01:32 PM

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.

#8 Tispe   Members   -  Reputation: 978

Like
0Likes
Like

Posted 04 February 2012 - 02:10 PM

lol fixed it:
SetRenderState(D3DRS_ALPHAREF , 0x80);
SetRenderState(D3DRS_ALPHAFUNC  , D3DCMP_GREATER);


#9 esgol   Members   -  Reputation: 105

Like
0Likes
Like

Posted 06 February 2012 - 08:21 AM

What DireCt version and what compiler and windows version are you using? I have problem finding AlphaBlend myself

#10 Tispe   Members   -  Reputation: 978

Like
0Likes
Like

Posted 06 February 2012 - 11:04 AM

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);


#11 Tispe   Members   -  Reputation: 978

Like
0Likes
Like

Posted 06 February 2012 - 03:20 PM

Does anyone have any idea why my alphas are getting darker the further away the mesh is from the camera?

#12 Tispe   Members   -  Reputation: 978

Like
0Likes
Like

Posted 07 February 2012 - 03:05 PM

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;
}


#13 Evil Steve   Members   -  Reputation: 1955

Like
0Likes
Like

Posted 07 February 2012 - 04:50 PM

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);

Steve Macpherson
Senior programmer, Firebrand Games


#14 Adam_42   Crossbones+   -  Reputation: 2352

Like
0Likes
Like

Posted 07 February 2012 - 04:58 PM

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().

#15 Tispe   Members   -  Reputation: 978

Like
0Likes
Like

Posted 08 February 2012 - 02:18 AM

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?

#16 Tispe   Members   -  Reputation: 978

Like
0Likes
Like

Posted 08 February 2012 - 10:52 AM

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...

#17 Tispe   Members   -  Reputation: 978

Like
0Likes
Like

Posted 08 February 2012 - 01:47 PM

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....

#18 Evil Steve   Members   -  Reputation: 1955

Like
0Likes
Like

Posted 09 February 2012 - 12:07 PM

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().

Steve Macpherson
Senior programmer, Firebrand Games





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS