#include "SM_CommonFXPCH.h"
#include "SM_Engine3DPCH.h"
#include <math.h>
#include "FXFilter.h"
#include "MBSTaticList.h"
#include "SM_Shader.h"
#include "SM_Matrix4X4.h"
#include "SM_RenderAux.h"
#include "SM_Sound.h"





int SIZEWIDTH =512;  
int SIZEHEIGHT=512; 
int LOGSIZEWIDTH=9;




FilterFX* g_SceneFilter=0;
 
void FilterFX::ResetStatus()
{  
  m_bInterceptRender=false;
  m_bHorizontalNoise      =false;
  m_bTransition           =false;
  m_bWobble               =false;
  m_bLens                 =false;  
  m_bBlur                 =false;
  m_bLensFadeIn           =false;
  m_bFadeIn               =false;
  m_bFadeOut              =false;
  m_bUnderwater           =false;
  m_bPlasma               =false;
  m_bMotionBlur           =false;
  m_bTransparentTransition=false;    
  m_bQualityBlur          =false;
  m_bComponent            =false;
  m_bRadialBlur           =false;
  m_bNoClear              =false;

  m_fComponentAmplitude[0] = m_fComponentAmplitude[1] = m_fComponentAmplitude[2] = 0.0f;
  m_fComponentFrequency[0] = m_fComponentFrequency[1] = m_fComponentFrequency[2] = 0.0f;
  m_fComponentOffset[0] = m_fComponentOffset[1] = m_fComponentOffset[2] = 0.0f;

  m_bSecondaryFadeIn      = false;
  m_bSecondaryFadeOut     = false;
  
  m_fBeatStartTime        = -100.0f;
  
  #ifdef _DEBUG
  m_uBackGround=0x00FF00;
  #else
  m_uBackGround=0;
  #endif
}

FilterFX::FilterFX(char const* pcName) : SM_DemoEffect(pcName)
{
  assert(!g_SceneFilter);
  g_SceneFilter=this;   

  ResetStatus();
  m_iFakeBufferID=-1;
  m_iFakeDepthBufferID=-1;
  m_bInit=false;      
  m_iMotionBlurTexture[0]=m_iMotionBlurTexture[1]=-1;
  m_iBlurTexture[0]=m_iBlurTexture[1]=-1;
  m_iTransparentTexture=-1;
}

FilterFX::~FilterFX()
{
  Shutdown();
  g_SceneFilter=0;
}


static  SM_DemoEffect::Helper  LoadHelp[] =
{
  {"RENDERTARGET", "enables post fx"},
  {"NORENDERTARGET", "disables post fx"},  
};



int FilterFX::LoadArgumentsHelp     (Helper*& pHelpers)
{
  pHelpers = LoadHelp;
  return (sizeof(LoadHelp)/sizeof(Helper));
}

struct HWMipMap
{
  HWMipMap()
  {
    m_piMips = 0;
    m_uMips = 0;
  }

  ~HWMipMap()
  {
    Shutdown();
  }

  int Init(unsigned uSize)
  {
    unsigned i;
    
    for (i = 0 ; i < uSize ; i++)
    {
      if ( (1 << i) & uSize)
      {
        break;
      }
    }

    if (i == (sizeof(unsigned)<<3))
    {
      // Oops
      return -1;
    }    
  
    m_uMips = i+1;

    m_piMips = new int[m_uMips];
    if (!m_piMips)
    {
      return -1;
    }

    for (i = 0 ; i < m_uMips ; i++)
    {
      m_piMips[i] = ResourceManager::CreateRenderTexture(uSize>>i, uSize>>i, D3DFMT_X8R8G8B8);
      if (m_piMips[i] == -1)
      {
        return -1;
      }
    }

    return 0;
  }

  int Shutdown()
  {
    unsigned i;

    if (m_piMips)
    {
      for (i = 0 ; i < m_uMips ; i++)
      {
        ResourceManager::ReleaseTexture(m_piMips[i]);
      }

      delete[] m_piMips;
      m_piMips = 0;
    }
   
    return 0;
  }


  int*     m_piMips;
  unsigned m_uMips;
};

HWMipMap g_HWMipMap;

int      FilterFX::Init(const char* pcCommand)
{
  assert(m_bInit == false);

  Shutdown();
  ResetStatus();  
  
  if (strcmp(pcCommand, "RENDERTARGET") == 0)
  {
    if ( (m_iFakeBufferID        =ResourceManager::CreateRenderTexture(SIZEWIDTH, SIZEHEIGHT, D3DFMT_X8R8G8B8)) == -1 ||
         (m_iFakeDepthBufferID   =ResourceManager::CreateDepthTexture (SIZEWIDTH, SIZEHEIGHT, D3DFMT_X8R8G8B8)) == -1 ||     
         (m_iMotionBlurTexture[0]=ResourceManager::CreateRenderTexture(SIZEWIDTH, SIZEHEIGHT, D3DFMT_X8R8G8B8)) == -1 ||
         (m_iMotionBlurTexture[1]=ResourceManager::CreateRenderTexture(SIZEWIDTH, SIZEHEIGHT, D3DFMT_X8R8G8B8)) == -1 ||
         (m_iBlurTexture      [0]=ResourceManager::CreateRenderTexture(SIZEWIDTH, SIZEHEIGHT, D3DFMT_X8R8G8B8)) == -1 ||
         (m_iBlurTexture      [1]=ResourceManager::CreateRenderTexture(SIZEWIDTH, SIZEHEIGHT, D3DFMT_X8R8G8B8)) == -1 ||
         (m_iTransparentTexture  =ResourceManager::CreateRenderTexture(SIZEWIDTH, SIZEHEIGHT, D3DFMT_X8R8G8B8)) == -1 ||
         g_HWMipMap.Init(SIZEWIDTH) == -1 )
    {   
      SM_Main::OutputError("Failed to initialize render to texture infrastructure. If your card supports this consider updating your drivers");
      return -1;
    }
  }

  m_bInit = true;
  return (0);
}

int      FilterFX::Shutdown()
{
  if (m_iFakeBufferID!=-1)
  {
    ResourceManager::ReleaseTexture(m_iFakeBufferID);
    m_iFakeBufferID=-1;
  }

  if (m_iFakeDepthBufferID!=-1)
  {
    ResourceManager::ReleaseTexture(m_iFakeDepthBufferID);
    m_iFakeDepthBufferID=-1;
  }

  if (m_iMotionBlurTexture[0]!=-1)
  {
    ResourceManager::ReleaseTexture(m_iMotionBlurTexture[0]);
    m_iMotionBlurTexture[0]=-1;
  }

  if (m_iMotionBlurTexture[1]!=-1)
  {
    ResourceManager::ReleaseTexture(m_iMotionBlurTexture[1]);
    m_iMotionBlurTexture[1]=-1;
  }

  if (m_iBlurTexture[0]!=-1)
  {
    ResourceManager::ReleaseTexture(m_iBlurTexture[0]);
    m_iBlurTexture[0]=-1;
  }

  if (m_iBlurTexture[1]!=-1)
  {
    ResourceManager::ReleaseTexture(m_iBlurTexture[1]);
    m_iBlurTexture[1]=-1;
  }

  if (m_iTransparentTexture!=-1)
  {
    ResourceManager::ReleaseTexture(m_iTransparentTexture);
    m_iTransparentTexture=-1;
  }



  g_HWMipMap.Shutdown();
  
  ResetStatus();

  m_bInit = false;
  
  return (0);
}

int      FilterFX::Start(float fTime)
{
  return (0);
}

int      FilterFX::Stop()
{
  return (0);
}

int      FilterFX::Reset()
{
  ResetStatus();
  return ResourceManager::ResetRenderTargetStack();
}

int      FilterFX::Run(float fTime)
{
  
  return (0);
}

