Unsure how to create a background

Started by
16 comments, last by MasterWorks 16 years, 2 months ago
Image files, when not in square power of two sizes get stretched by D3D when loaded into textures. If you want a background for a 1024x768 screen, make the image file 1024x1024 with a black (or any color) bar along the bottom. The stretching is default behavior and can be changed if the hardware supports non-square, non-pow2 texture sizes IIRC.
Advertisement
Quote:Original post by Cantos
If you want a background for a 1024x768 screen, make the image file 1024x1024 with a black (or any color) bar along the bottom.

I prefer an alternative method: create your image at some large resolution (at least 1365x1024) and then as your last step in an image editor, resize it (bilinear or better filtering!) to 1024x1024. Then, when you render the image fullscreen, it will be the correct aspect ratio AND contain more detail than the 'black bar' method (if your user chooses to run in a higher resolution) while still using the same amount of memory. Why fill valid space for pixel data with black?
I'm also having problems creating a background using D3DXCreateSprite. I'd be very grateful for some ideas without spawning a new topic!

i) How can you ensure all 3d appears in front of the background?

ii) The displayed image is scaled larger than life and I don't know why. I would ideally like to get pixel perfect texture from the file. How can I avoid this?


    // Load texture    if (FAILED(D3DXCreateTextureFromFile( m_pD3dDevice, L"..\\Clouds_over_hills.jpg", &g_pTexture)))    {       throw new turbine_exception("Could not find Clouds_over_hills.jpg");    }    // Create a sprite    if (FAILED(D3DXCreateSprite(m_pD3dDevice, &m_pSprite)))    {        throw new turbine_exception("Failed to create sprite");    }    D3DXVECTOR3 pos;    D3DCOLOR col = 0xffffffff;    pos.x = 0;    pos.y = 0;    pos.z = 1;// render loop    m_pSprite->Begin(0);    m_pSprite->Draw(g_pTexture, NULL, NULL, &pos, col);    m_pSprite->End();
What are the dimensions of Clouds_over_hills.jpg?

Quote:
I prefer an alternative method: create your image at some large resolution (at least 1365x1024) and then as your last step in an image editor, resize it (bilinear or better filtering!) to 1024x1024. Then, when you render the image fullscreen, it will be the correct aspect ratio AND contain more detail than the 'black bar' method (if your user chooses to run in a higher resolution) while still using the same amount of memory. Why fill valid space for pixel data with black?

Isn't that just needlessly complicated? You're never going to be seeing those extra 1024x256 pixels anyway.

Edit: Did not read your post correctly. Extra detail for higher resolutions. Got it.
Ok, I've (finally) managed to create a good looking background using TL Quads that were mentioned to me. My background is like so:

void gfxBackground::BuildVertexBuffer(){	g_device->CreateVertexBuffer(4*sizeof(VertPosRhwTex), // Number of vertices * Custom Vertex		D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &m_vb, 0);	VertPosRhwTex *v = 0;	m_vb->Lock(0, 0, (void**)&v, 0);	v[0] = VertPosRhwTex(    0.0f,    0.0f,  1.0f,  1.0f,  0.0f,  0.0f); // Top Left	v[1] = VertPosRhwTex( 1024.0f,    0.0f,  1.0f,  1.0f,  1.0f,  0.0f); // Top right	v[2] = VertPosRhwTex( 1024.0f,  768.0f,  1.0f,  1.0f,  1.0f,  1.0f); // Bottom right	v[3] = VertPosRhwTex(    0.0f,  768.0f,  1.0f,  1.0f,  0.0f,  1.0f); // Bottom left	m_vb->Unlock();}


with VertPosRhwTex declared as:

struct VertPosRhwTex{	VertPosRhwTex(float x, float y, float z, float rhw,			   float u, float v)		: p(x,y,z,rhw), t0(u,v) {}	D3DXVECTOR4 p;	D3DXVECTOR2 t0;	static LPDIRECT3DVERTEXDECLARATION9 Decl;};...D3DVERTEXELEMENT9 VertPosRhwTexElements[] =	{		{0, 0,	D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0},		{0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},		D3DDECL_END()	};	g_device->CreateVertexDeclaration(VertPosRhwTexElements, &VertPosRhwTex::Decl);


Now, i'm trying to configure it to get the best possible performance.

With a screen resolution of 1024x768 (also said when the vertex buffer is made) I have tried using a 1024x768 texture, 1024x1024 (stretch via photoshop, squash by d3d), and 1024x1024 with the top and bottom strips on (changing the vertex y positions to -128 or 896).

But I see no significant difference in frames per second, I assumed using a 1024x1024 texture would have been considerably faster?


also Zukix, I didn't understand why sprited were rather large, I think using this TL Quad i've just posted code for is very easy though and to make sure it's always in the background, just make the z value 1.0
>> What are the dimensions of Clouds_over_hills.jpg?

1024x681
300 dpi
24 bit

I tried removing the extra to make it 1024x680 but no difference.

I will try smally's code! (thanks smally).
Quote:
1024x681
300 dpi
24 bit

I tried removing the extra to make it 1024x680 but no difference.


Take your 1024x681 image into your image editor, turn off the "preserve aspect ratio" option, and stretch/resize it to 1024x1024, save it and see if that fixes your problem.

Quote:But I see no significant difference in frames per second, I assumed using a 1024x1024 texture would have been considerably faster?


Well, the hardware is not doing anything significantly different when it squashes a whole texture, or uses only part of it, the performance difference is likely to be similarly insignificant. Compare your method to an ID3DXSprite implementation.
Quote:Original post by smally
With a screen resolution of 1024x768 (also said when the vertex buffer is made) I have tried using a 1024x768 texture, 1024x1024 (stretch via photoshop, squash by d3d), and 1024x1024 with the top and bottom strips on (changing the vertex y positions to -128 or 896).

As you're discovering, there are a lot of ways to get the same results in D3D so choose whatever methods work best for your application.

I still think NOT using 'strips' and resampling to the correct power-of-2 image size is the best general purpose solution. In addition to faring better at higher resolutions, you get coding advantages as well. If you start having 'strips' or 'black areas' in your image files then you either need more complicated classes or ugly hard-coding on a per-sprite basis so that your engine knows how to deal with them correctly.

In my 2D games I have to use such techniques for many sprites, not just the background, so getting away from 'pixels' internally has a lot of advantages. One of my favorite things about doing 2D stuff in Direct3D is the flexibility that using texture coordinates for quads gives you. If you have a sprite that's using a 256x256 texture, you can open that image in Photoshop, resize it to whatever dimensions you want (even ignoring the proportions if you need to, like making it 1024x64), hit save, and it will work with no changes to your code. It might not be as pretty if you overdo it, but it will work. (More realistically, you can use this power to have high-resolution images for development and resize them as needed as a last step before release.)

As far as performance, note that your vertex buffer creation flags (and locking flags, when applicable) are usually going to influence performance far more than the pixel content of your data. Make sure you get the static/dynamic stuff right, make sure you're not recreating vertex buffers every frame, stuff like that. Not that you are, but these errors can create huge bottlenecks.

Quote:to make sure it's always in the background, just make the z value 1.0

Your textured quads don't even need to HAVE z values if you don't want; just turn z testing off and your render calls will overwrite whatever is in the backbuffer. If you're drawing a fullscreen quad, this effectively means that you'll erase whatever used to be there -- you don't even NEED to clear the backbuffer after every frame since you'll just be overwriting it anyways.

This topic is closed to new replies.

Advertisement