2025-11-28 00:35:46 +09:00

379 lines
9.5 KiB
C++

//--------------------------------------------------------------------------------------
// File: BackgroundThread.cpp
//
// Sample showing how to use D3D9Ex advanced features.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p) = NULL; } }
//-----------------------------------------------------------------------------
// structures
//-----------------------------------------------------------------------------
struct BACKGROUNDVERTEX
{
FLOAT x, y, z; // The untransformed position for the vertex
DWORD dwColor; // Color
};
#define D3DFVF_BACKGROUNDVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
bool g_bEndThread = false;
IDirect3DTexture9* g_pRenderTarget = NULL;
IDirect3DTexture9* g_pSharedTexture = NULL;
IDirect3DVertexBuffer9* g_pCubeVB = NULL;
IDirect3DIndexBuffer9* g_pCubeIB = NULL;
HANDLE g_SharedHandle = NULL;
UINT g_RTWidth = 1024;
UINT g_RTHeight = 1024;
int g_CubeCubes = 3;
float g_BoxRad = 30.0f;
CRITICAL_SECTION g_CSCubes;
float g_fBackLastFrameTime = 0.0f;
LARGE_INTEGER g_liBackLastTimerUpdate = {0};
LARGE_INTEGER g_liBackTimerFrequency = {0};
//--------------------------------------------------------------------------------------
// Function Prototypes and Externs
//--------------------------------------------------------------------------------------
extern HRESULT CreateD3D9VDevice( IDirect3D9Ex* pD3D, IDirect3DDevice9Ex** ppDev9Ex, D3DPRESENT_PARAMETERS* pD3DPresentParameters, HWND hWnd );
DWORD WINAPI BackgroundThreadProc( LPVOID lpParam );
HRESULT CreateCube(IDirect3DDevice9Ex* pDev);
HRESULT CreateSharedRenderTexture(IDirect3DDevice9Ex* pDev);
void RenderBackground(IDirect3DDevice9Ex* pDev);
void CleanupBackground();
//--------------------------------------------------------------------------------------
// Exported
//--------------------------------------------------------------------------------------
HANDLE CreateBackgroundThread(IDirect3D9Ex* pD3D9);
void KillBackgroundThread() { g_bEndThread = true; }
HANDLE GetSharedTextureHandle() { return g_SharedHandle; }
int IncreaseCubeCount();
int DecreaseCubeCount();
float GetFPS();
// main background thread proc
DWORD WINAPI BackgroundThreadProc( LPVOID lpParam )
{
// Create a critsec
InitializeCriticalSection( &g_CSCubes );
// Create a d3d9V device
IDirect3DDevice9Ex* pDevBackground = NULL;
IDirect3D9Ex* pD3D9 = (IDirect3D9Ex*)(lpParam);
D3DPRESENT_PARAMETERS d3dpp = {0};
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
if( FAILED( CreateD3D9VDevice( pD3D9, &pDevBackground, &d3dpp, NULL ) ) )
return 1;
if( FAILED( CreateCube( pDevBackground ) ) )
return 2;
if( FAILED( CreateSharedRenderTexture( pDevBackground ) ) )
return 3;
// Set the GPU thread priority
pDevBackground->SetGPUThreadPriority( -7 );
SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_LOWEST );
// Get Timer Frequency
QueryPerformanceFrequency( &g_liBackTimerFrequency );
QueryPerformanceCounter( &g_liBackLastTimerUpdate );
while(!g_bEndThread)
{
RenderBackground( pDevBackground );
// Uncomment next line to throttle rendering to no more then the refresh rate of the monitor.
// pDevBackground->WaitForVBlank(0);
}
// Cleanup
DeleteCriticalSection( &g_CSCubes );
CleanupBackground();
SAFE_RELEASE( pDevBackground );
return 0;
}
HANDLE CreateBackgroundThread(IDirect3D9Ex* pD3D9)
{
// create the thread
DWORD dwThreadID = 0;
HANDLE hBackgroundThread = NULL;
hBackgroundThread = CreateThread( NULL,
0,
BackgroundThreadProc,
(LPVOID)pD3D9,
CREATE_SUSPENDED,
&dwThreadID );
if( hBackgroundThread )
{
// set the priority
// resume the thread
ResumeThread( hBackgroundThread );
}
return hBackgroundThread;
}
HRESULT CreateCube( IDirect3DDevice9Ex* pDev )
{
// create the vb
if( FAILED( pDev->CreateVertexBuffer( 8*sizeof(BACKGROUNDVERTEX),
0,
D3DFVF_BACKGROUNDVERTEX,
D3DPOOL_DEFAULT,
&g_pCubeVB,
NULL ) ) )
{
return E_FAIL;
}
BACKGROUNDVERTEX vertices[] =
{
{ -1.0f, 1.0f, -1.0f, 0x000066 },
{ 1.0f, 1.0f, -1.0f, 0x006600 },
{ 1.0f, 1.0f, 1.0f, 0x006666 },
{ -1.0f, 1.0f, 1.0f, 0x660000 },
{ -1.0f, -1.0f, -1.0f, 0x660066 },
{ 1.0f, -1.0f, -1.0f, 0x666600 },
{ 1.0f, -1.0f, 1.0f, 0x666666 },
{ -1.0f, -1.0f, 1.0f, 0x000000 },
};
VOID* pVertices = NULL;
if( FAILED( g_pCubeVB->Lock( 0, sizeof(vertices), &pVertices, 0 ) ) )
return E_FAIL;
memcpy( pVertices, vertices, sizeof(vertices) );
g_pCubeVB->Unlock();
if( FAILED( pDev->CreateIndexBuffer( 36*sizeof(WORD),
0,
D3DFMT_INDEX16,
D3DPOOL_DEFAULT,
&g_pCubeIB,
NULL ) ) )
{
return E_FAIL;
}
WORD indices[] =
{
3,1,0,
2,1,3,
0,5,4,
1,5,0,
3,4,7,
0,4,3,
1,6,5,
2,6,1,
2,7,6,
3,7,2,
6,4,5,
7,4,6,
};
VOID* pIndices = NULL;
if( FAILED( g_pCubeIB->Lock( 0, sizeof(indices), &pIndices, 0 ) ) )
return E_FAIL;
memcpy( pIndices, indices, sizeof(indices) );
g_pCubeIB->Unlock();
return S_OK;
}
HRESULT CreateSharedRenderTexture(IDirect3DDevice9Ex* pDev)
{
if( FAILED( pDev->CreateTexture( g_RTWidth,
g_RTHeight,
1,
D3DUSAGE_RENDERTARGET,
D3DFMT_X8R8G8B8,
D3DPOOL_DEFAULT,
&g_pSharedTexture,
&g_SharedHandle ) ) )
{
return E_FAIL;
}
if( !g_SharedHandle )
return E_FAIL;
// create a render target
if( FAILED( pDev->CreateTexture( g_RTWidth,
g_RTHeight,
1,
D3DUSAGE_RENDERTARGET,
D3DFMT_X8R8G8B8,
D3DPOOL_DEFAULT,
&g_pRenderTarget,
NULL ) ) )
{
return E_FAIL;
}
IDirect3DSurface9* pRTSurf = NULL;
if( FAILED(g_pRenderTarget->GetSurfaceLevel( 0, &pRTSurf ) ) )
return E_FAIL;
if( FAILED(pDev->SetRenderTarget( 0, pRTSurf )) )
return E_FAIL;
pRTSurf->Release();
// viewport
D3DVIEWPORT9 vp;
vp.X = 0;
vp.Y = 0;
vp.Width = g_RTWidth;
vp.Height = g_RTHeight;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
pDev->SetViewport( &vp );
return S_OK;
}
void RenderBackground( IDirect3DDevice9Ex* pDev )
{
static float fRot = 0.0f;
fRot += g_fBackLastFrameTime*60.0f*(D3DX_PI/180.0f);
// setup the matrices
D3DXMATRIX mWorld;
D3DXMATRIX mView;
D3DXMATRIX mProj;
D3DXMatrixRotationY( &mWorld, fRot );
D3DXVECTOR3 eye( 0, 2.0f, g_BoxRad*3.5f );
D3DXVECTOR3 at( 0, 0, 0 );
D3DXVECTOR3 up( 0, 1, 0 );
D3DXMatrixLookAtLH( &mView, &eye, &at, &up );
D3DXMatrixPerspectiveFovLH( &mProj, D3DX_PI/4.0f, 1.0f, 0.1f, 1000.0f );
pDev->SetTransform( D3DTS_VIEW, &mView );
pDev->SetTransform( D3DTS_PROJECTION, &mProj );
// clear
HRESULT hr = S_OK;
pDev->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
// Begin the scene
if( SUCCEEDED( pDev->BeginScene() ) )
{
// set the texture stage states
pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE );
// disable lighting
pDev->SetRenderState( D3DRS_LIGHTING, FALSE );
// stream sources
pDev->SetStreamSource( 0, g_pCubeVB, 0, sizeof(BACKGROUNDVERTEX) );
pDev->SetIndices( g_pCubeIB );
pDev->SetFVF( D3DFVF_BACKGROUNDVERTEX );
// draw
float fStep = (g_BoxRad*2) / g_CubeCubes;
float fStart = -g_BoxRad + fStep/2.0f;
float fStop = fStart + fStep*g_CubeCubes;
EnterCriticalSection( &g_CSCubes );
for( float z=fStart; z<fStop; z+=fStep )
{
for( float y=fStart; y<fStop; y+=fStep )
{
for( float x=fStart; x<fStop; x+=fStep )
{
D3DXMATRIX mPos;
D3DXMatrixTranslation( &mPos, x,y,z );
mPos = mWorld*mPos;
pDev->SetTransform( D3DTS_WORLD, &mPos );
hr = pDev->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12 );
}
}
}
LeaveCriticalSection( &g_CSCubes );
// End the scene
pDev->EndScene();
}
// Stretch rect to our shared texture
IDirect3DSurface9* pSurfSrc;
IDirect3DSurface9* pSurfDest;
g_pRenderTarget->GetSurfaceLevel( 0, &pSurfSrc );
g_pSharedTexture->GetSurfaceLevel( 0, &pSurfDest );
hr = pDev->StretchRect( pSurfSrc, NULL, pSurfDest, NULL, D3DTEXF_POINT );
SAFE_RELEASE( pSurfSrc );
SAFE_RELEASE( pSurfDest );
// Get the time
LARGE_INTEGER liCurrentTime;
QueryPerformanceCounter( &liCurrentTime );
g_fBackLastFrameTime = (float)(liCurrentTime.QuadPart - g_liBackLastTimerUpdate.QuadPart) / (float)g_liBackTimerFrequency.QuadPart;
g_liBackLastTimerUpdate.QuadPart = liCurrentTime.QuadPart;
}
void CleanupBackground()
{
SAFE_RELEASE(g_pRenderTarget);
SAFE_RELEASE(g_pSharedTexture);
SAFE_RELEASE(g_pCubeVB);
SAFE_RELEASE(g_pCubeIB);
}
int IncreaseCubeCount()
{
EnterCriticalSection( &g_CSCubes );
g_CubeCubes ++;
if( g_CubeCubes > 100 )
g_CubeCubes = 100;
LeaveCriticalSection( &g_CSCubes );
return g_CubeCubes;
}
int DecreaseCubeCount()
{
EnterCriticalSection( &g_CSCubes );
g_CubeCubes --;
if( g_CubeCubes < 0 )
g_CubeCubes = 0;
LeaveCriticalSection( &g_CSCubes );
return g_CubeCubes;
}
float GetFPS()
{
return 1.0f / g_fBackLastFrameTime;
}