
#define __GLARE_CPP__

//--------------------
// 組み込みファイル名
//--------------------
#include "glare.h"

#define GLARE_TEX_SIZE		(256)
#define GLARE_TEX_SIZE_F	((FLOAT)GLARE_TEX_SIZE)

//----------------
// コンストラクタ
//----------------
CGlare::CGlare()
{
	m_invAspectPS			= NULL;
	m_invIntensityTexSizePS	= NULL;

	m_pTexture				= NULL;

	m_aspect				= 1.0f;
}

//--------------
// デストラクタ
//--------------
CGlare::~CGlare()
{
	if(m_pTexture != NULL){
		IDirect3DTexture9_Release(m_pTexture);
	}
}

//------------------
// メモリを確保する
//------------------
CGlare *CGlare::allocate(void)
{
	return(new CGlare());
}

//------------------
// メモリを解放する
//------------------
void CGlare::dispose(CGlare *&shd)
{
	CShader::dispose((CShader*&)shd);
}

//--------
// 初期化
//---------
void CGlare::init(LPDIRECT3DDEVICE9 pD3DDev)
{
	if(m_pTexture == NULL){
		D3DXCreateTexture(pD3DDev, GLARE_TEX_SIZE, GLARE_TEX_SIZE, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R8G8B8, D3DPOOL_DEFAULT, &m_pTexture);
	}
}

//------------------
// シェーダのビルド
//------------------
int CGlare::buildShader(LPDIRECT3DDEVICE9 pD3DDev, const char *pPixelProfile)
{	
	if(CShader::buildShader(pD3DDev, NULL, NULL, "glareShader/glareShader.psh", pPixelProfile) < 0){
		return(-1);
	}
	{
		LPD3DXCONSTANTTABLE	pPixCnsTbl;
		pPixCnsTbl = getPixelConstantTable();

		m_invAspectPS           = pPixCnsTbl->GetConstantByName(0, "u_invAspect");
		m_invIntensityTexSizePS = pPixCnsTbl->GetConstantByName(0, "u_invIntensityTexSize");
	}
	return(0);
}

//--------------
// グレアの描画
//--------------
void CGlare::drawGlare(LPDIRECT3DDEVICE9 pD3DDev, LPDIRECT3DTEXTURE9 pTexture)
{
	// カリング無効
	pD3DDev->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE);
	// ブレンド無効
	pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE);
	pD3DDev->SetRenderState( D3DRS_SEPARATEALPHABLENDENABLE , FALSE);
	//
	pD3DDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
	// 深度バッファリングを無効
	pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);

	// サンプラステート設定
	pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); // クランプ
	pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); // クランプ
	pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP);
	pD3DDev->SetSamplerState(0, D3DSAMP_BORDERCOLOR, D3DCOLOR_RGBA(255, 255, 255, 255));
	pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);	// バイリニア
	pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);	// バイリニア
	pD3DDev->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
	pD3DDev->SetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, 0);
	pD3DDev->SetSamplerState(0, D3DSAMP_MAXMIPLEVEL, 0);
	pD3DDev->SetSamplerState(0, D3DSAMP_MAXANISOTROPY,1);
	pD3DDev->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, 0);
	pD3DDev->SetSamplerState(0, D3DSAMP_ELEMENTINDEX, 0);
	pD3DDev->SetSamplerState(0, D3DSAMP_DMAPOFFSET, 0);

	FLOAT size = (FLOAT)GLARE_TEX_SIZE;
	struct TVERTEX{
		FLOAT p[4];
		FLOAT tu, tv;
	} Vertex[4] = {
		// x                y  z rhw tu tv
		{0.0f-0.5f, size-0.5f, 0, 1, 0, 1,},
		{size-0.5f, size-0.5f, 0, 1, 1, 1,},
		{size-0.5f, 0.0f-0.5f, 0, 1, 1, 0,},
		{0.0f-0.5f, 0.0f-0.5f, 0, 1, 0, 0,},
	};
	{
		LPD3DXCONSTANTTABLE	pPixCnsTbl;
		pPixCnsTbl = getPixelConstantTable();
		// 逆アスペクトのセット
		if( m_invAspectPS != NULL){
			pPixCnsTbl->SetFloat( pD3DDev, m_invAspectPS, 1.0f/m_aspect );
		}
		// 逆グレアテクスチャサイズのセット
		if( m_invIntensityTexSizePS != NULL){
			pPixCnsTbl->SetFloat( pD3DDev, m_invIntensityTexSizePS, 1.0f/(FLOAT)GLARE_TEX_SIZE );
		}
	}
	//DWORD fvf;
	//pD3DDev->GetFVF(&fvf);
	{
		// 輝度テクスチャセット
		pD3DDev->SetTexture( 0, pTexture );
		//
		pD3DDev->SetFVF( D3DFVF_XYZRHW | D3DFVF_TEX1 );
		pD3DDev->SetVertexShader(NULL);
		pD3DDev->SetPixelShader(getPixelShader()); // グレアのシェーダ
		pD3DDev->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, Vertex, sizeof( TVERTEX ) );
	}
	//pD3DDev->SetFVF( fvf );
	nnResetVertexDeclarationDXG20();
}