void FilterFX::RunPreLayer(int iLayer, float fTime)
{
  if (iLayer==m_iTransparentStartLayer)
  {      
    if (m_bTransparentTransition)
    {
      // Setup fake buffer
      int iDepthID=-1;
      ResourceManager::GetCurrentRenderTarget(0, 0, 0, &iDepthID, 0);  
      ResourceManager::SetRenderTarget(m_iTransparentTexture, g_SceneFilter->GetAuxDepthBufferID());

      if (g_SceneFilter)
      {
        SM_D3d::Device()->Clear(0, NULL, D3DCLEAR_TARGET |D3DCLEAR_ZBUFFER | (SM_D3d::GetCurrentMode()->bStencil?D3DCLEAR_STENCIL:0), g_SceneFilter->GetBackColor(), 1.0f, 0 );
      }
      else
      {
      #ifdef _DEBUG
      SM_D3d::Device()->Clear(0, NULL, D3DCLEAR_TARGET |D3DCLEAR_ZBUFFER | (SM_D3d::GetCurrentMode()->bStencil?D3DCLEAR_STENCIL:0), D3DCOLOR_XRGB(0,int(128+127.0f*sinf(Timer::GetTime())),0), 1.0f, 0 );
      #else
      SM_D3d::Device()->Clear(0, NULL, D3DCLEAR_TARGET |D3DCLEAR_ZBUFFER | (SM_D3d::GetCurrentMode()->bStencil?D3DCLEAR_STENCIL:0), D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
      #endif
      }

      Coordinates::UpdatePhysicalSize();
    }
  }
}

void FilterFX::RunPostLayer(int iLayer, float fTime)
{
  if (iLayer==m_iMotionBlurEndLayer)
  {
    if (m_bMotionBlur)
    {
      
      RenderMotionBlur();
      Coordinates::UpdatePhysicalSize();
    }
  }

  if (m_bTransparentTransition && iLayer==m_iTransparentEndLayer)
  {      
    float fAlpha;
    m_TransparentSlider.GetValue(Timer::GetTime(), &fAlpha);
    RenderTransparent(m_fTransparentStart+(m_fTransparentEnd-m_fTransparentStart)*fAlpha);
  }
}

int      FilterFX::ParseShaderCommand(float fTime)
{
  char* pcShaderName;
  pcShaderName=strtok(0, " \t");

  ShaderManager::Shader* pShader=ShaderManager::GetShader(pcShaderName);
  if (!pShader)
  {
    return -1;
  }

  char* pcVertexShader;
  pcVertexShader=strtok(0, " \t");

  if (strcmp(pcVertexShader, "NOISE")==0)
  {
    pShader->m_pVertexShader=&TheNoiseXYZShader;

    char* pcToken;
    pcToken=strtok(0, " \t");

    char* pcTime=strtok(0, " \t");
        
    if (strcmp(pcToken, "FADEIN")==0)
    {
      TheNoiseXYZShader.m_ExpSlider.Init((float)atof(pcTime), true);
    }
    else
    {
      TheNoiseXYZShader.m_ExpSlider.Init((float)atof(pcTime), false);
    }

    TheNoiseXYZShader.m_ExpSlider.Start(fTime);

    pcToken=strtok(0, " \t");
    TheNoiseXYZShader.m_fAmplitudeX=(float)atof(pcToken);

    pcToken=strtok(0, " \t");
    TheNoiseXYZShader.m_fAmplitudeY=(float)atof(pcToken);

    pcToken=strtok(0, " \t");
    TheNoiseXYZShader.m_fAmplitudeZ=(float)atof(pcToken);

    pcToken=strtok(0, " \t");
    TheNoiseXYZShader.m_fSpaceFrequency=(float)atof(pcToken);

    pcToken=strtok(0, " \t");
    TheNoiseXYZShader.m_fTimeFrequency=(float)atof(pcToken);    
  }
  else
  if (strcmp(pcVertexShader, "NOISENORMAL")==0)
  {
    pShader->m_pVertexShader=&TheNormalNoiseShader;
  }
  else if (strcmp(pcVertexShader, "TWIST")==0)
  {
    pShader->m_pVertexShader=&TheTwistShader;
  }
  else
  {
    pShader->m_pVertexShader=0;
  }



  return 0;
}

static SM_DemoEffect::Helper CommandsHelp[] =
{
  {"FADEIN time r g b", "Fade in to specified color. r,g,b go from 0.0 to 1.0. Time in seconds"},
  {"FADEOUT time r g b", "Fade out to specified color. r,g,b go from 0.0 to 1.0. Time in seconds"},
  {"FADEIN2 time r g b", "Secondary fade in to specified color. r,g,b go from 0.0 to 1.0. Time in seconds"},
  {"FADEOUT2 time r g b", "Secondary fade out to specified color. r,g,b go from 0.0 to 1.0. Time in seconds"},
  {"FADEIN time r g b limit", "Fade in to specified color. r,g,b go from 0.0 to 1.0. Time in seconds"},
  {"FADEOUT time r g b limit", "Fade out to specified color. r,g,b go from 0.0 to 1.0. Time in seconds"},
  {"FADEIN2 time r g b limit", "Secondary fade in to specified color. r,g,b go from 0.0 to 1.0. Time in seconds"},
  {"FADEOUT2 time r g b limit", "Secondary fade out to specified color. r,g,b go from 0.0 to 1.0. Time in seconds"},  
  {"BACKGROUND r g b", "Background color. r,g,b go from 0.0 to 1.0"},
  {"NOISE time", "noise postfx for time duration (seconds). requires BYPASS ON"},
  {"LENS FADEIN time strengh frequency", "lens effect, fades in time seconds"},
  {"LENS OFF", "turns off lens effect strengh frequency"},
  {"BLUR FADEIN time strength", "fade in blur all frame with strength (0.0 to 1.0)."},
  {"BLUR FADEOUT time strength", "fade out blur all frame with strength (0.0 to 1.0)."},  
  {"RADIALBLUR FADEIN time scale x y", ""},
  {"RADIALBLUR FADEOUT time scale x y", ""},       
  {"COMPONENT time", "fade de componentes en tiempo time. 0.0 para que se kede al maximo"},
  {"COMPONENT OFF", "quita el desplazamiento"},
  {"COMPONENT RED amplitude frequency offset", ""},
  {"COMPONENT GREEN amplitude frequency offset", ""},
  {"COMPONENT BLUE amplitude frequency offset", ""},
  {"UNDERWATER FADEIN time frequency amplitude","underwater effect. Requires BYPASS ON"},
  {"UNDERWATER FADEOUT time frequency amplitude","underwater effect. Requires BYPASS ON"},
  
  {"MOTIONBLUR FADEIN time factor iStartLayer iEndLayer", "Does motion blur fade in on selected layers\r\nfactor: [0..1] \r\niStartLayer-iEndLayer: range of layers affected by blur.\r\nRequires FXFILTER COMMAND BYPYASS ON"},   
  {"MOTIONBLUROFF", "turns off motion blur"},   
  {"CROSSFADE time startgrade endgrade startlayer endlayer", "crossfade between previous render and the layer range selected in selected time\r\nRequires FXFILTER COMMAND BYPYASS ON"},   
  {"CROSSFADEOFF", "turns off crossfade"},
  {"CLEARON", "turns on clearing"},   
  {"CLEAROFF", "turns off clearing"},

  {"SHADER ENVIROMENT NOISE FADEIN FADETIME SCALEX SCALEY SCALEZ SPACEFREQUENCY TIMEFREQUENCY", "noise shader"},
};


int FilterFX::CommandArgumentsHelp  (Helper*& pHelpers)
{
  pHelpers = CommandsHelp;
  return (sizeof(CommandsHelp)/sizeof(Helper));
}


int      FilterFX::Command           (float fTime, const char* pcCommand)
{
  char* pcToken;

  char* pcAux=new char[strlen(pcCommand)+1];
  strcpy(pcAux, pcCommand);

  pcToken=strtok(pcAux, " \t");
  if (strcmp(pcToken, "BACKGROUND")==0)
  {
    pcToken=strtok(0, " \t");
    float fr=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    float fg=(float)SafeAtof(pcToken);
    
    pcToken=strtok(0, " \t");
    float fb=(float)SafeAtof(pcToken);

    m_uBackGround=((int(fr*255.0f))<<16)|
                  ((int(fg*255.0f))<< 8)|
                  ((int(fb*255.0f))<< 0);
  }
  else if (strcmp(pcToken, "FADEIN")==0)
  { 
    pcToken=strtok(0, " \t");
    m_fDuration=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    m_fr=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    m_fg=(float)SafeAtof(pcToken);
    
    pcToken=strtok(0, " \t");
    m_fb=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    if (pcToken)
    {
      m_fFadeLimit = (float)SafeAtof(pcToken);
    }
    else
    {
      m_fFadeLimit = 1.0f;
    }

    m_fStartTime=fTime;   

    m_bFadeIn=true;
  }
  else
  if (strcmp(pcToken, "FADEOUT")==0)
  {         
    pcToken=strtok(0, " \t");
    m_fDuration=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    m_fr=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    m_fg=(float)SafeAtof(pcToken);
    
    pcToken=strtok(0, " \t");
    m_fb=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    if (pcToken)
    {
      m_fFadeLimit = (float)SafeAtof(pcToken);
    }
    else
    {
      m_fFadeLimit = 1.0f;
    }

    m_fStartTime=fTime;

    m_bFadeOut=true;
  }
  else if (strcmp(pcToken, "FADEIN2")==0)
  { 
    pcToken=strtok(0, " \t");
    m_fSecondaryDuration=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    m_fSecondaryr=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    m_fSecondaryg=(float)SafeAtof(pcToken);
    
    pcToken=strtok(0, " \t");
    m_fSecondaryb=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    if (pcToken)
    {
      m_fSecondaryFadeLimit = (float)SafeAtof(pcToken);
    }
    else
    {
      m_fSecondaryFadeLimit = 1.0f;
    }

    m_fSecondaryStartTime=fTime;

    m_bSecondaryFadeIn=true;
  }
  else
  if (strcmp(pcToken, "FADEOUT2")==0)
  {         
    pcToken=strtok(0, " \t");
    m_fSecondaryDuration=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    m_fSecondaryr=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    m_fSecondaryg=(float)SafeAtof(pcToken);
    
    pcToken=strtok(0, " \t");
    m_fSecondaryb=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    if (pcToken)
    {
      m_fSecondaryFadeLimit = (float)SafeAtof(pcToken);
    }
    else
    {
      m_fSecondaryFadeLimit = 1.0f;
    }

    m_fSecondaryStartTime=fTime;

    m_bSecondaryFadeOut=true;
  }
  else
  if (strcmp(pcToken, "BYPASS")==0)
  { 
    pcToken=strtok(0, " \t");
    if (strcmp(pcToken, "ON")==0)
    {
      m_bInterceptRender=true;
    }
    else
    {
      m_bInterceptRender=false;
    }    
  }
  else
  if (strcmp(pcToken, "NOISE")==0)
  {     
    pcToken=strtok(0, " \t");
    float fDuration=SafeAtof(pcToken);

    m_HorizontalNoiseSlider.Init(fDuration);
    m_HorizontalNoiseSlider.Start(fTime);

    pcToken=strtok(0, " \t");
    m_fHorizontalAmplitude=SafeAtof(pcToken);
    
    m_bHorizontalNoise=true;        
  }
  else if (strcmp(pcToken, "LENS")==0)
  { 
    pcToken=strtok(0, " \t");
    if (strcmp(pcToken, "OFF")==0)
    {
      m_bLens=false;        
    }
    else
    {
      if (strcmp(pcToken, "FADEIN")==0)
      {
        m_bLensFadeIn=true;
      }
      else 
      {
        m_bLensFadeIn=false;      
      }
   
      pcToken=strtok(0, " \t");
      float fDuration=SafeAtof(pcToken);
    
      m_LensSlider.Init(fDuration);
      m_LensSlider.Start(fTime);

      pcToken=strtok(0, " \t");
      m_fLensStrength=SafeAtof(pcToken);

      pcToken=strtok(0, " \t");
      m_fLensFrequency=SafeAtof(pcToken);

      m_bLens=true;        
    }
  }
  else if (strcmp(pcToken, "QUALITYBLUR")==0)
  {
    pcToken=strtok(0, " \t");    
    if (strcmp(pcToken, "ON")==0)
    {
      m_bQualityBlur=true;
    }
    else 
    {
      m_bQualityBlur=false;      
    }
  }
  else if (strcmp(pcToken, "COMPONENT")==0)
  {
    pcToken=strtok(0, " \t");    
    if (strcmp(pcToken, "RED")==0)
    {
      pcToken=strtok(0, " \t");    
      m_fComponentAmplitude[0]=SafeAtof(pcToken);

      pcToken=strtok(0, " \t");    
      m_fComponentFrequency[0]=SafeAtof(pcToken);

      pcToken=strtok(0, " \t");    
      m_fComponentOffset[0]=SafeAtof(pcToken);
    }
    else
    if (strcmp(pcToken, "GREEN")==0)
    {
      pcToken=strtok(0, " \t");    
      m_fComponentAmplitude[1]=SafeAtof(pcToken);

      pcToken=strtok(0, " \t");    
      m_fComponentFrequency[1]=SafeAtof(pcToken);

      pcToken=strtok(0, " \t");    
      m_fComponentOffset[1]=SafeAtof(pcToken);
    }
    else
    if (strcmp(pcToken, "BLUE")==0)
    {
      pcToken=strtok(0, " \t");    
      m_fComponentAmplitude[2]=SafeAtof(pcToken);

      pcToken=strtok(0, " \t");    
      m_fComponentFrequency[2]=SafeAtof(pcToken);

      pcToken=strtok(0, " \t");    
      m_fComponentOffset[2]=SafeAtof(pcToken);
    }
    else
    if (strcmp(pcToken, "OFF")==0)
    {
      m_bComponent=false;
    }
    else 
    {
      m_ComponentSlider.Init(SafeAtof(pcToken), false);
      m_ComponentSlider.Start(fTime); 
      m_bComponent=true;      
    }
  }  
  else if (strcmp(pcToken, "BLUR")==0)
  {
    pcToken=strtok(0, " \t");    
    if (strcmp(pcToken, "FADEIN")==0)
    {
      m_bBlurFadeIn=true;
    }
    else 
    {
      m_bBlurFadeIn=false;      
    }

    pcToken=strtok(0, " \t");
    float fDuration=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    m_fBlurStrength=SafeAtof(pcToken);

    m_bBlur=true;
  
    m_BlurSlider.Init(fDuration);
    m_BlurSlider.Start(fTime); 
  }
  else if (strcmp(pcToken, "RADIALBLUR")==0)
  {
    pcToken=strtok(0, " \t");    
    if (strcmp(pcToken, "FADEIN")==0)
    {
      m_bRadialBlurFadeIn=true;
    }
    else 
    {
      m_bRadialBlurFadeIn=false;      
    }

    pcToken=strtok(0, " \t");
    float fDuration=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    m_fRadialBlurStrength=SafeAtof(pcToken);

    m_bRadialBlur=true;
  
    m_RadialBlurSlider.Init(fDuration);
    m_RadialBlurSlider.Start(fTime); 
  }
  else if (strcmp(pcToken, "WOBBLE")==0)
  {
    m_bWobble=true;
  }
  else if (strcmp(pcToken, "TRANSITION")==0)
  {
    m_bTransition=true;
  }
  else if (strcmp(pcToken, "UNDERWATER")==0)
  {
    pcToken=strtok(0, " \t");    
    if (strcmp(pcToken, "FADEIN")==0)
    {
      m_bUnderwaterFadeIn=true;
    }
    else 
    {
      m_bUnderwaterFadeIn=false;      
    }

    pcToken=strtok(0, " \t");
    float fDuration=SafeAtof(pcToken);

    m_bUnderwater=true;
  
    m_UnderwaterSlider.Init(fDuration, m_bUnderwaterFadeIn);
    m_UnderwaterSlider.Start(fTime); 

    pcToken=strtok(0, " \t");
    m_fUnderwaterFrecuency=SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    m_fUnderwaterAmplitude=SafeAtof(pcToken);    
    
    /*
    pcToken=strtok(0, " \t");    
    if (strcmp(pcToken, "FADEIN")==0)
    {
      m_bUnderwaterFadeIn=true;
    }
    else 
    {
      m_bUnderwaterFadeIn=false;      
    }

    pcToken=strtok(0, " \t");
    float fDuration=SafeAtof(pcToken);

    m_UnderwaterSlider.Init(fDuration, m_bUnderwaterFadeIn);
    m_UnderwaterSlider.Start(fTime); 


    m_bPlasma = true;
    */
  }
  else
  if (strcmp(pcToken, "SHADER")==0)
  {
    ParseShaderCommand(fTime);
  }
  else if (strcmp(pcToken, "MOTIONBLUR")==0)
  {
    pcToken=strtok(0, " \t");
    if (strcmp(pcToken, "FADEIN")==0)
    {
      m_bMotionBlurFadeIn=true;
    }
    else
    {
      m_bMotionBlurFadeIn=false;
    }

    pcToken=strtok(0, " \t");
    m_MotionBlurSlider.Init((float)SafeAtof(pcToken));
    m_MotionBlurSlider.Start(fTime);                    

    pcToken=strtok(0, " \t");
    m_fMotionBlurFactor=(float)SafeAtof(pcToken);      

    pcToken=strtok(0, " \t");
    m_iMotionBlurStartLayer=SafeAtoi(pcToken);

    pcToken=strtok(0, " \t");
    m_iMotionBlurEndLayer=SafeAtoi(pcToken);
  
    if (m_fMotionBlurFactor==0.0f)
    {
      m_bMotionBlur=false;
    }
    else
    {
      m_bMotionBlur=true;
    }
  }
  else
  if (strcmp(pcToken, "MOTIONBLUROFF")==0)
  {
    m_bMotionBlur=false;
  }
  else
  if (strcmp(pcToken, "CROSSFADE")==0)
  {
    m_bTransparentTransition=true;

    pcToken=strtok(0, " \t");
    m_TransparentSlider.Init((float)SafeAtof(pcToken));
    m_TransparentSlider.Start(fTime);              

    pcToken=strtok(0, " \t");
    m_fTransparentStart=(float)SafeAtof(pcToken);

    pcToken=strtok(0, " \t");
    m_fTransparentEnd=(float)SafeAtof(pcToken);
    
    pcToken=strtok(0, " \t");
    m_iTransparentStartLayer=SafeAtoi(pcToken);

    pcToken=strtok(0, " \t");
    m_iTransparentEndLayer=SafeAtoi(pcToken);
  }
  else
  if (strcmp(pcToken, "CROSSFADEOFF")==0)
  {
    m_bTransparentTransition=false;
  }
  else 
  if (strcmp(pcToken, "CLEAROFF")==0)
  {
    m_bNoClear = true;
  }
  else
  if (strcmp(pcToken, "CLEARON")==0)
  {
    m_bNoClear = false;
  }
  


  delete[] pcAux;

  return (0);
}  

IDirect3DSurface8* g_pZStencilSurface=0;      
IDirect3DSurface8* g_pBackBuffer=0;

void FilterFX::RunPreStartFrame  (float fTime)
{
}

void FilterFX::RunPreRender      (float fTime)
{
  if (m_bMotionBlur || m_bTransparentTransition || 
      m_bHorizontalNoise || m_bLens || 
      m_bWobble || m_bBlur || m_bUnderwater || m_bTransition || m_bQualityBlur || m_bComponent || m_bRadialBlur || m_bPlasma)
  {
    m_bInterceptRender = true;
      
    assert(m_bInit == true);

    ResourceManager::SetRenderTarget(m_iFakeBufferID, m_iFakeDepthBufferID);

    DWORD dwClearTarget = D3DCLEAR_TARGET;

    if (m_bNoClear)
    {
      dwClearTarget = 0;
    }

    if (g_SceneFilter)
    {
      SM_D3d::Device()->Clear(0, NULL, dwClearTarget |D3DCLEAR_ZBUFFER | (SM_D3d::GetCurrentMode()->bStencil?D3DCLEAR_STENCIL:0), GetBackColor(), 1.0f, 0 );
    }
    else
    {
      #ifdef _DEBUG
      SM_D3d::Device()->Clear(0, NULL, dwClearTarget |D3DCLEAR_ZBUFFER | (SM_D3d::GetCurrentMode()->bStencil?D3DCLEAR_STENCIL:0), D3DCOLOR_XRGB(0,int(128+127.0f*sinf(Timer::GetTime())),0), 1.0f, 0 );
      #else
      SM_D3d::Device()->Clear(0, NULL, dwClearTarget |D3DCLEAR_ZBUFFER | (SM_D3d::GetCurrentMode()->bStencil?D3DCLEAR_STENCIL:0), D3DCOLOR_XRGB(255,255,255), 1.0f, 0 );
      #endif
    }
  }
  else
  {
    m_bInterceptRender = false;
  }

  Coordinates::UpdatePhysicalSize();
}

#define MAX_RES_Y 1024
void FilterFX::RenderHorizontalNoise(float fAmplitude)
{
  FVF_PosRhwDiffuseTex1 Vertices  [MAX_RES_Y*4];
  unsigned short        pIndices  [MAX_RES_Y*6];

  int i;

  float fWidth =Coordinates::PhysicalWidth();
  float fHeight=Coordinates::PhysicalHeight();
  int   iHeight=int(fHeight);


  FVF_PosRhwDiffuseTex1* pVertices=Vertices;

  float fScaleU=1.0f;
  float fScaleV=1.0f;

  float dv=1.0f/float(iHeight);
  for (i=0 ; i<iHeight ; i++)
  {    
    float fOffset=sinf(i+1.75f*float(i%2?-1:1))*fAmplitude;
    pVertices[0].x=0  -0.5f   ; pVertices[0].y=i  -0.5f; pVertices[0].z=0.0f; pVertices[0].u=0.0f   +fOffset; pVertices[0].v=i*dv; pVertices[0].oow=1.0f; pVertices[0].diffuse=0xFFFFFFFF;
    pVertices[1].x=fWidth-0.5f; pVertices[1].y=i  -0.5f; pVertices[1].z=0.0f; pVertices[1].u=fScaleU+fOffset; pVertices[1].v=i*dv; pVertices[1].oow=1.0f; pVertices[1].diffuse=0xFFFFFFFF;
    pVertices[2].x=fWidth-0.5f; pVertices[2].y=i+1-0.5f; pVertices[2].z=0.0f; pVertices[2].u=fScaleU+fOffset; pVertices[2].v=(i+1)*dv; pVertices[2].oow=1.0f; pVertices[2].diffuse=0xFFFFFFFF;
    pVertices[3].x=0  -0.5f   ; pVertices[3].y=i+1-0.5f; pVertices[3].z=0.0f; pVertices[3].u=0.0f   +fOffset; pVertices[3].v=(i+1)*dv; pVertices[3].oow=1.0f; pVertices[3].diffuse=0xFFFFFFFF;

    pVertices+=4;
  }

  unsigned uOffset=0;
  for (i=0 ; i<iHeight ; i++)
  {
    pIndices[uOffset++]=i*4+0;
    pIndices[uOffset++]=i*4+2;
    pIndices[uOffset++]=i*4+1;
    pIndices[uOffset++]=i*4+0;
    pIndices[uOffset++]=i*4+3;
    pIndices[uOffset++]=i*4+2;
  }
  

  SM_D3d::Device()->SetVertexShader(FVF_POSRHWDIFFUSETEX1);
  SM_D3d::SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);  
  SM_D3d::SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);  
  SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);  
  SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);                        

  SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP   , D3DTOP_MODULATE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1 , D3DTA_TEXTURE );
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG2 , D3DTA_DIFFUSE );

  SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(m_iFakeBufferID));    
  SM_D3d::Device()->DrawIndexedPrimitiveUP(
      D3DPT_TRIANGLELIST, 
      0,
      iHeight*4,
      iHeight*2,
      pIndices,
      D3DFMT_INDEX16,
      Vertices, sizeof(FVF_PosRhwDiffuseTex1));
}

