// Save the screen shot
if(!screenShotSaved && KEY_DOWN(VK_SNAPSHOT))
{
D3DDISPLAYMODE display;
d3ddev->GetDisplayMode(0, &display);
// Create the off screen surface with the same info as the back buffer
d3ddev->CreateOffscreenPlainSurface(display.Width, display.Height, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
&ScreenShotSurface, NULL);
// Save the back buffer to the surface
d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &ScreenShotSurface);
sprintf_s(screenshotdir,"Screenshots/Screenshot%d.png",i);
D3DXSaveSurfaceToFile(screenshotdir, D3DXIFF_PNG, ScreenShotSurface, NULL, NULL);
// Increase i for next screenshot (Only allow up to 10 screenshots max for memory safety)
if(i>=10)
i = 1;
else
i++;
screenShotSaved = true;
}
Screenshot Problem (Missing HUD images)
Hi Guys,
Recently I incorporated a Screenshot function into my tech demo.
The problem I am having is that when I take a screenshot everything is copied into the created .png image apart from any HUD images/textures I have set on the screen (these are also .png).
It seems like it is only drawing the 3d scene into the screenshot and leaving out 2d stuff. I am taking a screenshot of the backbuffer, is this my problem? If so how can I solve it?
Heres my code:
thanks.
First, that's a resource leak - GetBackBuffer() returns a pointer to a surface, so you newly created surface is lost. You're also not Release()ing the backbuffer pointer GetBackBuffer() gives you.
As for the actual problem, where are you calling that function? The correct place is after the last EndScene() call (and therefore after any ID3DXSprite::End() calls too), but before Present().
You should be using the Debug Runtimes, which will point out any obvious problems, and will show that memory leak I mentioned.
As for the actual problem, where are you calling that function? The correct place is after the last EndScene() call (and therefore after any ID3DXSprite::End() calls too), but before Present().
You should be using the Debug Runtimes, which will point out any obvious problems, and will show that memory leak I mentioned.
Hi EvilSteve,
thanks for taking out the time to help me.
I forgot to mention I am releasing it in my CleanD3D() function:
and as for the screenshot function i am calling it:
AH DAMN!! THanks Steve, just realised when I was going to actually copy the code here that I am calling it before I draw the HUD in my render function.
I will change it to appear just before Present!
Another question I wanted to ask was about the FPS, I am calling my FPS function straight after:
d3ddev->Present(NULL, NULL, NULL, NULL);
// This will get the frames per second
GetFPS();
I will show my FPS function below, but what my problem is that I am getting around the region of 33 fps everytime? All I am doing in my program is calling a few .x meshes and rotating them. Is their a reason why my FPS is low?
Because I have seen similar tutorial demos, and in them I get FPS of about 220 or even one demo at 700fps.
I know this question is probably very awkward to answer as it depends on a lot of things but do you have any sujjesstions?
Here is my code:
thanks alot for your help.
thanks for taking out the time to help me.
I forgot to mention I am releasing it in my CleanD3D() function:
if(ScreenShotSurface != NULL) { ScreenShotSurface->Release(); ScreenShotSurface = NULL; }
and as for the screenshot function i am calling it:
AH DAMN!! THanks Steve, just realised when I was going to actually copy the code here that I am calling it before I draw the HUD in my render function.
I will change it to appear just before Present!
Another question I wanted to ask was about the FPS, I am calling my FPS function straight after:
d3ddev->Present(NULL, NULL, NULL, NULL);
// This will get the frames per second
GetFPS();
I will show my FPS function below, but what my problem is that I am getting around the region of 33 fps everytime? All I am doing in my program is calling a few .x meshes and rotating them. Is their a reason why my FPS is low?
Because I have seen similar tutorial demos, and in them I get FPS of about 220 or even one demo at 700fps.
I know this question is probably very awkward to answer as it depends on a lot of things but do you have any sujjesstions?
Here is my code:
// Gets and displays the Frames Per Secondvoid GetFPS(){ // Hold the number of frames per second in between seconds static float FPS = 0.0f; // Check if a second has passed float nextSecond = 0.0f; // Last second that occured static float prevSecond = 0.0f; // Add to the frames per second every time this function is called FPS++; // Get the second in millisecond then convert to seconds (by multiplying 0.001) nextSecond = GetTickCount() * 0.001f; // If the time we have now substracted from the previous second is greater than // or equal to 1 (i.e. if a second has passed) then we display the FPS number if(nextSecond - prevSecond > 1.0f) { // Make the second we just got the previous second for next time the function is called prevSecond = nextSecond; // Display the FPS sprintf_s(frames,"FPS: %d",int(FPS)); // Reset the FPS counter FPS = 0; }}//End GetFPS
thanks alot for your help.
Quote:Original post by Nads
Hi EvilSteve,
thanks for taking out the time to help me.
I forgot to mention I am releasing it in my CleanD3D() function:
*** Source Snippet Removed ***
Why? Since you're not using it after you take the screenshot, you may as well release it as soon as you're done with it. This will also help prevent any mistakes; for example if you forget to call CleanD3D() every time you take a screenshot.
GetTickCount() is extremely inaccurate, it's only got a granularity of about 25ms. So if a frame takes under 25ms, it'll report a time of 0ms.
You should use QueryPerformanceCounter instead, or timeGetTime (QPC has it's own issues).
Here's my timer class (Which may have bugs of its own [smile]):
Header:
Source code:
It's a bit complicated, but it uses QPC for quick frames (Since it's more accurate), and timeGetTime for slower ones. If QPC returns rubbish (Which it can do on dual-core CPUs with no CPU driver, and laptops), it falls back to timeGetTime(). And it also averages the FPS over 16 frames to stop it jumping around wildly.
You should use QueryPerformanceCounter instead, or timeGetTime (QPC has it's own issues).
Here's my timer class (Which may have bugs of its own [smile]):
Header:
//============================================================================// PTimer.h - Timer class//============================================================================#ifndef __PTIMER_H__#define __PTIMER_H__#include <windows.h>class PTimer{public: PTimer(); ~PTimer(); // Get the time taken for the last frame in ms float GetFrameTime() const { return m_fFrameTime; } //======================================================================== void BeginFrame(); void EndFrame();protected: float m_fFrameTime; DWORD m_dwStartTime; size_t m_nIndex; bool m_bFirstLoop; LARGE_INTEGER m_liFreq; LARGE_INTEGER m_liStart; static const size_t ms_nFramesAverage = 16; float m_fFrameTimes[ms_nFramesAverage];};#endif // __PTIMER_H__
Source code:
//============================================================================// PTimer.cpp - Timer class//============================================================================#include "PTimer.h"#include <mmsystem.h>#pragma comment(lib, "winmm.lib")// Max time one frame can take (Clamped to this max value)static const DWORD s_dwMaxFrameTime = 1000;// Frame time threshold (in ms) under which QPC result is usedstatic const DWORD s_dwQPCThreshold = 5;//============================================================================PTimer::PTimer() : m_dwStartTime(0), m_nIndex(0), m_bFirstLoop(true){ timeBeginPeriod(1); QueryPerformanceFrequency(&m_liFreq); m_liStart.QuadPart = 0; for(size_t i=0; i<ms_nFramesAverage; ++i) m_fFrameTimes = 0.0f;}PTimer::~PTimer(){ timeEndPeriod(1);}//============================================================================void PTimer::BeginFrame(){ m_dwStartTime = timeGetTime(); QueryPerformanceCounter(&m_liStart);}void PTimer::EndFrame(){ // Get frame time (via QPC and timeGetTime()) LARGE_INTEGER liFrameTime; QueryPerformanceCounter(&liFrameTime); liFrameTime.QuadPart -= m_liStart.QuadPart; DWORD dwFrameTime = timeGetTime() - m_dwStartTime; bool bUseTimeGetTime; float fTime = 0.0f; // If this was a fast frame, use QPC, and check results with timeGetTime if(dwFrameTime < s_dwQPCThreshold) { fTime = ((float)(liFrameTime.QuadPart*1000) / (float)m_liFreq.QuadPart); // Validate nonsense answers if(fTime > (float)s_dwQPCThreshold) bUseTimeGetTime = true; else bUseTimeGetTime = false; } else bUseTimeGetTime = true; // This was a slow frame, don't care what QPC says, use timeGetTime if(bUseTimeGetTime) { if(dwFrameTime > s_dwMaxFrameTime) dwFrameTime = s_dwMaxFrameTime; fTime = (float)dwFrameTime; } // Record frame m_fFrameTimes[m_nIndex++] = fTime; if(m_nIndex >= ms_nFramesAverage) { m_bFirstLoop = false; m_nIndex = 0; } // Calculate total float fTotal = m_fFrameTimes[0]; for(size_t i=1; i<ms_nFramesAverage; ++i) fTotal += m_fFrameTimes; // Average if(m_bFirstLoop) m_fFrameTime = fTotal / (float)m_nIndex; else m_fFrameTime = fTotal / (float)ms_nFramesAverage;}//============================================================================
It's a bit complicated, but it uses QPC for quick frames (Since it's more accurate), and timeGetTime for slower ones. If QPC returns rubbish (Which it can do on dual-core CPUs with no CPU driver, and laptops), it falls back to timeGetTime(). And it also averages the FPS over 16 frames to stop it jumping around wildly.
Quote:Original post by Sc4FreakQuote:Original post by Nads
Hi EvilSteve,
thanks for taking out the time to help me.
I forgot to mention I am releasing it in my CleanD3D() function:
*** Source Snippet Removed ***
Why? Since you're not using it after you take the screenshot, you may as well release it as soon as you're done with it. This will also help prevent any mistakes; for example if you forget to call CleanD3D() every time you take a screenshot.
thanks, I will change that.
Quote:Original post by Evil Steve
GetTickCount() is extremely inaccurate, it's only got a granularity of about 25ms. So if a frame takes under 25ms, it'll report a time of 0ms.
You should use QueryPerformanceCounter instead, or timeGetTime (QPC has it's own issues).
Here's my timer class (Which may have bugs of its own [smile]):
Header:
*** Source Snippet Removed ***
Source code:
*** Source Snippet Removed ***
It's a bit complicated, but it uses QPC for quick frames (Since it's more accurate), and timeGetTime for slower ones. If QPC returns rubbish (Which it can do on dual-core CPUs with no CPU driver, and laptops), it falls back to timeGetTime(). And it also averages the FPS over 16 frames to stop it jumping around wildly.
Thanks Steve.
I did try using timeGetTime aswell last night, but it gave me the same result!
Your timer class looks highly complicated, but when I get home tonight (currently at work) I will try it out and see if I can understand and incorporate it into my demo.
Are you actually calling your begin and end functions in the render function, like how I called mine after ->Present()?
Do you use this timer class just for the FPS, or is it used for other things too?
Also in your header file you have:
PTimer();
~PTimer();
its probably a very beginner question but whats the ~ stand for?
Thanks.
Quote:Original post by NadsDid you call timeBeginPeriod(1); ? That increases the accuracy of timeGetTime() (Called from the constructor in my class).
Thanks Steve.
I did try using timeGetTime aswell last night, but it gave me the same result!
Quote:Original post by NadsYeah, my main loop is:
Your timer class looks highly complicated, but when I get home tonight (currently at work) I will try it out and see if I can understand and incorporate it into my demo.
Are you actually calling your begin and end functions in the render function, like how I called mine after ->Present()?
Do you use this timer class just for the FPS, or is it used for other things too?
void PApp::MainLoop(){ do { m_timer.BeginFrame(); Loop(true); m_timer.EndFrame(); } while(!ShouldExit());}
Where Loop() does all the game logic and rendering. I only use the timer for keeping track of FPS currently, but there's no reason it couldn't be used for anything else - although you'd probably want to remove the frame time averaging code.
Quote:Original post by NadsThe first function is the constructor, which is called when the object is created (And used to initialise any member variables and state). The second one (~PTimer) is the destructor, which is called when the object is destroyed (When it goes out of scope or it's deleted), and is used to clean up after the object.
Also in your header file you have:
PTimer();
~PTimer();
its probably a very beginner question but whats the ~ stand for?
For example, a rendering class might call IDirect3DDevice9::Release() from the destructor to make sure that the device was always cleaned up.
Thanks again Steve.
Quote:Did you call timeBeginPeriod(1); ? That increases the accuracy of timeGetTime() (Called from the constructor in my class).
No I didnt try that but will do tonight. But even then how much can it increase it by?? As I mentioned earlier I was getting about 33FPS, where I am expecting atleast over 100FPS. To me it just feels like I was doing the function wrong although i did take tips from many tutorials. Hence I dont think timeBeginPeriod(1) could fix it by that much (although I could be wrong and therefore will try it!)
Thanks for explaining about the deconstructor, it isnt something I had come across before but will also read up on it now that i know what it is.
Quote:Original post by NadsFrom the timeGetTime docs: "Windows NT/2000: The default precision of the timeGetTime function can be five milliseconds or more, depending on the machine." 5ms would give you a max FPS of 200FPS though, so I would have thought the default should be fine.
No I didnt try that but will do tonight. But even then how much can it increase it by?? As I mentioned earlier I was getting about 33FPS, where I am expecting atleast over 100FPS. To me it just feels like I was doing the function wrong although i did take tips from many tutorials. Hence I dont think timeBeginPeriod(1) could fix it by that much (although I could be wrong and therefore will try it!)
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement