Sign in to follow this  

Rendering textures with alpha channel, samplier causing black lines

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

G'day I'm using Direct3d 9 to render a 2d scene, however I have a little issue with alpha channels. When I render a polygon larger than the texture, the pixels are resized and smoothenned by a samplier. setSamplerState(0,D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); This works fantastic on images that dont have an alpha channel. However, when I render an image that has an alpha channel for transparent areas I get black edges around the shape. I am using the renderstates: SetRenderState(D3DRS_SRCBLEND , D3DBLEND_SRCALPHA); SetRenderState(D3DRS_DESTBLEND , D3DBLEND_INVSRCALPHA); I believe its due to the samplier resizing each channel. If we have a 2 pixel texture where is white to the left opaque and black transparent to the right, the alpha channel is a fade of white to black, and the colour channel is a fade of white to black, and the overall render results in white fading to black fading to the background colour of the buffer its being rendered onto. Is there any special tricks to avoid this appart from making black transparent be white transparent? Thanks :)

Share this post


Link to post
Share on other sites
I've not seen this on any of my recent GPU's, but I did notice this a lot on older ones (5-6 years ago). What hardware are you using, and if possible have you checked whether any quality/performance ratio's in the driver make a difference?

If you're using a colour-key to signify transparent areas then that solid colour can get pulled into the filtering equation and thus contribute to non-transparent areas.

On my GeForce 256 I ended up having lots of glowing pink plants in Deus Ex - they presumably used a pink colour key such that there was a 1-pixel pinkish line around every leaf [lol]

I'm not aware of any automagical ways of solving this artefact, but you can use a gutter/border around the opaque parts of an image. make the first transparent pixel have a zero alpha but the colour be the same as the neighbouring opaque pixel. It won't get rendered, but if it gets pulled into the filter for the opaque pixel it shouldn't make a noticeable contribution.

hth
Jack

Share this post


Link to post
Share on other sites
Sound like you're only enabling Alpha-Testing, and not Alpha-Blending. That would cause significant artifacts when filtering is applied to the texture.

If you've already enabled blending, your best bet is premultiplied alpha, as NTNET suggested. [smile]

Share this post


Link to post
Share on other sites
I think you can tried...
such as:
FinalColor = TexelColor * SourceBlendFactor + PixelColor * DestBlendFactor

struct CUSTOMVERTEX01
{
D3DXVECTOR3 position;
D3DXVECTOR3 normal;
};

struct CUSTOMVERTEX02
{
D3DXVECTOR3 position;
D3DCOLOR color;
FLOAT tu, tv;
};
struct CUSTOMVERTEX
{
FLOAT x, y, z;
DWORD color;
};

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
#define D3DFVF_CUSTOMVERTEX_ELLIPSE (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)
#define D3DFVF_CUSTOMVERTEX01 (D3DFVF_XYZ|D3DFVF_NORMAL)
#define D3DFVF_CUSTOMVERTEX02 (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)

................
................

g_pMyd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

g_pMyd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
g_pMyd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );

..............
..............
..............
g_pMyd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
g_pMyd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pMyd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

g_pMyd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
g_pMyd3dDevice->SetRenderState( D3DRS_ALPHAREF, 0x0f );
g_pMyd3dDevice->SetRenderState( D3DRS_ALPHAFUNC,D3DCMP_GREATEREQUAL );



Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Wow your right the premultiplied alpha channels work perfectly. I was actually using them before but stopped because it required me to make every texture a render target and i thought resizing wouldn't work properly...seems i thought wrong.

Dont supose theres a special way of loading a file and automatically premultiplying the alpha channel ?

Share this post


Link to post
Share on other sites
Preferably you can get your art tool to premultiply... I'm not sure if any support it. I think one of the Photoshop DDS plugins has an option, but I'm not 100% sure on that.

If that's no good, maybe make a utlity that load the images (into POOL_SCRATCH or SYSMEM), multiplies, then save them, and use those processed images in game.

If you want to skip a translation step, and don't mind a slight speed hit on each startup, you could do the pre multiply at load time. Load into SYSMEM, pre multiply it, wrapping it in a BMP header, then using D3DXCreateTextureFromFileInMemory.

It would be a nice thing to have added to the D3DXFILTER loading flags.


edit: Checked nVidia's normal map/DDS Photoshop tools. The have a DDS save tool with "Alpha modulate" under it's mip map settings. It works, except only for mip maps, so your top level surface isn't premodulated. I'm not quite sure what they were thinking. ;)

Share this post


Link to post
Share on other sites

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