void FilterFX::RenderComponent()
{
  FVF_PosRhwDiffuseTex1 pVertices[4];
  unsigned short        pIndices[6]={0,2,1,0,3,2};



  SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(m_iFakeBufferID));    



  float fScaleU=1.0f;
  float fScaleV=1.0f;    

  float fWidth =Coordinates::PhysicalWidth();
  float fHeight=Coordinates::PhysicalHeight();

  #define BLURWIDTH 16
  #define BLURALPHA ((255/BLURWIDTH)<<24)

  unsigned i;

  unsigned uMasks[3] = 
  {
    0x8 | 0x4,
    0x8 | 0x2,
    0x8 | 0x1,
  };

  float fFade;
  if (m_ComponentSlider.m_fLength == 0.0f)
  {
    fFade = 1.0f;
  }
  else
  {
    if (!m_ComponentSlider.GetValue(Timer::GetTime(), &fFade))
    {
      m_bComponent = false;
    }
  }
  
  for (i = 0 ; i<3 ; i++)
  {
    SM_D3d::SetRenderState(D3DRS_COLORWRITEENABLE, uMasks[i]);

    pVertices[0].x=fFade*m_fComponentAmplitude[i]*sinf(m_fComponentFrequency[i]*Timer::GetTime()+m_fComponentOffset[i])+0.0f  ; pVertices[0].y=0.0f   ; pVertices[0].z=0.0f; pVertices[0].u=0.0f; pVertices[0].v=0.0f; pVertices[0].oow=1.0f; pVertices[0].diffuse=BLURALPHA | 0xFFFFFF;
    pVertices[1].x=fFade*m_fComponentAmplitude[i]*sinf(m_fComponentFrequency[i]*Timer::GetTime()+m_fComponentOffset[i])+fWidth; pVertices[1].y=0.0f   ; pVertices[1].z=0.0f; pVertices[1].u=fScaleU; pVertices[1].v=0.0f; pVertices[1].oow=1.0f; pVertices[1].diffuse=BLURALPHA | 0xFFFFFF;
    pVertices[2].x=fFade*m_fComponentAmplitude[i]*sinf(m_fComponentFrequency[i]*Timer::GetTime()+m_fComponentOffset[i])+fWidth; pVertices[2].y=fHeight; pVertices[2].z=0.0f; pVertices[2].u=fScaleU; pVertices[2].v=fScaleV; pVertices[2].oow=1.0f; pVertices[2].diffuse=BLURALPHA | 0xFFFFFF;
    pVertices[3].x=fFade*m_fComponentAmplitude[i]*sinf(m_fComponentFrequency[i]*Timer::GetTime()+m_fComponentOffset[i])+0.0f  ; pVertices[3].y=fHeight; pVertices[3].z=0.0f; pVertices[3].u=0.0f; pVertices[3].v=fScaleV; pVertices[3].oow=1.0f; pVertices[3].diffuse=BLURALPHA | 0xFFFFFF;

    SM_D3d::Device()->SetVertexShader(FVF_POSRHWDIFFUSETEX1);
    SM_D3d::SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);  
    SM_D3d::SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);  
    SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
    SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
    SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);  
  
    SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);    
    SM_D3d::SetTextureStageState(0, D3DTSS_MIPMAPLODBIAS, 0.0f);

    SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP   , D3DTOP_MODULATE);
    SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1 , D3DTA_TEXTURE );
    SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG2 , D3DTA_DIFFUSE );

    SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAOP   , D3DTOP_SELECTARG1);
    SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAARG1 , D3DTA_DIFFUSE );

    SM_D3d::SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
    SM_D3d::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);    
    SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);                        



    SM_D3d::Device()->DrawIndexedPrimitiveUP(
        D3DPT_TRIANGLELIST, 
        0,
        6,
        2,
        pIndices,
        D3DFMT_INDEX16,
        pVertices, sizeof(FVF_PosRhwDiffuseTex1));
  }


  SM_D3d::SetRenderState(D3DRS_COLORWRITEENABLE, 0xF);
  SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
}



#define LENSTILESX  16
#define LENSTILESY  12
void FilterFX::RenderLens(float fAmplitude)
{
  // Material
  D3DMATERIAL8 Material;
  Material.Diffuse.r=Material.Diffuse.g=Material.Diffuse.b=Material.Diffuse.a=1.0f;
  Material.Ambient.r=Material.Ambient.g=Material.Ambient.b=Material.Ambient.a=1.0f;
  Material.Specular.r=Material.Specular.g=Material.Specular.b=Material.Specular.a=1.0f;
  Material.Emissive.r=Material.Emissive.g=Material.Emissive.b=Material.Emissive.a=0.0f;
  Material.Power=0.0f;
  SM_D3d::Device()->SetMaterial(&Material);


  // Render
  float fBias=0.0f;
  SM_D3d::SetTextureStageState(0, D3DTSS_MIPMAPLODBIAS, *((LPDWORD) (&fBias)));  
  SM_D3d::SetRenderState(D3DRS_COLORWRITEENABLE, 0xF);          
  SM_D3d::SetRenderState(D3DRS_FOGENABLE, FALSE);  
  SM_D3d::SetRenderState(D3DRS_SPECULARENABLE , FALSE);
  SM_D3d::SetRenderState(D3DRS_LOCALVIEWER , FALSE);
  SM_D3d::SetRenderState(D3DRS_LIGHTING, FALSE);    
  SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);                        
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU); 
  SM_D3d::SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );           
  SM_D3d::SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP , D3DTOP_MODULATE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  SM_D3d::SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);  
  SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  SM_D3d::Device()->SetVertexShader(FVF_POSNORMALDIFFUSETEX1);                              
  SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(m_iFakeBufferID));    

  // Matrix
  Matrix4X4 m;

  float fWidth =Coordinates::PhysicalWidth();
  float fHeight=Coordinates::PhysicalHeight();
  

  float w =4.0f /fWidth;
  float h =-4.0f/fHeight;
  float dw=-2.0f;
  float dh=2.0f;

  float fFar =2.0f;
  float fNear=0.001f;

  float Q =fFar/(fFar-fNear);

  m.m_11=w             ; m.m_12=0.0f; m.m_13=0.0f         ; m.m_14=0.0f;
  m.m_21=0.0f          ; m.m_22=h   ; m.m_23=0.0f         ; m.m_24=0.0f;
  m.m_31=0.0f          ; m.m_32=0.0f; m.m_33=Q            ; m.m_34=1.0f;
  m.m_41=dw            ; m.m_42=dh  ; m.m_43=-Q*fNear     ; m.m_44=1.0f;

  SM_D3d::Device()->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&Matrix4X4::Identity);    
  SM_D3d::Device()->SetTransform(D3DTS_WORLD, (D3DMATRIX*) &Matrix4X4::Identity);      
  SM_D3d::Device()->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)&m);  
  


  // Primitive
  FVF_PosNormalDiffuseTex1 Vertices  [LENSTILESX*LENSTILESY];
  unsigned short        pIndices  [(LENSTILESX-1)*(LENSTILESY-1)*6];

  
  int   iHeight=int(fHeight);


  FVF_PosNormalDiffuseTex1* pV=Vertices;

  float fScaleU=1.0f;
  float fScaleV=1.0f;

  float dx=fWidth/(LENSTILESX-1);;
  float dy=fHeight/(LENSTILESY-1);
  float du=1.0f/(LENSTILESX-1);
  float dv=1.0f/(LENSTILESY-1);
  int i,j;


  float v=0.0f;
  float y=0.0f;
  
        
  float D=fAmplitude;                  
  for (j=0 ; j<LENSTILESY ; j++)
  {    
    float u=0.0f;
    float x=0.0f;
    for (i=0 ; i<LENSTILESX ; i++)
    {
      pV[0].x=x-0.5f; pV[0].y=y-0.5f; 
      
      
      float rx=u*2.0f-1.0f;
      float ry=v*2.0f-1.0f;
      if (rx*rx+ry*ry<=1.0f)
      {
        pV[0].z=1.0f+(1.0f-(rx*rx+ry*ry))*fAmplitude;
      }
      else
      {
        pV[0].z=1.0;
      }

      pV[0].u=u;
      pV[0].v=v;    
      pV[0].diffuse=0xFFFFFFFF;    
      pV[0].nx=pV[0].ny=pV[0].nz=0.0f;
      pV++;
      u+=du;
      x+=dx;
    }    

    v+=dv;
    y+=dy;
  }

  unsigned uOffset=0;
  for (j=0 ; j<LENSTILESY-1 ; j++)
  {
    for (i=0 ; i<LENSTILESX-1 ; i++)
    {
      pIndices[uOffset++]= i   +(j  )*LENSTILESX;
      pIndices[uOffset++]=(i  )+(j+1)*LENSTILESX;
      pIndices[uOffset++]=(i+1)+(j  )*LENSTILESX;
      pIndices[uOffset++]=(i+1)+(j  )*LENSTILESX;
      pIndices[uOffset++]=(i  )+(j+1)*LENSTILESX;
      pIndices[uOffset++]=(i+1)+(j+1)*LENSTILESX;
      
    }
  }  
 
  SM_D3d::Device()->DrawIndexedPrimitiveUP(
      D3DPT_TRIANGLELIST, 
      0,
      LENSTILESX*LENSTILESY,
      (LENSTILESX-1)*(LENSTILESY-1)*2,
      pIndices,
      D3DFMT_INDEX16,
      Vertices, sizeof(FVF_PosNormalDiffuseTex1));
}

void FilterFX::RenderWobble(float fAmplitude)
{    
  GenerateMips();
  ResourceManager::RestoreRenderTarget();
    // Material
  D3DMATERIAL8 Material;
  Material.Diffuse.r=Material.Diffuse.g=Material.Diffuse.b=Material.Diffuse.a=1.0f;
  Material.Ambient.r=Material.Ambient.g=Material.Ambient.b=Material.Ambient.a=1.0f;
  Material.Specular.r=Material.Specular.g=Material.Specular.b=Material.Specular.a=1.0f;
  Material.Emissive.r=Material.Emissive.g=Material.Emissive.b=Material.Emissive.a=0.0f;
  Material.Power=0.0f;
  SM_D3d::Device()->SetMaterial(&Material);


  
  // Render
  float fBias=0.0f;
  SM_D3d::SetTextureStageState(0, D3DTSS_MIPMAPLODBIAS, *((LPDWORD) (&fBias)));  
  SM_D3d::SetRenderState(D3DRS_COLORWRITEENABLE, 0xF);          
  SM_D3d::SetRenderState(D3DRS_FOGENABLE, FALSE);  
  SM_D3d::SetRenderState(D3DRS_SPECULARENABLE , FALSE);
  SM_D3d::SetRenderState(D3DRS_LOCALVIEWER , FALSE);
  SM_D3d::SetRenderState(D3DRS_LIGHTING, FALSE);    
  SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);                        
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU); 
  SM_D3d::SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );           
  SM_D3d::SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP , D3DTOP_MODULATE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  SM_D3d::SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);  
  SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  SM_D3d::Device()->SetVertexShader(FVF_POSNORMALDIFFUSETEX1);                              
  SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(m_iFakeBufferID));    

  // Matrix
  Matrix4X4 m;

  float fWidth =Coordinates::PhysicalWidth();
  float fHeight=Coordinates::PhysicalHeight();
  

  float w =4.0f /fWidth;
  float h =-4.0f/fHeight;
  float dw=-2.0f;
  float dh=2.0f;

  float fFar =2.0f;
  float fNear=0.001f;

  float Q =fFar/(fFar-fNear);

  m.m_11=w             ; m.m_12=0.0f; m.m_13=0.0f         ; m.m_14=0.0f;
  m.m_21=0.0f          ; m.m_22=h   ; m.m_23=0.0f         ; m.m_24=0.0f;
  m.m_31=0.0f          ; m.m_32=0.0f; m.m_33=Q            ; m.m_34=1.0f;
  m.m_41=dw            ; m.m_42=dh  ; m.m_43=-Q*fNear     ; m.m_44=1.0f;

  SM_D3d::Device()->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&Matrix4X4::Identity);    
  SM_D3d::Device()->SetTransform(D3DTS_WORLD, (D3DMATRIX*) &Matrix4X4::Identity);      
  SM_D3d::Device()->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)&m);  
  


  // Primitive
  FVF_PosNormalDiffuseTex1 Vertices  [LENSTILESX*LENSTILESY];
  unsigned short        pIndices  [(LENSTILESX-1)*(LENSTILESY-1)*6];

  
  int   iHeight=int(fHeight);


  FVF_PosNormalDiffuseTex1* pV=Vertices;


  float dx=fWidth/(LENSTILESX-1);;
  float dy=fHeight/(LENSTILESY-1);
  float du=1.0f/(LENSTILESX-1);
  float dv=1.0f/(LENSTILESY-1);
  int i,j;


  float v=0.0f;
  float y=0.0f;
  

  float  fModulate=0.5f+0.5f*sinf(Timer::GetTime());
        
  for (j=0 ; j<LENSTILESY ; j++)
  {    
    float u=0.0f;
    float x=0.0f;
    for (i=0 ; i<LENSTILESX ; i++)
    {
      pV[0].x=x-0.5f; pV[0].y=y-0.5f; 
      
      pV[0].z=1.0f-fModulate*
          (0.5f+0.5f*sinf(Timer::GetTime()+float(i)/5.0f)*cosf(Timer::GetTime()+float(j)/5.0f)); 

      
      pV[0].u=u+2.5f*sinf(Timer::GetTime()+j*i)*fModulate;
      pV[0].v=v+2.5f*cosf(Timer::GetTime()+j*i)*fModulate;
      pV[0].diffuse=0xFFFFFFFF;    
      pV[0].nx=pV[0].ny=pV[0].nz=0.0f;
      pV++;
      u+=du;
      x+=dx;
    }    

    v+=dv;
    y+=dy;
  }

  unsigned uOffset=0;
  for (j=0 ; j<LENSTILESY-1 ; j++)
  {
    for (i=0 ; i<LENSTILESX-1 ; i++)
    {
      pIndices[uOffset++]= i   +(j  )*LENSTILESX;
      pIndices[uOffset++]=(i  )+(j+1)*LENSTILESX;
      pIndices[uOffset++]=(i+1)+(j  )*LENSTILESX;
      pIndices[uOffset++]=(i+1)+(j  )*LENSTILESX;
      pIndices[uOffset++]=(i  )+(j+1)*LENSTILESX;
      pIndices[uOffset++]=(i+1)+(j+1)*LENSTILESX;
      
    }
  }  
 
  SM_D3d::Device()->DrawIndexedPrimitiveUP(
      D3DPT_TRIANGLELIST, 
      0,
      LENSTILESX*LENSTILESY,
      (LENSTILESX-1)*(LENSTILESY-1)*2,
      pIndices,
      D3DFMT_INDEX16,
      Vertices, sizeof(FVF_PosNormalDiffuseTex1));
}