//--------------------------------
// グレアテクスチャのレンダリング
//--------------------------------
void CGlare::renderGlareTexture(LPDIRECT3DDEVICE9 pD3DDev, LPDIRECT3DTEXTURE9 pTexture)
{
	LPDIRECT3DSURFACE9 pRenTgtOld, pSuf;
	// 現在のレンダターゲット
	pD3DDev->GetRenderTarget(0, &pRenTgtOld);
	// サーフェースを得る
	m_pTexture->GetSurfaceLevel(0, &pSuf); 
	pD3DDev->SetRenderTarget(0, pSuf);
	pSuf->Release();
	{
		pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0x0, 0x0, 0x0), 1.0f, 0);
		// グレアの描画
		drawGlare(pD3DDev, pTexture);
	}
	// もとの設定に戻す
	pD3DDev->SetRenderTarget(0, pRenTgtOld);
	pRenTgtOld->Release();
}

//------------------------
// グレアテクスチャの描画
//------------------------
void CGlare::drawGlareTexture(LPDIRECT3DDEVICE9 pD3DDev)
{
	// カリング無効
	pD3DDev->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE);

	//
	pD3DDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);

	// 深度バッファリングを無効
	pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);

	// ブレンド有効(加算)
	pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);
	pD3DDev->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_ONE );
	pD3DDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
	pD3DDev->SetRenderState( D3DRS_BLENDOP,   D3DBLENDOP_ADD );
	//
	pD3DDev->SetRenderState( D3DRS_SEPARATEALPHABLENDENABLE , FALSE);

	// サンプラステート設定
	pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); // クランプ
	pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); // クランプ
	pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP);
	pD3DDev->SetSamplerState(0, D3DSAMP_BORDERCOLOR, D3DCOLOR_RGBA(255, 255, 255, 255));
	pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);	// バイリニア
	pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);	// バイリニア
	pD3DDev->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
	pD3DDev->SetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, 0);
	pD3DDev->SetSamplerState(0, D3DSAMP_MAXMIPLEVEL, 0);
	pD3DDev->SetSamplerState(0, D3DSAMP_MAXANISOTROPY,1);
	pD3DDev->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, 0);
	pD3DDev->SetSamplerState(0, D3DSAMP_ELEMENTINDEX, 0);
	pD3DDev->SetSamplerState(0, D3DSAMP_DMAPOFFSET, 0);

	//
	D3DVIEWPORT9  vp;
	pD3DDev->GetViewport(&vp);
	FLOAT sizeX = (FLOAT)vp.Width;
	FLOAT sizeY = (FLOAT)vp.Height;
	struct TVERTEX{
		FLOAT p[3];
		FLOAT tu, tv;
	} Vertex[4] = {
		//   x      y     z    tu    tv(座標系が逆)
		{ 0.0f,  0.0f, 0.0f, 0.0f, 1.0f},
		{ 0.0f, sizeY, 0.0f, 0.0f, 0.0f},
		{sizeX, sizeY, 0.0f, 1.0f, 0.0f},
		{sizeX,  0.0f, 0.0f, 1.0f, 1.0f},
	};

	//DWORD fvf;
	//pD3DDev->GetFVF(&fvf);
	{
		// グレアテクスチャセット
		pD3DDev->SetTexture( 0, m_pTexture );
		pD3DDev->SetFVF( D3DFVF_XYZ | D3DFVF_TEX1 );
		{
			{	// 正射影マトリクス
				D3DXMATRIX matProj;
				D3DXMatrixOrthoOffCenterRH(&matProj, 0.0f, sizeX-1, 0.0f, sizeY-1, -1.0f, 1.0f);
				pD3DDev->SetTransform(D3DTS_PROJECTION, &matProj);
			}
			{
				D3DXMATRIX mt;
				D3DXMatrixIdentity(&mt);
				//
				pD3DDev->SetTransform(D3DTS_VIEW, &mt);
				// テクスチャがスケールして描画されるので位置を調整する(テクスチャの座標系で調整)
				D3DXMatrixTranslation(&mt, -(nnFloor(sizeX/GLARE_TEX_SIZE_F*0.5f) + 0.5f), (nnFloor(sizeY/GLARE_TEX_SIZE_F*0.5f) + 0.5f), 0.0f);
				pD3DDev->SetTransform(D3DTS_WORLD, &mt);
			}
		}
		pD3DDev->SetVertexShader(NULL);
		pD3DDev->SetPixelShader(NULL);
		pD3DDev->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, Vertex, sizeof( TVERTEX ) );
	}
	//pD3DDev->SetFVF( fvf );
	nnResetVertexDeclarationDXG20();
}
