//-------------------------------------------------------------------------------------- // Name: CopyTexture() // Desc: Copy the src texture to the dst texture. The scale can (and should) be changed. //-------------------------------------------------------------------------------------- VOID PostProcess::CopyTexture( LPDIRECT3DTEXTURE9 pSrcTexture, LPDIRECT3DTEXTURE9 pDstTexture, LPDIRECT3DPIXELSHADER9 pPixelShader, DWORD dwEdramOffset ) { if( NULL == pPixelShader ) pPixelShader = m_pCopyTexturePS; // Make sure that the required shaders and objects exist assert( pPixelShader ); assert( pSrcTexture && pDstTexture ); XGTEXTURE_DESC SrcDesc; XGGetTextureDesc( pSrcTexture, 0, &SrcDesc ); // Create and set a render target D3DSURFACE_PARAMETERS surfaceParams = { 0 }; surfaceParams.Base = dwEdramOffset; PushRenderTarget( 0L, CreateRenderTarget( pDstTexture, &surfaceParams ) ); // Scale and copy the src texture g_pd3dDevice->SetPixelShader( pPixelShader ); g_pd3dDevice->SetTexture( 0, pSrcTexture ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP ); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(); XGTEXTURE_DESC DstDesc; XGGetTextureDesc( pDstTexture, 0, &DstDesc ); DWORD ColorExpBias = 0; if( DstDesc.Format == D3DFMT_G16R16_SIGNED_INTEGER ) ColorExpBias = ( DWORD ) D3DRESOLVE_EXPONENTBIAS( 10 ); else if( DstDesc.Format == D3DFMT_A16B16G16R16_SIGNED_INTEGER ) ColorExpBias = ( DWORD ) D3DRESOLVE_EXPONENTBIAS( 10 ); g_pd3dDevice->Resolve( D3DRESOLVE_RENDERTARGET0 | ColorExpBias, NULL, pDstTexture, NULL, 0, 0, NULL, 1.0f, 0L, NULL ); // Cleanup and return PopRenderTarget( 0L )->Release(); g_pd3dDevice->SetPixelShader( NULL ); }
//-------------------------------------------------------------------------------------- // Name: Downsample4x4Texture() // Desc: Scale down pSrcTexture by 1/4 x 1/4 and place the result in pDstTexture //-------------------------------------------------------------------------------------- VOID PostProcess::Downsample4x4Texture( LPDIRECT3DTEXTURE9 pSrcTexture, LPDIRECT3DTEXTURE9 pDstTexture ) { // Make sure that the required shaders and objects exist assert( m_pDownScale4x4PS ); assert( pSrcTexture && pDstTexture ); XGTEXTURE_DESC SrcDesc; XGGetTextureDesc( pSrcTexture, 0, &SrcDesc ); // Create and set a render target PushRenderTarget( 0L, CreateRenderTarget( pDstTexture ) ); // Get the sample offsets used within the pixel shader XMVECTOR avSampleOffsets[MAX_SAMPLES]; GetSampleOffsets_DownScale4x4( SrcDesc.Width, SrcDesc.Height, avSampleOffsets ); g_pd3dDevice->SetPixelShaderConstantF( PSCONST_avSampleOffsets, ( FLOAT* )avSampleOffsets, MAX_SAMPLES ); g_pd3dDevice->SetPixelShader( m_pDownScale4x4PS ); g_pd3dDevice->SetTexture( 0, pSrcTexture ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP ); // Draw a fullscreen quad DrawFullScreenQuad(); g_pd3dDevice->Resolve( D3DRESOLVE_RENDERTARGET0, NULL, pDstTexture, NULL, 0, 0, NULL, 1.0f, 0L, NULL ); // Cleanup and return PopRenderTarget( 0L )->Release(); g_pd3dDevice->SetPixelShader( NULL ); }
//-------------------------------------------------------------------------------------- // Name: SampleLuminance() // Desc: Measure the average log luminance in the scene. //-------------------------------------------------------------------------------------- VOID PostProcess::SampleLuminance( LPDIRECT3DTEXTURE9 pSrcTexture, BOOL bInitial, LPDIRECT3DTEXTURE9 pDstTexture ) { // Make sure that the required shaders and objects exist assert( m_pSampleLumInitialPS ); assert( m_pSampleLumFinalPS ); assert( pSrcTexture && pDstTexture ); XGTEXTURE_DESC SrcDesc; XGGetTextureDesc( pSrcTexture, 0, &SrcDesc ); // Create and set a render target PushRenderTarget( 0L, CreateRenderTarget( pDstTexture ) ); // Sample initial luminance if( bInitial ) { // Initialize the sample offsets for the initial luminance pass. XMVECTOR avSampleOffsets[MAX_SAMPLES]; GetSampleOffsets_DownScale3x3( SrcDesc.Width, SrcDesc.Height, avSampleOffsets ); g_pd3dDevice->SetPixelShaderConstantF( PSCONST_avSampleOffsets, ( FLOAT* )avSampleOffsets, MAX_SAMPLES ); g_pd3dDevice->SetPixelShader( m_pSampleLumInitialPS ); g_pd3dDevice->SetTexture( 0, pSrcTexture ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); } else // ( bIntial == FALSE ) { // Perform the final pass of the average luminance calculation. This pass // performs an exp() operation to return a single texel cooresponding to the // average luminance of the scene in m_pToneMapTexture. XMVECTOR avSampleOffsets[MAX_SAMPLES]; GetSampleOffsets_DownScale4x4( SrcDesc.Width, SrcDesc.Height, avSampleOffsets ); g_pd3dDevice->SetPixelShaderConstantF( PSCONST_avSampleOffsets, ( FLOAT* )avSampleOffsets, MAX_SAMPLES ); g_pd3dDevice->SetPixelShader( m_pSampleLumFinalPS ); g_pd3dDevice->SetTexture( 0, pSrcTexture ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP ); } // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(); g_pd3dDevice->Resolve( D3DRESOLVE_RENDERTARGET0, NULL, pDstTexture, NULL, 0, 0, NULL, 1.0f, 0L, NULL ); // Cleanup and return PopRenderTarget( 0L )->Release(); g_pd3dDevice->SetPixelShader( NULL ); }
static void xdk_convert_texture_to_as16_srgb( D3DTexture *pTexture ) { pTexture->Format.SignX = GPUSIGN_GAMMA; pTexture->Format.SignY = GPUSIGN_GAMMA; pTexture->Format.SignZ = GPUSIGN_GAMMA; XGTEXTURE_DESC desc; XGGetTextureDesc( pTexture, 0, &desc ); //convert to AS_16_16_16_16 format pTexture->Format.DataFormat = g_MapLinearToSrgbGpuFormat[ (desc.Format & D3DFORMAT_TEXTUREFORMAT_MASK) >> D3DFORMAT_TEXTUREFORMAT_SHIFT ]; }
//-------------------------------------------------------------------------------------- // Name: BuildMipMaps() // Desc: Generate mip maps from the base texture //-------------------------------------------------------------------------------------- VOID PostProcess::BuildMipMaps( LPDIRECT3DTEXTURE9 pTexture ) { // Make sure that the required shaders and objects exist assert( m_pCopyTexturePS ); assert( pTexture ); DWORD dwNumMipLevels = pTexture->GetLevelCount(); // Create and set a render target PushRenderTarget( 0L, CreateRenderTarget( pTexture ) ); // Scale and copy the src texture g_pd3dDevice->SetPixelShader( m_pCopyTexturePS ); g_pd3dDevice->SetTexture( 0, pTexture ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP ); D3DVIEWPORT9 vp; g_pd3dDevice->GetViewport( &vp ); for( DWORD i = 1; i < dwNumMipLevels; i++ ) { XGTEXTURE_DESC Desc; XGGetTextureDesc( pTexture, i, &Desc ); vp.Width = Desc.Width; vp.Height = Desc.Height; g_pd3dDevice->SetViewport( &vp ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINMIPLEVEL, i - 1 ); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(); DWORD ColorExpBias = 0; if( Desc.Format == D3DFMT_G16R16_SIGNED_INTEGER ) ColorExpBias = (DWORD) D3DRESOLVE_EXPONENTBIAS(10); else if( Desc.Format == D3DFMT_A16B16G16R16_SIGNED_INTEGER ) ColorExpBias = (DWORD) D3DRESOLVE_EXPONENTBIAS(10); g_pd3dDevice->Resolve( D3DRESOLVE_RENDERTARGET0 | ColorExpBias, NULL, pTexture, NULL, i, 0, NULL, 1.0f, 0L, NULL ); } // Cleanup and return g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINMIPLEVEL, 13 ); PopRenderTarget( 0L )->Release(); g_pd3dDevice->SetPixelShader( NULL ); }
//-------------------------------------------------------------------------------------- // Name: BloomTexture() // Desc: Bloom the pSrcTexture and place the result in pDstTexture //-------------------------------------------------------------------------------------- VOID PostProcess::BloomTexture( LPDIRECT3DTEXTURE9 pSrcTexture, BOOL bBloomAcrossWidth, LPDIRECT3DTEXTURE9 pDstTexture, FLOAT fSize, FLOAT fBrightness ) { // Make sure that the required shaders and objects exist assert( m_pBloomPS ); assert( pSrcTexture && pDstTexture ); XGTEXTURE_DESC SrcDesc; XGGetTextureDesc( pSrcTexture, 0, &SrcDesc ); // Create and set a render target PushRenderTarget( 0L, CreateRenderTarget( pDstTexture ) ); XMVECTOR avSampleOffsets[MAX_SAMPLES]; XMVECTOR avSampleWeights[MAX_SAMPLES]; if( bBloomAcrossWidth ) GetSampleOffsets_Bloom( SrcDesc.Width, SrcDesc.Height, 0.0f * XM_PIDIV2, avSampleOffsets, avSampleWeights, fSize, fBrightness ); else GetSampleOffsets_Bloom( SrcDesc.Width, SrcDesc.Height, 1.0f * XM_PIDIV2, avSampleOffsets, avSampleWeights, fSize, fBrightness ); g_pd3dDevice->SetPixelShaderConstantF( PSCONST_avSampleOffsets, ( FLOAT* )avSampleOffsets, MAX_SAMPLES ); g_pd3dDevice->SetPixelShaderConstantF( PSCONST_avSampleWeights, ( FLOAT* )avSampleWeights, MAX_SAMPLES ); g_pd3dDevice->SetPixelShader( m_pBloomPS ); g_pd3dDevice->SetTexture( 0, pSrcTexture ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP ); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(); g_pd3dDevice->Resolve( D3DRESOLVE_RENDERTARGET0, NULL, pDstTexture, NULL, 0, 0, NULL, 1.0f, 0L, NULL ); // Cleanup and return PopRenderTarget( 0L )->Release(); g_pd3dDevice->SetPixelShader( NULL ); }
//-------------------------------------------------------------------------------------- // Name: Downsample2x2Texture() // Desc: Scale down pSrcTexture by 1/2 x 1/2 and place the result in pDstTexture //-------------------------------------------------------------------------------------- VOID PostProcess::Downsample2x2Texture( LPDIRECT3DTEXTURE9 pSrcTexture, LPDIRECT3DTEXTURE9 pDstTexture, DWORD dwEdramOffset ) { // Make sure that the required shaders and objects exist assert( m_pDownScale2x2PS ); assert( pSrcTexture && pDstTexture ); XGTEXTURE_DESC SrcDesc; XGGetTextureDesc( pSrcTexture, 0, &SrcDesc ); // Create and set a render target D3DSURFACE_PARAMETERS surfaceParams = { 0 }; surfaceParams.Base = dwEdramOffset; PushRenderTarget( 0L, CreateRenderTarget( pDstTexture, &surfaceParams ) ); XMVECTOR avSampleOffsets[MAX_SAMPLES]; GetSampleOffsets_DownScale2x2( SrcDesc.Width, SrcDesc.Height, avSampleOffsets ); g_pd3dDevice->SetPixelShaderConstantF( PSCONST_avSampleOffsets, ( FLOAT* )avSampleOffsets, MAX_SAMPLES ); // Create an exact 1/2 x 1/2 copy of the source texture g_pd3dDevice->SetPixelShader( m_pDownScale2x2PS ); g_pd3dDevice->SetTexture( 0, pSrcTexture ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP ); // TODO: This should use border addressing with a black border! //m_pStarSourceTexture->Format.ClampX = GPUCLAMP_CLAMP_TO_BORDER; //m_pStarSourceTexture->Format.ClampY = GPUCLAMP_CLAMP_TO_BORDER; //m_pStarSourceTexture->Format.BorderColor = GPUBORDERCOLOR_ABGR_BLACK; //g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER ); //g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER ); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(); g_pd3dDevice->Resolve( D3DRESOLVE_RENDERTARGET0, NULL, pDstTexture, NULL, 0, 0, NULL, 1.0f, 0L, NULL ); // Cleanup and return PopRenderTarget( 0L )->Release(); g_pd3dDevice->SetPixelShader( NULL ); }
//-------------------------------------------------------------------------------------- // Name: BrightPassFilterTexture() // Desc: Run the bright-pass filter on m_pScaledSceneTexture and place the result // in m_pBrightPassTexture //-------------------------------------------------------------------------------------- VOID PostProcess::BrightPassFilterTexture( LPDIRECT3DTEXTURE9 pSrcTexture, LPDIRECT3DTEXTURE9 pAdaptedLuminanceTexture, FLOAT fMiddleGrayKeyValue, LPDIRECT3DTEXTURE9 pDstTexture ) { // Make sure that the required shaders and objects exist assert( m_pBrightPassFilterPS ); assert( pSrcTexture && pDstTexture ); XGTEXTURE_DESC SrcDesc; XGGetTextureDesc( pSrcTexture, 0, &SrcDesc ); // Create and set a render target PushRenderTarget( 0L, CreateRenderTarget( pDstTexture ) ); // Get the offsets to be used within the GaussBlur5x5 pixel shader XMVECTOR avSampleOffsets[MAX_SAMPLES]; XMVECTOR avSampleWeights[MAX_SAMPLES]; GetSampleOffsets_GaussBlur5x5( SrcDesc.Width, SrcDesc.Height, avSampleOffsets, avSampleWeights ); g_pd3dDevice->SetPixelShaderConstantF( PSCONST_avSampleOffsets, ( FLOAT* )avSampleOffsets, MAX_SAMPLES ); g_pd3dDevice->SetPixelShaderConstantF( PSCONST_avSampleWeights, ( FLOAT* )avSampleWeights, MAX_SAMPLES ); g_pd3dDevice->SetPixelShaderConstantF( PSCONST_fMiddleGray, &fMiddleGrayKeyValue, 1 ); g_pd3dDevice->SetPixelShader( m_pBrightPassFilterPS ); g_pd3dDevice->SetTexture( 0, pSrcTexture ); g_pd3dDevice->SetTexture( 1, pAdaptedLuminanceTexture ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT ); g_pd3dDevice->SetSamplerState( 1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); g_pd3dDevice->SetSamplerState( 1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP ); g_pd3dDevice->SetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_POINT ); g_pd3dDevice->SetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_POINT ); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(); g_pd3dDevice->Resolve( D3DRESOLVE_RENDERTARGET0, NULL, pDstTexture, NULL, 0, 0, NULL, 1.0f, 0L, NULL ); // Cleanup and return PopRenderTarget( 0L )->Release(); g_pd3dDevice->SetPixelShader( NULL ); }
//-------------------------------------------------------------------------------------- // Name: GaussBlur5x5Texture() // Desc: Perform a 5x5 gaussian blur on pSrcTexture and place the result in pDstTexture //-------------------------------------------------------------------------------------- VOID PostProcess::GaussBlur5x5Texture( LPDIRECT3DTEXTURE9 pSrcTexture, LPDIRECT3DTEXTURE9 pDstTexture, DWORD dwEdramOffset ) { // Make sure that the required shaders and objects exist assert( m_pGaussBlur5x5PS ); assert( pSrcTexture && pDstTexture ); XGTEXTURE_DESC SrcDesc; XGGetTextureDesc( pSrcTexture, 0, &SrcDesc ); // Create and set a render target D3DSURFACE_PARAMETERS surfaceParams = { 0 }; surfaceParams.Base = dwEdramOffset; PushRenderTarget( 0L, CreateRenderTarget( pDstTexture, &surfaceParams ) ); XMVECTOR avSampleOffsets[MAX_SAMPLES]; XMVECTOR avSampleWeights[MAX_SAMPLES]; GetSampleOffsets_GaussBlur5x5( SrcDesc.Width, SrcDesc.Height, avSampleOffsets, avSampleWeights ); g_pd3dDevice->SetPixelShaderConstantF( PSCONST_avSampleOffsets, ( FLOAT* )avSampleOffsets, MAX_SAMPLES ); g_pd3dDevice->SetPixelShaderConstantF( PSCONST_avSampleWeights, ( FLOAT* )avSampleWeights, MAX_SAMPLES ); g_pd3dDevice->SetPixelShader( m_pGaussBlur5x5PS ); g_pd3dDevice->SetTexture( 0, pSrcTexture ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP ); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(); g_pd3dDevice->Resolve( D3DRESOLVE_RENDERTARGET0, NULL, pDstTexture, NULL, 0, 0, NULL, 1.0f, 0L, NULL ); // Cleanup and return PopRenderTarget( 0L )->Release(); g_pd3dDevice->SetPixelShader( NULL ); }
//-------------------------------------------------------------------------------------- // Name: Render() // Desc: Renders the gamepad help image and its labelled callouts //-------------------------------------------------------------------------------------- VOID Help::Render( Font* pFont, const HELP_CALLOUT* pTags, DWORD dwNumCallouts ) { #ifdef ALLOW_CALLOUT_EDITTING // Use the shoulder buttons, triggers, and dpad to edit callout positions XINPUT_STATE CurrInputState; static XINPUT_STATE LastInputState = {0}; static DWORD dwCurrCallout = 0; if( XInputGetState( 0, &CurrInputState ) == ERROR_SUCCESS ) { if( ( 0 != (CurrInputState.Gamepad.wButtons&XINPUT_GAMEPAD_LEFT_SHOULDER) ) && ( 0 == (LastInputState.Gamepad.wButtons&XINPUT_GAMEPAD_LEFT_SHOULDER) ) ) dwCurrCallout = (dwCurrCallout+dwNumCallouts-1) % dwNumCallouts; if( ( 0 != (CurrInputState.Gamepad.wButtons&XINPUT_GAMEPAD_RIGHT_SHOULDER) ) && ( 0 == (LastInputState.Gamepad.wButtons&XINPUT_GAMEPAD_RIGHT_SHOULDER) ) ) dwCurrCallout = (dwCurrCallout+dwNumCallouts+1) % dwNumCallouts; HELP_CALLOUT_POS* pCallout = &g_pHelpCallouts[pTags[dwCurrCallout].wControl]; XMFLOAT2* pPos1 = &pCallout->Button; XMFLOAT2* pPos2 = &pCallout->Placement[pTags[dwCurrCallout].wPlacement].Line; XMFLOAT2* pPos3 = &pCallout->Placement[pTags[dwCurrCallout].wPlacement].Text; if( CurrInputState.Gamepad.bLeftTrigger ) { pPos1->x -= CurrInputState.Gamepad.wButtons&XINPUT_GAMEPAD_DPAD_LEFT ? 1.0f : 0.0f; pPos1->x += CurrInputState.Gamepad.wButtons&XINPUT_GAMEPAD_DPAD_RIGHT ? 1.0f : 0.0f; pPos1->y -= CurrInputState.Gamepad.wButtons&XINPUT_GAMEPAD_DPAD_UP ? 1.0f : 0.0f; pPos1->y += CurrInputState.Gamepad.wButtons&XINPUT_GAMEPAD_DPAD_DOWN ? 1.0f : 0.0f; } else if( CurrInputState.Gamepad.bRightTrigger ) { pPos2->x -= CurrInputState.Gamepad.wButtons&XINPUT_GAMEPAD_DPAD_LEFT ? 1.0f : 0.0f; pPos2->x += CurrInputState.Gamepad.wButtons&XINPUT_GAMEPAD_DPAD_RIGHT ? 1.0f : 0.0f; pPos2->y -= CurrInputState.Gamepad.wButtons&XINPUT_GAMEPAD_DPAD_UP ? 1.0f : 0.0f; pPos2->y += CurrInputState.Gamepad.wButtons&XINPUT_GAMEPAD_DPAD_DOWN ? 1.0f : 0.0f; pPos3->x -= CurrInputState.Gamepad.wButtons&XINPUT_GAMEPAD_DPAD_LEFT ? 1.0f : 0.0f; pPos3->x += CurrInputState.Gamepad.wButtons&XINPUT_GAMEPAD_DPAD_RIGHT ? 1.0f : 0.0f; pPos3->y -= CurrInputState.Gamepad.wButtons&XINPUT_GAMEPAD_DPAD_UP ? 1.0f : 0.0f; pPos3->y += CurrInputState.Gamepad.wButtons&XINPUT_GAMEPAD_DPAD_DOWN ? 1.0f : 0.0f; } memcpy( &LastInputState, &CurrInputState, sizeof(XINPUT_STATE) ); } #endif // ALLOW_CALLOUT_EDITTING // Calculate a scale factor based on the video mode D3DDISPLAYMODE ModeDesc; XGTEXTURE_DESC TextureDesc; g_pd3dDevice->GetDisplayMode( 0, &ModeDesc ); XGGetTextureDesc( m_pGamepadTexture, 0, &TextureDesc ); FLOAT fScale = ModeDesc.Width / 1280.0f; FLOAT h = fScale * 720 * 0.48f; FLOAT w = TextureDesc.Width * h / TextureDesc.Height; FLOAT x = ( ModeDesc.Width - w ) / 2; FLOAT y = ( ModeDesc.Height - h ) / 2; D3DRECT rcSaved = pFont->m_rcWindow; pFont->SetWindow( 0, 0, ModeDesc.Width, ModeDesc.Height ); // Setup the gamepad vertices struct VERTEX { FLOAT sx, sy; FLOAT tu, tv; }; // Set up state for rendering the gamepad g_pd3dDevice->SetVertexDeclaration( g_pHelpVertexDecl ); g_pd3dDevice->SetVertexShader( g_pHelpVertexShader ); g_pd3dDevice->SetTexture( 0, m_pGamepadTexture ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ); g_pd3dDevice->SetRenderState( D3DRS_VIEWPORTENABLE, FALSE ); g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); g_pd3dDevice->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD ); // Draw the scene-darkening quad { VERTEX GamepadVertices[4] = { { 0.0f, 0.0f, 0.0f, 0.0f }, { 1.0f * ModeDesc.Width, 0.0f, 1.0f, 0.0f }, { 1.0f * ModeDesc.Width, 1.0f * ModeDesc.Height, 1.0f, 1.0f }, { 0.0f, 1.0f * ModeDesc.Height, 0.0f, 1.0f }, }; g_pd3dDevice->SetPixelShader( g_pDarkPixelShader ); g_pd3dDevice->DrawPrimitiveUP( D3DPT_QUADLIST, 1, GamepadVertices, sizeof( GamepadVertices[0] ) ); } // Draw the gamepad image { VERTEX GamepadVertices[4] = { { x, y, 0.0f, 0.0f }, { x + w, y, 1.0f, 0.0f }, { x + w, y + h, 1.0f, 1.0f }, { x, y + h, 0.0f, 1.0f }, }; g_pd3dDevice->SetPixelShader( g_pHelpPixelShader ); g_pd3dDevice->DrawPrimitiveUP( D3DPT_QUADLIST, 1, GamepadVertices, sizeof( GamepadVertices[0] ) ); } // Set state to draw the lines g_pd3dDevice->SetTexture( 0, m_pLineTexture ); g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); for( DWORD i = 0; i < dwNumCallouts; i++ ) { if( pTags[i].wControl >= ARRAYSIZE( g_vHelpCallouts ) ) continue; HELP_CALLOUT_POS* pCallout = &g_pHelpCallouts[pTags[i].wControl]; XMFLOAT2 line1 = pCallout->Button; XMFLOAT2 line2 = pCallout->Placement[pTags[i].wPlacement].Line; line1.x = fScale * ( line1.x - 640 ) + ModeDesc.Width / 2; line1.y = fScale * ( line1.y - 360 ) + ModeDesc.Height / 2; line2.x = fScale * ( line2.x - 640 ) + ModeDesc.Width / 2; line2.y = fScale * ( line2.y - 360 ) + ModeDesc.Height / 2; XMVECTOR vc = XMVector2Normalize( XMVectorSet( line2.y - line1.y, -line2.x + line1.x, 0, 0 ) ); #ifdef ALLOW_CALLOUT_EDITTING if( dwCurrCallout == i ) vc *= 2; #endif // ALLOW_CALLOUT_EDITTING // Initialize the callout line vertices VERTEX LineVertices[4] = { { ( line1.x - 2 * vc.x ), ( line1.y - 2 * vc.y ), 0.0f, 0.0f }, { ( line1.x + 2 * vc.x ), ( line1.y + 2 * vc.y ), 1.0f, 0.0f }, { ( line2.x + 2 * vc.x ), ( line2.y + 2 * vc.y ), 1.0f, 1.0f }, { ( line2.x - 2 * vc.x ), ( line2.y - 2 * vc.y ), 0.0f, 1.0f }, }; g_pd3dDevice->DrawPrimitiveUP( D3DPT_QUADLIST, 1, LineVertices, sizeof( LineVertices[0] ) ); } // Turn the viewport back on g_pd3dDevice->SetRenderState( D3DRS_VIEWPORTENABLE, TRUE ); // Prepare font for rendering pFont->Begin(); static FLOAT fFontXScale = 1.0f; static FLOAT fFontYScale = 1.0f; pFont->SetScaleFactors( fFontXScale * fScale, fFontYScale * fScale ); // Render the callouts for( DWORD i = 0; i < dwNumCallouts; i++ ) { if( pTags[i].wControl >= ARRAYSIZE( g_vHelpCallouts ) ) continue; HELP_CALLOUT_POS* pCallout = &g_pHelpCallouts[pTags[i].wControl]; XMFLOAT2 pos = pCallout->Placement[pTags[i].wPlacement].Text; pos.x = fScale * ( pos.x - 640 ) + ModeDesc.Width / 2; pos.y = fScale * ( pos.y - 360 ) + ModeDesc.Height / 2; // Draw the callout text pFont->DrawText( pos.x, pos.y, 0xffffffff, pTags[i].strText, g_pHelpCallouts[pTags[i].wControl].dwFontFlags ); } // Flush the text drawing pFont->SetScaleFactors( 1.0f, 1.0f ); pFont->End(); pFont->m_rcWindow = rcSaved; }