Home » Community » Forums » » 2D Rendering in DirectX 8
  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

Page:   1 2 3 »»

 Last Thread Next Thread 
 2D Rendering in DirectX 8
Post Reply 
As you state in your conclusion, it IS a rather involved way of doing a blit...and I can't see how I could have two things on the same screen (like a static background and a movable sprite) without either using multiple vertex buffers (which requires a lot of setup and LOTS of memory if I have, say, 128 sprites I want to use) or locking and unlocking a single buffer (which is slow). Is there no better way to just blit data to the screen in DirectX 8? If so, then Direct3D and DirectDraw weren't merged; DirectDraw was simply eliminated.

I can't see how I could wrap the code you've provided to create a generic "blit(texture, screenx, screeny);" function like I used to have in DOS.

This is unfortunate, since most beginning game programmers shouldn't start by trying to write a 3D game; it's too overwhelming. Most game programmers start by writing 2D stuff, but now they can't; EVERYTHING must touch Direct3D somehow.



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

quote:
Original post by BadmanX
I can't see how I could have two things on the same screen (like a static background and a movable sprite) without either using multiple vertex buffers (which requires a lot of setup and LOTS of memory if I have, say, 128 sprites I want to use) or locking and unlocking a single buffer (which is slow).




Use one vertex buffer and index into it.

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

Wouldn't that still require me to lock/unlock the buffer in order to change what's in it?



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

Finally! Thanks, Kelly. I really didn't like the idea of hunting odwn the DX7 docs just to do some 2d stuff. As for having to learn using 3d.. well, there are some 2d API/libs out there, if someone REALLY doesn't want to learn D3D. Mot of them are realy rappers for DD or D3d, so they will choke performance a little. But in a 2d APP, that usually isn't as much of a consideration, anyway.

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

Why lock&unlock? Just draw the vertices 1, 2, 3 of the VB, then change the appropriate matrix to draw in a different screen position, then draw vertices 4, 5, 6 with a different texture, if you like. If you need other changes (texture coordinates), you would need to lock the small VB's too, if you make 1 VB for every object.

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

That's doable, but it's still far more complex than I'm used to just to blit a sprite onto a screen.



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

DOH! I've been using 2 triangles (6 v's). I didn't even think to use a fan and save 2 verts.



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

If you only wanna do 2d graphics. I suggest that you take a look ID3DXSrite interface. You must use this interface like you use IDirect3DDevice interface. Check this interface under,
Dx8SDK->DirectX Graphics->D3DX Reference.

ID3DXSprite interface let you do 2D graphics in Dx8. You dont have to bother about matrices transformations, vertex buffer, index buffer and any other 3d related stuff.

To use ID3DXSprite correctly, i suggest that u make or re-edit your own tile or sprite class. Make them use a Texture instead of a bitmap, then use ID3DXSprite to draw.


simple render loop

void Render()
{
m_pDirectXDevice8->Clear (...); // clear the back-buffer
m_pDirectXDevice8->BeginScene ();

// 2d graphics stuff (like : tiles, sprites, console, ...)
m_pDxSprite->Begin();

// Here, call Draw of every 2d entity that you see.


m_pDxSprite->End ();

m_pDirectXDevice8->EndScene();
m_pDirectXDevice8->Present(0,0,0,0);
}


Simple drawing routine of a tile

void Entity::Render (LPD3DXSPRITE pSpriteSys)
{
// the draw function of ID3DXSprite
LPDIRECT3DTEXTURE8 pSrcTexture, // use your gfx texture
CONST RECT* pSrcRect, // rect of the tile you want inside your texture
CONST D3DXVECTOR2* pScaling, // if you want to scale it
CONST D3DXVECTOR2* pRotationCenter,
FLOAT Rotation,
CONST D3DVECTOR2* pTranslation, // want it to move !
D3DCOLOR Color // Color keying, usefull to do alpha-blending
}


Anyway, check that interface for your new tile-based game. You wont regret it !

Jonathan

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

