//=========================================================================
//	レンダラー処理(renderer.cpp)
//	作成者：小暮大樹
//	作成日：2016/10/31
//=========================================================================
//=========================================================================
//	インクルードファイル
//=========================================================================
#include "main.h"
#include "renderer.h"
#include "scene.h"
#include "scene2D.h"
#include "scene3D.h"

//=========================================================================
//	静的変数
//=========================================================================
LPDIRECT3D9			CRenderer::m_pD3D = NULL;
LPDIRECT3DDEVICE9	CRenderer::m_pD3DDevice;

#ifdef _DEBUG
LPD3DXFONT			CRenderer::m_pFont = NULL;			// フォントへのポインタ
#endif


//=========================================================================
//	初期化処理
//=========================================================================
HRESULT	CRenderer::Init( HWND hwnd , BOOL bWindow)
{
	D3DPRESENT_PARAMETERS d3dpp;
    D3DDISPLAYMODE d3ddm;

	// Direct3Dオブジェクトの作成
	m_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
	if(m_pD3D == NULL)
	{
		return E_FAIL;
	}

	// 現在のディスプレイモードを取得
    if(FAILED(m_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
	{
		return E_FAIL;
	}

	// デバイスのプレゼンテーションパラメータの設定
	ZeroMemory(&d3dpp, sizeof(d3dpp));								// ワークをゼロクリア
	d3dpp.BackBufferCount			 = 1;							// バックバッファの数
	d3dpp.BackBufferWidth			 = SCREEN_WIDTH;				// ゲーム画面サイズ(幅)
	d3dpp.BackBufferHeight			 = SCREEN_HEIGHT;				// ゲーム画面サイズ(高さ)
	d3dpp.BackBufferFormat			 = d3ddm.Format;				// カラーモードの指定
	d3dpp.SwapEffect				 = D3DSWAPEFFECT_DISCARD;		// 映像信号に同期してフリップする
	d3dpp.EnableAutoDepthStencil	 = TRUE;						// デプスバッファ（Ｚバッファ）とステンシルバッファを作成
	d3dpp.AutoDepthStencilFormat	 = D3DFMT_D16;					// デプスバッファとして16bitを使う
	d3dpp.Windowed					 = bWindow;						// ウィンドウモード
	d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;		// リフレッシュレート
	d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_DEFAULT;	// インターバル

	// デバイスの生成
	// ディスプレイアダプタを表すためのデバイスを作成
	// 描画と頂点処理をハードウェアで行なう
	if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, 
									D3DDEVTYPE_HAL, 
									hwnd, 
									D3DCREATE_HARDWARE_VERTEXPROCESSING, 
									&d3dpp, &m_pD3DDevice)))
	{
		// 上記の設定が失敗したら
		// 描画をハードウェアで行い、頂点処理はCPUで行なう
		if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, 
										D3DDEVTYPE_HAL, 
										hwnd, 
										D3DCREATE_SOFTWARE_VERTEXPROCESSING, 
										&d3dpp, &m_pD3DDevice)))
		{
			// 上記の設定が失敗したら
			// 描画と頂点処理をCPUで行なう
			if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, 
											D3DDEVTYPE_REF, hwnd, 
											D3DCREATE_SOFTWARE_VERTEXPROCESSING, 
											&d3dpp, &m_pD3DDevice)))
			{
				// 生成失敗
				return E_FAIL;
			}
		}
	}

	m_pD3DDevice = NULL;

	//Direct3Dデバイスの作成
	if( FAILED(m_pD3D->CreateDevice(
		D3DADAPTER_DEFAULT ,	//ハードウエアや、グラフィックボードなどが複数ある場合、OSが決めたデフォルトのやつを指定
		D3DDEVTYPE_HAL ,	//描画処理タイプの指定、ハードウエアかCPUか
		hwnd ,			//デバイスを乗っける対象
		D3DCREATE_HARDWARE_VERTEXPROCESSING ,	//ハードウエアで頂点処理をする　デバイス作成オプションフラグ
		&d3dpp ,			//その他の設定値
		&m_pD3DDevice ) ) )//出来上がったインターフェースを設定するためのポインターのポインター
	{
		//ハードウエアでの処理が失敗した場合　頂点処理をソフトウエアに
		if( FAILED(m_pD3D->CreateDevice(
			D3DADAPTER_DEFAULT ,	//ハードウエアや、グラフィックボードなどが複数ある場合、OSが決めたデフォルトのやつを指定
			D3DDEVTYPE_HAL ,	//描画処理タイプの指定、ハードウエアかCPUか
			hwnd ,			//デバイスを乗っける対象
			D3DCREATE_SOFTWARE_VERTEXPROCESSING ,	//ハードウエアで頂点処理をする　デバイス作成オプションフラグ
			&d3dpp ,			//その他の設定値
			&m_pD3DDevice ) ) )//出来上がったインターフェースを設定するためのポインターのポインター
		{
			//描画も頂点処理もソフトウエア
			if( FAILED(m_pD3D->CreateDevice(
				D3DADAPTER_DEFAULT ,	//ハードウエアや、グラフィックボードなどが複数ある場合、OSが決めたデフォルトのやつを指定
				D3DDEVTYPE_REF ,	//描画処理タイプの指定、ハードウエアかCPUか
				hwnd ,			//デバイスを乗っける対象
				D3DCREATE_SOFTWARE_VERTEXPROCESSING ,	//ハードウエアで頂点処理をする　デバイス作成オプションフラグ
				&d3dpp ,			//その他の設定値
				&m_pD3DDevice ) ) )//出来上がったインターフェースを設定するためのポインターのポインター
			{
				//それでもダメだったら
				return	E_FAIL; 
			}
		}
	}

	// レンダーステートの設定
    m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);				// カリングを行わない
	m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);						// Zバッファを使用
	m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);				// αブレンドを行う
	m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);		// αソースカラーの指定
	m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);	// αデスティネーションカラーの指定

	// サンプラーステートの設定
	m_pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);	// テクスチャＵ値の繰り返し設定
	m_pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);	// テクスチャＶ値の繰り返し設定
	m_pD3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);	// テクスチャ拡大時の補間設定
	m_pD3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);	// テクスチャ縮小時の補間設定

	// テクスチャステージステートの設定
	m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);	// アルファブレンディング処理(初期値はD3DTOP_SELECTARG1)
	m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);		// 最初のアルファ引数(初期値はD3DTA_TEXTURE、テクスチャがない場合はD3DTA_DIFFUSE)
	m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT);		// ２番目のアルファ引数(初期値はD3DTA_CURRENT)

		//ワイヤーフレームで表示