void FilterFX::RenderTransparent(float fAlpha)
{
  ResourceManager::RestoreRenderTarget();


  FVF_PosRhwDiffuseTex1 pVertices[4];
  unsigned short        pIndices[6]={0,2,1,0,3,2};
  SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(m_iTransparentTexture));    

  float fScaleU=1.0f;
  float fScaleV=1.0f;        
  
  pVertices[0].x=0               ; pVertices[0].y=0                ; pVertices[0].z=0.0f; pVertices[0].u=0.0f; pVertices[0].v=0; pVertices[0].oow=1.0f; pVertices[0].diffuse=0xFFFFFFFF;
  pVertices[1].x=(float)SIZEWIDTH; pVertices[1].y=0                ; pVertices[1].z=0.0f; pVertices[1].u=fScaleU; pVertices[1].v=0; pVertices[1].oow=1.0f; pVertices[1].diffuse=0x00FFFFFF;
  pVertices[2].x=(float)SIZEWIDTH; pVertices[2].y=(float)SIZEHEIGHT; pVertices[2].z=0.0f; pVertices[2].u=fScaleU; pVertices[2].v=fScaleV; pVertices[2].oow=1.0f; pVertices[2].diffuse=0xFFFFFFFF;
  pVertices[3].x=0               ; pVertices[3].y=(float)SIZEHEIGHT; pVertices[3].z=0.0f; pVertices[3].u=0.0f; pVertices[3].v=fScaleV; pVertices[3].oow=1.0f; pVertices[3].diffuse=0x00FFFFFF;

  SM_D3d::Device()->SetVertexShader(FVF_POSRHWDIFFUSETEX1);
  SM_D3d::SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);  
  SM_D3d::SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);  
  SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
  

  SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);                        
  SM_D3d::SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  SM_D3d::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);  
  SM_D3d::SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
    

  SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP   , D3DTOP_MODULATE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1 , D3DTA_TEXTURE );
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG2 , D3DTA_DIFFUSE );

  SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAOP   , D3DTOP_SELECTARG1);
  SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAARG1 , D3DTA_TFACTOR);

  SM_D3d::SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);    
  

  unsigned uFactor=int(fAlpha*255.0f)<<24;
  SM_D3d::SetRenderState(D3DRS_TEXTUREFACTOR, uFactor);
  //SM_D3d::SetRenderState(D3DRS_TEXTUREFACTOR, 0x80000000);
  
  SM_D3d::Device()->DrawIndexedPrimitiveUP(
      D3DPT_TRIANGLELIST, 
      0,
      6,
      2,
      pIndices,
      D3DFMT_INDEX16,
      pVertices, sizeof(FVF_PosRhwDiffuseTex1));

  SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);                        
  SM_D3d::SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);    
}


void FilterFX::RenderRadialBlur(float x, float y, float scale)
{
  RenderAuxRadialBlur(x, y, scale, m_iFakeBufferID, m_iBlurTexture);  
}

void FilterFX::RenderMotionBlur()
{
  FVF_PosRhwDiffuseTex1 pVertices[4];
  unsigned short        pIndices[6]={0,2,1,0,3,2};

  float fScaleU=1.0f;
  float fScaleV=1.0f;    

  pVertices[0].x=0               -0.5f; pVertices[0].y=0                -0.5f; pVertices[0].z=0.0f; pVertices[0].u=0.0f; pVertices[0].v=0; pVertices[0].oow=1.0f; pVertices[0].diffuse=0xFFFFFFFF;
  pVertices[1].x=(float)Coordinates::PhysicalWidth()-0.5f; pVertices[1].y=0                -0.5f; pVertices[1].z=0.0f; pVertices[1].u=fScaleU; pVertices[1].v=0; pVertices[1].oow=1.0f; pVertices[1].diffuse=0x00FFFFFF;
  pVertices[2].x=(float)Coordinates::PhysicalWidth()-0.5f; pVertices[2].y=(float)Coordinates::PhysicalHeight()-0.5f; pVertices[2].z=0.0f; pVertices[2].u=fScaleU; pVertices[2].v=fScaleV; pVertices[2].oow=1.0f; pVertices[2].diffuse=0xFFFFFFFF;
  pVertices[3].x=0               -0.5f; pVertices[3].y=(float)Coordinates::PhysicalHeight()-0.5f; pVertices[3].z=0.0f; pVertices[3].u=0.0f; pVertices[3].v=fScaleV; pVertices[3].oow=1.0f; pVertices[3].diffuse=0x00FFFFFF;
  

  IDirect3DTexture8* pTexture=0;
  ResourceManager::GetCurrentRenderTarget(0, 0, &pTexture, 0, 0);

  assert(pTexture);

  static bool bFirst=true;

  int iBuffer[2];
  static int iCounter=0;

  iCounter++;

  if (iCounter%2)
  {
    iBuffer[0] = m_iMotionBlurTexture[0];
    iBuffer[1] = m_iMotionBlurTexture[1];
  }
  else
  {
    iBuffer[0] = m_iMotionBlurTexture[1];
    iBuffer[1] = m_iMotionBlurTexture[0];
  }
  
  // Do preprocess
  SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(iBuffer[0]));    
  ResourceManager::SetRenderTarget(iBuffer[1], m_iFakeDepthBufferID);
  Coordinates::UpdatePhysicalSize();  

  SM_D3d::SetRenderState(D3DRS_COLORWRITEENABLE, 0xF);          
  SM_D3d::SetRenderState(D3DRS_FOGENABLE, FALSE);  
  SM_D3d::SetRenderState(D3DRS_SPECULARENABLE , FALSE);
  SM_D3d::SetRenderState(D3DRS_LOCALVIEWER , FALSE);
  SM_D3d::SetRenderState(D3DRS_LIGHTING, FALSE);    
  SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);                        
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU); 
  SM_D3d::SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );           
  SM_D3d::SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP , D3DTOP_MODULATE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  SM_D3d::SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);  
  SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  SM_D3d::SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE );    
  SM_D3d::Device()->SetVertexShader(FVF_POSRHWDIFFUSETEX1);
  

  #define ANOTHERPI 3.1415926535897932384626433832795
  #define FACTOR (1.0/*+0.05*sinf(Timer::GetTime())*0.02*/)
  
  /*
  pVertices[0].x=FACTOR*float(Coordinates::PhysicalWidth()/2.0f)*cosf(fTime)+Coordinates::PhysicalWidth()/2.0f;
  pVertices[0].y=FACTOR*float(Coordinates::PhysicalHeight()/2.0f)*cosf(fTime)+Coordinates::PhysicalHeight()/2.0f;

  pVertices[1].x=FACTOR*float(Coordinates::PhysicalWidth()/2.0f)*sinf(fTime+ANOTHERPI/2)+Coordinates::PhysicalWidth()/2.0f;
  pVertices[1].y=FACTOR*float(Coordinates::PhysicalHeight()/2.0f)*cosf(fTime+ANOTHERPI/2)+Coordinates::PhysicalHeight()/2.0f;

  pVertices[2].x=FACTOR*float(Coordinates::PhysicalWidth()/2.0f)*sinf(fTime+ANOTHERPI)+Coordinates::PhysicalWidth()/2.0f;
  pVertices[2].y=FACTOR*float(Coordinates::PhysicalHeight()/2.0f)*cosf(fTime+ANOTHERPI)+Coordinates::PhysicalHeight()/2.0f;

  pVertices[3].x=FACTOR*float(Coordinates::PhysicalWidth()/2.0f)*sinf(fTime+3.0*ANOTHERPI/2.0)+Coordinates::PhysicalWidth()/2.0f;
  pVertices[3].y=FACTOR*float(Coordinates::PhysicalHeight()/2.0f)*cosf(fTime+3.0*ANOTHERPI/2.0)+Coordinates::PhysicalHeight()/2.0f;
  */
  pVertices[0].x=Coordinates::PhysicalWidth()/2.0f-FACTOR*float(Coordinates::PhysicalWidth()/2.0f);
  pVertices[0].y=Coordinates::PhysicalHeight()/2.0f-FACTOR*float(Coordinates::PhysicalHeight()/2.0f);

  pVertices[1].x=Coordinates::PhysicalWidth()/2.0f+FACTOR*float(Coordinates::PhysicalWidth()/2.0f);
  pVertices[1].y=Coordinates::PhysicalHeight()/2.0f-FACTOR*float(Coordinates::PhysicalHeight()/2.0f);

  pVertices[2].x=Coordinates::PhysicalWidth()/2.0f+FACTOR*float(Coordinates::PhysicalWidth()/2.0f);
  pVertices[2].y=Coordinates::PhysicalHeight()/2.0f+FACTOR*float(Coordinates::PhysicalHeight()/2.0f);

  pVertices[3].x=Coordinates::PhysicalWidth()/2.0f-FACTOR*float(Coordinates::PhysicalWidth()/2.0f);
  pVertices[3].y=Coordinates::PhysicalHeight()/2.0f+FACTOR*float(Coordinates::PhysicalHeight()/2.0f);  

  SM_D3d::Device()->DrawIndexedPrimitiveUP(
      D3DPT_TRIANGLELIST, 
      0,
      6,
      2,
      pIndices,
      D3DFMT_INDEX16,
      pVertices, sizeof(FVF_PosRhwDiffuseTex1));
  
  ResourceManager::RestoreRenderTarget();

  


  // Do blur
  ResourceManager::SetRenderTarget(iBuffer[1], m_iFakeDepthBufferID);
  SM_D3d::Device()->SetTexture(0, pTexture);    
  Coordinates::UpdatePhysicalSize();  

  if (bFirst)
  {
    bFirst=false;

    if (g_SceneFilter)
    {
      SM_D3d::Device()->Clear(0, NULL, D3DCLEAR_TARGET , GetBackColor(), 1.0f, 0 );
    }
    else
    {
    #ifdef _DEBUG
    SM_D3d::Device()->Clear(0, NULL, D3DCLEAR_TARGET , D3DCOLOR_XRGB(0,int(128+127.0f*sinf(Timer::GetTime())),0), 1.0f, 0 );
    #else
    SM_D3d::Device()->Clear(0, NULL, D3DCLEAR_TARGET , D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
    #endif
    }
  }
  

  float fOffset;
  if (!m_MotionBlurSlider.GetValue(Timer::GetTime(), &fOffset) && !m_bMotionBlurFadeIn)
  {
    m_bMotionBlur=false;
  }

  float fBlurValue;
  if (m_bMotionBlurFadeIn)
  {
    fBlurValue=1.0f+fOffset*(m_fMotionBlurFactor-1.0f);
  }
  else
  {
    fBlurValue=m_fMotionBlurFactor+fOffset*(1.0f-m_fMotionBlurFactor);
  }
    
  //fBlurValue=0.05;
  SM_D3d::Device()->SetTexture(0, pTexture);    


  
  //float fScale  =1.0f+0.0f*sinf(fTime);

  

  SM_D3d::SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);    
  SM_D3d::Device()->SetVertexShader(FVF_POSRHWDIFFUSETEX1);
  SM_D3d::SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);  
  SM_D3d::SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);  
  SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
  SM_D3d::SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE );    
  

  SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);                        
  SM_D3d::SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  SM_D3d::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);  
    

  SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP   , D3DTOP_MODULATE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1 , D3DTA_TEXTURE );
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG2 , D3DTA_DIFFUSE );

  SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAOP   , D3DTOP_SELECTARG1);
  SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAARG1 , D3DTA_TFACTOR );

  unsigned uFactor=int(fBlurValue*255.0f)<<24;
  SM_D3d::SetRenderState(D3DRS_TEXTUREFACTOR, uFactor);
  

  pVertices[0].x=-0.5f  ; pVertices[0].y=-0.5f  ; pVertices[0].z=1.0f; pVertices[0].u=0.0f; pVertices[0].v=0; pVertices[0].oow=1.0f; pVertices[0].diffuse=0xFFFFFFFF;
  pVertices[1].x=(float)Coordinates::PhysicalWidth()-0.5f; pVertices[1].y=-0.5f  ; pVertices[1].z=1.0f; pVertices[1].u=fScaleU; pVertices[1].v=0; pVertices[1].oow=1.0f; pVertices[1].diffuse=0x00FFFFFF;
  pVertices[2].x=(float)Coordinates::PhysicalWidth()-0.5f; pVertices[2].y=(float)Coordinates::PhysicalHeight()-0.5f; pVertices[2].z=1.0f; pVertices[2].u=fScaleU; pVertices[2].v=fScaleV; pVertices[2].oow=1.0f; pVertices[2].diffuse=0xFFFFFFFF;
  pVertices[3].x=-0.5f  ; pVertices[3].y=(float)Coordinates::PhysicalHeight()-0.5f; pVertices[3].z=1.0f; pVertices[3].u=0.0f; pVertices[3].v=fScaleV; pVertices[3].oow=1.0f; pVertices[3].diffuse=0x00FFFFFF;


  SM_D3d::Device()->DrawIndexedPrimitiveUP(
      D3DPT_TRIANGLELIST, 
      0,
      6,
      2,
      pIndices,
      D3DFMT_INDEX16,
      pVertices, sizeof(FVF_PosRhwDiffuseTex1));

  ResourceManager::RestoreRenderTarget();
  Coordinates::UpdatePhysicalSize();

  pVertices[0].x=0  ; pVertices[0].y=0-0.5f  ; pVertices[0].z=1.0f; pVertices[0].u=0.0f; pVertices[0].v=0; pVertices[0].oow=1.0f; pVertices[0].diffuse=0xFFFFFFFF;
  pVertices[1].x=(float)Coordinates::PhysicalWidth()-0.5f; pVertices[1].y=0-0.5f  ; pVertices[1].z=1.0f; pVertices[1].u=fScaleU; pVertices[1].v=0; pVertices[1].oow=1.0f; pVertices[1].diffuse=0x00FFFFFF;
  pVertices[2].x=(float)Coordinates::PhysicalWidth()-0.5f; pVertices[2].y=(float)Coordinates::PhysicalHeight()-0.5f; pVertices[2].z=1.0f; pVertices[2].u=fScaleU; pVertices[2].v=fScaleV; pVertices[2].oow=1.0f; pVertices[2].diffuse=0xFFFFFFFF;
  pVertices[3].x=0-0.5f  ; pVertices[3].y=(float)Coordinates::PhysicalHeight()-0.5f; pVertices[3].z=1.0f; pVertices[3].u=0.0f; pVertices[3].v=fScaleV; pVertices[3].oow=1.0f; pVertices[3].diffuse=0x00FFFFFF;


  SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(iBuffer[1]));    
  SM_D3d::Device()->DrawIndexedPrimitiveUP(
      D3DPT_TRIANGLELIST, 
      0,
      6,
      2,
      pIndices,
      D3DFMT_INDEX16,
      pVertices, sizeof(FVF_PosRhwDiffuseTex1));


}