Is doing 2d in D3D really worth all the extra pain of thinking 3d while doing 2d?? Sure you can do different effects with it, but are those extra's worth it?

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

I think ID3DXSprite is now the easiest way to make a 2d game. It would be a great idea to update the "For beginner" section of gamedev.net for more information about this. It seems that even tutorial writers are too much deep in pure D3D to see that D3DXSprite is the replacement of DirectDraw !

Here is a simple tutorial that saved my life... (as I was choosing between dd7, d3d8 or even opengl... for a simple 2d game) :
http://www.angelfire.com/realm/zeroone/2dsprite.htm

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

It's absolutely true that the sprite class is the easiest way to go, but it's good to explain the guts so that people would know what's going on under the hood.

About locking - everyone always talks about locking, but I can think of very few instances where you absolutely need to. You could set up a framework that has one vertex buffer of a unit square with full texture coordinates, then use a matrix to rescale and reposition, and a texture matrix to mess with the tex coords if need be - no locking!

Two things on one screen:
//Scale/Position Background
//Set Background texture
//Draw
//Scale/Position Sprite
//Set Sprite Texture
//Draw

-One VB, no locking. The only memory usage is two textures and ONLY 4 vertices!

About a generic Blit(Texture, X, Y) function - assuming the texture is a preloaded DX8 texture pointer, the function looks like:

Blit(Texture, X, Y)
{
//use texture interface methods to find the size
//Build my translation/scaling matrix based on X, Y, and size
//set the transform to my matrix
//set the current texture to my texture
//draw my vertices
}

About thinking in 3D/complexity, etc. - Keep in mind that by doing things this way, you're not "thinking in 3D", you are "thinking like the card thinks". Like it or not, the card is REALLY good at dealing with vertices, vectors, and matrices. You can ignore all that and think in terms of blits, but you are ignoring alot of the horsepower available to you!

Having said all that, the D3DXSprite class (or the wrapper) is easy to use, but for anyone who's interested, there are probably lots of custom optimizations you can make if you know what's under the hood (better vertex usage, texture usage, etc.) As far as I can tell, this is essentially how D3DXSprite is done.


Edited by - CrazedGenius on July 6, 2001 4:16:18 PM

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

One thing missing from the article - make sure you release the interface pointers when the program terminates.

