/////////////////////////////////////////////////////////////////////// // CLensFlare Class // // (c) 2003 IDV, Inc. // // *** INTERACTIVE DATA VISUALIZATION (IDV) PROPRIETARY INFORMATION *** // // This software is supplied under the terms of a license agreement or // nondisclosure agreement with Interactive Data Visualization and may // not be copied or disclosed except in accordance with the terms of // that agreement. // // Copyright (c) 2001-2003 IDV, Inc. // All Rights Reserved. // // IDV, Inc. // 1233 Washington St. Suite 610 // Columbia, SC 29201 // Voice: (803) 799-1699 // Fax: (803) 931-0320 // Web: http://www.idvinc.com // /////////////////////////////////////////////////////////////////////// // Preprocessor #include "StdAfx.h" #include "LensFlare.h" #include "Camera.h" #include "StateManager.h" #include "ResourceManager.h" #include using namespace std; /////////////////////////////////////////////////////////////////////// // Variables static string g_strFiles[] = { "flare2.dds", "flare1.dds", "flare2.dds", "flare1.dds", "flare6.dds", "flare4.dds", "flare2.dds", "flare3.dds", "" }; static float g_fPosition[] = { -0.55f, -0.5f, -0.45f, 0.2f, 0.3f, 0.95f, 0.9f, 1.0f }; static float g_fWidth[] = { 20.0f, 32.0f, 20.0f, 32.0f, 100.0f, 32.0f, 20.0f, 250.0f }; static float g_afColors[ ][4] = { { 1.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 0.8f }, { 0.3f, 0.5f, 1.0f, 0.9f }, { 0.3f, 0.5f, 1.0f, 0.6f }, { 1.0f, 0.6f, 0.9f, 0.4f }, { 1.0f, 0.0f, 0.0f, 0.5f }, { 1.0f, 0.6f, 0.3f, 0.4f } }; /////////////////////////////////////////////////////////////////////// // CLensFlare::CLensFlare CLensFlare::CLensFlare() : m_fSunSize(0), m_fBeforeBright(0.0f), m_fAfterBright(0.0f), m_bFlareVisible(false), m_bDrawFlare(true), m_bDrawBrightScreen(true), m_bEnabled(true), m_bShowMainFlare(true), m_fMaxBrightness(1.0f) { m_pControlPixels = new float[c_nDepthTestDimension * c_nDepthTestDimension]; m_pTestPixels = new float[c_nDepthTestDimension * c_nDepthTestDimension]; m_afColor[0] = m_afColor[1] = m_afColor[2] = 1.0f; } /////////////////////////////////////////////////////////////////////// // CLensFlare::~CLensFlare CLensFlare::~CLensFlare() { delete[] m_pControlPixels; delete[] m_pTestPixels; } /////////////////////////////////////////////////////////////////////// // CLensFlare::Interpolate float CLensFlare::Interpolate(float fStart, float fEnd, float fPercent) { return fStart + (fEnd - fStart) * fPercent; } /////////////////////////////////////////////////////////////////////// // CLensFlare::DrawBeforeFlare void CLensFlare::Compute(const D3DXVECTOR3 & c_rv3LightDirection) { float afSunPos[3]; D3DXVECTOR3 v3Target = CCameraManager::Instance().GetCurrentCamera()->GetTarget(); afSunPos[0] = v3Target.x - c_rv3LightDirection.x * 99999999.0f; afSunPos[1] = v3Target.y - c_rv3LightDirection.y * 99999999.0f; afSunPos[2] = v3Target.z - c_rv3LightDirection.z * 99999999.0f; float fX, fY; ProjectPosition(afSunPos[0], afSunPos[1], afSunPos[2], &fX, &fY); // set flare location SetFlareLocation(fX, fY); // determine visibility float fSunVectorMagnitude = sqrtf(afSunPos[0] * afSunPos[0] + afSunPos[1] * afSunPos[1] + afSunPos[2] * afSunPos[2]); float afSunVector[3]; afSunVector[0] = -afSunPos[0] / fSunVectorMagnitude; afSunVector[1] = -afSunPos[1] / fSunVectorMagnitude; afSunVector[2] = -afSunPos[2] / fSunVectorMagnitude; float afCameraDirection[3]; afCameraDirection[0] = ms_matView._13; afCameraDirection[1] = ms_matView._23; afCameraDirection[2] = ms_matView._33; float fDotProduct = (afSunVector[0] * afCameraDirection[0]) + (afSunVector[1] * afCameraDirection[1]) + (afSunVector[2] * afCameraDirection[2]); if (acosf(fDotProduct) < 0.5f * D3DX_PI) SetVisible(true); else SetVisible(false); // set flare brightness fX /= ms_Viewport.Width; fY /= ms_Viewport.Height; float fDistance = sqrtf(((0.5f - fX) * (0.5f - fX)) + ((0.5f - fY) * (0.5f - fY))); float fBeforeBright = Interpolate(0.0f, c_fHalfMaxBright, 1.0f - (fDistance * c_fDistanceScale)); float fAfterBright = Interpolate(0.0f, 1.0f, 1.0f - (fDistance * c_fDistanceScale)); SetBrightnesses(fBeforeBright, fAfterBright); } /////////////////////////////////////////////////////////////////////// // CLensFlare::DrawBeforeFlare void CLensFlare::DrawBeforeFlare() { if (!m_bFlareVisible || !m_bEnabled || !m_bShowMainFlare) return; if (m_SunFlareImageInstance.IsEmpty()) return; D3DXMATRIX matProj; D3DXMatrixOrthoOffCenterRH(&matProj, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f); STATEMANAGER.SaveTransform(D3DTS_PROJECTION, &matProj); STATEMANAGER.SaveTransform(D3DTS_VIEW, &ms_matIdentity); D3DXMATRIX matWorld; D3DXMatrixTranslation(&matWorld, m_afFlarePos[0], m_afFlarePos[1], 0.0f); STATEMANAGER.SetTransform(D3DTS_WORLD, &matWorld); STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, FALSE); STATEMANAGER.SaveRenderState(D3DRS_ZENABLE, FALSE); // glDisable(GL_DEPTH_TEST); STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE); STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE); // glDisable(GL_CULL_FACE); STATEMANAGER.SaveRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); // glShadeModel(GL_FLAT); STATEMANAGER.SaveRenderState(D3DRS_ALPHATESTENABLE, FALSE); // glDisable(GL_ALPHA_TEST); STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE); // glEnable(GL_BLEND); STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); /* if (m_fBeforeBright != 0.0f && m_bDrawFlare && m_bDrawBrightScreen && false) // ¿Ø false? { glColor4f(1.0f, 1.0f, 1.0f, m_fBeforeBright); glDisable(GL_TEXTURE_2D); glBegin(GL_TRIANGLE_STRIP); glVertex2f(0.0f, 0.0f); glVertex2f(0.0f, 1.0f); glVertex2f(1.0f, 0.0f); glVertex2f(1.0f, 1.0f); glEnd(); } */ float fAspectRatio = ms_Viewport.Width / float(ms_Viewport.Height); float fHeight = m_fSunSize * fAspectRatio; D3DXCOLOR color(1.0f, 1.0f, 1.0f, 1.0f); SVertex vertices[4]; vertices[0].x = -m_fSunSize; vertices[0].y = -fHeight; vertices[0].z = 0.0f; vertices[0].color = color; vertices[0].u = 0.0f; vertices[0].v = 0.0f; vertices[1].x = -m_fSunSize; vertices[1].y = fHeight; vertices[1].z = 0.0f; vertices[1].color = color; vertices[1].u = 0.0f; vertices[1].v = 1.0f; vertices[2].x = m_fSunSize; vertices[2].y = -fHeight; vertices[2].z = 0.0f; vertices[2].color = color; vertices[2].u = 1.0f; vertices[2].v = 0.0f; vertices[3].x = m_fSunSize; vertices[3].y = fHeight; vertices[3].z = 0.0f; vertices[3].color = color; vertices[3].u = 1.0f; vertices[3].v = 1.0f; STATEMANAGER.SetTexture(0, m_SunFlareImageInstance.GetTexturePointer()->GetD3DTexture()); STATEMANAGER.SetTexture(1, NULL); STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(SVertex)); STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING); STATEMANAGER.RestoreRenderState(D3DRS_ZENABLE); // glDisable(GL_DEPTH_TEST); STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE); STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE); // glDisable(GL_CULL_FACE); STATEMANAGER.RestoreRenderState(D3DRS_SHADEMODE); // glShadeModel(GL_FLAT); STATEMANAGER.RestoreRenderState(D3DRS_ALPHATESTENABLE); // glDisable(GL_ALPHA_TEST); STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE); // glEnable(GL_BLEND); STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND); STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND); STATEMANAGER.RestoreTransform(D3DTS_VIEW); STATEMANAGER.RestoreTransform(D3DTS_PROJECTION); } /////////////////////////////////////////////////////////////////////// // CLensFlare::DrawAfterFlare void CLensFlare::DrawAfterFlare() { if (m_bEnabled && m_fAfterBright != 0.0f && m_bDrawBrightScreen) { SetDiffuseColor(m_afColor[0], m_afColor[1], m_afColor[2], m_fAfterBright); RenderBar2d(0.0f, 0.0f, 1024.0f, 1024.0f); } } /////////////////////////////////////////////////////////////////////// // CLensFlare::SetMainFlare void CLensFlare::SetMainFlare(string strSunFile, float fSunSize) { if (m_bEnabled && m_bShowMainFlare) { m_fSunSize = fSunSize; CResource * pResource = CResourceManager::Instance().GetResourcePointer(strSunFile.c_str()); if (!pResource->IsType(CGraphicImage::Type())) assert(false); m_SunFlareImageInstance.SetImagePointer(static_cast (pResource)); } } /////////////////////////////////////////////////////////////////////// // CLensFlare::DrawFlare void CLensFlare::DrawFlare() { if (m_bEnabled && m_bFlareVisible && m_bDrawFlare && m_fAfterBright != 0.0f) { //glPushAttrib(GL_ENABLE_BIT); STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, FALSE); // glDisable(GL_LIGHTING); STATEMANAGER.SaveRenderState(D3DRS_ZENABLE, FALSE); // glDisable(GL_DEPTH_TEST); STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE); // glDisable(GL_CULL_FACE); STATEMANAGER.SaveRenderState(D3DRS_ALPHATESTENABLE, FALSE); // glDisable(GL_ALPHA_TEST); STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE); // glEnable(GL_BLEND); D3DXMATRIX matProj; D3DXMatrixOrthoOffCenterRH(&matProj, 0.0f, ms_Viewport.Width, ms_Viewport.Height, 0.0f, -1.0f, 1.0f); STATEMANAGER.SaveTransform(D3DTS_PROJECTION, &matProj); STATEMANAGER.SaveTransform(D3DTS_VIEW, &ms_matIdentity); STATEMANAGER.SetTransform(D3DTS_WORLD, &ms_matIdentity); //glMatrixMode(GL_MODELVIEW); //glLoadIdentity(); //glDisable(GL_TEXTURE_2D); DrawAfterFlare(); //glEnable(GL_TEXTURE_2D); m_cFlare.Draw(m_fAfterBright, ms_Viewport.Width, ms_Viewport.Height, static_cast(m_afFlareWinPos[0]), static_cast(m_afFlareWinPos[1])); STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING); // glDisable(GL_LIGHTING); STATEMANAGER.RestoreRenderState(D3DRS_ZENABLE); // glDisable(GL_DEPTH_TEST); STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE); // glDisable(GL_CULL_FACE); STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE); // glEnable(GL_BLEND); STATEMANAGER.RestoreRenderState(D3DRS_ALPHATESTENABLE); // glDisable(GL_ALPHA_TEST); STATEMANAGER.RestoreTransform(D3DTS_PROJECTION); STATEMANAGER.RestoreTransform(D3DTS_VIEW); //glDisable(GL_TEXTURE_2D); //glPopAttrib(); } } /////////////////////////////////////////////////////////////////////// // CLensFlare::CharacterizeFlare void CLensFlare::CharacterizeFlare(bool bEnabled, bool bShowMainFlare, float fMaxBrightness, const D3DXCOLOR & c_rColor) { m_bEnabled = bEnabled; m_bShowMainFlare = bShowMainFlare; m_fMaxBrightness = fMaxBrightness; m_afColor[0] = c_rColor.r; m_afColor[1] = c_rColor.g; m_afColor[2] = c_rColor.b; } /////////////////////////////////////////////////////////////////////// // CLensFlare::Initialize void CLensFlare::Initialize(std::string strPath) { if (m_bEnabled) m_cFlare.Init(strPath); } /////////////////////////////////////////////////////////////////////// // CLensFlare::SetFlareLocation void CLensFlare::SetFlareLocation(double dX, double dY) { if (m_bEnabled) { m_afFlareWinPos[0] = float(dX); m_afFlareWinPos[1] = float(dY); m_afFlarePos[0] = float(dX) / ms_Viewport.Width; m_afFlarePos[1] = float(dY) / ms_Viewport.Height; } } /////////////////////////////////////////////////////////////////////// // CLensFlare::SetBrightnesses void CLensFlare::SetBrightnesses(float fBeforeBright, float fAfterBright) { if (m_bEnabled) { m_fBeforeBright = fBeforeBright; m_fAfterBright = fAfterBright; ClampBrightness(); } } /////////////////////////////////////////////////////////////////////// // CLensFlare::ReadControlPixels void CLensFlare::ReadControlPixels() { if (m_bEnabled) ReadDepthPixels(m_pControlPixels); } /////////////////////////////////////////////////////////////////////// // CLensFlare::AdjustBrightness void CLensFlare::AdjustBrightness() { if (m_bEnabled) { ReadDepthPixels(m_pTestPixels); int nDifferent = 0; for (int i = 0; i < c_nDepthTestDimension * c_nDepthTestDimension; ++i) if (m_pTestPixels[i] != m_pControlPixels[i]) ++nDifferent; float fAdjust = (static_cast(nDifferent) / (c_nDepthTestDimension * c_nDepthTestDimension)); fAdjust = sqrtf(fAdjust) * 0.85f; m_fAfterBright *= 1.0f - fAdjust; } } /////////////////////////////////////////////////////////////////////// // CLensFlare::ReadDepthPixels void CLensFlare::ReadDepthPixels(float * /*pPixels*/) { /* LPDIRECT3DSURFACE8 lpSurface; if (FAILED(ms_lpd3dDevice->GetDepthStencilSurface(&lpSurface))) assert(false); D3DLOCKED_RECT rect; lpSurface->LockRect(&rect, NULL, D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE); lpSurface->UnlockRect(); */ /* glReadPixels(GLint(m_afFlareWinPos[0] - c_nDepthTestDimension / 2), GLint(m_afFlareWinPos[1] - c_nDepthTestDimension / 2), c_nDepthTestDimension, c_nDepthTestDimension, GL_DEPTH_COMPONENT, GL_FLOAT, pPixels); */ } /////////////////////////////////////////////////////////////////////// // CLensFlare::ClampBrightness void CLensFlare::ClampBrightness() { // before if (m_fBeforeBright < 0.0f) m_fBeforeBright = 0.0f; else if (m_fBeforeBright > 1.0f) m_fBeforeBright = 1.0f; m_fBeforeBright *= m_fMaxBrightness; if (m_fAfterBright < 0.0f) m_fAfterBright = 0.0f; else if (m_fAfterBright > 1.0f) m_fAfterBright = 1.0f; m_fAfterBright *= m_fMaxBrightness; } /////////////////////////////////////////////////////////////////////// // CFlare implementation /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // CFlare::CFlare CFlare::CFlare() { } /////////////////////////////////////////////////////////////////////// // CFlare::~CFlare CFlare::~CFlare() { } /////////////////////////////////////////////////////////////////////// // CFlare::Init void CFlare::Init(std::string strPath) { int i = 0; while (g_strFiles[i] != "") { CResource * pResource = CResourceManager::Instance().GetResourcePointer((strPath + "/" + string(g_strFiles[i])).c_str()); if (!pResource->IsType(CGraphicImage::Type())) assert(false); SFlarePiece * pPiece = new SFlarePiece; pPiece->m_imageInstance.SetImagePointer(static_cast (pResource)); pPiece->m_fPosition = g_fPosition[i]; pPiece->m_fWidth = g_fWidth[i]; pPiece->m_pColor = g_afColors[i]; m_vFlares.push_back(pPiece); i++; } } /////////////////////////////////////////////////////////////////////// // CFlare::Draw void CFlare::Draw(float fBrightScale, int nWidth, int nHeight, int nX, int nY) { STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); float fDX = float(nX) - float(nWidth) / 2.0f; float fDY = float(nY) - float(nHeight) / 2.0f; STATEMANAGER.SetTexture(1, NULL); STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); for (unsigned int i = 0; i < m_vFlares.size(); i++) { float fCenterX = float(nX) - (m_vFlares[i]->m_fPosition + 1.0f) * fDX; float fCenterY = float(nY) - (m_vFlares[i]->m_fPosition + 1.0f) * fDY; float fW = m_vFlares[i]->m_fWidth; D3DXCOLOR d3dColor(m_vFlares[i]->m_pColor[0] * fBrightScale, m_vFlares[i]->m_pColor[1] * fBrightScale, m_vFlares[i]->m_pColor[2] * fBrightScale, m_vFlares[i]->m_pColor[3] * fBrightScale); STATEMANAGER.SetTexture(0, m_vFlares[i]->m_imageInstance.GetTexturePointer()->GetD3DTexture()); TVertex vertices[4]; vertices[0].u = 0.0f; vertices[0].v = 0.0f; vertices[0].x = fCenterX - fW; vertices[0].y = fCenterY - fW; vertices[0].z = 0.0f; vertices[0].color = d3dColor; vertices[1].u = 0.0f; vertices[1].v = 1.0f; vertices[1].x = fCenterX - fW; vertices[1].y = fCenterY + fW; vertices[1].z = 0.0f; vertices[1].color = d3dColor; vertices[2].u = 1.0f; vertices[2].v = 0.0f; vertices[2].x = fCenterX + fW; vertices[2].y = fCenterY - fW; vertices[2].z = 0.0f; vertices[2].color = d3dColor; vertices[3].u = 1.0f; vertices[3].v = 1.0f; vertices[3].x = fCenterX + fW; vertices[3].y = fCenterY + fW; vertices[3].z = 0.0f; vertices[3].color = d3dColor; STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(TVertex)); } STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND); }