void FilterFX::RenderUnderwater(float fTime, float fAmplitude)
{     
  // Material
  D3DMATERIAL8 Material;
  Material.Diffuse.r=Material.Diffuse.g=Material.Diffuse.b=Material.Diffuse.a=1.0f;
  Material.Ambient.r=Material.Ambient.g=Material.Ambient.b=Material.Ambient.a=1.0f;
  Material.Specular.r=Material.Specular.g=Material.Specular.b=Material.Specular.a=1.0f;
  Material.Emissive.r=Material.Emissive.g=Material.Emissive.b=Material.Emissive.a=0.0f;
  Material.Power=0.0f;
  SM_D3d::Device()->SetMaterial(&Material);


  // Render
  float fBias=0.0f;
  SM_D3d::SetTextureStageState(0, D3DTSS_MIPMAPLODBIAS, *((LPDWORD) (&fBias)));  
  SM_D3d::SetRenderState(D3DRS_COLORWRITEENABLE, 0xF);          
  SM_D3d::SetRenderState(D3DRS_FOGENABLE, FALSE);  
  SM_D3d::SetRenderState(D3DRS_SPECULARENABLE , FALSE);
  SM_D3d::SetRenderState(D3DRS_LOCALVIEWER , FALSE);
  SM_D3d::SetRenderState(D3DRS_LIGHTING, FALSE);    
  SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);                        
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU); 
  SM_D3d::SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );           
  SM_D3d::SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP , D3DTOP_MODULATE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  SM_D3d::SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);  
  SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  SM_D3d::Device()->SetVertexShader(FVF_POSNORMALDIFFUSETEX1);                              
  SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(m_iFakeBufferID));    

  // Matrix
  Matrix4X4 m;

  float fWidth =Coordinates::PhysicalWidth();
  float fHeight=Coordinates::PhysicalHeight();
  

  float w =4.0f /fWidth;
  float h =-4.0f/fHeight;
  float dw=-2.0f;
  float dh=2.0f;

  float fFar =2.0f;
  float fNear=0.001f;

  float Q =fFar/(fFar-fNear);

  m.m_11=w             ; m.m_12=0.0f; m.m_13=0.0f         ; m.m_14=0.0f;
  m.m_21=0.0f          ; m.m_22=h   ; m.m_23=0.0f         ; m.m_24=0.0f;
  m.m_31=0.0f          ; m.m_32=0.0f; m.m_33=Q            ; m.m_34=1.0f;
  m.m_41=dw            ; m.m_42=dh  ; m.m_43=-Q*fNear     ; m.m_44=1.0f;

  SM_D3d::Device()->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&Matrix4X4::Identity);    
  SM_D3d::Device()->SetTransform(D3DTS_WORLD, (D3DMATRIX*) &Matrix4X4::Identity);      
  SM_D3d::Device()->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)&m);  
  


  // Primitive
  FVF_PosNormalDiffuseTex1 Vertices  [LENSTILESX*LENSTILESY];
  unsigned short        pIndices  [(LENSTILESX-1)*(LENSTILESY-1)*6];

  


  FVF_PosNormalDiffuseTex1* pV=Vertices;


  float dx=fWidth/(LENSTILESX-1);;
  float dy=fHeight/(LENSTILESY-1);
  float du=1.0f/(LENSTILESX-1);
  float dv=1.0f/(LENSTILESY-1);
  int i,j;


  float v=0.0f;
  float y=0.0f;
  
        
  for (j=0 ; j<LENSTILESY ; j++)
  {    
    float u=0.0f;
    float x=0.0f;
    for (i=0 ; i<LENSTILESX ; i++)
    {
      pV[0].x=x-0.5f; pV[0].y=y-0.5f;       
      pV[0].z=1.0f;       

      if (i==0 || i==LENSTILESX-1)
      {
        pV[0].u=u;
      }
      else
      {
        pV[0].u=u+fAmplitude*sinf(fTime+float(j*i)/8.0f);
      }

      if (j==0 || j==LENSTILESY-1)
      {
        pV[0].v=v;
      }
      else
      {
        pV[0].v=v+fAmplitude*cosf(fTime+float(j*i)/5.0f);
      }
      
      
      pV[0].diffuse=0xFFFFFFFF;    
      pV[0].nx=pV[0].ny=pV[0].nz=0.0f;
      pV++;
      u+=du;
      x+=dx;
    }    

    v+=dv;
    y+=dy;
  }

  unsigned uOffset=0;
  for (j=0 ; j<LENSTILESY-1 ; j++)
  {
    for (i=0 ; i<LENSTILESX-1 ; i++)
    {
      pIndices[uOffset++]= i   +(j  )*LENSTILESX;
      pIndices[uOffset++]=(i  )+(j+1)*LENSTILESX;
      pIndices[uOffset++]=(i+1)+(j  )*LENSTILESX;
      pIndices[uOffset++]=(i+1)+(j  )*LENSTILESX;
      pIndices[uOffset++]=(i  )+(j+1)*LENSTILESX;
      pIndices[uOffset++]=(i+1)+(j+1)*LENSTILESX;
      
    }
  }  
 
  SM_D3d::Device()->DrawIndexedPrimitiveUP(
      D3DPT_TRIANGLELIST, 
      0,
      LENSTILESX*LENSTILESY,
      (LENSTILESX-1)*(LENSTILESY-1)*2,
      pIndices,
      D3DFMT_INDEX16,
      Vertices, sizeof(FVF_PosNormalDiffuseTex1));
}


void PaintFade(unsigned uColor)
{
  FVF_PosRhwDiffuseTex1 pVertices[4];
  unsigned short        pIndices[6]={0,1,2,1,2,3};


  pVertices[0].x=0.0f  ; pVertices[0].y=0.0f; pVertices[0].oow=pVertices[0].z=1.0f; pVertices[0].u=pVertices[0].v=0.0f; pVertices[0].diffuse=0xFFFFFFFF;
  pVertices[1].x=Coordinates::PhysicalWidth(); pVertices[1].y=0.0f; pVertices[1].oow=pVertices[1].z=1.0f; pVertices[1].u=pVertices[1].v=0.0f; pVertices[1].diffuse=0xFFFFFFFF;
  pVertices[2].x=0.0f; pVertices[2].y=Coordinates::PhysicalHeight(); pVertices[2].oow=pVertices[2].z=1.0f; pVertices[2].u=pVertices[2].v=0.0f; pVertices[2].diffuse=0xFFFFFFFF;
  pVertices[3].x=Coordinates::PhysicalWidth(); pVertices[3].y=Coordinates::PhysicalHeight(); pVertices[3].oow=pVertices[3].z=1.0f; pVertices[3].u=pVertices[3].v=0.0f; pVertices[3].diffuse=0xFFFFFFFF;


  SM_D3d::SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);  
  SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  SM_D3d::SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
  SM_D3d::SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  SM_D3d::SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_FALSE);
  SM_D3d::SetRenderState(D3DRS_COLORWRITEENABLE, 0xF);          
  SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP   , D3DTOP_SELECTARG1);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1 , D3DTA_TFACTOR);
  SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAOP   , D3DTOP_SELECTARG1);
  SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAARG1 , D3DTA_TFACTOR);
  SM_D3d::SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  SM_D3d::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  SM_D3d::SetRenderState(D3DRS_TEXTUREFACTOR, uColor);


  SM_D3d::SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE );    
  SM_D3d::Device()->SetVertexShader(FVF_POSRHWDIFFUSETEX1);


  SM_D3d::Device()->DrawIndexedPrimitiveUP(
      D3DPT_TRIANGLELIST, 
      0,
      6,
      2,
      pIndices,
      D3DFMT_INDEX16,
      pVertices, sizeof(FVF_PosRhwDiffuseTex1)); 


  SM_D3d::SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
  SM_D3d::SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
  SM_D3d::SetRenderState(D3DRS_COLORWRITEENABLE, 0xF);          
}

