I can paste code if needed, but I'm wondering if there may simply be some 'fundamental' aspect of drawing sprites in DirectX that I may have missed.
Edited by Interminable, 13 July 2012 - 04:37 AM.
Posted 13 July 2012 - 04:36 AM
Edited by Interminable, 13 July 2012 - 04:37 AM.
Posted 13 July 2012 - 05:05 AM
Posted 13 July 2012 - 06:20 AM
Nope, you haven't missed anything. Thankfully, sprites do move very smoothly
I am currently writing a game with sprites alone and initially had poor movement. It was jumpy and ugly, and not smooth. But, it turned out it was the way I was calculating movement speed against framerate and I was using INT for positioning (which sounds logical as I was working in screenspace).
How did I fix it?Not having seen any of your code I would check these two things. I would love to know how you go (and happy to help where I can)
- Multiply the sprites movement speed against the time since last frame
- Position the sprites using float instead of int
And if you can share more info on your timers etc, that would be great.
void Object::Update()
{
coordinates.x += (20 * frameRenderTime);
}
try
{
GetSystemTime(&systemTime);
milliseconds = systemTime.wMilliseconds;
if(milliseconds != prevMilliseconds && milliseconds%10 == 0)
{
if(milliseconds<prevMilliseconds)
{
prevMilliseconds -= 1000;
// This will update roughly once every second.
}
frameRenderTime = milliseconds - prevMilliseconds;
frameRenderTime /= 1000;
prevMilliseconds = milliseconds;
mainWindow.enginePointer()->Update();
}
mainWindow.enginePointer()->rendererPointer()->Render();
}
catch(std::exception e)
{
e.what();
return 1;
}
Edited by Interminable, 13 July 2012 - 06:21 AM.
Posted 13 July 2012 - 10:02 AM
Edited by JWBaker, 13 July 2012 - 10:03 AM.
Posted 13 July 2012 - 02:05 PM
This might help the issue.
http://msdn.microsof...0(v=vs.85).aspx
Posted 13 July 2012 - 08:38 PM
This might help the issue.
http://msdn.microsof...0(v=vs.85).aspx
What the article describes sounds like it could be related to the issue I'm having.
The problem is, I'm not drawing a 2D texture to a surface. It's a standalone sprite. I'm unsure how I can deal with this.
Posted 14 July 2012 - 02:08 AM
This might help the issue.
http://msdn.microsof...0(v=vs.85).aspx
What the article describes sounds like it could be related to the issue I'm having.
The problem is, I'm not drawing a 2D texture to a surface. It's a standalone sprite. I'm unsure how I can deal with this.
Do you mean you are using the Sprite class?
What you need to do is shift your Projection Matrix to account for the issue. This is how i setup mine and it seems to work. I'm not a DX master by any means but give it a shot and see if it helps. My Coordinate system has 0,0 at the center of the screen and +Y is up.
Device.SetTransform(TransformState.Projection, Matrix.Translation(-0.5f, 0.5f, 0.0f) * Matrix.OrthoLH(_form.ClientSize.Width, _form.ClientSize.Height, 0, 1));
void Renderer::PrepareTransform(int input)
{
transformStateType->Projection;
d3dXSprite->SetTransform(
D3DXMatrixTransformation2D(&d3dMatrix,
NULL,
0.0,
&D3DXVECTOR2(1.0,1.0),
&D3DXVECTOR2(texturesToRender[input].objectPointer->originPointer()->x,texturesToRender[input].objectPointer->originPointer()->y),
0.0f,
&D3DXVECTOR2(texturesToRender[input].objectPointer->coordinatesPointer()->x,texturesToRender[input].objectPointer->coordinatesPointer()->y));
d3dXSprite->SetTransform(&d3dMatrix);
}
if(FAILED(hResult = d3dXSprite->Draw(*texturesToRender[i].objectPointer->texturePointer()->texturePointer(), NULL, NULL, NULL, 0xffffffff)))
{
Edited by Interminable, 14 July 2012 - 02:10 AM.
Posted 14 July 2012 - 02:54 AM
#pragma once
class Timer
{
public:
Timer()
{
liCurrent.QuadPart=0;
liPrevious.QuadPart=0;
}
~Timer()
{
}
long double TimeSinceLastFrame()
{
QueryPerformanceFrequency(&liPerfFreq);
QueryPerformanceCounter(&liCurrent);
ddFrameTime=(liCurrent.QuadPart-liPrevious.QuadPart)/long double(liPerfFreq.QuadPart)*1000;
liPrevious.QuadPart=liCurrent.QuadPart;
return ddFrameTime;
}
private:
LARGE_INTEGER liCurrent;
LARGE_INTEGER liPrevious;
LARGE_INTEGER liPerfFreq;
LARGE_INTEGER liStart;
long double ddFrameTime;
};
TimeSinceLastFrame() will return exactly that (but using the performance counters)Edited by lonewolff, 14 July 2012 - 02:54 AM.
Posted 14 July 2012 - 03:12 AM
I still think it is to do with your timer. GetSystemTime() seems to be only accurate to the millisecond.
If you have a basic scene you might be rendering faster than 1000 fps, so your scene will be choppy as the timer wont be acurate enough.
On my 3 year old video card my application (that also uses sprites) is rendering at 8000 FPS. This is why I had the same problems that your are experiencing. I had to re-think my timer.
Give my timer a try#pragma once class Timer { public: Timer() { liCurrent.QuadPart=0; liPrevious.QuadPart=0; } ~Timer() { } long double TimeSinceLastFrame() { QueryPerformanceFrequency(&liPerfFreq); QueryPerformanceCounter(&liCurrent); ddFrameTime=(liCurrent.QuadPart-liPrevious.QuadPart)/long double(liPerfFreq.QuadPart)*1000; liPrevious.QuadPart=liCurrent.QuadPart; return ddFrameTime; } private: LARGE_INTEGER liCurrent; LARGE_INTEGER liPrevious; LARGE_INTEGER liPerfFreq; LARGE_INTEGER liStart; long double ddFrameTime; };TimeSinceLastFrame() will return exactly that (but using the performance counters)
I would love to know how you go
Edited by Interminable, 14 July 2012 - 03:24 AM.
Posted 14 July 2012 - 03:16 AM
I'll give it a try...but I'm also updating how far they should move using the time it takes to render the last frame.
Edited by lonewolff, 14 July 2012 - 03:17 AM.
Posted 14 July 2012 - 03:31 AM
Edited by Interminable, 14 July 2012 - 03:41 AM.
Posted 21 July 2012 - 05:19 AM
void Sprite::ConfigureVertices()
{
if(vertexBuffer)
{
vertexBuffer->Release();
}
if(FAILED(hResult = (*mTexturePointer->rendererPointer()->d3dDevicePointer())->CreateVertexBuffer
(sizeof(TLVERTEX)*4,
D3DUSAGE_WRITEONLY,
mTexturePointer->rendererPointer()->GetD3DFVF_CUSTOMVERTEXFORMAT(),
D3DPOOL_MANAGED,
&vertexBuffer,
NULL)))
{
logWindow.AddLogEntry(3, TEXT("IDirect3DDevice9::CreateVertexBuffer() FAILED"), hResult, GetLastError());
MessageBox(*mTexturePointer->rendererPointer()->hwndPointer(), TEXT("IDirect3DDevice9::CreateVertexBuffer() failed! This program will now close."), TEXT("CRITICAL FAILURE"), MB_OK | MB_ICONERROR | MB_TOPMOST);
CheckCriticalExit();
}
else
logWindow.AddLogEntry(6, TEXT("IDirect3DDevice9::CreateVertexBuffer() succeeded"), hResult);
vertices.resize(4);
vertices[0].colour = 0xFFFF00FF;
vertices[0].x = (float) objectPointer->coordinatesPointer()->x - 0.5f; // Left
vertices[0].y = (float) objectPointer->coordinatesPointer()->y - 0.5f; // Top
vertices[0].z = 0.0f;
vertices[0].rhw = 1.0f;
vertices[0].u = 0.0f;
vertices[0].v = 0.0f;
vertices[1].colour = 0xFFFF00FF;
vertices[1].x = vertices[0].x+mTexturePointer->textureDescPointer()->Width;// - 0.5f; // Right
vertices[1].y = objectPointer->coordinatesPointer()->y - 0.5f; // Top
vertices[1].z = 0.0f;
vertices[1].rhw = 1.0f;
vertices[1].u = 1.0f;
vertices[1].v = 0.0f;
vertices[2].colour = 0xFFFF00FF;
vertices[2].x = (float) vertices[0].x+mTexturePointer->textureDescPointer()->Width;// - 0.5f; // Right
vertices[2].y = (float) vertices[0].y+mTexturePointer->textureDescPointer()->Height;// - 0.5f; // Bottom
vertices[2].z = 0.0f;
vertices[2].rhw = 1.0f;
vertices[2].u = 1.0f;
vertices[2].v = 1.0f;
vertices[3].colour = 0xFFFF00FF;
vertices[3].x = (float) objectPointer->coordinatesPointer()->x - 0.5f; // Left
vertices[3].y = (float) vertices[0].y+mTexturePointer->textureDescPointer()->Height;// - 0.5f; // Bottom
vertices[3].z = 0.0f;
vertices[3].rhw = 1.0f;
vertices[3].u = 0.0f;
vertices[3].v = 1.0f;
if(FAILED(hResult = vertexBuffer->Lock(0,0, (void**)&vertexVoidPointer, 0)))
{
logWindow.AddLogEntry(3, TEXT("IDirect3DVertexBuffer9::Lock() FAILED"), hResult, GetLastError());
MessageBox(*mTexturePointer->rendererPointer()->hwndPointer(), TEXT("IDirect3DVertexBuffer9::Lock() failed! This program will now close."), TEXT("CRITICAL FAILURE"), MB_OK | MB_ICONERROR | MB_TOPMOST);
CheckCriticalExit();
}
else
logWindow.AddLogEntry(6, TEXT("IDirect3DVertexBuffer9::Lock() succeeded"), hResult);
memcpy(vertexVoidPointer, vertices.data(), (sizeof(TLVERTEX)*vertices.capacity()));
vertexBuffer->Unlock();
}
Edited by Interminable, 21 July 2012 - 05:19 AM.
Posted 26 July 2012 - 01:03 AM
Posted 26 July 2012 - 03:33 PM
What kind of filtering are you using?
I'm not sure if filtering applies to the edges of sprite renders but it may be worth looking at, since it's just changing a flag.
Posted 28 July 2012 - 04:25 AM
This. If Im understanding the issue right, thats definitely the problem. In the texture sampler filter, set everything to POINT instead of LINEAR. I remember finding the same "issue" the first time I did my pixel perfect sprite class.
What kind of filtering are you using?
I'm not sure if filtering applies to the edges of sprite renders but it may be worth looking at, since it's just changing a flag.
Linear is good if you will rotate the sprite, but for translation it leaves a ghost when the sprite moves/lies across/on coords that arent pixel perfect ( i.e. 1.06 pixels to righ)
md3dDevice->SetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); md3dDevice->SetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); md3dDevice->SetSamplerState( 1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR ); md3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ); md3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT ); md3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT );
If you want pixel perfect sprites you have to make sure that coordinates get mapped exactly to pixels. I think that is the problem you seem to experience.
Do you mean you are using the Sprite class?
What the article describes sounds like it could be related to the issue I'm having.
This might help the issue.
http://msdn.microsof...0(v=vs.85).aspx
The problem is, I'm not drawing a 2D texture to a surface. It's a standalone sprite. I'm unsure how I can deal with this.
What you need to do is shift your Projection Matrix to account for the issue. This is how i setup mine and it seems to work. I'm not a DX master by any means but give it a shot and see if it helps. My Coordinate system has 0,0 at the center of the screen and +Y is up.
Device.SetTransform(TransformState.Projection, Matrix.Translation(-0.5f, 0.5f, 0.0f) * Matrix.OrthoLH(_form.ClientSize.Width, _form.ClientSize.Height, 0, 1));
D3DXMATRIXA16 projectionMatrix; D3DXMatrixPerspectiveFovLH(&projectionMatrix, fieldOfView, aspectRatio, closestZLimit, furthestZLimit); md3dDevice->SetTransform(D3DTS_PROJECTION, &projectionMatrix);
Edited by Interminable, 28 July 2012 - 04:40 AM.
Posted 30 July 2012 - 04:28 AM
void Renderer::SetProjectionMatrix(float fieldOfView, float aspectRatio, float closestZLimit, float furthestZLimit)
{
D3DXMATRIXA16 projectionMatrix;
//D3DXMatrixPerspectiveFovLH(&projectionMatrix, fieldOfView, aspectRatio, closestZLimit, furthestZLimit);
D3DXMatrixTranslation(&projectionMatrix, -0.5f, 0.5f, 0.0f);
D3DXMatrixOrthoLH(&projectionMatrix, window_width, window_height, 0, 1);
md3dDevice->SetTransform(D3DTS_PROJECTION, &projectionMatrix);
}
Edited by Interminable, 30 July 2012 - 04:32 AM.