#ifdef	WIRE_FRAME_MODE
	m_pD3DDevice->SetRenderState( D3DRS_FILLMODE , D3DFILL_WIREFRAME );
#endif

#ifdef _DEBUG
	// デバッグ情報表示用フォントの生成
	D3DXCreateFont(m_pD3DDevice, 18, 0, 0, 0, FALSE, SHIFTJIS_CHARSET,
					OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Terminal", &m_pFont);
#endif

	return S_OK;
}

//=========================================================================
//	終了処理
//=========================================================================
void	CRenderer::Uninit(void)
{
#ifdef _DEBUG
	// デバッグ情報表示用フォントの破棄
	if(m_pFont != NULL)
	{
		m_pFont->Release();
		m_pFont = NULL;
	}
#endif

	// デバイスの破棄
	if(m_pD3DDevice != NULL)
	{
		m_pD3DDevice->Release();
		m_pD3DDevice = NULL;
	}

	// Direct3Dオブジェクトの破棄
	if(m_pD3D != NULL)
	{
		m_pD3D->Release();
		m_pD3D = NULL;
	}
}

//=========================================================================
//	更新処理
//=========================================================================
void	CRenderer::Update(void)
{
	
}

//=========================================================================
//	描画処理開始
//=========================================================================
void	CRenderer::DrawBigin(void)
{
	// バックバッファ＆Ｚバッファのクリア
	m_pD3DDevice->Clear(0, NULL, (D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER), D3DCOLOR_RGBA( 64, 128 , 128, 255 ), 1.0f, 0);

	// Direct3Dによる描画の開始
	if(FAILED(m_pD3DDevice->BeginScene()))
	{
		UINT nID = MessageBox( NULL , "描画開始できません\n" , "ERROR[ renderer.cpp ]" , MB_OK | MB_ICONEXCLAMATION );		
	}

#ifdef _DEBUG
		// FPS表示
		DrawFPS();
#endif
}

//=========================================================================
//	描画終了
//=========================================================================
void	CRenderer::DrawEnd(void)
{
	// Direct3Dによる描画の終了
	m_pD3DDevice->EndScene();

	// バックバッファとフロントバッファの入れ替え
	m_pD3DDevice->Present(NULL, NULL, NULL, NULL);
}


#ifdef _DEBUG
//=============================================================================
// FPS表示
//=============================================================================
void CRenderer::DrawFPS(void)
{
	RECT rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
	char str[256];
	int nCountFPS;

	nCountFPS = GetFPS();
	wsprintf(str, "FPS:%d\n", nCountFPS);

	// テキスト描画
	m_pFont->DrawText(NULL, str, -1, &rect, DT_LEFT, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff));
}
#endif
