2D Problem

Started by
4 comments, last by BlazingClaymore 16 years, 11 months ago
Hi guys, I have my 2D engine working almost perfectly but occasionally the texture coordinates come out wrong; it happens randomly but just enough that's it's noticable but there doesn't seem to be anything causing it. For example, if I have a 40x40 pixel sprite that I make all black and make the rest of the texture pink and display it on a black background I'll occasionally see a 1-pixel wide pink line so it's getting the soure coordinates wrong. I'm using pretransformed vertices (D3DFVF_XYZRHW|D3DFVF_TEX1) and subtract 0.5f from the X and Y values when I render. My texture is 1024x1024. It's driving me crazy because it hardly happens so I can't figure out the conditions that are causing it, I can't even duplicate it except by randomly moving my sprite around the screen waiting for it to happen. Any ideas ? The game is like a scrolling asteroids just so you have an idea. Here are the states I set right after I create D3D and setup the vertex/index buffers and texture: g_d3d_device->SetVertexShader(NULL); g_d3d_device->SetRenderState(D3DRS_ZENABLE,D3DZB_FALSE); g_d3d_device->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); g_d3d_device->SetRenderState(D3DRS_LIGHTING,FALSE); g_d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE); g_d3d_device->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA); g_d3d_device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA); g_d3d_device->SetFVF(D3DFVF_CUSTOMVERTEX); g_d3d_device->SetStreamSource(0,g_vertex_buffer,0,sizeof(CUSTOMVERTEX)); g_d3d_device->SetIndices(g_index_buffer); g_d3d_device->SetTexture(0,g_texture);
Advertisement
Two things I can think of:

1) Make sure you're using POINT filtering. How you set this depends on whether you're using the programmable pipeline or the fixed function one, but either way, you'll want to be using POINT filtering (unless you want scaling or rotation).

2) Try different numbers other than 0.5. I've heard people talk about 0.375 or 0.425 instead of 0.5, but the exact value may vary. Try different values and see if it helps at all.

Hope this helps.
Sirob Yes.» - status: Work-O-Rama.
Yeah, this is a common artifact when using linear filtering. Your texture coordinates are slightly wrong and sampler is fetching a pixel outside your intended region and this gets blended slightly into the final value - giving you the results you're observing [smile]

When using sprites the size of the entire texture you can set up your TC's to CLAMP to avoid similar wrap-around artifacts. For your case, where you're using a texture palette/atlas you're going to have to get your TC's 100% correct.

Draw it out on paper if I were you - and if you're not familiar with bilinear filtering (provided sirob's suggesting of using POINT isn't acceptable) then read up on how it fetches texels. Chances are you can quickly spot how/why it's getting unwanted values...

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

Hi guys,

Thanks for trying to help me but I'm still not sure what to research.

I don't know if I'm using the programmable pipeline or the fixed function one but I added these (even though they are the default):

g_d3d_device->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_POINT);
g_d3d_device->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_POINT);

I'm not sure if that's what you meant.

When I compute my texture coordinates I do it like this:

int angle=(between 0 and 17 inclusive);

tex_l=((float)angle*40.0f)/1024.0f;
tex_r=((float)angle*40.0f+40.0f)/1024.0f;
tex_t=100.0f/1024.0f;
tex_b=140.0f/1024.0f;

...the sprites on the bitmap start at (0,100), are 40x40 pixels, and are tiled left to right.

I usually see the artifact on the top or bottom, but most of the time it's perfectly fine. I'm not scaling, rotating or anything like that, it's all straight 2D (like DirectDraw).

I'll try some numbers other than 0.5 as well but i don't feel comfortable with that because I don't know what will happen on other people's computers.

Then I'll do some research on bilinear filtering.

I'm using VS2005 and doing everything in C++ (if that matters).

Thanks again.
The problem can be in z coordinate sorting. For example:
You have red background. In front of it are green woods, and then in front of woods is your blue ship.
If you position ship to 0.4 z coordinate and woods to 0.5, and you draw ship first, and then woods, you will see red line around your ship.
The program works fine, but ship 'alpha' piece is taken from background, and if you don't draw woods before ship, alpha piece will be red, because background is red.
So, even if direct x sort things right on z axis, you need to draw things in right order (background, woods and ship), it gives less headache.

Quote:
tex_l=((float)angle*40.0f)/1024.0f;
tex_r=((float)angle*40.0f+40.0f)/1024.0f;
tex_t=100.0f/1024.0f;
tex_b=140.0f/1024.0f;

I see you are using u,v coordinates that can be from 0.0f to 1.0f. That can be very painful if you use sprites of for example, 33x33 because 33/1024 will give you floating number that isn't so precise. You will get non-precise sprites coordinates , if you work with numbers like 0.32323232323 etc.

Easier way: DirectX have also ID3DXSprite interface. Defining sprite coordinates with this interface is much more easier. You need to define one rect structure and put coordinates in it.
In your example it will be:
rect.left = 40;
rect.right = 40;
rect.top = 100;
rect.bottom = 140;
and then you call draw method wit these coordinates.
Look at it.

Also one more thing [smile]
in
Quote:
tex_l=((float)angle*40.0f)/1024.0f;
tex_r=((float)angle*40.0f+40.0f)/1024.0f;
tex_t=100.0f/1024.0f;
tex_b=140.0f/1024.0f;


You don't need downcast to float because if angle is integer, multiplying integer with float is float, and you don't even get a warning.
So the shorter version is:
tex_l=angle*40.0f/1024.0f;
tex_r=(angle*40.0f+40.0f)/1024.0f;
tex_t=100.0f/1024.0f;
tex_b=140.0f/1024.0f;
well not really looked at the forum very much but I think it may be mipmaping see if you are using mipmaping it will mix the pixels from the top with the bottom so just turn it off or you can make the textures not tile. that will work probaly? yeah do that turn off the tiling. hope that helps

This topic is closed to new replies.

Advertisement