So in my noodlings around the world of D3D10 with the illustrious SlimDX as my guide, I came upon the need to pop up some debugging type info on the screen. Though sprites are somewhat of an outmoded concept, they are a convenient way to throw up a rectangle full of gunk, so I figured I'd go that route.
Now, the sprite's I remember are a rectangle defined against screen coordinates, with junk drawn in it. In dx9 you would declare them with the sprites offset and size, in pixels.
But this is D3D10, and I'm using it through SlimDX, which has no documentation or method of support (other than going on IRC so smug wanna be know it alls who can't answer your question mouth off and pretend that the question is beneath them -- note to library developers, do not have a IRC channel, ok? everyone on IRC is an asshole and you will just lose support)
So anyways, I find a nice Sprite class, so I go to new one up. It wants a Device, and that's cool - I got that, and it wants an int called 'bufSize'. What is bufSize, you ask? That's what I asked!
So the Sprite is only the interface to D3D for drawing sprites, the sprites themselves are defined in a class called SpriteInstance (which is how SlimDX wraps the sprite structure in D3D10). Sprite class can draw an array of SpriteInstances, either immediate mode, or buffered mode. That bufSize is how many sprites it should buffer in buffered mode.
So once I realized I needed to make a SpriteInstance, I went ahead and new'ed up one of those. It takes three paramaters, one of type ShaderResource - which binds it to the texture it's to draw, and two more of type Vector2D. The parameters are called 'coordinates' and 'dimensions'.
So I foolishly assumed coordinates and dimensions were the sprites location and size, in pixels, just like in the old APIs. Boy oh boy, I couldn't have been more wrong!
After examing the D3D10 api, and realizing that SpriteInstance mapped back to the sprite structure, I discovered that the texture you are attaching the sprite to is a sprite sheet. Coordinates is the offset in the sprite sheet to where your sprite starts, and dimensions is the dimensions of the image data in the sprite sheet that you want. Both are specified in texture coordinates (0 to 1).
So that's fine and good, now I have a sprite square in the middle of the screen, drawing what I want. But that's not where I want it, and that's not the size I want it to be. So now what?
Well, you apply a Transform to the SpriteInstance, of course.
By default the Sprite class draws against screen coordinates (which go from -1 to 1). The default center of a sprite is actual center (width/2, height/2), and not the top left corner like one might be used to. So, translating the sprite by -1 on the x axis effectively puts the center of the sprite on the edge of the screen, so half of it is clipped.
You can set the view and projection matrices on the Sprite class to change the default behaviour, but since my whole app is dealing in screen coordinates anyways, I never bothered.
So, lessons learned about Sprites in D3D10:
- designed to work off of a sprite sheet, created with coordinates and dimensions based off texture coordinates in said sprite sheet
- by default they live in screen space
- good for quick little popups and such, like the MessageBox.Show or Console.Writeline of the D3D debugging space, but if you really need "sprites" in your game or app, you are better off drawing and texturing quads by yourself. This way you will:
a) be doing the work on the GPU,
b) have the flexibility of applying whatever shader effects you want
c) keeping the ability to rearrange your geometry down the road when you decide those rectangles don't have enough zazz
Tuesday, November 17, 2009
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment