Home » Community » Forums » » Dissecting Sprites in Direct3D
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic


 Last Thread Next Thread 
 Dissecting Sprites in Direct3D
Post Reply 
Color keying works fine in DX8. If you use it
instead of alpha blending, you can use the
D3DFMT_R5G6B5 format which looks better than
D3DFMT_A1R5G5B5 and you'll get higher performance
than with blending.

You simply have to load surfaces/textures with
a color key argument and set up your device like
this:

dev->SetRenderState(D3DRS_ALPHATESTENABLE, true);
dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NOTEQUAL);
dev->SetRenderState(D3DRS_ALPHAREF, 0x00);


 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

If you don't have any alpha information in your pixel format, how the alpha test can work ? It doesn't make sense...

 User Rating: 1025   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I use sprites alot even when making 3D games: for UI, for iconizing 3D objects when zoomed far and so on. D3D provides VERY powerful ways to blit sprites, much more powerful that regular Blit.

1. The best way to load textures in DX8 is to use D3DXCreateTextureFromFile family of functions (those are part of D3DX library included with DX8). It loads textures wonderfully; creates MipMaps if requested; makes pixels with given color transparent; and the best of all - it can load 32-bit TGAs that allows to specify 8-bit alpha-channel.
Try it! And dont forget to set the right states: ALPHABLENDENABLE - TRUE, SRCBLEND - SRCALPHA, DSTBLEND - INVSRCALPHA, etc.

2. Some neat effects can be achieved by specifying diffuse colors for your vertices. If the same color used for all the vertices, texture will be "evenly colorized", otherwise "colorisation" will be interpolated from one vertex to another. As ususal, dont forget to set right states: COLOROP - MODULATE; COLORARG1 - TEXTURE; COLORARG2 - DIFFUSE, etc

3. Set SRCBLEND and DSTBLEND render states to ONE and sprite pixels will be added (as oppose to replace) to the screen pixels (good for glow, fire, smoke)

4. Try to set vertex color's alpha to regulate transparency of your sprites.

5. Try to avoid changing textures as much as possible. For example: in 256x256 texture one can have 16 64x64 sprites.
Then to draw sprite #0 use following UVs: (0,0, 0.25f,0.25f); to draw sprite #1 use (0.25f,0, 0.5f,0.25f), etc.

6. Try to use as little DrawPrimitive as possible. I.e. to draw 100 spries on screen dont call DrawPrimitive 100 times. Instead create and fill an array of 100x3x2 vertices and DrawPrimitive( TRIANLELIST ) once with those.

PS: About "off my one Microsoft bug":
From my knowledge Microsoft stole this bug (along with the UI and GDI) from Apple's MacOS back in 1980s. I remember reading "Inside Macintosh" at the time and reading something about "mathematically pixels are infinitely thin" and blah blah blah... Whoever inveneted it must die, but now it's too late to change for compatibility reasons.

Cheers!
Meduzza

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

maybe it's just me, but when I run that demo program included with the article, I can see NO difference whatsoever between the 1st, 2nd and 4th sprites, ie, the authors blit routine seems to produce the EXACT same result as ID3DXSprite.

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I get exactly same result as Anozireth. No difference in the three different blit types (exept color and size/rotation...)

but performance is slightly better with the authors blits!

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by Ninebit
I get exactly same result as Anozireth. No difference in the three different blit types (exept color and size/rotation...)



Me to...

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Read this article when trying to achieve pixel-per-pixel mapping for my GUI... and spend a whole lot of time figuring out how it would work. I had a basic D3D8 setup, but I did want to keep my DirectX transformation matrices (orthogonal of course) instead of using TLVERTICES, in order to be able to move windows without locking the vertex buffer etc. . With the method from the MSDN article ("Directly Mapping Texels to Pixels"), it did not really work - my test picture (pixel grid) still was very blurred and showed artifacts. After several hours I came to the idea to turn off filtering when loading the texture :-)

The blur was no longer there, but there were still visible artifacts - double top and left borders and some problems in the middle. Offsetting the vertices by 0.5 pixels horizontally to the left and vertically to the top only fixed the borders, after some trying out I managed to get a pixel-perfect copy of my grid by using following offsets: -0.75 horizontal, -0.85 vertical (No shrinking/expanding of the rectangle as recommended by the "microsoft bug" guys). This is kind of strange and I'd like to know how these numbers come along - I tried it with other values and there were artifacts - has anyone of you experienced sth. like that or what method for achieving pixel-perfect mapping did/did not work for you? BTW, in the blit demo, the sprites 1-4 are identical for me as well. My gfx card is a TNT2, I run WXP with DX 8.1 (latest nVidia drivers).

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

My program will not compile, I get these errors

Compiling...
d3dblit.cpp
Linking...
d3dx8.lib(cpudetect.obj) : error LNK2001: unresolved external symbol __imp__RegCloseKey@4
d3dx8.lib(cd3dxassembler.obj) : error LNK2001: unresolved external symbol __imp__RegCloseKey@4
d3dx8.lib(cpudetect.obj) : error LNK2001: unresolved external symbol __imp__RegQueryValueExA@24
d3dx8.lib(cd3dxassembler.obj) : error LNK2001: unresolved external symbol __imp__RegQueryValueExA@24
d3dx8.lib(cpudetect.obj) : error LNK2001: unresolved external symbol __imp__RegOpenKeyA@12
d3dx8.lib(cd3dxassembler.obj) : error LNK2001: unresolved external symbol __imp__RegOpenKeyA@12
Debug/d3dblit.exe : fatal error LNK1120: 3 unresolved externals
Error executing link.exe.

d3dblit.exe - 7 error(s), 0 warning(s)


Please help. I got the as my modules

d3d8.lib d3dx8.lib dxerr8.lib user32.lib gdi32.lib

and the library and include in the right directories

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link


I used following modules:
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib d3d8.lib d3dx8.lib dxerr8.lib user32.lib gdi32.lib

worked fine in release and debug

(VC++ 6.0, DX9SDK (update summer 2003)



[edited by - w2d on January 5, 2004 6:57:54 AM]

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I have linking errors when trying to build the .exe

I had problems finding libci.lib to link and I found it in the IA64 subdirectory of the Microsoft SDK\lib\ so I set the path and tried to link

but...

LIBC.lib(typinfo.obj) : fatal error LNK1112: module machine type 'IA64' conflicts with target machine type 'X86'

 User Rating: 1517   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Add libc.lib in "Ignore Specific Library" and try again.

Thanks,
Karthik

 User Rating: 1015    Report this Post to a Moderator | Link

It's not working for me.. I can't ignore the libci.lib without having problem with my texture.
Other idea?

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Trying to port this across to directx9, it all seems to run perfectly but I only get the first sprite which is just a black empty box.

Any ideas? replaced my old 2D sprite loading code with it as it made more sense (some of my sprite sheets are over the texture size limits you see).

Thanks!

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by PaperFace
Trying to port this across to directx9, it all seems to run perfectly but I only get the first sprite which is just a black empty box.

Any ideas? replaced my old 2D sprite loading code with it as it made more sense (some of my sprite sheets are over the texture size limits you see).

Thanks!
We'll need to see relevant code. I'd suggest starting a new topic in the DirectX forum.

 User Rating: 2014   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

One glaring problem I noticed with this tutorial is that he blames Microsoft for not reading the documentation right or searching for the problem on the internet.

It's stated pretty clearly in this article:

"The column of pixels at the right edge and the row of pixels at the bottom edge are not included in the RECT."

So the documentation is correct. As for not reading the documentation right, the writer of the article thought that in order to get correct pixel to texel alignment, they had to expand the blit rectangle by 0.5 on each side. What SHOULD have been done, however, is well discussed in this article.

His source also seems to blame until you actually read the article in question. It DOES say to expand the rectangle in the FAQ, but the article itself presents the correct fix.

I do agree, though, that a custom sprite implementation would be worth the work since it would be much more flexible, and depending on what you need and how well it's coded, faster.

(Do forgive me if I'm bumping an old topic, I followed a link from google to the article and felt obliged to correct the problems for those who may be confused.)

Edit: I caught this while I was reading the above just now:
"6. Try to use as little DrawPrimitive as possible. I.e. to draw 100 spries on screen dont call DrawPrimitive 100 times. Instead create and fill an array of 100x3x2 vertices and DrawPrimitive( TRIANLELIST ) once with those."

It's actually faster to create 4 vertices, one triangle strip or fan (strips are ever so slightly faster according to what I've read), then change the world transform matrix and draw primitive. There's less data being sent to the GPU :
Well I suppose people should check both ways to see what's faster. I'm sure there's a trade-off point somewhere in there.

[Edited by - MushroomSamba on January 30, 2009 3:48:43 AM]

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: