Sign in to follow this  
lonewolff

Using sprites for a GUI

Recommended Posts

I figure sprites would be an easy option for an overlay or GUI. Is there a way to position these into relative screen co-ordinates, so they are in fixed screen position, so they stay in the same place when the camera moves? Something like as follows? SpritePos(0.1,0.1) // Position sprite at 10% from top & left of screen I'd be interested if this could be done with models as well.

Share this post


Link to post
Share on other sites
If you use XYZRHW for your vertex declaration, it lets DirectX know that your coordinates are already transformed into screen space and it won't change them. I.E. (0,0) will correspond to the top left pixel and (640,480) the bottom right one (For that resolution monitor in fullscreen) to use your percentage based method it's pretty obvious to just multiply the percentage desired by your windows size.

Share this post


Link to post
Share on other sites
Of course you can.
A sprite is basically a [0, 0]->[1, 1] quad, so everything you have to do is set the corresponding world-view-projection matrix in order to scale, translate (and if needed rotate) its x,y coordinates to the position and size you want it to occupy in clip space.

If you are using ID3DXSprite helper class, you just have to set its WVP matrix with

HRESULT SetTransform(
CONST D3DXMATRIX * pTransform
);




that will be something like this

sx 0 0 0
0 sy 0 0
0 0 1 0
tx ty 0 1
([sx, sy] = size in clip space
[tx, ty] = position in clip space, in your case [0.1f, 0.1f])

then, during the rendering, inside the BeginScene EndScene couple you first

HRESULT ID3DXSprite::Begin(
DWORD Flags
);




with Flags = 0
then declare the texture bound to the sprite with

HRESULT ID3DXSprite::Draw(
LPDIRECT3DTEXTURE9 pTexture,
CONST RECT * pSrcRect,
CONST D3DXVECTOR3 * pCenter,
CONST D3DXVECTOR3 * pPosition,
D3DCOLOR Color
);




if you have just one texture per sprite, and don't need to change its color, you can use

pCenter = NULL
pPosition = NULL
Color = 0xFFFFFFFF

finally you call

HRESULT ID3DXSprite::End();


Share this post


Link to post
Share on other sites
Quote:
Original post by gabe83
sx 0 0 0
0 sy 0 0
0 0 1 0
tx ty 0 1
([sx, sy] = size in clip space
[tx, ty] = position in clip space, in your case [0.1f, 0.1f])

I am unsure of how to implement this. The following code is what I have in my main loop.
// Position and display sprite for GUI
mSprite->Begin(D3DXSPRITE_OBJECTSPACE|D3DXSPRITE_DONOTMODIFY_RENDERSTATE);

D3DXMATRIX mSpritePos;
D3DXMatrixTranslation(&mSpritePos,0.1f,0.1f,0);
mSprite->SetTransform(&mSpritePos);

RECT pRect={0,0,128,128};
mSprite->Draw(mSpriteTex,&pRect,&mSpriteCenter,0,D3DCOLOR_XRGB(255,255,255));
mSprite->Flush();
mSprite->End();

At the moment I am able to display my sprite but it is still in 3D space, not screen space. Could you please give an example of how to implement the matrix you have shown?

Thanks again.

Share this post


Link to post
Share on other sites
Quote:
Original post by gabe83
sx 0 0 0
0 sy 0 0
0 0 1 0
tx ty 0 1
([sx, sy] = size in clip space
[tx, ty] = position in clip space, in your case [0.1f, 0.1f])

I am struggling with this. I understand where sx & sy work but where does tx & ty come from?

Can anyone enlighten me?

Share this post


Link to post
Share on other sites
You are specifying D3DXSPRITE_OBJECTSPACE in the call to ID3DXSprite::Begin
this means that SetTransform will be ignored, since (taken from the DX Documentation)
Quote:

D3DXSPRITE_OBJECTSPACE :
The world, view, and projection transforms are not modified. The transforms currently set to the device are used to transform the sprites when the batched sprites are drawn (when ID3DXSprite::Flush or ID3DXSprite::End is called). If this flag is not specified, then world, view, and projection transforms are modified so that sprites are drawn in screen-space coordinates.


As for the question about tx, ty they are the x and y coordinates in clip space where you want the top left corner of the quad to be placed.
Those four lines i posted represent a transformation matrix that will be multiplied to the positions in world space of the four vertices of the quad in order to calculate their position in clip space. This means that the four vertexes of the quad whose coordinates are


[0, 0, z, 1],
[0, 1, z, 1],
[1, 1, z, 1],
[1, 0, z, 1]

(z coordinate is uninfluent)


after this transformation will be at


[tx, ty, 0, 1],
[tx, ty + sy, z, 1],
[tx + sx, ty + sy, z, 1],
[tx + sx, ty, z, 1]


You can get that matrix this way


D3DXMATRIX mSpritePos;
D3DXMatrixScale(&mSpritePos, 0.2f, 0.2f, 1.0f);
D3DXMATRIX translation;
D3DXMatrixTranslation(&translation,0.1f,0.1f,0);
D3DXMatrixMultiply(&mSpritePos, &mSpritePos, &translation);
mSprite->SetTransform(&mSpritePos);

([0.2f, 0.2f]=[sx, sx] that is the size of the sprite in clip space
[0.1f, 0.1f]=[tx, ty] the position of the sprite in clip space)

Share this post


Link to post
Share on other sites
Thanks for that gabe83.

Running through your example I cant see where 'D3DXMatrixScale()' is defined. There seems to be no mention on MSDN either.

The other odd thing is that in you MSDN note where SetTransform is ignored between Sprite begin & end, I seem to be able to move the sprite anywhere around 3D space in all directions x,y,&z using the snippet I supplied. Odd one...

Share this post


Link to post
Share on other sites

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