Jump to content


Transparent Image Sorting?


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

#1 Thales

    Member

  • Members
  • PipPip
  • 32 posts

Posted 16 March 2006 - 06:54 PM

Hello,

I'm using DX9.0, and am rendering 2D images on quads. Right now the images are simply trees, with transparent sections where there is no tree.

Is z-sorting required when two or more of these images overlap? It is the way I'm doing it now, but it seems to me that if the z buffer's value is retained (ignored) for sections where the image is transparent, this wouldn't be an issue. I wouldn't have to z-sort. Iows, where the alpha channel value is zero, don't change the z buffer's value, but do change it where the current image is opaque and closer than previous images.

Is this doable?

Note, I'm not doing translucency, i.e. partial transparency, but, rather full transparency, which means that the technique should work, so long as there is a means to doing it.

Is there some other trivial way of doing this without z-sorting?

I'm using the following code now:


	g_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);

	g_pDevice->SetTextureStageState(0,D3DTSS_ALPHAARG1, D3DTA_TEXTURE);

	g_pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);

	

	g_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);

	g_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);


	g_pDevice->SetStreamSource(0, m_pQuad, 0, sizeof(VertTx));

	g_pDevice->SetFVF(VertTx::FVF);

	g_pDevice->SetTexture(0, m_pTexture);

	g_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

	g_pDevice->SetTexture(0, NULL);

	g_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);


Thanks for any feedback!

#2 Reedbeta

    DevMaster Staff

  • Administrators
  • 4979 posts
  • LocationBellevue, WA

Posted 16 March 2006 - 07:02 PM

The functionality you're looking for is called 'alpha test'. I don't know how to enable it in Direct3D though; try googling.
reedbeta.com - developer blog, OpenGL demos, and other projects

#3 Wernaeh

    Senior Member

  • Members
  • PipPipPipPip
  • 368 posts

Posted 16 March 2006 - 07:04 PM

How many sprites do you render anyways ? :)

Usually you can get away with manually sorting them if there aren't too many (thinking of a simple 2D top down game here).

There are some other ways though. I'm more on the OpenGl-side of things, but I guess there is an alpha testing option in DX too. This option disables writing on pixels that have an alpha value smaller than some given bias. Consequently, it neither updates the depth buffer.
You say you only have full transparency, and no translucency. If so, this could be your way of choice. However, note that any filtering or mipmapping might still create continuous changes in alpha.

The usual way to go if not manually sorting is to first render all solid geometry, then to enable alpha testing and render all translucent geometry, and live with the artifacts.

More sophisticated, hardware based approaches use special tricks, but still are limited in the depth of sprites until artifacts still show up. For example, see the Depth Peeling techdoc at nvidia's page.

Finally an alternative approach is to choose a commutative blending mode, such as additive blending (though I think it's not your intent if you only use full translucency)

Cheers,
- Wernaeh

#4 Wernaeh

    Senior Member

  • Members
  • PipPipPipPip
  • 368 posts

Posted 16 March 2006 - 07:04 PM

@ Reedbeta
Hehe took me too long to write that post :)
Cheers,
- Wernaeh

#5 bignobody

    Valued Member

  • Members
  • PipPipPip
  • 155 posts

Posted 16 March 2006 - 07:20 PM

Wow. 3 posts in the time it took me to check my code.

For D3D check the D3DRS_ZFUNC and various D3DCMPFUNC values that are available. I usually set to D3DCMP_GREATER before rendering my particles and then back to D3DCMP_LESSEQUAL when finished (the default value).

Regards,
-bignobody
notsoftgames.com - Creator of Shlongg!

#6 bignobody

    Valued Member

  • Members
  • PipPipPip
  • 155 posts

Posted 16 March 2006 - 07:25 PM

Oops. D3DRS_ALPHAFUNC, not D3DRS_ZFUNC.


// from the DX8 docs...

dev->SetRenderState(D3DRS_ALPHAREF, (DWORD)0x00000001);

dev->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); 

dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);


-bignobody
notsoftgames.com - Creator of Shlongg!

#7 Thales

    Member

  • Members
  • PipPip
  • 32 posts

Posted 16 March 2006 - 09:08 PM

Hey, it's good to see three quick and thoughtful responses.
:yes:

The alpha test method works perfectly.

Just as the example above, the code I ended up with was the following:


	g_pDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER); 

	g_pDevice->SetRenderState(D3DRS_ALPHAREF, (DWORD)0); 

	g_pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);


	g_pDevice->SetStreamSource(0, m_pQuad, 0, sizeof(VertTx));

	g_pDevice->SetFVF(VertTx::FVF);

	g_pDevice->SetTexture(0, m_pTexture);

	g_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

	g_pDevice->SetTexture(0, NULL);

	g_pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);




Btw, to create a texture with an alpha channel, I'm using the DirectX Texture Tool (with Photoshop), to create a dds texture, e.g. mytexture.dds. Is there a more convenient way to create such a texture using Photoshop only? Do jpegs retain alpha channel info? dds textures are rather large in size in comparison to jpegs.

Thanks again for the help.

#8 bignobody

    Valued Member

  • Members
  • PipPipPip
  • 155 posts

Posted 16 March 2006 - 09:32 PM

You're probably stuck with .dds (it's what I use too).

Found this here: http://www.faqs.org/...jpeg-faq/part1/


Subject: [12] Can I make a transparent JPEG?

No. JPEG does not support transparency and is not likely to do so any time
soon. It turns out that adding transparency to JPEG would not be a simple
task; read on if you want the gory details.

The traditional approach to transparency, as found in GIF and some other
file formats, is to choose one otherwise-unused color value to denote a
transparent pixel. That can't work in JPEG because JPEG is lossy: a pixel
won't necessarily come out *exactly* the same color that it started as.
Normally, a small error in a pixel value is OK because it affects the image
only slightly. But if it changes the pixel from transparent to normal or
vice versa, the error would be highly visible and annoying, especially if
the actual background were quite different from the transparent color.

A more reasonable approach is to store an alpha channel (transparency
percentage) as a separate color component in a JPEG image. That could work
since a small error in alpha makes only a small difference in the result.
The problem is that a typical alpha channel is exactly the sort of image
that JPEG does very badly on: lots of large flat areas and sudden jumps.
You'd have to use a very high quality setting for the alpha channel. It
could be done, but the penalty in file size is large. A transparent JPEG
done this way could easily be double the size of a non-transparent JPEG.
That's too high a price to pay for most uses of transparency.

The only real solution is to combine lossy JPEG storage of the image
with lossless storage of a transparency mask using some other algorithm.
Developing, standardizing, and popularizing a file format capable of
doing that is not a small task. As far as I know, no serious work is
being done on it; transparency doesn't seem worth that much effort.


Regards,
-bignobody
notsoftgames.com - Creator of Shlongg!

#9 geon

    Senior Member

  • Members
  • PipPipPipPip
  • 893 posts

Posted 16 March 2006 - 10:28 PM

bignobody:

Just store the aplha as a 2-colored .GIF, then. That would compress very well, and there are no artifacts.

#10 Reedbeta

    DevMaster Staff

  • Administrators
  • 4979 posts
  • LocationBellevue, WA

Posted 17 March 2006 - 01:11 AM

And if you ever decide you need a full 8-bit alpha channel to allow translucency as well, you can use the PNG format (though I don't know how well its compression compares to that of DDS).
reedbeta.com - developer blog, OpenGL demos, and other projects

#11 juhnu

    Valued Member

  • Members
  • PipPipPip
  • 292 posts

Posted 17 March 2006 - 01:44 AM

you could try compressing .dds files using a .zip or some other file compression method to make file sizes more bearable.

If you are only using alpha-testing and not blending, you might have a problem with the mipmaps. You tend to get haloes around silhouettes because of the downsampling so it might be useful to sort your geometry from back to front and using the alpha blending.

#12 bignobody

    Valued Member

  • Members
  • PipPipPip
  • 155 posts

Posted 17 March 2006 - 02:09 AM

I'm with juhnu on this one. .dds is convenient, and I just did a quick test and zipped a 512x512 texture with an alpha channel. It went from 1024 kb to 213kb. Good enough for me!
-bignobody
notsoftgames.com - Creator of Shlongg!





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users