/*============================================================================= D3DHDRRender.cpp : Direct3D specific high dynamic range post-processing Copyright (c) 2001 Crytek Studios. All Rights Reserved. Revision history: * Created by Honitch Andrey =============================================================================*/ #include "RenderPCH.h" #include "DriverD3D9.h" #include "D3DCGPShader.h" #include "D3DCGVProgram.h" //============================================================================= //---------------------------------------------------------------------------------------- // Render Target Management functions // Allocation order affects performance. These functions try to find an optimal allocation // order for an arbitrary number of render targets. //----------------------------------------------------------------------------------------- static DWORD FormatSize( D3DFORMAT Format ) { switch ( Format ) { case D3DFMT_R16F: return 2; case D3DFMT_A8R8G8B8: case D3DFMT_X8R8G8B8: case D3DFMT_G16R16: case D3DFMT_G16R16F: case D3DFMT_R32F: return 4; case D3DFMT_A16B16G16R16: case D3DFMT_A16B16G16R16F: return 8; default: assert(0); } return 4; } // defer allocation of render targets until we have a list of all required targets... // then, sort the list to make "optimal" use of GPU memory struct DeferredRenderTarget { DWORD dwWidth; DWORD dwHeight; D3DFORMAT Format; STexPic **lplpStorage; char szName[64]; DWORD dwPitch; float fPriority; }; std::vector< DeferredRenderTarget* > g_vAllRenderTargets; #define SORT_RENDERTARGETS TRUE struct DescendingRenderTargetSort { bool operator()( DeferredRenderTarget* drtStart, DeferredRenderTarget *drtEnd ) { return (drtStart->dwPitch*drtStart->fPriority) > (drtEnd->dwPitch*drtEnd->fPriority); } }; // This function just clears the vector void StartRenderTargetList( ) { std::vector< DeferredRenderTarget* >::iterator _it = g_vAllRenderTargets.begin(); while ( _it != g_vAllRenderTargets.end() ) { DeferredRenderTarget *drt = (DeferredRenderTarget*)*_it++; delete drt; } g_vAllRenderTargets.clear(); } // Add a render target to the list void AllocateDeferredRenderTarget( DWORD dwWidth, DWORD dwHeight, D3DFORMAT Format, float fPriority, const char *szName, STexPic **pStorage ) { DeferredRenderTarget *drt = new DeferredRenderTarget; drt->dwWidth = dwWidth; drt->dwHeight = dwHeight; drt->Format = Format; drt->fPriority = fPriority; drt->lplpStorage = pStorage; strcpy(drt->szName, szName); drt->dwPitch = dwWidth * FormatSize( Format ); g_vAllRenderTargets.push_back( drt ); } // Now, sort and allocate all render targets bool EndRenderTargetList( ) { if ( SORT_RENDERTARGETS ) std::sort( g_vAllRenderTargets.begin(), g_vAllRenderTargets.end(), DescendingRenderTargetSort() ); std::vector< DeferredRenderTarget* >::iterator _it = g_vAllRenderTargets.begin(); bool bRes = true; while ( _it != g_vAllRenderTargets.end() ) { DeferredRenderTarget *drt = (DeferredRenderTarget*)*_it++; CD3D9TexMan *tm = (CD3D9TexMan *)gcpRendD3D->m_TexMan; STexPic *tp = tm->CreateTexture(drt->dwWidth, drt->dwHeight, drt->Format, D3DUSAGE_RENDERTARGET, false, drt->szName); if (tp) *drt->lplpStorage = tp; else bRes = false; } StartRenderTargetList( ); return S_OK; } STexPic *CD3D9TexMan::CreateTexture(int nWidth, int nHeight, D3DFORMAT d3dFMT, int d3dUsage, bool bMips, const char *szName) { LPDIRECT3DTEXTURE9 pTexture; STexPic *tp; if(FAILED(D3DXCreateTexture(gcpRendD3D->mfGetD3DDevice(), nWidth, nHeight, bMips ? D3DX_DEFAULT : 1, d3dUsage, d3dFMT, D3DPOOL_DEFAULT, &pTexture))) return NULL; int nFlags = FT_NOREMOVE | FT_NOSTREAM; if (!bMips) nFlags |= FT_NOMIPS; tp = LoadTexture(szName, nFlags, FT2_NODXT | FT2_RENDERTARGET, eTT_Base, -1.0f, -1.0f); STexPicD3D *ti = (STexPicD3D *)tp; ti->m_RefTex.m_VidTex = (void *)pTexture; ti->m_RefTex.m_MipFilter = bMips ? GetMipFilter() : D3DTEXF_NONE; ti->m_RefTex.m_MinFilter = GetMinFilter(); ti->m_RefTex.m_MagFilter = GetMagFilter(); ti->m_RefTex.m_AnisLevel = 1; ti->m_RefTex.m_Type = TEXTGT_2D; ti->m_DstFormat = d3dFMT; ti->m_Width = nWidth; ti->m_Height = nHeight; CD3D9TexMan::CalcMipsAndSize(ti); AddToHash(ti->m_Bind, ti); ti->Unlink(); ti->Link(&STexPic::m_Root); gRenDev->m_TexMan->m_StatsCurTexMem += ti->m_Size; HRESULT hr = S_OK; PDIRECT3DSURFACE9 pSurface = NULL; hr = pTexture->GetSurfaceLevel(0, &pSurface); if (SUCCEEDED(hr)) gcpRendD3D->m_pd3dDevice->ColorFill(pSurface, NULL, D3DCOLOR_ARGB(0, 0, 0, 0)); SAFE_RELEASE( pSurface ); return ti; } void CD3D9TexMan::DestroyHDRMaps() { CD3D9Renderer *r = gcpRendD3D; int i; SAFE_RELEASE( m_HDR_RT_FSAA ); if (m_Text_HDRTarget) m_Text_HDRTarget->Release(true); m_Text_HDRTarget = NULL; if (m_Text_HDRTarget_Temp) m_Text_HDRTarget_Temp->Release(true); m_Text_HDRTarget_Temp = NULL; //if (m_Text_HDRTarget_K) // m_Text_HDRTarget_K->Release(true); //m_Text_HDRTarget_K = NULL; if (m_Text_ScreenMap_HDR) m_Text_ScreenMap_HDR->Release(true); m_Text_ScreenMap_HDR = NULL; if (r->m_TexMan->m_Text_HDRTargetScaled[0]) r->m_TexMan->m_Text_HDRTargetScaled[0]->Release(true); r->m_TexMan->m_Text_HDRTargetScaled[0] = NULL; if (r->m_TexMan->m_Text_HDRTargetScaled[1]) r->m_TexMan->m_Text_HDRTargetScaled[1]->Release(true); r->m_TexMan->m_Text_HDRTargetScaled[1] = NULL; if (r->m_TexMan->m_Text_HDRBrightPass) r->m_TexMan->m_Text_HDRBrightPass->Release(true); r->m_TexMan->m_Text_HDRBrightPass = NULL; if (r->m_TexMan->m_Text_HDRStarSource) r->m_TexMan->m_Text_HDRStarSource->Release(true); r->m_TexMan->m_Text_HDRStarSource = NULL; if (r->m_TexMan->m_Text_HDRBloomSource) r->m_TexMan->m_Text_HDRBloomSource->Release(true); r->m_TexMan->m_Text_HDRBloomSource = NULL; if (r->m_TexMan->m_Text_HDRAdaptedLuminanceCur) r->m_TexMan->m_Text_HDRAdaptedLuminanceCur->Release(true); r->m_TexMan->m_Text_HDRAdaptedLuminanceCur = NULL; if (r->m_TexMan->m_Text_HDRAdaptedLuminanceLast) r->m_TexMan->m_Text_HDRAdaptedLuminanceLast->Release(true); r->m_TexMan->m_Text_HDRAdaptedLuminanceLast = NULL; for(i=0; iRelease(true); m_Text_HDRToneMaps[i] = NULL; } for(i=0; iRelease(true); m_Text_HDRBloomMaps[i] = NULL; } for(i=0; iRelease(true); m_Text_HDRStarMaps[i][0] = NULL; if (m_Text_HDRStarMaps[i][1]) m_Text_HDRStarMaps[i][1]->Release(true); m_Text_HDRStarMaps[i][1] = NULL; } } void CD3D9TexMan::GenerateHDRMaps() { int i; char szName[256]; CD3D9Renderer *r = gcpRendD3D; r->m_dwHDRCropWidth = r->m_width - r->m_width % 8; r->m_dwHDRCropHeight = r->m_height - r->m_height % 8; DestroyHDRMaps(); StartRenderTargetList(); if (r->m_nHDRType == 2) { AllocateDeferredRenderTarget(r->m_width, r->m_height, D3DFMT_A8R8G8B8, 1.0f, "$HDRTarget", &m_Text_HDRTarget); //AllocateDeferredRenderTarget(r->m_width, r->m_height, D3DFMT_A8R8G8B8, 1.0f, "$HDRTarget_K", &m_Text_HDRTarget_K); AllocateDeferredRenderTarget(r->m_width, r->m_height, D3DFMT_A16B16G16R16F, 1.0f, "$HDRTarget_Temp", &m_Text_HDRTarget_Temp); AllocateDeferredRenderTarget(r->m_width, r->m_height, D3DFMT_A8R8G8B8, 0.8f, "$HDRScreenMap", &m_Text_ScreenMap_HDR); } else { if( r->CV_r_fsaa == 2 ) { HRESULT hr = r->m_pd3dDevice->CreateRenderTarget( r->m_width, r->m_height, D3DFMT_A16B16G16R16F, ConvertFSAASamplesToType( r->m_FSAA_samples ), r->m_FSAA_quality, FALSE, &m_HDR_RT_FSAA, 0 ); //if( SUCCEEDED( hr ) ) // iLog->Log( "HDR-FSAA: Created multi-sampled HDR render target for current FSAA settings (samples = %d / quality = %d).", r->m_FSAA_samples, r->m_FSAA_quality ); //else // iLog->Log( "HDR-FSAA: Multi-sampled HDR render target creation failed!" ); } AllocateDeferredRenderTarget(r->m_width, r->m_height, D3DFMT_A16B16G16R16F, 1.0f, "$HDRTarget", &m_Text_HDRTarget); AllocateDeferredRenderTarget(r->m_width, r->m_height, D3DFMT_A16B16G16R16F, 0.8f, "$HDRScreenMap", &m_Text_ScreenMap_HDR); } // Scaled version of the HDR scene texture if (r->m_bDeviceSupportsMRT) { AllocateDeferredRenderTarget(r->m_dwHDRCropWidth/4, r->m_dwHDRCropHeight/4, D3DFMT_G16R16F, 1.f, "$HDRTargetScaled0", &m_Text_HDRTargetScaled[0]); AllocateDeferredRenderTarget(r->m_dwHDRCropWidth/4, r->m_dwHDRCropHeight/4, D3DFMT_G16R16F, 1.f, "$HDRTargetScaled1", &m_Text_HDRTargetScaled[1]); } else { AllocateDeferredRenderTarget(r->m_dwHDRCropWidth/4, r->m_dwHDRCropHeight/4, D3DFMT_A16B16G16R16F, 1.f, "$HDRTargetScaled", &m_Text_HDRTargetScaled[0] ); m_Text_HDRTargetScaled[1] = NULL; } AllocateDeferredRenderTarget(r->m_dwHDRCropWidth/4+2, r->m_dwHDRCropHeight/4+2, D3DFMT_A8R8G8B8, 0.5f, "$HDRBrightPass", &m_Text_HDRBrightPass); AllocateDeferredRenderTarget(r->m_dwHDRCropWidth/4+2, r->m_dwHDRCropHeight/4+2, D3DFMT_A8R8G8B8, 0.5f, "$HDRStarSource", &m_Text_HDRStarSource); AllocateDeferredRenderTarget(r->m_dwHDRCropWidth/8+2, r->m_dwHDRCropHeight/8+2, D3DFMT_A8R8G8B8, 0.8f, "$HDRBloomSource", &m_Text_HDRBloomSource); AllocateDeferredRenderTarget(1, 1, r->m_HDR_FloatFormat_Scalar, 0.1f, "$HDRAdaptedLuminanceCur", &m_Text_HDRAdaptedLuminanceCur); AllocateDeferredRenderTarget(1, 1, r->m_HDR_FloatFormat_Scalar, 0.1f, "$HDRAdaptedLuminanceLast", &m_Text_HDRAdaptedLuminanceLast); // For each scale stage, create a texture to hold the intermediate results // of the luminance calculation for(i=0; im_HDR_FloatFormat_Scalar, 0.7f, szName, &m_Text_HDRToneMaps[i]); } // Create the temporary blooming effect textures // Texture has a black border of single texel thickness to fake border // addressing using clamp addressing for(i=1; im_dwHDRCropWidth/8+2, r->m_dwHDRCropHeight/8+2, D3DFMT_A8R8G8B8, 0.8f, szName, &m_Text_HDRBloomMaps[i]); } AllocateDeferredRenderTarget(r->m_dwHDRCropWidth/8, r->m_dwHDRCropHeight/8, D3DFMT_A8R8G8B8, 0.5f, "$HDRBloomMap_0", &m_Text_HDRBloomMaps[0]); // Create the star effect textures for(i=0; im_bDeviceSupportsMRT ) { sprintf(szName, "$HDRStarMap_%d(0)", i); AllocateDeferredRenderTarget(r->m_dwHDRCropWidth/4, r->m_dwHDRCropHeight/4, D3DFMT_G16R16F, 0.8f, szName, &m_Text_HDRStarMaps[i][0]); sprintf(szName, "$HDRStarMap_%d(1)", i); AllocateDeferredRenderTarget(r->m_dwHDRCropWidth/4, r->m_dwHDRCropHeight/4, D3DFMT_G16R16F, 0.8f, szName, &m_Text_HDRStarMaps[i][1]); } else { sprintf(szName, "$HDRStarMap_%d", i); AllocateDeferredRenderTarget(r->m_dwHDRCropWidth/4, r->m_dwHDRCropHeight/4, D3DFMT_A16B16G16R16F, 0.8f, szName, &m_Text_HDRStarMaps[i][0]); m_Text_HDRStarMaps[i][1] = NULL; } } EndRenderTargetList(); } //============================================================================= //---------------------------------------------------------- // Star generation // Define each line of the star. typedef struct STARLINE { int nPasses ; float fSampleLength ; float fAttenuation ; float fInclination ; } *LPSTARLINE ; // Simple definition of the star. typedef struct STARDEF { TCHAR *szStarName ; int nStarLines ; int nPasses ; float fSampleLength ; float fAttenuation ; float fInclination ; bool bRotation ; } *LPSTARDEF ; // Simple definition of the sunny cross filter typedef struct STARDEF_SUNNYCROSS { TCHAR *szStarName ; float fSampleLength ; float fAttenuation ; float fInclination ; } *LPSTARDEF_SUNNYCROSS ; // Star form library enum ESTARLIBTYPE { STLT_DISABLE = 0, STLT_CROSS, STLT_CROSSFILTER, STLT_SNOWCROSS, STLT_VERTICAL, NUM_BASESTARLIBTYPES, STLT_SUNNYCROSS = NUM_BASESTARLIBTYPES, NUM_STARLIBTYPES, } ; //---------------------------------------------------------- // Star generation object class CStarDef { public: TCHAR m_strStarName[256] ; int m_nStarLines ; LPSTARLINE m_pStarLine ; // [m_nStarLines] float m_fInclination ; bool m_bRotation ; // Rotation is available from outside ? // Static library public: static CStarDef *ms_pStarLib ; static D3DXCOLOR ms_avChromaticAberrationColor[8] ; // Public method public: CStarDef() ; CStarDef(const CStarDef& src) ; ~CStarDef() ; CStarDef& operator =(const CStarDef& src) { Initialize(src) ; return *this ; } HRESULT Construct() ; void Destruct() ; void Release() ; HRESULT Initialize(const CStarDef& src) ; HRESULT Initialize(ESTARLIBTYPE eType) { return Initialize(ms_pStarLib[eType]) ; } /// Generic simple star generation HRESULT Initialize(const TCHAR *szStarName, int nStarLines, int nPasses, float fSampleLength, float fAttenuation, float fInclination, bool bRotation) ; HRESULT Initialize(const STARDEF& starDef) { return Initialize(starDef.szStarName, starDef.nStarLines, starDef.nPasses, starDef.fSampleLength, starDef.fAttenuation, starDef.fInclination, starDef.bRotation) ; } /// Specific star generation // Sunny cross filter HRESULT Initialize_SunnyCrossFilter(const TCHAR *szStarName = TEXT("SunnyCross"), float fSampleLength = 1.0f, float fAttenuation = 0.88f, float fLongAttenuation = 0.95f, float fInclination = D3DXToRadian(0.0f)) ; // Public static method public: /// Create star library static HRESULT InitializeStaticStarLibs() ; static HRESULT DeleteStaticStarLibs() ; /// Access to the star library static const CStarDef& GetLib(DWORD dwType) { return ms_pStarLib[dwType] ; } static const D3DXCOLOR& GetChromaticAberrationColor(DWORD dwID) { return ms_avChromaticAberrationColor[dwID] ; } } ; //============================================================================ // Glare form library enum EGLARELIBTYPE { GLT_DISABLE = 0, GLT_CAMERA, GLT_NATURAL, GLT_CHEAPLENS, //GLT_AFTERIMAGE, GLT_FILTER_CROSSSCREEN, GLT_FILTER_CROSSSCREEN_SPECTRAL, GLT_FILTER_SNOWCROSS, GLT_FILTER_SNOWCROSS_SPECTRAL, GLT_FILTER_SUNNYCROSS, GLT_FILTER_SUNNYCROSS_SPECTRAL, GLT_CINECAM_VERTICALSLITS, GLT_CINECAM_HORIZONTALSLITS, NUM_GLARELIBTYPES, GLT_USERDEF = -1, GLT_DEFAULT = GLT_FILTER_CROSSSCREEN, } ; // Simple glare definition typedef struct GLAREDEF { TCHAR *szGlareName ; float fGlareLuminance ; float fBloomLuminance ; float fGhostLuminance ; float fGhostDistortion ; float fStarLuminance ; ESTARLIBTYPE eStarType ; float fStarInclination ; float fChromaticAberration ; float fAfterimageSensitivity ; // Current weight float fAfterimageRatio ; // Afterimage weight float fAfterimageLuminance ; } *LPGLAREDEF ; class CGlareDef { public: TCHAR m_strGlareName[256] ; float m_fGlareLuminance ; // Total glare intensity (not effect to "after image") float m_fBloomLuminance ; float m_fGhostLuminance ; float m_fGhostDistortion ; float m_fStarLuminance ; float m_fStarInclination ; float m_fChromaticAberration ; float m_fAfterimageSensitivity ; // Current weight float m_fAfterimageRatio ; // Afterimage weight float m_fAfterimageLuminance ; CStarDef m_starDef ; // Static library public: static CGlareDef *ms_pGlareLib ; // Public method public: CGlareDef() ; CGlareDef(const CGlareDef& src) ; ~CGlareDef() ; CGlareDef& operator =(const CGlareDef& src) { Initialize(src) ; return *this ; } HRESULT Construct() ; void Destruct() ; void Release() ; HRESULT Initialize(const CGlareDef& src) ; HRESULT Initialize(const TCHAR *szStarName, float fGlareLuminance, float fBloomLuminance, float fGhostLuminance, float fGhostDistortion, float fStarLuminance, ESTARLIBTYPE eStarType, float fStarInclination, float fChromaticAberration, float fAfterimageSensitivity, // Current weight float fAfterimageRatio, // After Image weight float fAfterimageLuminance) ; HRESULT Initialize(const GLAREDEF& glareDef) { return Initialize(glareDef.szGlareName, glareDef.fGlareLuminance, glareDef.fBloomLuminance, glareDef.fGhostLuminance, glareDef.fGhostDistortion, glareDef.fStarLuminance, glareDef.eStarType, glareDef.fStarInclination, glareDef.fChromaticAberration, glareDef.fAfterimageSensitivity, glareDef.fAfterimageRatio, glareDef.fAfterimageLuminance) ; } HRESULT Initialize(EGLARELIBTYPE eType) { return Initialize(ms_pGlareLib[eType]) ; } // Public static method public: /// Create glare library static HRESULT InitializeStaticGlareLibs() ; static HRESULT DeleteStaticGlareLibs() ; /// Access to the glare library static const CGlareDef& GetLib(DWORD dwType) { return ms_pGlareLib[dwType] ; } } ; //---------------------------------------------------------- // Dummy to generate static object of glare class __CGlare_GenerateStaticObjects { public: __CGlare_GenerateStaticObjects() { CStarDef::InitializeStaticStarLibs() ; CGlareDef::InitializeStaticGlareLibs() ; } ~__CGlare_GenerateStaticObjects() { CGlareDef::DeleteStaticGlareLibs() ; CStarDef::DeleteStaticStarLibs() ; } static __CGlare_GenerateStaticObjects ms_staticObject ; } ; __CGlare_GenerateStaticObjects __CGlare_GenerateStaticObjects::ms_staticObject ; CGlareDef g_GlareDef; #define _Rad D3DXToRadian // Static star library information static STARDEF s_aLibStarDef[NUM_BASESTARLIBTYPES] = { // star name lines passes length attn rotate bRotate { TEXT("Disable"), 0, 0, 0.0f, 0.0f, _Rad(00.0f), false, }, // STLT_DISABLE { TEXT("Cross"), 4, 3, 1.0f, 0.85f, _Rad(0.0f), true, }, // STLT_CROSS { TEXT("CrossFilter"), 4, 3, 1.0f, 0.95f, _Rad(0.0f), true, }, // STLT_CROSS { TEXT("snowCross"), 6, 3, 1.0f, 0.96f, _Rad(20.0f), true, }, // STLT_SNOWCROSS { TEXT("Vertical"), 2, 3, 1.0f, 0.96f, _Rad(00.0f), false, }, // STLT_VERTICAL } ; static int s_nLibStarDefs = sizeof(s_aLibStarDef) / sizeof(STARDEF) ; // Static glare library information static GLAREDEF s_aLibGlareDef[NUM_GLARELIBTYPES] = { // glare name glare bloom ghost distort star star type // rotate C.A current after ai lum { TEXT("Disable"), 0.0f, 0.0f, 0.0f, 0.01f, 0.0f, STLT_DISABLE, _Rad(0.0f), 0.5f, 0.00f, 0.00f, 0.0f, }, // GLT_DISABLE { TEXT("Camera"), 1.5f, 1.2f, 1.0f, 0.00f, 1.0f, STLT_CROSS, _Rad(00.0f), 0.5f, 0.25f, 0.90f, 1.0f, }, // GLT_CAMERA { TEXT("Natural Bloom"), 1.5f, 1.2f, 0.0f, 0.00f, 0.0f, STLT_DISABLE, _Rad(00.0f), 0.0f, 0.40f, 0.85f, 0.5f, }, // GLT_NATURAL { TEXT("Cheap Lens Camera"), 1.25f, 2.0f, 1.5f, 0.05f, 2.0f, STLT_CROSS, _Rad(00.0f), 0.5f, 0.18f, 0.95f, 1.0f, }, // GLT_CHEAPLENS /* { TEXT("Afterimage"), 1.5f, 1.2f, 0.5f, 0.00f, 0.7f, STLT_CROSS, _Rad(00.0f), 0.5f, 0.1f, 0.98f, 2.0f, }, // GLT_AFTERIMAGE */ { TEXT("Cross Screen Filter"), 1.0f, 2.0f, 1.7f, 0.00f, 1.5f, STLT_CROSSFILTER, _Rad(25.0f), 0.5f, 0.20f, 0.93f, 1.0f, }, // GLT_FILTER_CROSSSCREEN { TEXT("Spectral Cross Filter"), 1.0f, 2.0f, 1.7f, 0.00f, 1.8f, STLT_CROSSFILTER, _Rad(70.0f), 1.5f, 0.20f, 0.93f, 1.0f, }, // GLT_FILTER_CROSSSCREEN_SPECTRAL { TEXT("Snow Cross Filter"), 1.0f, 2.0f, 1.7f, 0.00f, 1.5f, STLT_SNOWCROSS, _Rad(10.0f), 0.5f, 0.20f, 0.93f, 1.0f, }, // GLT_FILTER_SNOWCROSS { TEXT("Spectral Snow Cross"), 1.0f, 2.0f, 1.7f, 0.00f, 1.8f, STLT_SNOWCROSS, _Rad(40.0f), 1.5f, 0.20f, 0.93f, 1.0f, }, // GLT_FILTER_SNOWCROSS_SPECTRAL { TEXT("Sunny Cross Filter"), 1.0f, 2.0f, 1.7f, 0.00f, 1.5f, STLT_SUNNYCROSS, _Rad(00.0f), 0.5f, 0.20f, 0.93f, 1.0f, }, // GLT_FILTER_SUNNYCROSS { TEXT("Spectral Sunny Cross"), 1.0f, 2.0f, 1.7f, 0.00f, 1.8f, STLT_SUNNYCROSS, _Rad(45.0f), 1.5f, 0.20f, 0.93f, 1.0f, }, // GLT_FILTER_SUNNYCROSS_SPECTRAL { TEXT("Cine Camera Vertical Slits"), 1.0f, 2.0f, 1.5f, 0.00f, 1.0f, STLT_VERTICAL, _Rad(90.0f), 0.5f, 0.20f, 0.93f, 1.0f, }, // GLT_CINECAM_VERTICALSLIT { TEXT("Cine Camera Horizontal Slits"), 1.0f, 2.0f, 1.5f, 0.00f, 1.0f, STLT_VERTICAL, _Rad(00.0f), 0.5f, 0.20f, 0.93f, 1.0f, }, // GLT_CINECAM_HORIZONTALSLIT } ; static int s_nLibGlareDefs = sizeof(s_aLibGlareDef) / sizeof(GLAREDEF) ; //---------------------------------------------------------- // Information object for star generation CStarDef *CStarDef::ms_pStarLib = NULL ; D3DXCOLOR CStarDef::ms_avChromaticAberrationColor[] ; CStarDef::CStarDef() { Construct() ; } CStarDef::CStarDef(const CStarDef& src) { Construct() ; Initialize(src) ; } CStarDef::~CStarDef() { Destruct() ; } HRESULT CStarDef::Construct() { ZeroMemory( m_strStarName, sizeof(m_strStarName) ); m_nStarLines = 0 ; m_pStarLine = NULL ; m_fInclination = 0.0f ; m_bRotation = false ; return S_OK ; } void CStarDef::Destruct() { Release() ; } void CStarDef::Release() { SAFE_DELETE_ARRAY(m_pStarLine) ; m_nStarLines = 0 ; } HRESULT CStarDef::Initialize(const CStarDef& src) { if (&src == this) { return S_OK ; } // Release the data Release() ; // Copy the data from source lstrcpyn( m_strStarName, src.m_strStarName, 255 ); m_nStarLines = src.m_nStarLines ; m_fInclination = src.m_fInclination ; m_bRotation = src.m_bRotation ; m_pStarLine = new STARLINE[m_nStarLines] ; for (int i = 0 ; i < m_nStarLines ; i ++) { m_pStarLine[i] = src.m_pStarLine[i] ; } return S_OK ; } /// generic simple star generation HRESULT CStarDef::Initialize(const TCHAR *szStarName, int nStarLines, int nPasses, float fSampleLength, float fAttenuation, float fInclination, bool bRotation) { // Release the data Release() ; // Copy from parameters lstrcpyn( m_strStarName, szStarName, 255 ); m_nStarLines = nStarLines ; m_fInclination = fInclination ; m_bRotation = bRotation ; m_pStarLine = new STARLINE[m_nStarLines] ; float fInc = D3DXToRadian(360.0f / (float)m_nStarLines) ; for (int i = 0 ; i < m_nStarLines ; i ++) { m_pStarLine[i].nPasses = nPasses ; m_pStarLine[i].fSampleLength = fSampleLength ; m_pStarLine[i].fAttenuation = fAttenuation ; m_pStarLine[i].fInclination = fInc * (float)i ; } return S_OK ; } /// Specific start generation // Sunny cross filter HRESULT CStarDef::Initialize_SunnyCrossFilter(const TCHAR *szStarName, float fSampleLength, float fAttenuation, float fLongAttenuation, float fInclination) { // Release the data Release() ; // Create parameters lstrcpyn( m_strStarName, szStarName, 255 ); m_nStarLines = 8 ; m_fInclination = fInclination ; // m_bRotation = true ; m_bRotation = false ; m_pStarLine = new STARLINE[m_nStarLines] ; float fInc = D3DXToRadian(360.0f / (float)m_nStarLines) ; for (int i = 0 ; i < m_nStarLines ; i ++) { m_pStarLine[i].fSampleLength = fSampleLength ; m_pStarLine[i].fInclination = fInc * (float)i + D3DXToRadian(0.0f) ; if ( 0 == (i % 2) ) { m_pStarLine[i].nPasses = 3 ; m_pStarLine[i].fAttenuation = fLongAttenuation ; // long } else { m_pStarLine[i].nPasses = 3 ; m_pStarLine[i].fAttenuation = fAttenuation ; } } return S_OK ; } HRESULT CStarDef::InitializeStaticStarLibs() { if (ms_pStarLib) { return S_OK ; } ms_pStarLib = new CStarDef[NUM_STARLIBTYPES] ; // Create basic form for (int i = 0 ; i < NUM_BASESTARLIBTYPES ; i ++) { ms_pStarLib[i].Initialize(s_aLibStarDef[i]) ; } // Create special form // Sunny cross filter ms_pStarLib[STLT_SUNNYCROSS].Initialize_SunnyCrossFilter() ; // Initialize color aberration table /* { D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.0f), D3DXCOLOR(1.0f, 0.2f, 0.2f, 0.0f), D3DXCOLOR(0.2f, 0.6f, 0.2f, 0.0f), D3DXCOLOR(0.2f, 0.2f, 1.0f, 0.0f), } ; */ D3DXCOLOR avColor[8] = { /* D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.0f), D3DXCOLOR(0.3f, 0.3f, 0.8f, 0.0f), D3DXCOLOR(0.2f, 0.2f, 1.0f, 0.0f), D3DXCOLOR(0.2f, 0.4f, 0.5f, 0.0f), D3DXCOLOR(0.2f, 0.6f, 0.2f, 0.0f), D3DXCOLOR(0.5f, 0.4f, 0.2f, 0.0f), D3DXCOLOR(0.7f, 0.3f, 0.2f, 0.0f), D3DXCOLOR(1.0f, 0.2f, 0.2f, 0.0f), */ D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.0f), // w D3DXCOLOR(0.8f, 0.3f, 0.3f, 0.0f), D3DXCOLOR(1.0f, 0.2f, 0.2f, 0.0f), // r D3DXCOLOR(0.5f, 0.2f, 0.6f, 0.0f), D3DXCOLOR(0.2f, 0.2f, 1.0f, 0.0f), // b D3DXCOLOR(0.2f, 0.3f, 0.7f, 0.0f), D3DXCOLOR(0.2f, 0.6f, 0.2f, 0.0f), // g D3DXCOLOR(0.3f, 0.5f, 0.3f, 0.0f), } ; memcpy( ms_avChromaticAberrationColor, avColor, sizeof(D3DXCOLOR) * 8 ) ; /* ms_avChromaticAberrationColor[0] = D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.0f) ; ms_avChromaticAberrationColor[1] = D3DXCOLOR(0.7f, 0.3f, 0.3f, 0.0f) ; ms_avChromaticAberrationColor[2] = D3DXCOLOR(1.0f, 0.2f, 0.2f, 0.0f) ; ms_avChromaticAberrationColor[3] = D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.0f) ; ms_avChromaticAberrationColor[4] = D3DXCOLOR(0.2f, 0.6f, 0.2f, 0.0f) ; ms_avChromaticAberrationColor[5] = D3DXCOLOR(0.2f, 0.4f, 0.5f, 0.0f) ; ms_avChromaticAberrationColor[6] = D3DXCOLOR(0.2f, 0.3f, 0.8f, 0.0f) ; ms_avChromaticAberrationColor[7] = D3DXCOLOR(0.2f, 0.2f, 1.0f, 0.0f) ; */ return S_OK ; } HRESULT CStarDef::DeleteStaticStarLibs() { // Delete all libraries SAFE_DELETE_ARRAY( ms_pStarLib ) ; return S_OK ; } //---------------------------------------------------------- // Glare definition CGlareDef *CGlareDef::ms_pGlareLib = NULL ; CGlareDef::CGlareDef() { Construct() ; } CGlareDef::CGlareDef(const CGlareDef& src) { Construct() ; Initialize(src) ; } CGlareDef::~CGlareDef() { Destruct() ; } HRESULT CGlareDef::Construct() { ZeroMemory( m_strGlareName, sizeof(m_strGlareName) ); m_fGlareLuminance = 0.0f ; m_fBloomLuminance = 0.0f ; m_fGhostLuminance = 0.0f ; m_fStarLuminance = 0.0f ; m_fStarInclination = 0.0f ; m_fChromaticAberration = 0.0f ; m_fAfterimageSensitivity = 0.0f ; m_fAfterimageRatio = 0.0f ; m_fAfterimageLuminance = 0.0f ; return S_OK ; } void CGlareDef::Destruct() { m_starDef.Release() ; } void CGlareDef::Release() { } HRESULT CGlareDef::Initialize(const CGlareDef& src) { if (&src == this) { return S_OK ; } // Release the data Release() ; // Copy data from source lstrcpyn( m_strGlareName, src.m_strGlareName, 255 ); m_fGlareLuminance = src.m_fGlareLuminance ; m_fBloomLuminance = src.m_fBloomLuminance ; m_fGhostLuminance = src.m_fGhostLuminance ; m_fGhostDistortion = src.m_fGhostDistortion ; m_fStarLuminance = src.m_fStarLuminance ; m_fStarLuminance = src.m_fStarLuminance ; m_fStarInclination = src.m_fStarInclination ; m_fChromaticAberration = src.m_fChromaticAberration ; m_fAfterimageSensitivity = src.m_fStarLuminance ; m_fAfterimageRatio = src.m_fStarLuminance ; m_fAfterimageLuminance = src.m_fStarLuminance ; m_starDef = src.m_starDef ; return S_OK ; } HRESULT CGlareDef::Initialize(const TCHAR *szStarName, float fGlareLuminance, float fBloomLuminance, float fGhostLuminance, float fGhostDistortion, float fStarLuminance, ESTARLIBTYPE eStarType, float fStarInclination, float fChromaticAberration, float fAfterimageSensitivity, // Current weight float fAfterimageRatio, // Afterimage weight float fAfterimageLuminance) { // Release the data Release() ; // Create parameters lstrcpyn( m_strGlareName, szStarName, 255 ); m_fGlareLuminance = fGlareLuminance ; m_fBloomLuminance = fBloomLuminance ; m_fGhostLuminance = fGhostLuminance ; m_fGhostDistortion = fGhostDistortion ; m_fStarLuminance = fStarLuminance ; m_fStarInclination = fStarInclination ; m_fChromaticAberration = fChromaticAberration ; m_fAfterimageSensitivity = fAfterimageSensitivity ; m_fAfterimageRatio = fAfterimageRatio ; m_fAfterimageLuminance = fAfterimageLuminance ; // Create star form data m_starDef = CStarDef::GetLib(eStarType) ; return S_OK ; } HRESULT CGlareDef::InitializeStaticGlareLibs() { if (ms_pGlareLib) { return S_OK ; } CStarDef::InitializeStaticStarLibs() ; ms_pGlareLib = new CGlareDef[NUM_GLARELIBTYPES] ; // Create glare form for (int i = 0 ; i < NUM_GLARELIBTYPES ; i ++) { ms_pGlareLib[i].Initialize(s_aLibGlareDef[i]) ; } return S_OK ; } HRESULT CGlareDef::DeleteStaticGlareLibs() { // Delete all libraries SAFE_DELETE_ARRAY( ms_pGlareLib ) ; return S_OK ; } //============================================================================= // Texture coordinate rectangle struct CoordRect { float fLeftU, fTopV; float fRightU, fBottomV; }; // Screen quad vertex format struct ScreenVertex { D3DXVECTOR4 p; // position D3DCOLOR color; D3DXVECTOR2 t; // texture coordinate }; // log helper #define LOG_EFFECT(msg)\ if (gRenDev->m_LogFile)\ {\ gRenDev->Logv(SRendItem::m_RecurseLevel, msg);\ }\ // =============================================================== // SetTexture - sets texture stage inline void SetTexture(CD3D9Renderer *pRenderer, STexPic *pTex, int iStage, int iMinFilter, int iMagFilter, bool bClamp) { pRenderer->EF_SelectTMU(iStage); if(pTex) { pTex->m_RefTex.m_MinFilter=iMinFilter; pTex->m_RefTex.m_MagFilter=iMagFilter; pTex->m_RefTex.bRepeats=(!bClamp); pTex->Set(); } else { pRenderer->SetTexture(0); } } PDIRECT3DSURFACE9 GetSurfaceTP(STexPic *tp) { PDIRECT3DSURFACE9 pSurf = NULL; if (tp) { LPDIRECT3DTEXTURE9 pTexture = (LPDIRECT3DTEXTURE9)tp->m_RefTex.m_VidTex; assert(pTexture); HRESULT hr = pTexture->GetSurfaceLevel(0, &pSurf); } return pSurf; } #define NV_CACHE_OPTS_ENABLED TRUE //----------------------------------------------------------------------------- // Name: DrawFullScreenQuad // Desc: Draw a properly aligned quad covering the entire render target //----------------------------------------------------------------------------- void DrawFullScreenQuad(float fLeftU, float fTopV, float fRightU, float fBottomV) { D3DSURFACE_DESC dtdsdRT; PDIRECT3DSURFACE9 pSurfRT; CD3D9Renderer *rd = gcpRendD3D; LPDIRECT3DDEVICE9 dv = rd->m_pd3dDevice; // Acquire render target width and height dv->GetRenderTarget(0, &pSurfRT); pSurfRT->GetDesc(&dtdsdRT); pSurfRT->Release(); // Ensure that we're directly mapping texels to pixels by offset by 0.5 // For more info see the doc page titled "Directly Mapping Texels to Pixels" int nWidth = min((int)dtdsdRT.Width, rd->GetWidth()); int nHeight = min((int)dtdsdRT.Height, rd->GetHeight()); float fWidth5 = (float)nWidth; float fHeight5 = (float)nHeight; fWidth5 = (NV_CACHE_OPTS_ENABLED) ? (2.f*fWidth5) - 0.5f : fWidth5 - 0.5f; fHeight5 = (NV_CACHE_OPTS_ENABLED) ? (2.f*fHeight5)- 0.5f : fHeight5 - 0.5f; // Draw the quad ScreenVertex svQuad[4]; svQuad[0].p = D3DXVECTOR4(-0.5f, -0.5f, 0.5f, 1.0f); svQuad[0].color = -1; svQuad[0].t = D3DXVECTOR2(fLeftU, fTopV); if (NV_CACHE_OPTS_ENABLED) { float tWidth = fRightU - fLeftU; float tHeight = fBottomV - fTopV; svQuad[1].p = D3DXVECTOR4(fWidth5, -0.5f, 0.5f, 1.f); svQuad[1].t = D3DXVECTOR2(fLeftU + (tWidth*2.f), fTopV); svQuad[2].p = D3DXVECTOR4(-0.5f, fHeight5, 0.5f, 1.f); svQuad[2].t = D3DXVECTOR2(fLeftU, fTopV + (tHeight*2.f)); } else { svQuad[1].p = D3DXVECTOR4(fWidth5, -0.5f, 0.5f, 1.0f); svQuad[1].color = -1; svQuad[1].t = D3DXVECTOR2(fRightU, fTopV); svQuad[2].p = D3DXVECTOR4(-0.5f, fHeight5, 0.5f, 1.0f); svQuad[2].color = -1; svQuad[2].t = D3DXVECTOR2(fLeftU, fBottomV); svQuad[3].p = D3DXVECTOR4(fWidth5, fHeight5, 0.5f, 1.0f); svQuad[3].color = -1; svQuad[3].t = D3DXVECTOR2(fRightU, fBottomV); } rd->EF_SetState(GS_NODEPTHTEST); rd->EF_SetVertexDeclaration(0, VERTEX_FORMAT_TRP3F_COL4UB_TEX2F); dv->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, (NV_CACHE_OPTS_ENABLED)?1:2, svQuad, sizeof(ScreenVertex)); } void DrawFullScreenQuad(CoordRect c) { DrawFullScreenQuad( c.fLeftU, c.fTopV, c.fRightU, c.fBottomV ); } //----------------------------------------------------------------------------- // Name: GetTextureRect() // Desc: Get the dimensions of the texture //----------------------------------------------------------------------------- HRESULT GetTextureRect(STexPic *pTexture, RECT* pRect) { pRect->left = 0; pRect->top = 0; pRect->right = pTexture->m_Width; pRect->bottom = pTexture->m_Height; return S_OK; } //----------------------------------------------------------------------------- // Name: GetTextureCoords() // Desc: Get the texture coordinates to use when rendering into the destination // texture, given the source and destination rectangles //----------------------------------------------------------------------------- HRESULT GetTextureCoords( STexPic *pTexSrc, RECT* pRectSrc, STexPic *pTexDest, RECT* pRectDest, CoordRect* pCoords) { float tU, tV; // Validate arguments if( pTexSrc == NULL || pTexDest == NULL || pCoords == NULL ) return E_INVALIDARG; // Start with a default mapping of the complete source surface to complete // destination surface pCoords->fLeftU = 0.0f; pCoords->fTopV = 0.0f; pCoords->fRightU = 1.0f; pCoords->fBottomV = 1.0f; // If not using the complete source surface, adjust the coordinates if(pRectSrc != NULL) { // These delta values are the distance between source texel centers in // texture address space tU = 1.0f / pTexSrc->m_Width; tV = 1.0f / pTexSrc->m_Height; pCoords->fLeftU += pRectSrc->left * tU; pCoords->fTopV += pRectSrc->top * tV; pCoords->fRightU -= (pTexSrc->m_Width - pRectSrc->right) * tU; pCoords->fBottomV -= (pTexSrc->m_Height - pRectSrc->bottom) * tV; } // If not drawing to the complete destination surface, adjust the coordinates if(pRectDest != NULL) { // These delta values are the distance between source texel centers in // texture address space tU = 1.0f / pTexDest->m_Width; tV = 1.0f / pTexDest->m_Height; pCoords->fLeftU -= pRectDest->left * tU; pCoords->fTopV -= pRectDest->top * tV; pCoords->fRightU += (pTexDest->m_Width - pRectDest->right) * tU; pCoords->fBottomV += (pTexDest->m_Height - pRectDest->bottom) * tV; } return S_OK; } //----------------------------------------------------------------------------- // Name: GaussianDistribution // Desc: Helper function for GetSampleOffsets function to compute the // 2 parameter Gaussian distrubution using the given standard deviation // rho //----------------------------------------------------------------------------- float GaussianDistribution( float x, float y, float rho ) { float g = 1.0f / sqrtf(2.0f * D3DX_PI * rho * rho); g *= expf( -(x*x + y*y)/(2*rho*rho) ); return g; } //----------------------------------------------------------------------------- // Name: GetSampleOffsets_GaussBlur5x5 // Desc: Get the texture coordinate offsets to be used inside the GaussBlur5x5 // pixel shader. //----------------------------------------------------------------------------- HRESULT GetSampleOffsets_GaussBlur5x5(DWORD dwD3DTexWidth, DWORD dwD3DTexHeight, D3DXVECTOR4* avTexCoordOffset, D3DXVECTOR4* avSampleWeight, FLOAT fMultiplier) { float tu = 1.0f / (float)dwD3DTexWidth ; float tv = 1.0f / (float)dwD3DTexHeight ; D3DXVECTOR4 vWhite( 1.0f, 1.0f, 1.0f, 1.0f ); float totalWeight = 0.0f; int index=0; for(int x=-2; x<=2; x++) { for(int y=-2; y<=2; y++) { // Exclude pixels with a block distance greater than 2. This will // create a kernel which approximates a 5x5 kernel using only 13 // sample points instead of 25; this is necessary since 2.0 shaders // only support 16 texture grabs. if( abs(x) + abs(y) > 2 ) continue; // Get the unscaled Gaussian intensity for this offset avTexCoordOffset[index] = D3DXVECTOR4(x*tu, y*tv, 0, 1); avSampleWeight[index] = vWhite * GaussianDistribution( (float)x, (float)y, 1.0f); totalWeight += avSampleWeight[index].x; index++; } } // Divide the current weight by the total weight of all the samples; Gaussian // blur kernels add to 1.0f to ensure that the intensity of the image isn't // changed when the blur occurs. An optional multiplier variable is used to // add or remove image intensity during the blur. for(int i=0; im_pd3dDevice; // Get the new render target surface PDIRECT3DSURFACE9 pSurfScaledScene[2]; PDIRECT3DSURFACE9 pSurfTempScene; pSurfScaledScene[0] = GetSurfaceTP(rd->m_TexMan->m_Text_HDRTargetScaled[0]); pSurfScaledScene[1] = GetSurfaceTP(rd->m_TexMan->m_Text_HDRTargetScaled[1]); pSurfTempScene = GetSurfaceTP(rd->m_TexMan->m_Text_HDRTarget_Temp); // Create a 1/4 x 1/4 scale copy of the HDR texture. Since bloom textures // are 1/8 x 1/8 scale, border texels of the HDR texture will be discarded // to keep the dimensions evenly divisible by 8; this allows for precise // control over sampling inside pixel shaders. CCGPShader_D3D *fpDownScale; CCGPShader_D3D *fpTemp; // Place the rectangle in the center of the back buffer surface RECT rectSrc; rectSrc.left = (rd->GetWidth() - rd->m_dwHDRCropWidth) / 2; rectSrc.top = (rd->GetHeight() - rd->m_dwHDRCropHeight) / 2; rectSrc.right = rectSrc.left + rd->m_dwHDRCropWidth; rectSrc.bottom = rectSrc.top + rd->m_dwHDRCropHeight; if (rd->m_nHDRType == 2) { SetTexture(rd, rd->m_TexMan->m_Text_HDRTarget, 0, D3DTEXF_POINT, D3DTEXF_POINT, true); //SetTexture(rd, rd->m_TexMan->m_Text_HDRTarget_K, 1, D3DTEXF_POINT, D3DTEXF_POINT, true); SetTexture(rd, rd->m_TexMan->m_Text_White, 1, D3DTEXF_POINT, D3DTEXF_POINT, true); dv->SetRenderTarget(0, pSurfTempScene); fpTemp = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRTemp, "CGRC_HDR_MRTK_2_FP16_PS20"); assert(fpTemp); if (fpTemp) { fpTemp->mfSet(true); DrawFullScreenQuad(0, 0, 1, 1); fpTemp->mfSet(false); } SetTexture(rd, NULL, 1, D3DTEXF_POINT, D3DTEXF_POINT, true); rd->EF_SelectTMU(0); } // Get the texture coordinates for the render target CoordRect coords; GetTextureCoords(rd->m_TexMan->m_Text_HDRTarget, &rectSrc, rd->m_TexMan->m_Text_HDRTargetScaled[0], NULL, &coords); int nBitPlanes = rd->m_bDeviceSupportsMRT ? 2 : 1; for (int i=0; iSetRenderTarget(0, pSurfScaledScene[i]); if (!rd->m_bDeviceSupportsMRT) { if (rd->m_bDeviceSupportsFP16Filter) fpDownScale = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRDownScale4x4, "CGRC_HDR_DownScale4x4_Bilinear_PS20"); else fpDownScale = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRDownScale4x4, "CGRC_HDR_DownScale4x4_PS20"); } else { if (rd->m_bDeviceSupportsFP16Filter) { if (!i) fpDownScale = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRDownScale4x4_RG, "CGRC_HDR_DownScale4x4_Bilinear_RG_PS20"); else fpDownScale = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRDownScale4x4_BA, "CGRC_HDR_DownScale4x4_Bilinear_BA_PS20"); } else { if (!i) fpDownScale = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRDownScale4x4_RG, "CGRC_HDR_DownScale4x4_RG_PS20"); else fpDownScale = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRDownScale4x4_BA, "CGRC_HDR_DownScale4x4_BA_PS20"); } } if (!fpDownScale) return false; fpDownScale->mfSet(true, 0); if (!i) { // Get the sample offsets used within the pixel shader SCGBind *bind = fpDownScale->mfGetParameterBind("vSampleOffsets"); assert(bind); if (rd->m_bDeviceSupportsFP16Filter) { GetSampleOffsets_DownScale4x4Bilinear(rd->GetWidth(), rd->GetHeight(), avSampleOffsets); fpDownScale->mfParameter(bind, &avSampleOffsets[0].x, 4); SetTexture(rd, rd->m_TexMan->m_Text_HDRTarget, 0, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); } else { GetSampleOffsets_DownScale4x4(rd->GetWidth(), rd->GetHeight(), avSampleOffsets); fpDownScale->mfParameter(bind, &avSampleOffsets[0].x, 16); if (rd->m_nHDRType == 2) SetTexture(rd, rd->m_TexMan->m_Text_HDRTarget_Temp, 0, D3DTEXF_POINT, D3DTEXF_POINT, true); else SetTexture(rd, rd->m_TexMan->m_Text_HDRTarget, 0, D3DTEXF_POINT, D3DTEXF_POINT, true); } } // Draw a fullscreen quad DrawFullScreenQuad(coords); } fpDownScale->mfSet(false, 0); SAFE_RELEASE(pSurfScaledScene[0]); SAFE_RELEASE(pSurfScaledScene[1]); SAFE_RELEASE(pSurfTempScene); if (rd->m_bDeviceSupportsMRT) dv->SetRenderTarget(1, NULL); return true; } bool HDR_MeasureLuminance() { HRESULT hr = S_OK; int i, x, y, index; D3DXVECTOR4 avSampleOffsets[16]; CD3D9Renderer *rd = gcpRendD3D; LPDIRECT3DDEVICE9 dv = rd->m_pd3dDevice; CCGPShader_D3D *fpSampleAvgLum = NULL; CCGPShader_D3D *fpResampleAvgLum = NULL; CCGPShader_D3D *fpResampleAvgLumExp = NULL; SCGBind *bind; bool bResult = false; DWORD dwCurTexture = NUM_HDR_TONEMAP_TEXTURES-1; // Sample log average luminance PDIRECT3DSURFACE9 apSurfToneMap[NUM_HDR_TONEMAP_TEXTURES] = {0}; // Retrieve the tonemap surfaces for(i=0; im_TexMan->m_Text_HDRToneMaps[i]); if (!apSurfToneMap[i]) goto LCleanReturn; } // Initialize the sample offsets for the initial luminance pass. float tU, tV; tU = 1.0f / (3.0f * rd->m_TexMan->m_Text_HDRToneMaps[dwCurTexture]->m_Width); tV = 1.0f / (3.0f * rd->m_TexMan->m_Text_HDRToneMaps[dwCurTexture]->m_Height); index=0; for(x=-1; x<=1; x++) { for(y=-1; y<=1; y++) { avSampleOffsets[index].x = x * tU; avSampleOffsets[index].y = y * tV; avSampleOffsets[index].z = 0; avSampleOffsets[index].w = 1; index++; } } // After this pass, the CTexMan::m_Text_HDRToneMaps[NUM_TONEMAP_TEXTURES-1] texture will contain // a scaled, grayscale copy of the HDR scene. Individual texels contain the log // of average luminance values for points sampled on the HDR texture. if (rd->m_bDeviceSupportsMRT) fpSampleAvgLum = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRSampleAvgLum, "CGRC_HDR_SampleAvgLum_FromMRT_PS20"); else fpSampleAvgLum = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRSampleAvgLum, "CGRC_HDR_SampleAvgLum_PS20"); if (!fpSampleAvgLum) goto LCleanReturn; fpSampleAvgLum->mfSet(true, 0); bind = fpSampleAvgLum->mfGetParameterBind("vSampleOffsets"); assert(bind); fpSampleAvgLum->mfParameter(bind, &avSampleOffsets[0].x, 9); if (rd->m_bDeviceSupportsMRT) { SetTexture(rd, rd->m_TexMan->m_Text_HDRTargetScaled[0], 0, D3DTEXF_POINT, D3DTEXF_POINT, true); SetTexture(rd, rd->m_TexMan->m_Text_HDRTargetScaled[1], 1, D3DTEXF_POINT, D3DTEXF_POINT, true); } else SetTexture(rd, rd->m_TexMan->m_Text_HDRTargetScaled[0], 0, D3DTEXF_POINT, D3DTEXF_POINT, true); dv->SetRenderTarget(0, apSurfToneMap[dwCurTexture]); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(0.0f, 0.0f, 1.0f, 1.0f); if (rd->m_bDeviceSupportsMRT ) dv->SetTexture(1, NULL); dwCurTexture--; // Initialize the sample offsets for the iterative luminance passes while(dwCurTexture > 0) { dv->SetRenderTarget(0, apSurfToneMap[dwCurTexture]); if (rd->m_bDeviceSupportsFP16Filter) { GetSampleOffsets_DownScale4x4Bilinear(rd->m_TexMan->m_Text_HDRToneMaps[dwCurTexture+1]->m_Width, rd->m_TexMan->m_Text_HDRToneMaps[dwCurTexture+1]->m_Height, avSampleOffsets); // Each of these passes continue to scale down the log of average // luminance texture created above, storing intermediate results in // HDRToneMaps[1] through HDRToneMaps[NUM_HDR_TONEMAP_TEXTURES-1]. fpResampleAvgLum = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRResampleAvgLum, "CGRC_HDR_ResampleAvgLum_Bilinear_PS20"); if (!fpResampleAvgLum) goto LCleanReturn; fpResampleAvgLum->mfSet(true, 0); bind = fpResampleAvgLum->mfGetParameterBind("vSampleOffsets"); assert(bind); fpResampleAvgLum->mfParameter(bind, &avSampleOffsets[0].x, 4); dv->SetRenderTarget(0, apSurfToneMap[dwCurTexture]); SetTexture(rd, rd->m_TexMan->m_Text_HDRToneMaps[dwCurTexture+1], 0, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); } else { GetSampleOffsets_DownScale4x4(rd->m_TexMan->m_Text_HDRToneMaps[dwCurTexture+1]->m_Width, rd->m_TexMan->m_Text_HDRToneMaps[dwCurTexture+1]->m_Height, avSampleOffsets); // Each of these passes continue to scale down the log of average // luminance texture created above, storing intermediate results in // HDRToneMaps[1] through HDRToneMaps[NUM_HDR_TONEMAP_TEXTURES-1]. fpResampleAvgLum = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRResampleAvgLum, "CGRC_HDR_ResampleAvgLum_PS20"); if (!fpResampleAvgLum) goto LCleanReturn; fpResampleAvgLum->mfSet(true, 0); bind = fpResampleAvgLum->mfGetParameterBind("vSampleOffsets"); assert(bind); fpResampleAvgLum->mfParameter(bind, &avSampleOffsets[0].x, 16); SetTexture(rd, rd->m_TexMan->m_Text_HDRToneMaps[dwCurTexture+1], 0, D3DTEXF_POINT, D3DTEXF_POINT, true); } // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(0.0f, 0.0f, 1.0f, 1.0f); dwCurTexture--; } if (rd->m_bDeviceSupportsFP16Filter) { GetSampleOffsets_DownScale4x4Bilinear(rd->m_TexMan->m_Text_HDRToneMaps[1]->m_Width, rd->m_TexMan->m_Text_HDRToneMaps[1]->m_Height, avSampleOffsets); // Perform the final pass of the average luminance calculation. This pass // scales the 4x4 log of average luminance texture from above and performs // an exp() operation to return a single texel cooresponding to the average // luminance of the scene in CTexMan::m_Text_HDRToneMaps[0]. fpResampleAvgLumExp = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRResampleAvgLumExp, "CGRC_HDR_ResampleAvgLumExp_Bilinear_PS20"); if (!fpResampleAvgLumExp) goto LCleanReturn; fpResampleAvgLumExp->mfSet(true, 0); bind = fpResampleAvgLumExp->mfGetParameterBind("vSampleOffsets"); assert(bind); fpResampleAvgLumExp->mfParameter(bind, &avSampleOffsets[0].x, 4); SetTexture(rd, rd->m_TexMan->m_Text_HDRToneMaps[1], 0, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); } else { GetSampleOffsets_DownScale4x4(rd->m_TexMan->m_Text_HDRToneMaps[1]->m_Width, rd->m_TexMan->m_Text_HDRToneMaps[1]->m_Height, avSampleOffsets); // Each of these passes continue to scale down the log of average // luminance texture created above, storing intermediate results in // HDRToneMaps[1] through HDRToneMaps[NUM_HDR_TONEMAP_TEXTURES-1]. fpResampleAvgLumExp = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRResampleAvgLumExp, "CGRC_HDR_ResampleAvgLumExp_PS20"); if (!fpResampleAvgLumExp) goto LCleanReturn; fpResampleAvgLumExp->mfSet(true, 0); bind = fpResampleAvgLumExp->mfGetParameterBind("vSampleOffsets"); assert(bind); fpResampleAvgLumExp->mfParameter(bind, &avSampleOffsets[0].x, 16); SetTexture(rd, rd->m_TexMan->m_Text_HDRToneMaps[1], 0, D3DTEXF_POINT, D3DTEXF_POINT, true); } dv->SetRenderTarget(0, apSurfToneMap[0]); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(0.0f, 0.0f, 1.0f, 1.0f); bResult = true; LCleanReturn: for(i=0; imfSet(false, 0); if (fpResampleAvgLum) fpResampleAvgLum->mfSet(false, 0); if (fpResampleAvgLumExp) fpResampleAvgLumExp->mfSet(false, 0); return bResult; } //----------------------------------------------------------------------------- // Name: HDR_CalculateAdaptation() // Desc: Increment the user's adapted luminance //----------------------------------------------------------------------------- bool HDR_CalculateAdaptation() { HRESULT hr = S_OK; CD3D9Renderer *rd = gcpRendD3D; LPDIRECT3DDEVICE9 dv = rd->m_pd3dDevice; CD3D9TexMan *tm = (CD3D9TexMan *)rd->m_TexMan; CCGPShader_D3D *fpCalcAdaptedLum = NULL; bool bResult = false; // Swap current & last luminance STexPic *pTexSwap = tm->m_Text_HDRAdaptedLuminanceLast; tm->m_Text_HDRAdaptedLuminanceLast = tm->m_Text_HDRAdaptedLuminanceCur; tm->m_Text_HDRAdaptedLuminanceCur = pTexSwap; PDIRECT3DSURFACE9 pSurfAdaptedLum = GetSurfaceTP(tm->m_Text_HDRAdaptedLuminanceCur); if(!pSurfAdaptedLum) return false; // This simulates the light adaptation that occurs when moving from a // dark area to a bright area, or vice versa. The g_pTexAdaptedLuminance // texture stores a single texel cooresponding to the user's adapted // level. fpCalcAdaptedLum = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRCalcAdaptedLum, "CGRC_HDR_CalculateAdaptedLum_PS20"); if (!fpCalcAdaptedLum) goto LCleanReturn; fpCalcAdaptedLum->mfSet(true, 0); float v[4]; v[0] = iTimer->GetFrameTime(); v[1] = v[2] = v[3] = 0; fpCalcAdaptedLum->mfParameter4f("fElapsedTime", v); dv->SetRenderTarget(0, pSurfAdaptedLum); SetTexture(rd, tm->m_Text_HDRAdaptedLuminanceLast, 0, D3DTEXF_POINT, D3DTEXF_POINT, true); SetTexture(rd, tm->m_Text_HDRToneMaps[0], 1, D3DTEXF_POINT, D3DTEXF_POINT, true); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(0.0f, 0.0f, 1.0f, 1.0f); bResult = true; LCleanReturn: if (fpCalcAdaptedLum) fpCalcAdaptedLum->mfSet(false, 0); rd->EF_SelectTMU(0); SAFE_RELEASE(pSurfAdaptedLum); return bResult; } //----------------------------------------------------------------------------- // Name: SceneScaled_To_BrightPass // Desc: Run the bright-pass filter on CTexman::m_Text_HDRTargetScaled and place the result // in CTexMan::m_Text_HDRBrightPass //----------------------------------------------------------------------------- bool HDR_SceneScaledToBrightPass() { HRESULT hr = S_OK; CD3D9Renderer *rd = gcpRendD3D; LPDIRECT3DDEVICE9 dv = rd->m_pd3dDevice; CD3D9TexMan *tm = (CD3D9TexMan *)rd->m_TexMan; CCGPShader_D3D *fpBrightPassFilter = NULL; bool bResult = false; // Get the new render target surface PDIRECT3DSURFACE9 pSurfBrightPass = GetSurfaceTP(tm->m_Text_HDRBrightPass); if(!pSurfBrightPass) return false; // clear destination surface dv->ColorFill(pSurfBrightPass, NULL, D3DCOLOR_ARGB(0, 0, 0, 0)); // Get the rectangle describing the sampled portion of the source texture. // Decrease the rectangle to adjust for the single pixel black border. RECT rectSrc; GetTextureRect(tm->m_Text_HDRTargetScaled[0], &rectSrc); InflateRect(&rectSrc, -1, -1); // Get the destination rectangle. // Decrease the rectangle to adjust for the single pixel black border. RECT rectDest; GetTextureRect(tm->m_Text_HDRBrightPass, &rectDest); InflateRect(&rectDest, -1, -1); // Get the correct texture coordinates to apply to the rendered quad in order // to sample from the source rectangle and render into the destination rectangle CoordRect coords; GetTextureCoords(tm->m_Text_HDRTargetScaled[0], &rectSrc, tm->m_Text_HDRBrightPass, &rectDest, &coords); // The bright-pass filter removes everything from the scene except lights and // bright reflections if (rd->m_bDeviceSupportsMRT) fpBrightPassFilter = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRBrightPassFilter, "CGRC_HDR_BrightPassFilter_FromMRT_PS20"); else fpBrightPassFilter = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRBrightPassFilter, "CGRC_HDR_BrightPassFilter_PS20"); if (!fpBrightPassFilter) goto LCleanReturn; fpBrightPassFilter->mfSet(true, 0); float v[4]; v[0] = CRenderer::CV_r_hdrlevel; v[1] = CRenderer::CV_r_hdrbrightoffset; v[2] = CRenderer::CV_r_hdrbrightthreshold; v[3] = 0; fpBrightPassFilter->mfParameter4f("Params", v); dv->SetRenderTarget(0, pSurfBrightPass); if (rd->m_bDeviceSupportsMRT) { SetTexture(rd, tm->m_Text_HDRTargetScaled[0], 0, D3DTEXF_POINT, D3DTEXF_POINT, true); SetTexture(rd, tm->m_Text_HDRTargetScaled[1], 1, D3DTEXF_POINT, D3DTEXF_POINT, true); SetTexture(rd, tm->m_Text_HDRAdaptedLuminanceCur, 2, D3DTEXF_POINT, D3DTEXF_POINT, true); } else { SetTexture(rd, tm->m_Text_HDRTargetScaled[0], 0, D3DTEXF_POINT, D3DTEXF_POINT, true); SetTexture(rd, tm->m_Text_HDRAdaptedLuminanceCur, 1, D3DTEXF_POINT, D3DTEXF_POINT, true); } dv->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); dv->SetScissorRect(&rectDest); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(coords); dv->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); bResult = true; LCleanReturn: SAFE_RELEASE(pSurfBrightPass); rd->EF_SelectTMU(0); if (fpBrightPassFilter) fpBrightPassFilter->mfSet(false, 0); return bResult; } //----------------------------------------------------------------------------- // Name: HDR_BrightPass_To_StarSource // Desc: Perform a 5x5 gaussian blur on g_pTexBrightPass and place the result // in g_pTexStarSource. The bright-pass filtered image is blurred before // being used for star operations to avoid aliasing artifacts. //----------------------------------------------------------------------------- bool HDR_BrightPassToStarSource() { HRESULT hr = S_OK; CD3D9Renderer *rd = gcpRendD3D; LPDIRECT3DDEVICE9 dv = rd->m_pd3dDevice; CD3D9TexMan *tm = (CD3D9TexMan *)rd->m_TexMan; CCGPShader_D3D *fpGaussBlur5x5 = NULL; bool bResult = false; SCGBind *bind = NULL; D3DXVECTOR4 avSampleOffsets[16]; D3DXVECTOR4 avSampleWeights[16]; // Get the new render target surface PDIRECT3DSURFACE9 pSurfStarSource = GetSurfaceTP(tm->m_Text_HDRStarSource); if(!pSurfStarSource) return false; // clear destination surface dv->ColorFill(pSurfStarSource, NULL, D3DCOLOR_ARGB(0, 0, 0, 0)); // Get the destination rectangle. // Decrease the rectangle to adjust for the single pixel black border. RECT rectDest; GetTextureRect(tm->m_Text_HDRStarSource, &rectDest); InflateRect(&rectDest, -1, -1); // Get the correct texture coordinates to apply to the rendered quad in order // to sample from the source rectangle and render into the destination rectangle CoordRect coords; GetTextureCoords(tm->m_Text_HDRBrightPass, NULL, tm->m_Text_HDRStarSource, &rectDest, &coords); // The gaussian blur smooths out rough edges to avoid aliasing effects // when the star effect is run if (rd->m_bDeviceSupportsFP16Filter) { GetSampleOffsets_GaussBlur5x5Bilinear(tm->m_Text_HDRBrightPass->m_Width, tm->m_Text_HDRBrightPass->m_Height, avSampleOffsets, avSampleWeights, 1.0f); fpGaussBlur5x5 = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRGaussBlur5x5_Bilinear, "CGRC_HDR_GaussBlur5x5_Bilinear_PS20"); } else { GetSampleOffsets_GaussBlur5x5(tm->m_Text_HDRBrightPass->m_Width, tm->m_Text_HDRBrightPass->m_Height, avSampleOffsets, avSampleWeights, 1.0f); fpGaussBlur5x5 = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRGaussBlur5x5, "CGRC_HDR_GaussBlur5x5_PS20"); } if (!fpGaussBlur5x5) goto LCleanReturn; fpGaussBlur5x5->mfSet(true, 0); bind = fpGaussBlur5x5->mfGetParameterBind("vSampleOffsets"); assert(bind); if (rd->m_bDeviceSupportsFP16Filter) fpGaussBlur5x5->mfParameter(bind, &avSampleOffsets[0].x, 9); else fpGaussBlur5x5->mfParameter(bind, &avSampleOffsets[0].x, 13); bind = fpGaussBlur5x5->mfGetParameterBind("vSampleWeights"); assert(bind); if (rd->m_bDeviceSupportsFP16Filter) fpGaussBlur5x5->mfParameter(bind, &avSampleWeights[0].x, 9); else fpGaussBlur5x5->mfParameter(bind, &avSampleWeights[0].x, 13); dv->SetRenderTarget(0, pSurfStarSource); if (rd->m_bDeviceSupportsFP16Filter) SetTexture(rd, tm->m_Text_HDRBrightPass, 0, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); else SetTexture(rd, tm->m_Text_HDRBrightPass, 0, D3DTEXF_POINT, D3DTEXF_POINT, true); dv->SetScissorRect(&rectDest); dv->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); // Draw a fullscreen quad DrawFullScreenQuad(coords); dv->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); bResult = true; LCleanReturn: SAFE_RELEASE(pSurfStarSource); rd->EF_SelectTMU(0); if (fpGaussBlur5x5) fpGaussBlur5x5->mfSet(false, 0); return bResult; } //----------------------------------------------------------------------------- // Name: HDR_StarSource_To_BloomSource // Desc: Scale down g_pTexStarSource by 1/2 x 1/2 and place the result in // CTexMan::m_Text_HDRBloomSource //----------------------------------------------------------------------------- bool HDR_StarSourceToBloomSource() { HRESULT hr = S_OK; CD3D9Renderer *rd = gcpRendD3D; LPDIRECT3DDEVICE9 dv = rd->m_pd3dDevice; CD3D9TexMan *tm = (CD3D9TexMan *)rd->m_TexMan; CCGPShader_D3D *fpDownScale2x2 = NULL; bool bResult = false; SCGBind *bind = NULL; D3DXVECTOR4 avSampleOffsets[4]; // Get the new render target surface PDIRECT3DSURFACE9 pSurfBloomSource = GetSurfaceTP(tm->m_Text_HDRBloomSource); if(!pSurfBloomSource) return false; // clear destination surface dv->ColorFill(pSurfBloomSource, NULL, D3DCOLOR_ARGB(0, 0, 0, 0)); // Get the rectangle describing the sampled portion of the source texture. // Decrease the rectangle to adjust for the single pixel black border. RECT rectSrc; GetTextureRect(tm->m_Text_HDRStarSource, &rectSrc); InflateRect(&rectSrc, -1, -1); // Get the destination rectangle. // Decrease the rectangle to adjust for the single pixel black border. RECT rectDest; GetTextureRect(tm->m_Text_HDRBloomSource, &rectDest); InflateRect(&rectDest, -1, -1); // Get the correct texture coordinates to apply to the rendered quad in order // to sample from the source rectangle and render into the destination rectangle CoordRect coords; GetTextureCoords(tm->m_Text_HDRStarSource, &rectSrc, tm->m_Text_HDRBloomSource, &rectDest, &coords); if (rd->m_bDeviceSupportsFP16Filter) { GetSampleOffsets_DownScale2x2Bilinear(tm->m_Text_HDRBrightPass->m_Width, tm->m_Text_HDRBrightPass->m_Height, avSampleOffsets); fpDownScale2x2 = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRDownScale2x2, "CGRC_HDR_DownScale2x2_Bilinear_PS20"); } else { GetSampleOffsets_DownScale2x2(tm->m_Text_HDRBrightPass->m_Width, tm->m_Text_HDRBrightPass->m_Height, avSampleOffsets); fpDownScale2x2 = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRDownScale2x2, "CGRC_HDR_DownScale2x2_PS20"); } // Create an exact 1/2 x 1/2 copy of the source texture if (!fpDownScale2x2) goto LCleanReturn; fpDownScale2x2->mfSet(true, 0); bind = fpDownScale2x2->mfGetParameterBind("vSampleOffsets"); assert(bind); if (rd->m_bDeviceSupportsFP16Filter) fpDownScale2x2->mfParameter(bind, &avSampleOffsets[0].x, 1); else fpDownScale2x2->mfParameter(bind, &avSampleOffsets[0].x, 4); dv->SetRenderTarget(0, pSurfBloomSource); if (rd->m_bDeviceSupportsFP16Filter) SetTexture(rd, tm->m_Text_HDRStarSource, 0, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); else SetTexture(rd, tm->m_Text_HDRStarSource, 0, D3DTEXF_POINT, D3DTEXF_POINT, true); dv->SetScissorRect(&rectDest); dv->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); // Draw a fullscreen quad DrawFullScreenQuad(coords); dv->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); bResult = true; LCleanReturn: SAFE_RELEASE(pSurfBloomSource); if (fpDownScale2x2) fpDownScale2x2->mfSet(false, 0); return bResult; } //----------------------------------------------------------------------------- // Name: HDR_RenderBloom() // Desc: Render the blooming effect //----------------------------------------------------------------------------- bool HDR_RenderBloom() { HRESULT hr = S_OK; CD3D9Renderer *rd = gcpRendD3D; LPDIRECT3DDEVICE9 dv = rd->m_pd3dDevice; CD3D9TexMan *tm = (CD3D9TexMan *)rd->m_TexMan; CCGPShader_D3D *fpGaussBlur5x5 = NULL; CCGPShader_D3D *fpBloom = NULL; bool bResult = false; SCGBind *bind = NULL; int i; D3DXVECTOR4 avSampleOffsets[16]; FLOAT afSampleOffsets[16]; D3DXVECTOR4 avSampleWeights[16]; PDIRECT3DSURFACE9 pSurfScaledHDR0 = GetSurfaceTP(tm->m_Text_HDRTargetScaled[0]); PDIRECT3DSURFACE9 pSurfBloom = GetSurfaceTP(tm->m_Text_HDRBloomMaps[0]); PDIRECT3DSURFACE9 pSurfHDR = GetSurfaceTP(tm->m_Text_HDRTarget); PDIRECT3DSURFACE9 pSurfTempBloom = GetSurfaceTP(tm->m_Text_HDRBloomMaps[1]); PDIRECT3DSURFACE9 pSurfBloomSource = GetSurfaceTP(tm->m_Text_HDRBloomMaps[2]); // Clear the bloom texture dv->ColorFill(pSurfBloom, NULL, D3DCOLOR_ARGB(0, 0, 0, 0)); if (g_GlareDef.m_fGlareLuminance <= 0.0f || g_GlareDef.m_fBloomLuminance <= 0.0f) { hr = S_OK; goto LCleanReturn; } RECT rectSrc; GetTextureRect(tm->m_Text_HDRBloomSource, &rectSrc); InflateRect(&rectSrc, -1, -1); RECT rectDest; GetTextureRect(tm->m_Text_HDRBloomMaps[2], &rectDest); InflateRect(&rectDest, -1, -1); CoordRect coords; GetTextureCoords(tm->m_Text_HDRBloomSource, &rectSrc, tm->m_Text_HDRBloomMaps[2], &rectDest, &coords); if (rd->m_bDeviceSupportsFP16Filter) { hr = GetSampleOffsets_GaussBlur5x5Bilinear(tm->m_Text_HDRBloomSource->m_Width, tm->m_Text_HDRBloomSource->m_Height, avSampleOffsets, avSampleWeights, 1.0f); fpGaussBlur5x5 = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRGaussBlur5x5_Bilinear, "CGRC_HDR_GaussBlur5x5_Bilinear_PS20"); } else { hr = GetSampleOffsets_GaussBlur5x5(tm->m_Text_HDRBloomSource->m_Width, tm->m_Text_HDRBloomSource->m_Height, avSampleOffsets, avSampleWeights, 1.0f); fpGaussBlur5x5 = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRGaussBlur5x5, "CGRC_HDR_GaussBlur5x5_PS20"); } if (!fpGaussBlur5x5) goto LCleanReturn; fpGaussBlur5x5->mfSet(true, 0); bind = fpGaussBlur5x5->mfGetParameterBind("vSampleOffsets"); assert(bind); if (rd->m_bDeviceSupportsFP16Filter) fpGaussBlur5x5->mfParameter(bind, &avSampleOffsets[0].x, 9); else fpGaussBlur5x5->mfParameter(bind, &avSampleOffsets[0].x, 13); bind = fpGaussBlur5x5->mfGetParameterBind("vSampleWeights"); assert(bind); if (rd->m_bDeviceSupportsFP16Filter) fpGaussBlur5x5->mfParameter(bind, &avSampleWeights[0].x, 9); else fpGaussBlur5x5->mfParameter(bind, &avSampleWeights[0].x, 13); dv->SetRenderTarget(0, pSurfBloomSource); if (rd->m_bDeviceSupportsFP16Filter) SetTexture(rd, tm->m_Text_HDRBloomSource, 0, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); else SetTexture(rd, tm->m_Text_HDRBloomSource, 0, D3DTEXF_POINT, D3DTEXF_POINT, true); dv->SetScissorRect(&rectDest); dv->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(coords); dv->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); int n; if (rd->m_bDeviceSupportsFP16Filter) { hr = GetSampleOffsets_BloomBilinear(tm->m_Text_HDRBloomMaps[2]->m_Width, afSampleOffsets, avSampleWeights, 3.0f, 2.0f); n = 8; fpBloom = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRBloom, "CGRC_HDR_Bloom_Bilinear_PS20"); } else { hr = GetSampleOffsets_Bloom(tm->m_Text_HDRBloomMaps[2]->m_Width, afSampleOffsets, avSampleWeights, 3.0f, 2.0f); n = 16; fpBloom = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRBloom, "CGRC_HDR_Bloom_PS20"); } for(i=0; imfSet(true, 0); bind = fpBloom->mfGetParameterBind("vSampleOffsets"); assert(bind); fpBloom->mfParameter(bind, &avSampleOffsets[0].x, n); bind = fpBloom->mfGetParameterBind("vSampleWeights"); assert(bind); fpBloom->mfParameter(bind, &avSampleWeights[0].x, n); dv->SetRenderTarget(0, pSurfTempBloom); if (rd->m_bDeviceSupportsFP16Filter) SetTexture(rd, tm->m_Text_HDRBloomMaps[2], 0, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); else SetTexture(rd, tm->m_Text_HDRBloomMaps[2], 0, D3DTEXF_POINT, D3DTEXF_POINT, true); dv->SetScissorRect(&rectDest); dv->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad( coords ); dv->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); if (rd->m_bDeviceSupportsFP16Filter) { hr = GetSampleOffsets_BloomBilinear(tm->m_Text_HDRBloomMaps[1]->m_Width, afSampleOffsets, avSampleWeights, 3.0f, 2.0f); n = 8; } else { hr = GetSampleOffsets_Bloom(tm->m_Text_HDRBloomMaps[1]->m_Width, afSampleOffsets, avSampleWeights, 3.0f, 2.0f); n = 16; } for(i=0; im_Text_HDRBloomMaps[1], &rectSrc); InflateRect(&rectSrc, -1, -1); GetTextureCoords(tm->m_Text_HDRBloomMaps[1], &rectSrc, tm->m_Text_HDRBloomMaps[0], NULL, &coords); bind = fpBloom->mfGetParameterBind("vSampleOffsets"); assert(bind); fpBloom->mfParameter(bind, &avSampleOffsets[0].x, n); bind = fpBloom->mfGetParameterBind("vSampleWeights"); assert(bind); fpBloom->mfParameter(bind, &avSampleWeights[0].x, n); dv->SetRenderTarget(0, pSurfBloom); if (rd->m_bDeviceSupportsFP16Filter) SetTexture(rd, tm->m_Text_HDRBloomMaps[1], 0, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); else SetTexture(rd, tm->m_Text_HDRBloomMaps[1], 0, D3DTEXF_POINT, D3DTEXF_POINT, true); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(coords); bResult = true; LCleanReturn: SAFE_RELEASE(pSurfBloomSource); SAFE_RELEASE(pSurfTempBloom); SAFE_RELEASE(pSurfBloom); SAFE_RELEASE(pSurfHDR); SAFE_RELEASE(pSurfScaledHDR0); return bResult; } //----------------------------------------------------------------------------- // Name: HDR_RenderStar() // Desc: Render the blooming effect //----------------------------------------------------------------------------- bool HDR_RenderStar() { HRESULT hr = S_OK; CD3D9Renderer *rd = gcpRendD3D; LPDIRECT3DDEVICE9 dv = rd->m_pd3dDevice; CD3D9TexMan *tm = (CD3D9TexMan *)rd->m_TexMan; CCGPShader_D3D *fpStar = NULL; CCGPShader_D3D *fpMergeTextures = NULL; bool bResult = false; SCGBind *bind = NULL; D3DXVECTOR4 avSampleOffsets[16]; D3DXVECTOR4 avSampleWeights[16]; int i, d, p, s; // Loop variables LPDIRECT3DSURFACE9 pSurfStar0 = GetSurfaceTP(tm->m_Text_HDRStarMaps[0][0]); if(!pSurfStar0) return false; LPDIRECT3DSURFACE9 pSurfStar1 = GetSurfaceTP(tm->m_Text_HDRStarMaps[0][1]); // Clear the star texture dv->ColorFill(pSurfStar0, NULL, D3DCOLOR_ARGB(0, 0, 0, 0)); SAFE_RELEASE(pSurfStar0); if (pSurfStar1) { dv->ColorFill(pSurfStar1, NULL, D3DCOLOR_ARGB(0, 0, 0, 0)); SAFE_RELEASE(pSurfStar1); } // Avoid rendering the star if it's not being used in the current glare if(g_GlareDef.m_fGlareLuminance <= 0.0f || g_GlareDef.m_fStarLuminance <= 0.0f) return true; // Initialize the constants used during the effect const CStarDef& starDef = g_GlareDef.m_starDef; const float fTanFoV = atanf(D3DX_PI/8) ; const D3DXVECTOR4 vWhite( 1.0f, 1.0f, 1.0f, 1.0f ); static const s_maxPasses = 3 ; static const int nSamples = 8 ; static D3DXVECTOR4 s_aaColor[s_maxPasses][8] ; static const D3DXCOLOR s_colorWhite(0.63f, 0.63f, 0.63f, 0.0f) ; rd->EF_SetState(GS_NODEPTHTEST); PDIRECT3DSURFACE9 pSurfDest[2] = {NULL, NULL}; // Set aside all the star texture surfaces as a convenience PDIRECT3DSURFACE9 apSurfStar[NUM_HDR_STAR_TEXTURES][2] = {0}; for(i=0; im_Text_HDRStarMaps[i][0]); if(!apSurfStar[i][0]) goto LCleanReturn; if (rd->m_bDeviceSupportsMRT) { apSurfStar[i][1] = GetSurfaceTP(tm->m_Text_HDRStarMaps[i][1]); if(!apSurfStar[i][1]) goto LCleanReturn; } } float srcW; srcW = (FLOAT)tm->m_Text_HDRStarSource->m_Width; float srcH; srcH= (FLOAT)tm->m_Text_HDRStarSource->m_Height; for (p=0; pm_Text_HDRStarSource; pTexSource[1] = NULL; float rad; rad = radOffset + starLine.fInclination; float sn, cs; sn = sinf(rad), cs = cosf(rad); D3DXVECTOR2 vtStepUV; vtStepUV.x = sn / srcW * starLine.fSampleLength; vtStepUV.y = cs / srcH * starLine.fSampleLength; float attnPowScale; attnPowScale = (fTanFoV + 0.1f) * 1.0f * (160.0f + 120.0f) / (srcW + srcH) * 1.2f; // 1 direction expansion loop rd->EF_SetState(GS_NODEPTHTEST); int iWorkTexture; iWorkTexture = 1 ; for (p=0; p= 0.9f || fabs(avSampleOffsets[i].y) >= 0.9f) { avSampleOffsets[i].x = 0.0f; avSampleOffsets[i].y = 0.0f; avSampleWeights[i] *= 0.0f; } } D3DSURFACE_DESC srcDesc; LPDIRECT3DTEXTURE9 pTex = (LPDIRECT3DTEXTURE9)pTexSource[0]->m_RefTex.m_VidTex; pTex->GetLevelDesc(0, &srcDesc); int nBitPlanes = 1; BOOL bSplitOutput = FALSE; if (rd->m_bDeviceSupportsMRT && srcDesc.Format==D3DFMT_G16R16F) { fpStar = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRStar, "CGRC_HDR_Star_PS20"); nBitPlanes = 2; bSplitOutput = FALSE; } else if (rd->m_bDeviceSupportsMRT && (srcDesc.Format==D3DFMT_A8R8G8B8)) { fpStar = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRStar_MRT, "CGRC_HDR_Star_MRT_PS20"); nBitPlanes = 1; bSplitOutput = TRUE; } else { fpStar = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRStar, "CGRC_HDR_Star_PS20"); nBitPlanes = 1; bSplitOutput = FALSE; } if (!fpStar) goto LCleanReturn; fpStar->mfSet(true, 0); bind = fpStar->mfGetParameterBind("vSampleOffsets"); assert(bind); fpStar->mfParameter(bind, &avSampleOffsets[0].x, nSamples); for (int iBitPlane=0; iBitPlanemfGetParameterBind("vSampleWeights"); assert(bind); fpStar->mfParameter(bind, &avSampleWeights[0].x, nSamples); dv->SetRenderTarget( 0, pSurfDest[iBitPlane] ); SetTexture(rd, pTexSource[iBitPlane], 0, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); if (bSplitOutput) dv->SetRenderTarget(1, pSurfDest[1]); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(0.0f, 0.0f, 1.0f, 1.0f); } if (bSplitOutput) dv->SetRenderTarget(1, NULL); // Setup next expansion vtStepUV *= nSamples ; attnPowScale *= nSamples ; // Set the work drawn just before to next texture source. pTexSource[0] = tm->m_Text_HDRStarMaps[iWorkTexture][0]; pTexSource[1] = tm->m_Text_HDRStarMaps[iWorkTexture][1]; iWorkTexture += 1; if (iWorkTexture > 2) iWorkTexture = 1; } } pSurfDest[0] = apSurfStar[0][0]; pSurfDest[1] = apSurfStar[0][1]; int nBitPlanes = (rd->m_bDeviceSupportsMRT) ? 2 : 1; for (int iBitPlane=0; iBitPlanem_Text_HDRStarMaps[i+4][iBitPlane], i, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); avSampleWeights[i] = vWhite * 1.0f / (FLOAT) starDef.m_nStarLines; } CHAR strTechnique[256]; _snprintf(strTechnique, 256, "CGRC_HDR_MergeTextures_%d_PS20", starDef.m_nStarLines); strTechnique[255] = 0; fpMergeTextures = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRMergeTextures[starDef.m_nStarLines], strTechnique); if (!fpMergeTextures) goto LCleanReturn; fpMergeTextures->mfSet(true, 0); bind = fpMergeTextures->mfGetParameterBind("vSampleWeights"); assert(bind); fpMergeTextures->mfParameter(bind, &avSampleWeights[0].x, starDef.m_nStarLines); dv->SetRenderTarget(0, pSurfDest[iBitPlane]); // Draw a fullscreen quad to sample the RT DrawFullScreenQuad(0.0f, 0.0f, 1.0f, 1.0f); } bResult = true; LCleanReturn: for (int iPlane=0; iPlane<2; iPlane++) { for(i=0; iEF_SelectTMU(0); if (fpMergeTextures) fpMergeTextures->mfSet(false, 0); return bResult; } bool HDR_RenderFinalScene() { HRESULT hr = S_OK; CD3D9Renderer *rd = gcpRendD3D; LPDIRECT3DDEVICE9 dv = rd->m_pd3dDevice; CD3D9TexMan *tm = (CD3D9TexMan *)rd->m_TexMan; CCGPShader_D3D *fpFinalScene = NULL; bool bResult = false; // Draw the high dynamic range scene texture to the low dynamic range // back buffer. As part of this final pass, the scene will be tone-mapped // using the user's current adapted luminance, blue shift will occur // if the scene is determined to be very dark, and the post-process lighting // effect textures will be added to the scene. if (rd->m_bDeviceSupportsMRT) fpFinalScene = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRFinalScene, "CGRC_HDR_FinalScene_BlueShift_ToneMap_FromMRT_PS20"); else fpFinalScene = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDRFinalScene, "CGRC_HDR_FinalScene_BlueShift_ToneMap_PS20"); if (!fpFinalScene) return false; fpFinalScene->mfSet(true, 0); float fKeyValue = CRenderer::CV_r_hdrlevel; float fBloomScale = 1.0f; float fStarScale = 0.5f; float v[4]; v[0] = fStarScale; v[1] = fBloomScale; v[2] = 0; v[3] = fKeyValue; fpFinalScene->mfParameter4f("Params", v); dv->SetRenderTarget(0, rd->mfGetBackSurface()); if (rd->m_bDeviceSupportsMRT) { SetTexture(rd, tm->m_Text_HDRTarget, 0, D3DTEXF_POINT, D3DTEXF_POINT, true); SetTexture(rd, tm->m_Text_HDRBloomMaps[0], 1, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); SetTexture(rd, tm->m_Text_HDRStarMaps[0][0], 2, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); SetTexture(rd, tm->m_Text_HDRStarMaps[0][1], 3, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); SetTexture(rd, tm->m_Text_HDRAdaptedLuminanceCur, 4, D3DTEXF_POINT, D3DTEXF_POINT, true); } else { if (rd->m_nHDRType == 2) SetTexture(rd, tm->m_Text_HDRTarget_Temp, 0, D3DTEXF_POINT, D3DTEXF_POINT, true); else SetTexture(rd, tm->m_Text_HDRTarget, 0, D3DTEXF_POINT, D3DTEXF_POINT, true); SetTexture(rd, tm->m_Text_HDRBloomMaps[0], 1, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); SetTexture(rd, tm->m_Text_HDRStarMaps[0][0], 2, D3DTEXF_LINEAR, D3DTEXF_LINEAR, true); SetTexture(rd, tm->m_Text_HDRAdaptedLuminanceCur, 3, D3DTEXF_POINT, D3DTEXF_POINT, true); } DrawFullScreenQuad( 0.0f, 0.0f, 1.0f, 1.0f ); fpFinalScene->mfSet(false, 0); rd->EF_SelectTMU(0); return true; } void HDR_DrawDebug() { #ifdef USE_HDR if (!CRenderer::CV_r_hdrrendering) return; #endif CD3D9Renderer *rd = gcpRendD3D; rd->EF_SetState(GS_NODEPTHTEST); int iTmpX, iTmpY, iTempWidth, iTempHeight; rd->GetViewport(&iTmpX, &iTmpY, &iTempWidth, &iTempHeight); rd->EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0); rd->Set2DMode(true, 1, 1); rd->m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT ); rd->m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ); CCGPShader_D3D *fpShowR = NULL; CCGPShader_D3D *fpShowMRT = NULL; fpShowR = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDR_ShowR, "CGRC_HDR_ShowR_PS20"); fpShowMRT = (CCGPShader_D3D *)PShaderForName(rd->m_RP.m_PS_HDR_ShowRG_MRT, "CGRC_HDR_ShowRG_MRT_PS20"); rd->SetViewport(10, 400, 100, 100); if (rd->m_nHDRType == 2) rd->DrawImage(0, 0, 1, 1, rd->m_TexMan->m_Text_HDRTarget_Temp->m_Bind, 0, 1, 1, 0, 1,1,1,1); else rd->DrawImage(0, 0, 1, 1, rd->m_TexMan->m_Text_HDRTarget->m_Bind, 0, 1, 1, 0, 1,1,1,1); rd->SetViewport(120, 400, 100, 100); if (rd->m_bDeviceSupportsMRT && fpShowMRT) { fpShowMRT->mfSet(true, 0); rd->EF_SelectTMU(1); rd->m_TexMan->m_Text_HDRTargetScaled[1]->Set(); rd->EF_SelectTMU(0); rd->DrawImage(0, 0, 1, 1, rd->m_TexMan->m_Text_HDRTargetScaled[0]->m_Bind, 0, 1, 1, 0, 1,1,1,1); rd->EF_SelectTMU(1); rd->SetTexture(0); rd->EF_SelectTMU(0); fpShowMRT->mfSet(false, 0); } else rd->DrawImage(0, 0, 1, 1, rd->m_TexMan->m_Text_HDRTargetScaled[0]->m_Bind, 0, 1, 1, 0, 1,1,1,1); if (fpShowR) { fpShowR->mfSet(true, 0); rd->SetViewport(10, 510, 100, 100); rd->DrawImage(0, 0, 1, 1, rd->m_TexMan->m_Text_HDRToneMaps[0]->m_Bind, 0, 1, 1, 0, 1,1,1,1); rd->SetViewport(120, 510, 100, 100); rd->DrawImage(0, 0, 1, 1, rd->m_TexMan->m_Text_HDRAdaptedLuminanceCur->m_Bind, 0, 1, 1, 0, 1,1,1,1); fpShowR->mfSet(false, 0); } rd->SetViewport(230, 400, 100, 100); rd->DrawImage(0, 0, 1, 1, rd->m_TexMan->m_Text_HDRBrightPass->m_Bind, 0, 1, 1, 0, 1,1,1,1); rd->SetViewport(340, 400, 100, 100); rd->DrawImage(0, 0, 1, 1, rd->m_TexMan->m_Text_HDRStarSource->m_Bind, 0, 1, 1, 0, 1,1,1,1); rd->SetViewport(450, 400, 100, 100); rd->DrawImage(0, 0, 1, 1, rd->m_TexMan->m_Text_HDRBloomSource->m_Bind, 0, 1, 1, 0, 1,1,1,1); rd->SetViewport(560, 400, 100, 100); rd->DrawImage(0, 0, 1, 1, rd->m_TexMan->m_Text_HDRBloomMaps[0]->m_Bind, 0, 1, 1, 0, 1,1,1,1); rd->SetViewport(670, 400, 100, 100); if (rd->m_bDeviceSupportsMRT && fpShowMRT) { fpShowMRT->mfSet(true, 0); rd->EF_SelectTMU(1); rd->m_TexMan->m_Text_HDRStarMaps[0][1]->Set(); rd->EF_SelectTMU(0); rd->DrawImage(0, 0, 1, 1, rd->m_TexMan->m_Text_HDRStarMaps[0][0]->m_Bind, 0, 1, 1, 0, 1,1,1,1); rd->EF_SelectTMU(1); rd->SetTexture(0); rd->EF_SelectTMU(0); fpShowMRT->mfSet(false, 0); } else rd->DrawImage(0, 0, 1, 1, rd->m_TexMan->m_Text_HDRStarMaps[0][0]->m_Bind, 0, 1, 1, 0, 1,1,1,1); //rd->SetViewport(300, 210, 100, 100); //rd->DrawImage(0, 0, 1, 1, rd->m_TexMan->m_Text_ScreenMap_HDR->m_Bind, 0, 1, 1, 0, 1,1,1,1); rd->Set2DMode(false, 1, 1); rd->SetViewport(iTmpX, iTmpY, iTempWidth, iTempHeight); } void CD3D9Renderer::EF_HDRPostProcessing() { static EGLARELIBTYPE seGlareType = (EGLARELIBTYPE)-1; PROFILE_FRAME(Draw_HDR_PostProcessing); #ifdef USE_HDR if ((int)seGlareType != CV_r_hdrrendering) { if (CV_r_hdrrendering >= NUM_GLARELIBTYPES) { ICVar *var = iConsole->GetCVar("r_HDRRendering"); if (var) var->Set(NUM_GLARELIBTYPES-1); } else if (CV_r_hdrrendering < 0) { ICVar *var = iConsole->GetCVar("r_HDRRendering"); if (var) var->Set(1); } seGlareType = (EGLARELIBTYPE)CV_r_hdrrendering; g_GlareDef.Initialize(seGlareType); } #endif CD3D9TexMan *tm = (CD3D9TexMan *)m_TexMan; if (!tm->m_Text_HDRTarget) return; if (tm->m_Text_HDRTarget->m_Width != m_width || tm->m_Text_HDRTarget->m_Height != m_height) tm->GenerateHDRMaps(); if( tm->m_HDR_RT_FSAA ) { STexPic *tp = tm->m_Text_HDRTarget; LPDIRECT3DTEXTURE9 pTexture = (LPDIRECT3DTEXTURE9)tp->m_RefTex.m_VidTex; assert(pTexture); LPDIRECT3DSURFACE9 pSurf; pTexture->GetSurfaceLevel(0, &pSurf); assert(pSurf); HRESULT hr = m_pd3dDevice->StretchRect( tm->m_HDR_RT_FSAA, 0, pSurf, 0, D3DTEXF_NONE ); pSurf->Release(); } bool bMeasureLuminance = true; EF_SetState(GS_NODEPTHTEST); D3DSetCull(eCULL_None); CD3D9TexMan::BindNULL(1); EF_SelectTMU(0); m_RP.m_PersFlags &= ~(RBPF_VSNEEDSET | RBPF_PS1NEEDSET); m_RP.m_FlagsModificators = 0; m_RP.m_CurrentVLights = 0; m_RP.m_FlagsPerFlush = 0; EF_CommitShadersState(); EF_CommitVLightsState(); m_pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); if (m_RP.m_TexStages[0].TCIndex != 0) { m_RP.m_TexStages[0].TCIndex = 0; m_pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | 0); } EF_Scissor(false, 0, 0, 0, 0); m_RP.m_pShader = NULL; if (m_nHDRType == 2) m_pd3dDevice->SetRenderTarget(1, NULL); m_pCurBackBuffer = m_pBackBuffer; // Create a scaled copy of the scene HDR_SceneToSceneScaled(); // Setup tone mapping technique if (bMeasureLuminance) HDR_MeasureLuminance(); // Calculate the current luminance adaptation level HDR_CalculateAdaptation(); // Now that luminance information has been gathered, the scene can be bright-pass filtered // to remove everything except bright lights and reflections. HDR_SceneScaledToBrightPass(); // Blur the bright-pass filtered image to create the source texture for the star effect HDR_BrightPassToStarSource(); // Scale-down the source texture for the star effect to create the source texture // for the bloom effect HDR_StarSourceToBloomSource(); // Render post-process lighting effects HDR_RenderBloom(); HDR_RenderStar(); // Render final scene to the back buffer HDR_RenderFinalScene(); SAFE_RELEASE(m_pHDRTargetSurf); SAFE_RELEASE(m_pHDRTargetSurf_K); m_RP.m_PersFlags &= ~RBPF_HDR; ResetToDefault(); }