Sign in to follow this  
n44in4

Direct3D - Very strange 2D displaying problem

Recommended Posts

n44in4    123
Hello guys, I have discovered a strange problem while developing a 2D Engine using Direct3D 9. I'm working on two different systems on the same project - one (my workstation) with AMD Athlon 1000 w. ATI Radeon 9600 Pro and one (my notebook) Intel Pentium M 1500 w. ATI Radeon 9200 Mobility. Take a look at following picture, which I made on my notebook: APIX Engine screenshot Do you see the little glitches I marked red? I guess the right triangle of the screen quad is somewhat distorted. Whyever, that's my problem, I don't know where they are coming from, since I don't have this problem on my workstation. Hoping this is not a driver issue... Now take a look at the code responsible for the problem:
/* SOME DEFINITIONS */
struct AG_VERTEX {
/* XYZ */     FLOAT x, y, z;
/* DIFFUSE */ DWORD c;
/* TEX0 */    FLOAT u, v;
};

#define D3DFVF_AG_VERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)

#define AG_SCREENQUAD_X 1.0f
#define AG_SCREENQUAD_Y 1.0f
#define AG_TEXQUAD_MAX	1.0f // !!! BAD BOY !!!

const static AG_VERTEX AG_SCREENQUAD[] = {
/*               X                 Y          Z       Color     U               V */        
/*1*/	{-AG_SCREENQUAD_X, -AG_SCREENQUAD_Y, 0.0f, 0x00000000, 0.0f,			AG_TEXQUAD_MAX},
/*2*/	{-AG_SCREENQUAD_X, +AG_SCREENQUAD_Y, 0.0f, 0x00000000, 0.0f,			0.0f},
/*3*/	{+AG_SCREENQUAD_X, +AG_SCREENQUAD_Y, 0.0f, 0x00000000, AG_TEXQUAD_MAX,	0.0f},
/*4*/	{+AG_SCREENQUAD_X, -AG_SCREENQUAD_Y, 0.0f, 0x00000000, AG_TEXQUAD_MAX,	AG_TEXQUAD_MAX},
/*5*/	{-AG_SCREENQUAD_X, -AG_SCREENQUAD_Y, 0.0f, 0x00000000, 0.0f,			AG_TEXQUAD_MAX},
/*6*/	{+AG_SCREENQUAD_X, +AG_SCREENQUAD_Y, 0.0f, 0x00000000, AG_TEXQUAD_MAX,	0.0f},
};

/* SETUP VERTEX BUFFER */
register VOID*	l_dst;
if(p_i->vertex_buffer->Lock(0, 0, &l_dst, 0) == D3D_OK) {
 memcpy(l_dst, (pvoid)AG_SCREENQUAD, 6 * sizeof(AG_VERTEX));
 p_i->vertex_buffer->Unlock();
}

/* DRAWING */
p_i->device->SetTexture(p_stage, p_i->texture[p_stage]);
p_i->device->SetStreamSource( 0, p_i->vertex_buffer, 0, sizeof(AG_VERTEX) );
p_i->device->SetFVF(D3DFVF_AG_VERTEX);
p_i->device->SetSamplerState(p_stage, D3DSAMP_MINFILTER, D3DTEXF_POINT);
p_i->device->SetSamplerState(p_stage, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
p_i->device->SetSamplerState(p_stage, D3DSAMP_MIPFILTER, D3DTEXF_NONE);

p_i->device->DrawPrimitive(
 D3DPT_TRIANGLELIST,
 0,
 2
);

If I set AG_TEXQUAD_MAX to 1.001f on my notebook, it is working and he is showing everything correct. But in this case my workstation is showing the screen quad distorted :-( Any ideas or suggestions, what I could make better? Help me, please! :-) Regards, André

Share this post


Link to post
Share on other sites
domin    130
Hi, it seems to me like a perspective correction problem - try to use D3DFVF_XYZRHW in FVF when displaying 2d elements - with this you can skip any 'camera' setup and placing verictes exactly in screen space.

HTH.

Share this post


Link to post
Share on other sites
Evil Steve    2017
How is your projection matrix set up? If it's a perspective projection, then domin is almost certainly correct.
You should be using an orthogonal projection matrix to do 2D in 3D like this, or as domin suggested, use pre-transformed vertices. Personally, I'd go for an orthogonal projection matrix, since that'll let you use rotation and stuff for free.

Share this post


Link to post
Share on other sites
n44in4    123
Domin, thank you! This is working as you said - with following code:

#define AG_TEXQUAD_MAX	1.0f

struct AG_VERTEX {
/* XYZ */ FLOAT x, y, z;
/* RHW */ FLOAT rhw;
/* DIFFUSE */ DWORD c;
/* TEX0 */ FLOAT u, v;
};

const static AG_VERTEX AG_SCREENQUAD[] = {
/* X Y Z RHW Color U V */
/*1*/ {0.0f, 256.0f, 0.0f, 1.0f, 0x00000000, 0.0f, AG_TEXQUAD_MAX},
/*2*/ {0.0f, 0.0f, 0.0f, 1.0f, 0x00000000, 0.0f, 0.0f},
/*3*/ {512.0f, 0.0f, 0.0f, 1.0f, 0x00000000, AG_TEXQUAD_MAX, 0.0f},
/*4*/ {512.0f, 256.0f, 0.0f, 1.0f, 0x00000000, AG_TEXQUAD_MAX, AG_TEXQUAD_MAX},
/*5*/ {0.0f, 256.0f, 0.0f, 1.0f, 0x00000000, 0.0f, AG_TEXQUAD_MAX},
/*6*/ {512.0f, 0.0f, 0.0f, 1.0f, 0x00000000, AG_TEXQUAD_MAX, 0.0f},
};

#define D3DFVF_AG_VERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)



Steve, at the moment I do not set any projection matrix. I guess I have to read some basics about the transformation pipeline in order to fully understand the process from model into screen coordinates :-) But I will also try your solution with the orthogonal matrix. Since I'm working on an engine for testing new GUI concepts, I would like to try 3D-accelerated transforms.

André

Share this post


Link to post
Share on other sites
n44in4    123
Okay, after some tests I found my mistake:

The D3D Transformation Pipeline says that the matrix for scaling the viewport (MVS) is applied at last on the vertex. I placed the screen quad over the whole window with the whole texture - then I used a viewport, because, as you know, texture dimensions of 2^n are working better on some (old, I know) cards - that's why I used a 512x256 texture. Since I have a window height of 480 and a texture height of 256, this is resulting in a scaling ratio for Y of 0.5333333333333.... and so on. In this stage of the pipeline he is calculating the wrong result for the MVS, thus a wrong vertex coordinate.

So, now I use pre-transformed vertices. Thank you again! :-)

André

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