void FilterFX::GenerateMips()
{ 
  SM_D3d::SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  SM_D3d::SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  SM_D3d::SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);  
  SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
  SM_D3d::Device()->SetVertexShader(FVF_POSRHWDIFFUSETEX1);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);  
  
  SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP   , D3DTOP_MODULATE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1 , D3DTA_TEXTURE );
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG2 , D3DTA_DIFFUSE );

  SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAOP   , D3DTOP_SELECTARG1);
  SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAARG1 , D3DTA_DIFFUSE );

  SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);                        


  FVF_PosRhwDiffuseTex1 pVertices[4];
  unsigned short        pIndices[6]={0,2,1,0,3,2};

  pVertices[0].x=0.0f-0.5f ; pVertices[0].y=0.0f-0.5f; pVertices[0].z=0.0f; pVertices[0].u=0.0f; pVertices[0].v=0.0f; pVertices[0].oow=1.0f; pVertices[0].diffuse=0xFFFFFFFF;
  pVertices[1].x=0.0f-0.5f ; pVertices[1].y=0.0f-0.5f; pVertices[1].z=0.0f; pVertices[1].u=1.0f; pVertices[1].v=0.0f; pVertices[1].oow=1.0f; pVertices[1].diffuse=0x00FFFFFF;
  pVertices[2].x=0.0f-0.5f ; pVertices[2].y=0.0f-0.5f; pVertices[2].z=0.0f; pVertices[2].u=1.0f; pVertices[2].v=1.0f; pVertices[2].oow=1.0f; pVertices[2].diffuse=0xFFFFFFFF;
  pVertices[3].x=0.0f-0.5f ; pVertices[3].y=0.0f-0.5f; pVertices[3].z=0.0f; pVertices[3].u=0.0f; pVertices[3].v=1.0f; pVertices[3].oow=1.0f; pVertices[3].diffuse=0x00FFFFFF;
  

  // Render to highest mip
  SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(m_iFakeBufferID));

  IDirect3DSurface8* pMip;
  D3DSURFACE_DESC dd;
    
  ResourceManager::GetTextureFromID(g_HWMipMap.m_piMips[0])->GetSurfaceLevel(0, &pMip);
  pMip->GetDesc(&dd);

  pVertices[1].x=dd.Width-0.5f;
  pVertices[2].x=dd.Width-0.5f;
  pVertices[2].y=dd.Height-0.5f;
  pVertices[3].y=dd.Height-0.5f;

  SM_D3d::Device()->SetRenderTarget(pMip, 0);
  
  SM_D3d::Device()->DrawIndexedPrimitiveUP(
        D3DPT_TRIANGLELIST, 
        0,
        6,
        2,
        pIndices,
        D3DFMT_INDEX16,
        pVertices, sizeof(FVF_PosRhwDiffuseTex1));

  pMip->Release();
  
  // Render fake mip map chain
  unsigned i;
  for (i = 1 ; i < g_HWMipMap.m_uMips ; i++)
  {
    ResourceManager::GetTextureFromID(g_HWMipMap.m_piMips[i])->GetSurfaceLevel(0, &pMip);
    pMip->GetDesc(&dd);

    pVertices[1].x=dd.Width-0.5f;
    pVertices[2].x=dd.Width-0.5f;
    pVertices[2].y=dd.Height-0.5f;
    pVertices[3].y=dd.Height-0.5f;

    SM_D3d::Device()->SetRenderTarget(pMip, 0);    
    SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(g_HWMipMap.m_piMips[i-1]));

    SM_D3d::Device()->DrawIndexedPrimitiveUP(
        D3DPT_TRIANGLELIST, 
        0,
        6,
        2,
        pIndices,
        D3DFMT_INDEX16,
        pVertices, sizeof(FVF_PosRhwDiffuseTex1));

    pMip->Release();  
  }

  /*
  LPDIRECT3DTEXTURE8 pTexture;
  HRESULT            hres;


  SM_D3d::SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  SM_D3d::SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  SM_D3d::SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);  
  SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
  SM_D3d::Device()->SetVertexShader(FVF_POSRHWDIFFUSETEX1);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);  
  
  SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP   , D3DTOP_MODULATE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1 , D3DTA_TEXTURE );
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG2 , D3DTA_DIFFUSE );

  SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAOP   , D3DTOP_SELECTARG1);
  SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAARG1 , D3DTA_DIFFUSE );

  SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);                        


  FVF_PosRhwDiffuseTex1 pVertices[4];
  unsigned short        pIndices[6]={0,2,1,0,3,2};

  pVertices[0].x=0.0f-0.5f ; pVertices[0].y=0.0f-0.5f; pVertices[0].z=0.0f; pVertices[0].u=0.0f; pVertices[0].v=0.0f; pVertices[0].oow=1.0f; pVertices[0].diffuse=0xFFFFFFFF;
  pVertices[1].x=0.0f-0.5f ; pVertices[1].y=0.0f-0.5f; pVertices[1].z=0.0f; pVertices[1].u=1.0f; pVertices[1].v=0.0f; pVertices[1].oow=1.0f; pVertices[1].diffuse=0x00FFFFFF;
  pVertices[2].x=0.0f-0.5f ; pVertices[2].y=0.0f-0.5f; pVertices[2].z=0.0f; pVertices[2].u=1.0f; pVertices[2].v=1.0f; pVertices[2].oow=1.0f; pVertices[2].diffuse=0xFFFFFFFF;
  pVertices[3].x=0.0f-0.5f ; pVertices[3].y=0.0f-0.5f; pVertices[3].z=0.0f; pVertices[3].u=0.0f; pVertices[3].v=1.0f; pVertices[3].oow=1.0f; pVertices[3].diffuse=0x00FFFFFF;
  
  unsigned i;  
  pTexture=ResourceManager::GetTextureFromID(m_iFakeBufferID);  
  unsigned uLevels=pTexture->GetLevelCount();
  hres=SM_D3d::Device()->SetTexture(0, pTexture);    
  
  SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(14)  );
    
  IDirect3DSurface8* ppZStencilSurface;
  SM_D3d::Device()->GetDepthStencilSurface(&ppZStencilSurface); 
    
  for (i=1 ; i<uLevels ; i++)
  {
    IDirect3DSurface8* pMip;
    pTexture->GetSurfaceLevel(i, &pMip);

    hres=SM_D3d::Device()->SetRenderTarget(pMip, 0);        
    //hres=SM_D3d::SetTextureStageState(0, D3DTSS_MAXMIPLEVEL, i-1);
       
    D3DSURFACE_DESC dd;
    pMip->GetDesc(&dd);

    pVertices[1].x=dd.Width-0.5f;
    pVertices[2].x=dd.Width-0.5f;
    pVertices[2].y=dd.Height-0.5f;
    pVertices[3].y=dd.Height-0.5f;

    SM_D3d::Device()->DrawIndexedPrimitiveUP(
        D3DPT_TRIANGLELIST, 
        0,
        6,
        2,
        pIndices,
        D3DFMT_INDEX16,
        pVertices, sizeof(FVF_PosRhwDiffuseTex1));
    
    pMip->Release();
  }

  ppZStencilSurface->Release();

  SM_D3d::SetTextureStageState(0, D3DTSS_MAXMIPLEVEL, 0); 
  */
}

void FilterFX::RunPostRender     (float fTime)
{
  SM_D3d::SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
  

  if (m_bRadialBlur)
  {
    float fScale;
    if (!m_RadialBlurSlider.GetValue(fTime, &fScale) && !m_bRadialBlurFadeIn)
    {
      m_bRadialBlur=false;
    }

    RenderRadialBlur(0, 0, m_fRadialBlurStrength*(m_bRadialBlurFadeIn?fScale:1.0f-fScale));    
  }
  
  if (m_bHorizontalNoise)
  {
    ResourceManager::RestoreRenderTarget();

    if (!m_HorizontalNoiseSlider.GetValue(fTime, &fTime))
    {
      m_bHorizontalNoise=false;
    }

    RenderHorizontalNoise((1.0f-fTime)*m_fHorizontalAmplitude);
  }
  else if (m_bWobble)
  {
    

    RenderWobble(fTime);
  }
  else if (m_bTransition)
  {
  }
  /*
  else if (m_bQualityBlur)
  {
    ResourceManager::RestoreRenderTarget();

    RenderQualityBlur();
  }*/
  else if (m_bComponent)
  {
    ResourceManager::RestoreRenderTarget();

    RenderComponent();
  }
  else if (m_bUnderwater)
  {
    ResourceManager::RestoreRenderTarget();
    
    float fOffset;
    if (!m_UnderwaterSlider.GetValue(fTime, &fOffset) && m_UnderwaterSlider.m_fLength)
    {
      m_bUnderwater=false;
    }

    RenderUnderwater(      
        fTime*m_fUnderwaterFrecuency,
        m_fUnderwaterAmplitude*1.0f*(m_bLensFadeIn?(1.0f-fOffset):(fOffset)));    
    /*double pi = 3.1415926535897932384626433832795;
    RenderPlasma(fTime, sinf((pi/2.0f)*(1.0f-fOffset)));*/
  }
  else if (m_bLens)
  {
    ResourceManager::RestoreRenderTarget();


    float fOffset;
    if (!m_LensSlider.GetValue(fTime, &fOffset) )
    {
      m_bLens=false;
    }

    RenderLens(
      (m_bLensFadeIn?sinf(fOffset*m_fLensFrequency):cosf(fOffset*m_fLensFrequency))*
        m_fLensStrength*(m_bLensFadeIn?(1.0f-fOffset):(fOffset)));
  }
  else
  if (m_bInterceptRender)
  {

    if (m_bBlur)
    {
      GenerateMips();      
    }

    ResourceManager::RestoreRenderTarget();
    
    FVF_PosRhwDiffuseTex1 pVertices[4];
    unsigned short        pIndices[6]={0,2,1,0,3,2};


    SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(m_iFakeBufferID));    
     
    float fScaleU=1.0f;
    float fScaleV=1.0f;    

    float fWidth =Coordinates::PhysicalWidth();
    float fHeight=Coordinates::PhysicalHeight();

    
    float fScale  =1.0f+0.0f*sinf(fTime);

    pVertices[0].x=0.0f  ; pVertices[0].y=0.0f   ; pVertices[0].z=0.0f; pVertices[0].u=0.0f; pVertices[0].v=0.0f; pVertices[0].oow=1.0f; pVertices[0].diffuse=0xFFFF0000;
    pVertices[1].x=fWidth; pVertices[1].y=0.0f   ; pVertices[1].z=0.0f; pVertices[1].u=fScaleU; pVertices[1].v=0.0f; pVertices[1].oow=1.0f; pVertices[1].diffuse=0x00FFFFFF;
    pVertices[2].x=fWidth; pVertices[2].y=fHeight; pVertices[2].z=0.0f; pVertices[2].u=fScaleU; pVertices[2].v=fScaleV; pVertices[2].oow=1.0f; pVertices[2].diffuse=0xFFFFFFFF;
    pVertices[3].x=0.0f  ; pVertices[3].y=fHeight; pVertices[3].z=0.0f; pVertices[3].u=0.0f; pVertices[3].v=fScaleV; pVertices[3].oow=1.0f; pVertices[3].diffuse=0xFF0000FF;

    SM_D3d::Device()->SetVertexShader(FVF_POSRHWDIFFUSETEX1);
    SM_D3d::SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);  
    SM_D3d::SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);  
    SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
    SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
    SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);  
    SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);                        


    float fMip=-1.0f;

    if (m_bBlur)
    {
      if (m_bBlurFadeIn && m_BlurSlider.m_fLength == 0.0f)
      {
        fMip+=m_fBlurStrength*((float)LOGSIZEWIDTH);
      }
      else
      {
        float fBlur;
        if (!m_BlurSlider.GetValue(fTime, &fBlur))
        {
          m_bBlur=false;
        }
        fMip+=(m_bBlurFadeIn?(m_fBlurStrength-m_fBlurStrength*fBlur):m_fBlurStrength*fBlur)*((float)(g_HWMipMap.m_uMips-1));
      }       


      int iMip = min(int(fMip), g_HWMipMap.m_uMips-1);

      unsigned uBlend = int(255.0f*(fMip - float(iMip))) << 24;

      if (iMip == g_HWMipMap.m_uMips-1)
      {
        iMip = g_HWMipMap.m_uMips-2;
        uBlend = 0;
      }
            
      SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);    
      SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP   , D3DTOP_SELECTARG1);
      SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1 , D3DTA_TEXTURE );

      SM_D3d::SetTextureStageState(1, D3DTSS_COLOROP   , D3DTOP_BLENDFACTORALPHA);
      SM_D3d::SetTextureStageState(1, D3DTSS_COLORARG1 , D3DTA_CURRENT );
      SM_D3d::SetTextureStageState(1, D3DTSS_COLORARG2 , D3DTA_TEXTURE );

      SM_D3d::SetRenderState(D3DRS_TEXTUREFACTOR, uBlend);
            
      SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(g_HWMipMap.m_piMips[iMip+1]));
      SM_D3d::Device()->SetTexture(1, ResourceManager::GetTextureFromID(g_HWMipMap.m_piMips[iMip]));

      SM_D3d::Device()->DrawIndexedPrimitiveUP(
        D3DPT_TRIANGLELIST, 
        0,
        6,
        2,
        pIndices,
        D3DFMT_INDEX16,
        pVertices, sizeof(FVF_PosRhwDiffuseTex1));

      SM_D3d::SetTextureStageState(1, D3DTSS_COLOROP   , D3DTOP_DISABLE);           
      
    }
    else
    {
      SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);          

      SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP   , D3DTOP_SELECTARG1);
      SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1 , D3DTA_TEXTURE );
      SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG2 , D3DTA_TEXTURE );
  
      SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAOP   , D3DTOP_SELECTARG1);
      SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAARG1 , D3DTA_DIFFUSE );

      SM_D3d::Device()->DrawIndexedPrimitiveUP(
        D3DPT_TRIANGLELIST, 
        0,
        6,
        2,
        pIndices,
        D3DFMT_INDEX16,
        pVertices, sizeof(FVF_PosRhwDiffuseTex1));
    }
    
    
    

    
  }  


  bool bPaint=false;
  bool bSecondaryPaint=false;
  unsigned uColor = 0xFFFFFFFF;
  unsigned uSecondaryColor = 0xFFFFFFFF;

  if (m_bFadeIn || m_bFadeOut)
  {
    
    float fFade=min(1.0f, (fTime-m_fStartTime)/m_fDuration);
    if (fFade>=1.0f)
    {
      m_bFadeIn=false;
      m_bFadeOut=false;
    }
    else
    {
      bPaint=true;

      float a=m_bFadeIn?(1.0f-fFade):fFade;
      a*=m_fFadeLimit;

      uColor=(int(255.0f*a   )<<24) |
             (int(255.0f*m_fr)<<16) |
             (int(255.0f*m_fg)<< 8) |
             (int(255.0f*m_fb)<< 0);

    }        
  }

  if (m_bSecondaryFadeIn || m_bSecondaryFadeOut)
  {
    
    float fFade=min(1.0f, (fTime-m_fSecondaryStartTime)/m_fSecondaryDuration);
    if (fFade>=1.0f)
    {
      m_bSecondaryFadeIn=false;
      m_bSecondaryFadeOut=false;
    }
    else
    {
      bSecondaryPaint=true;

      float a=m_bSecondaryFadeIn?(1.0f-fFade):fFade;
      a*=m_fSecondaryFadeLimit;

      uSecondaryColor=(int(255.0f*a   )<<24) |
             (int(255.0f*m_fSecondaryr)<<16) |
             (int(255.0f*m_fSecondaryg)<< 8) |
             (int(255.0f*m_fSecondaryb)<< 0);

    }        
  }

  if (bPaint)
  {
    PaintFade(uColor);   
  }

  if (bSecondaryPaint)
  {
    PaintFade(uSecondaryColor);    
  }

  RenderMDMABackground(fTime); 
}

void FilterFX::RunPostEndFrame   (float fTime)
{
}

unsigned  FilterFX::GetBackColor()
{
  return m_uBackGround;
}

void FilterFX::RenderPlasma(float fTime, float fLerp)
{
  float fAmplitude = 1.0f;
  // Material
  D3DMATERIAL8 Material;
  Material.Diffuse.r=Material.Diffuse.g=Material.Diffuse.b=Material.Diffuse.a=1.0f;
  Material.Ambient.r=Material.Ambient.g=Material.Ambient.b=Material.Ambient.a=1.0f;
  Material.Specular.r=Material.Specular.g=Material.Specular.b=Material.Specular.a=1.0f;
  Material.Emissive.r=Material.Emissive.g=Material.Emissive.b=Material.Emissive.a=0.0f;
  Material.Power=0.0f;
  SM_D3d::Device()->SetMaterial(&Material);


  // Render
  float fBias=0.0f;
  SM_D3d::SetTextureStageState(0, D3DTSS_MIPMAPLODBIAS, *((LPDWORD) (&fBias)));  
  SM_D3d::SetRenderState(D3DRS_COLORWRITEENABLE, 0xF);          
  SM_D3d::SetRenderState(D3DRS_FOGENABLE, FALSE);  
  SM_D3d::SetRenderState(D3DRS_SPECULARENABLE , FALSE);
  SM_D3d::SetRenderState(D3DRS_LOCALVIEWER , FALSE);
  SM_D3d::SetRenderState(D3DRS_LIGHTING, FALSE);    
  SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);                        
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU); 
  SM_D3d::SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );           
  SM_D3d::SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP , D3DTOP_MODULATE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  SM_D3d::SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  SM_D3d::SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);  
  SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  SM_D3d::Device()->SetVertexShader(FVF_POSNORMALDIFFUSETEX1);                              
  SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(m_iFakeBufferID));    

  // Matrix
  Matrix4X4 m;

  float fWidth =Coordinates::PhysicalWidth();
  float fHeight=Coordinates::PhysicalHeight();
  

  float w =4.0f /fWidth;
  float h =-4.0f/fHeight;
  float dw=-2.0f;
  float dh=2.0f;

  float fFar =2.0f;
  float fNear=0.001f;

  float Q =fFar/(fFar-fNear);

  m.m_11=w             ; m.m_12=0.0f; m.m_13=0.0f         ; m.m_14=0.0f;
  m.m_21=0.0f          ; m.m_22=h   ; m.m_23=0.0f         ; m.m_24=0.0f;
  m.m_31=0.0f          ; m.m_32=0.0f; m.m_33=Q            ; m.m_34=1.0f;
  m.m_41=dw            ; m.m_42=dh  ; m.m_43=-Q*fNear     ; m.m_44=1.0f;

  SM_D3d::Device()->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&Matrix4X4::Identity);    
  SM_D3d::Device()->SetTransform(D3DTS_WORLD, (D3DMATRIX*) &Matrix4X4::Identity);      
  SM_D3d::Device()->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)&m);  
  


  // Primitive
  FVF_PosNormalDiffuseTex1 Vertices  [LENSTILESX*LENSTILESY];
  unsigned short        pIndices  [(LENSTILESX-1)*(LENSTILESY-1)*6];

  


  FVF_PosNormalDiffuseTex1* pV=Vertices;

  float f11, f12,
        f21, f22;

  f11=-float(cos(fTime));
  f21=-float(sin(fTime));
  f12=float(sin(fTime));
  f22=-float(cos(fTime));

  float a_dudx[LENSTILESX];
  float a_dvdx[LENSTILESX];
  float a_dudy[LENSTILESY];
  float a_dvdy[LENSTILESY];

  int i,j;

  
  float baseu=fLerp*(0.2f*(cosf(fTime)+0.1f*sinf(fTime*2.0f)));
  float basev=fLerp*(0.4f*(sinf(fTime*1.37f)+0.1f*cosf(fTime*4.0f)));
  
  float dx=fWidth/(LENSTILESX-1);;
  float dy=fHeight/(LENSTILESY-1);
  float du=1.0f/(LENSTILESX-1);
  float dv=1.0f/(LENSTILESY-1);

  
  for (i=0 ; i<LENSTILESX ; i++)
  {
    float a,b,c,d;
    
    a=1.5f+sinf(fTime*2.0f+float(i)/3.1416f)/3.0f;
    b=1.5f+cosf(fTime*1.0f+float(i)/4.1416f)/2.0f;
    c=1.25f+cosf(fTime*2.0f+float(i)/4.1416f)/3.0f;
    d=-(1.5f+sinf(fTime*1.0f+float(i)/5.1416f)/3.0f);      




    a_dudx[i]=0.1f*(a*f11+b*f21)*fLerp + (1.0f-fLerp)*du;
    a_dvdx[i]=0.1f*(a*f12+b*f22)*fLerp;    
  }

  for (i=0 ; i<LENSTILESY ; i++)
  {
    float a,b,c,d;
    
    a=0.5f+sinf(fTime*2.0f+float(i)/3.1416f)/3.0f;
    b=0.5f+cosf(fTime*1.0f+float(i)/4.1416f)/2.0f;
    c=0.25f+cosf(fTime*2.0f+float(i)/4.1416f)/3.0f;
    d=-(0.5f+sinf(fTime*1.0f+float(i)/5.1416f)/3.0f);      

    a_dudy[i]=0.1f*(c*f11+d*f21)*fLerp;
    a_dvdy[i]=0.1f*(c*f12+d*f22)*fLerp+ (1.0f-fLerp)*dv;;
  }
  


  

  float v=0.0f;
  float y=0.0f;
  
        
  for (j=0 ; j<LENSTILESY ; j++)
  {    
    float u=0.0f;
    float x=0.0f;

    float tu = baseu;
    float tv = basev;
      
    for (i=0 ; i<LENSTILESX ; i++)
    {
      pV[0].x=x-0.5f; pV[0].y=y-0.5f;       
      pV[0].z=1.0f;       
      pV[0].diffuse=0xFFFFFFFF;    
      pV[0].nx=pV[0].ny=pV[0].nz=0.0f;
      
      pV[0].u= tu;
      pV[0].v= tv;

      pV++;

      tu += a_dudx[i];
      tv += a_dvdx[i];
      
      x += dx;    
    } 
    
    baseu += a_dudy[j];
    basev += a_dvdy[j];
    y+=dy;
  }

  unsigned uOffset=0;
  for (j=0 ; j<LENSTILESY-1 ; j++)
  {
    for (i=0 ; i<LENSTILESX-1 ; i++)
    {
      pIndices[uOffset++]= i   +(j  )*LENSTILESX;
      pIndices[uOffset++]=(i  )+(j+1)*LENSTILESX;
      pIndices[uOffset++]=(i+1)+(j  )*LENSTILESX;
      pIndices[uOffset++]=(i+1)+(j  )*LENSTILESX;
      pIndices[uOffset++]=(i  )+(j+1)*LENSTILESX;
      pIndices[uOffset++]=(i+1)+(j+1)*LENSTILESX;
      
    }
  }  
 
  SM_D3d::Device()->DrawIndexedPrimitiveUP(
      D3DPT_TRIANGLELIST, 
      0,
      LENSTILESX*LENSTILESY,
      (LENSTILESX-1)*(LENSTILESY-1)*2,
      pIndices,
      D3DFMT_INDEX16,
      Vertices, sizeof(FVF_PosNormalDiffuseTex1));
}

void FilterFX::RenderMDMABackground(float fTime)
{
    
}

DEFINE_EFFECT(FilterFX)
FilterFX Efecto00("FILTER");
