Jump to content
  • Advertisement
Sign in to follow this  
smally

Unsure how to create a background

This topic is 3788 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, i'm currently unsure of how to go about doing my background in Direct3D 9. I'm making a small game (simple point and click e.g monkey island) that will have a 2D Texture as the background, with a few 3D models in the foreground. The only way I know on how to do this is to create a geometric quad, however I'm struggling to get the 'perfect' lookat camera angle to work (there are either gaps between the window edge and the quad or part of the quad is cut off from viewing). I'm not very familiar with sprites, as the book that I'm learning from only ever talks about the 3d stuff, plus I think I've read somewhere that its best to use quads anyway. How should I go about do this, and if using a quad is the best idea, how do I get the view right? Thanks in advance

Share this post


Link to post
Share on other sites
Advertisement
From your description you really want to be rendering your background in 2D rather than as a billboard/imposter.

It is perfectly normal to mix rendering like this, so just because you have some 3D elements doesn't mean everything must be 3D (although, strictly speaking its more "2D in 3D" as you still have a depth axis [smile]).

Use of ID3DXSprite is a nice and simple way of doing things, but manually creating a full-screen "transformed and lit quad" (aka 'TL Quad') is easy enough. Look up the D3DFVF_XYZRHW or POSITIONT vertex data formats.

hth
Jack

Share this post


Link to post
Share on other sites
This is how I've been doing this sort of thing.


d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

IDirect3DSurface9* backBuffer = NULL;
d3dDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&backBuffer);

// IDirect3DSurface9* background;
// Initialized outside the render loop!
d3dDevice->UpdateSurface(background,NULL,backBuffer,NULL);

d3dDevice->BeginScene();
// ... rest of render loop ...



No idea of the performance of this method compared to ID3DXSprite or a textured quad.

Share this post


Link to post
Share on other sites
Whilst not as terrible as messing with the raw backbuffer data, I'd suspect that your code is not as efficient as a full-screen TL quad. Then again, if you're not stressing out the GPU and performance isn't an issue it is a neat and elegant solution to the problem [smile]

Jack

Share this post


Link to post
Share on other sites
I've followed this websites advise http://nexe.gamedev.net/directKnowledge/default.asp?p=2D%20In%20Direct3D , and created the follow (bear in mind i'm using vertex elements in preparation for when I implement shaders)


struct VertPosTexRhw
{
VertPosTexRhw(float x, float y, float z, float RHW
float u, float v)
: p(x,y,z), t0(u,v), rhw(RHW) {}

D3DXVECTOR3 p;
float rhw;
D3DXVECTOR2 t0;

static LPDIRECT3DVERTEXDECLARATION9 Decl;
};

...

D3DVERTEXELEMENT9 VertPosTexRhwElements[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
{0, 20, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 1},
D3DDECL_END()
};
device->CreateVertexDeclaration(VertPosTexRhwElements, &VertPosTexRhw::Decl);




and for creating the quad i've done:


void gfxBackground::BuildVertexBuffer(LPDIRECT3DDEVICE9 device)
{
device->CreateVertexBuffer(4*sizeof(VertPosTexRhw), // Number of vertices * Custom Vertex
D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &m_vb, 0);

VertPosTexRhw *v = 0;

m_vb->Lock(0, 0, (void**)&v, 0);

v[0] = VertPosTexRhw(-1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f);
v[1] = VertPosTexRhw( 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f);
v[2] = VertPosTexRhw( 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f);
v[3] = VertPosTexRhw(-1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f);

m_vb->Unlock();
}

...

void gfxBackground::BuildIndexBuffer(LPDIRECT3DDEVICE9 device)
{
device->CreateIndexBuffer(2*3*sizeof(WORD), // Number of triangles * 3 * sizeof
D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_ib, 0);

WORD *i = 0;

m_ib->Lock(0, 0, (void**)&i, 0);

i[0] = 0; i[1] = 1; i[2] = 2;
i[3] = 0; i[4] = 2; i[5] = 3;

m_ib->Unlock();
}

...

void gfxBackground::Display(LPDIRECT3DDEVICE9 device, const D3DMATERIAL9* mtrl, LPDIRECT3DTEXTURE9 tex)
{
device->SetTexture(0, tex);
device->SetMaterial(mtrl);

device->SetStreamSource(0, m_vb, 0, sizeof(VertPosTexRhw));
device->SetIndices(m_ib);
device->SetVertexDeclaration(VertPosTexRhw::Decl);

// Draw the background
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2);
// TRIANGLELIST, 0, 0, How many vertices, 0, How many triangles
}




But the quad doesn't show now? Am I miss using the rhw thing

Share this post


Link to post
Share on other sites
Quote:
Original post by jollyjeffers
Whilst not as terrible as messing with the raw backbuffer data, I'd suspect that your code is not as efficient as a full-screen TL quad. Then again, if you're not stressing out the GPU and performance isn't an issue it is a neat and elegant solution to the problem [smile]

Jack


I built a simple application to test your suspicion and found that using ID3DXSprite in place of an UpdateSurface call like I had above was about 8% faster in my test case (1024x768 windowed, no other geometry). Good to know.

Share this post


Link to post
Share on other sites
I think this type of problem comes up a lot because people don't realize how general-purpose Direct3D is. When I was learning D3D coming from a 2D game background I didn't realize the full flexibility you have to render things both '2D' and '3D' in the same frame. You're free to build up the frame buffer(s) with all kinds of pixels coming from different textures, vertex formats, models, whatever. It's totally up to you how to paint the blank canvas that you're given at the start of each frame. Whatever you render first (like a huge sprite or textured quad) will be in the background; don't worry about making sure it fits into your 'world' with the correct units, alignment, and all that garbage.

Share this post


Link to post
Share on other sites
So what is more popular/effecient to use for a background, a sprite or this TL Quads I can't get the hang of

Share this post


Link to post
Share on other sites
As my understanding of Direct3D and ID3DXSprite goes, sprites are actually textured, lit quads. They just come wrapped in a handy interface to handle the complex bits for you.

Share this post


Link to post
Share on other sites
Ok, well I tried to get the POSITIONT stuff to work but either nothing shows up on screen or it just acts as a normal quad.

I've now implemented a sprite correctly, but I'm still struggling on how I get it to fit the window properly?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!