(I'm hoping most people know that, but just in case...)

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

BadmanX: DirectX has gotten easier to use with every revision, and Direct3D is a lot easier to do now, for 2D OR 3D graphics than DirectDraw was a few releases back. Sure, when you're beginning you need it easier than at any other point, but that's what this tutorial and the huge amount of tutorials/libs are for. Also, if you have 128 sprites, are they all facing the same way? How much memory does it take to have local copies of each direction it faces? It's going to be a lot smaller if you use a vertex buffer and ONE texture. And yes, using that tutorial you can come up with a way to get it down to one function call to blit an image to the screen. Just like in DirectDraw, it's not one function call, you have to set up your surface beforehand. There's not much of a difference now, it's just another type of setup.

In the end, if you need to do something and you just don't want to learn how, get a tool.

G'luck,
-Alamar

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

It's true that D3DXSprite is just a D3D wrapper for 2d stuff but when beginners just want to get something on the screen, I think it should be the first thing to learn. Beginners simply don't want to learn 3D stuff first.

If you compare D3DXSprite with DirectDraw, you can say it's better for a lot of simple things like alpha blending, rotation, filtering and it's still really simple ! I don't want to set up a 3d matrix when I just want an image on the screen.

I don't care how the card work for now because I just want to have fun seeing my game working... After all, these optimization are not really needed for a simple 2d game. Optimization fever is really a bad thing. I want to program my game, not a new graphic engine. D3DXSprite is there and it's really what I need. That's all.

alexk7@alexk7.com

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

D3DXSprite has compatibility problems. If the video card does not support A1R3G3B3 pixel format then you cannot get transparency in hardware mode w/ out using an alpha channel (like dds files). This will require an extra bmp for every image you want to use. Its a huge pain. Plus you have problems w/ textures that arent in powers of 2.

You can never be sure a video card supports any particular pixel format.

I had a D3D8 2D engine, but gave it up and went back to DirectDraw to get more compatibility. I sure do miss the alpha blending though...

ratman

---------------
Ratfest.org

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

Ratman - are you sure about that?

On pixel formats - I think you can use D3DXCreateTextureFromFileEx and specify a format that works plus a color key value. I haven't tried this in all possible combinations, but it should work. You can also find out which formats are supported, and I think A8R8G8B8 is a pretty safe bet and alpha/ColorKey friendly.

On powers of 2 - Yes, but a couple things...
1. That's changing, newer hardware can handle arbitrary sizes and you can ask the device if it needs powers of 2.
2. You can write a pretty simple function to load bitmaps, figure out the nearest power of 2, and copy the bitmap into the texture. You'll also have to take that into account when you specify coordinates.
3. Yes, it's a real pain in the behind, no argument. I guess the only reason I like it is because it is more efficient and that ultimately means less trips across the pipe.

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

Thanks to everyone who replied, especially alexK7, b2Funny and CrazedGenius. I found out what I wanted to know, which is the interface that recreates DirectDraw under DirectX 8. While the docs for DX8 _are_ complete, they are not terribly well-organized, IMO.

Thanks again.

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

quote:
From article...
In short, 2D rendering in D3D on 2D hardware should have pretty much the same performance as DirectDraw, assuming decent fillrate.


Direct3D 8.0 does not have a software renderer, so it will not function on purely 2D hardware. It has a pluggable renderer function, but it is the application developer who must write the software renderer.

Steve 'Sly' Williams  Code Monkey  Krome Studios

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

I can remember installing D3D8 SDK and found that the samples didn't work on older non3d video cards. The reason is that D3D8 don't have a Software rastrerizer and forced to use its reference rasterizer which is TOO slow.

So, I can't run this in D3D8 but its ok for D3D7 which has a SW raster AND the D3DX interfaces (which are really good).



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

Useful article for us newbies, thanks. However...

Anyone actually try and type in the code from this article? I assume that in the line:

//Set all the colors to white
pVertices[0].d = pVertices[1].d = pVertices[2].d = pVertices[3].d = 0xffffffff;

the .d fields should actually be .color?

Even still, I ended up with a green window, with no rectangle (at the point in the article before texturing).



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

quote:
Original post by Anonymous Poster
Useful article for us newbies, thanks. However...

Anyone actually try and type in the code from this article? I assume that in the line:

//Set all the colors to white
pVertices[0].d = pVertices[1].d = pVertices[2].d = pVertices[3].d = 0xffffffff;

the .d fields should actually be .color?

Even still, I ended up with a green window, with no rectangle (at the point in the article before texturing).




Ignore me, unlocking the VB TOTALLY helps.



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

yes - .d = .color

that's the problem with pasting code from multiple projects...

Other than that, it should work.

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

Hmm, that whole tutorial seems a little bit inefficient. Why not use pretransformed verices when doing 2D? Sending the triangles directly to the rasterizer is much more effective than sending them through the transformation pipeline first. Seems very stupid.

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

I was first using DX7. To perform alpha-blending, I used pretransformed triangles directly sent to the rasterizer as well as the method described in the tutorial. Performance decrease was only significant for really large amount of sprites (above 300 in high resolution), and I am almost convinced (after some trials) that this decrease is due to 3D card fillrate and not to matrix calculation (performed by CPU or card for newer system). When I switch to DX8, the use of ID3DXSprite interface simplified the whole procedure, for even better performances. The tutorial describes a good and efficient method. The author says that his method is not optimized, and some improvement could be done. Yet, I would have been really happy to find such a tutorial when I was learning this part of DX.

It's definitely a good tutorial, and a good introduction to DX8 2D rendering.

 User Rating: 1015    Report this Post to a Moderator | Link
Page:   1 2 3 »»
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: