Sign in to follow this  
zyrolasting

Scrolling Background, what am I doing wrong?

Recommended Posts

I wanted to get a seamless texture scrolling in my background, so I placed a simple 4 vertex buffer. (This is a 2D top view, orthographic) and placed the texture on it. Of course, the struct where I actually defined UVs was local to a function. I can get the texture to repeat, but I think this method would be a flop if there's no way to get the texture to scroll using UVs in my FVF. My next thought was to have two objects with the same large background sprite always fly by and reset their position to where they came from. Of course, I think that would be harder than once thought I I want to come from an angle. Is there a way to change the UVs for my vertex buffer vertices, or am I just doing this all wrong?

Share this post


Link to post
Share on other sites
Yup, you can use IDirect3DDevice9::SetTransform with D3DTS_TEXTURE0 as the first parameter to set a texture matrix. If you just want scrolling, then you can just set a translation matrix, using something like D3DXMatrixTranslation. Example:

D3DXMATRIX mat;
D3DXMatrixTranslation(&mat, xScroll, yScroll, 0.0f);
pDevice->SetTransform(D3DTS_TEXTURE0, &mat);

Where xScroll and yScroll are the X and Y pixel offsets to use.

Share this post


Link to post
Share on other sites
Um, shoot. Sorry for the double post, but false alarm.
Nothing is moving. This was my original attempt.

D3DXMATRIX Background_Scroll;
D3DXMatrixTranslation(&Background_Scroll, BG.xSpeed, BG.ySpeed, 0.0f);
Game_Util.D3D_Device->SetTransform(D3DTS_TEXTURE0, &Background_Scroll);

When that didn't work, I began adding 0.5 to Bg.ySpeed every frame.
Still no movement. Yes, my FVF is on TEX0. What else could cause the transform to flop?

Share this post


Link to post
Share on other sites
IIRC, there are some additional steps needed to enable the use of the texture matrix. Read the section "Texture Coordinate Transformations" in the SDK for more info.

Share this post


Link to post
Share on other sites
Quote:
Original post by Gage64
IIRC, there are some additional steps needed to enable the use of the texture matrix. Read the section "Texture Coordinate Transformations" in the SDK for more info.
Ah yeah, it's been a while since I did fixed function stuff.

Clicky for the lazy - relevant paragraph:
Quote:
Enabling Texture Coordinate Transformations
The D3DTSS_TEXTURETRANSFORMFLAGS texture stage state controls the application of texture coordinate transformations. Values for this texture stage state are defined by the D3DTEXTURETRANSFORMFLAGS enumerated type.
Texture coordinate transformations are disabled when D3DTSS_TEXTURETRANSFORMFLAGS is set to D3DTTFF_DISABLE (the default value).


So you'd also want to call:
Game_Util.D3D_Device-SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
(Also untested)

Share this post


Link to post
Share on other sites
That's not enough either. DirectX uses only rotation and scaling components of the texture transform, so it's not so simple to do translation.

See:
http://www.gamedev.net/community/forums/topic.asp?topic_id=336096

Quote:

All right, problem solved. It appears that DirectX handles 2D transformation differently than 3D transformations for some reason, though I have no idea why. The following code does the trick.


I looked at the last post of that thread where the author posted solution, but that solution didn't work for me :(

I was going to make my own thread about this, but now I don't have to since EvilSteve has come to the rescue :)

Share this post


Link to post
Share on other sites
Oooog, I honestly had no idea an issue like this would stick around for as long as it has.

I checked out the links. I didn't get much help from the other topic, and the MSDN article was clear enough, and I think I understand it, but the code I attempted to use from it would not compile initially.

D3DMATRIX matTrans = D3DXMatrixIdentity( NULL ); // << !

This was the original code. It made this error:

error C2664: 'D3DXMatrixIdentity' : cannot convert parameter 1 from 'D3DMATRIX *' to 'D3DXMATRIX *'

For this line, which followed directly after.
D3DXMatrixTranslation(&matTrans, xScroll, yScroll, 0.0f);

So I changed the matTrans type to D3DXMATRIX, and I'm stuck with
error C2440: 'initializing' : cannot convert from 'D3DXMATRIX *' to 'D3DXMATRIX'

I tried to remedy it by moving D3DXMatrixIdentity() to the next line, making a new matrix pointer and using the Identity call to assign it the value, and it now compiles. However, nothing... is... moving...

Even worse, my texture flat out disappeared! It's all black! I think the vertices may have taken the translation instead of the texture... But where is that apparent? You know what? Here's my entire call.
Assuming the scene is already rendering.


void OMD_Background::DrawBackground()
{
if (OMD_Settings.D3D_Rendering) //Ensure that the device is ready to render.
{
D3DXMATRIX matTrans, *m;
m = D3DXMatrixIdentity( &matTrans );
// Set up the matrix for the desired transformation.
D3DXMatrixTranslation(m, xScroll, yScroll, 0.0f);

xScroll += xSpeed; yScroll += ySpeed; /*Increase the scroll of the background by the speed of the background.*/

OMD_Settings.D3D_Device->SetTransform( D3DTS_TEXTURE0, m );

OMD_Settings.D3D_Device->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );

OMD_Settings.D3D_Device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX0); //2D translation, Diffuse, Texture stage 0
OMD_Settings.D3D_Device->SetStreamSource(0, Buffer, 0, sizeof(tVertex));
OMD_Settings.D3D_Device->SetTexture(NULL, Image);
OMD_Settings.D3D_Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
}
}





Share this post


Link to post
Share on other sites
In regards to your latest compiler error, change this

D3DXMATRIX matTrans, *m;
m = D3DXMatrixIdentity( &matTrans );
// Set up the matrix for the desired transformation.
D3DXMatrixTranslation(m, xScroll, yScroll, 0.0f);


to this


D3DXMATRIX matTrans;

D3DXMatrixTranslation(&matTrans, xScroll, yScroll, 0.0f);


Your code should compile and the texture should display, but it will not scroll (see my post above).

Share this post


Link to post
Share on other sites
Ok, well... Back to square one.

I'm still looking around to an answer to this on google, but all the tutorials I find use every method but this one. For example, one article suggested using two RECTS on a large sprite. Even so, I want to use this method for many reasons.

I get a little frustrated when a problem that seems simple hangs around.
Is there anything else at all I'm missing here for this method?

Here's my current call. Texture displays with appropriate repetitions, but as mentioned, no movement. I put the function that build the buffer in the first box, and my render call in the second. I'm really at a loss of what to look for.


bool OMD_Background::LoadBackground(LPCTSTR ImageFile)
{
if ( FAILED ( D3DXCreateTextureFromFile( OMD_Settings.D3D_Device, ImageFile, &Image ) ) )
{
char ErrorString[256];
sprintf(ErrorString, "%s has failed to load.\n", ImageFile);
OutputDebugString(ErrorString);
return false;
}

//Set the vertices to the four corners of the screen.
struct UnlistedVertex t_vert[] =
{
{0, 0, 1.0, 1.0, 0xffffffff, 0, 0,},
{OMD_Settings.Screen_W, 0, 1.0, 1.0, 0xffffffff, xRepeat, 0,},
{0, OMD_Settings.Screen_H, 1.0, 1.0, 0xffffffff, 0, yRepeat,},
{OMD_Settings.Screen_W, OMD_Settings.Screen_H, 1.0, 1.0, 0xffffffff, xRepeat, yRepeat,},
};

// create a vertex buffer interface called t_buffer
if ( FAILED (OMD_Settings.D3D_Device->CreateVertexBuffer(4*sizeof(UnlistedVertex),
0,
D3DFVF_XYZRHW | D3DFVF_TEX0,
D3DPOOL_MANAGED,
&Buffer,
NULL) ) )
{
OutputDebugString("Error creating vertex buffer for Background resource.\n");
return false;
}

VOID* pVoid; // Void pointer

// Lock buffer and input vertices
Buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, t_vert, sizeof(t_vert));
Buffer->Unlock();

return true;
}




void OMD_Background::DrawBackground()
{
if (OMD_Settings.D3D_Rendering) //Ensure that the device is ready to render.
{
D3DXMATRIX matTrans;
// Set up the matrix for the desired transformation.
D3DXMatrixTranslation(&matTrans , xScroll, yScroll, 0.0f);

//Scroll the background based on it's speed. If it bypasses window bounds, reset it to 0.
xScroll += (xScroll > OMD_Settings.Screen_W) ? (-xScroll) : (xSpeed);
yScroll += (yScroll > OMD_Settings.Screen_H) ? (-yScroll) : (ySpeed);

OMD_Settings.D3D_Device->SetTransform( D3DTS_TEXTURE0, &matTrans);
OMD_Settings.D3D_Device->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );

OMD_Settings.D3D_Device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX0);
OMD_Settings.D3D_Device->SetStreamSource(0, Buffer, 0, sizeof(UnlistedVertex));
OMD_Settings.D3D_Device->SetTexture(NULL, Image);
OMD_Settings.D3D_Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
}
}




If someone sees a flaw, please tell me why it was flawed.

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