#include "Mix/Private/Scene/Standard/DX11/Renderer.h"

#include "Mix/Graphics/IDevice.h"
#include "Mix/Graphics/IShaderConstant.h"
#include "Mix/Scene/ISkyDome.h"

//#include "Mix/Private/Scene/Common/Material.h"

namespace Mix{ namespace Scene{ namespace Standard{ namespace DX11{

Renderer* Renderer::CreateInstance( Mix::Scene::Standard::Common::EffectPackage* pEffectPackage, const wchar_t* pName )
{
	return MIX_LIB_NEW_T( Mix::Memory::SECTION_SCENE, Renderer, pEffectPackage, pName );
}

Renderer::Renderer( Mix::Scene::Standard::Common::EffectPackage* pEffectPackage, const wchar_t* pName ) :
Mix::Scene::Standard::Common::Renderer( pEffectPackage, pName ),
m_pGeneralVSC( NULL ),
m_pGeneralPSC( NULL ),
m_pSkyDomeVSC( NULL ),
m_pSkyDomePSC( NULL ),
m_pPanoramaVSC( NULL ),
m_pPanoramaPSC( NULL ),
m_pTransformVSC( NULL ),
m_pLocalLightPSC( NULL ),
m_pSamplingPSC( NULL ),
m_pBlurPSC( NULL ),
m_pGaussianBlurVSC( NULL ),
m_pGaussianBlurPSC( NULL ),
m_pGaussianBlurExPSC( NULL ),
m_pShadowMappingPSC( NULL ),
m_pSsaoPSC( NULL ),
m_pLumTransformPSC( NULL ),
m_pLumAdaptedPSC( NULL ),
m_pLumOperatorPSC( NULL ),
m_pBrightPassPSC( NULL ),
m_pLSInitPSC( NULL ),
m_pLSBlurPSC( NULL ),
m_pUnderWaterPSC( NULL ),
m_pLFImagePSC( NULL ),
m_pLFModifyPSC( NULL ),
m_pFIHablePSC( NULL ),
m_pCAImagePSC( NULL ),
m_pCAFinishPSC( NULL ),
m_pGammaCorrectPSC( NULL ),
m_pCamMotBlurPSC( NULL ),
m_pDofPSC( NULL ),
m_pLensDistPSC( NULL ),
m_pVignettePSC( NULL ),
m_pFxaaPSC( NULL )
{
}

Renderer::~Renderer( void )
{
	MIX_RELEASE( m_pGeneralVSC );
	MIX_RELEASE( m_pGeneralPSC );
	MIX_RELEASE( m_pSkyDomeVSC );
	MIX_RELEASE( m_pSkyDomePSC );
	MIX_RELEASE( m_pPanoramaVSC );
	MIX_RELEASE( m_pPanoramaPSC );
	MIX_RELEASE( m_pTransformVSC );
	MIX_RELEASE( m_pLocalLightPSC );
	MIX_RELEASE( m_pSamplingPSC );
	MIX_RELEASE( m_pBlurPSC );
	MIX_RELEASE( m_pGaussianBlurVSC );
	MIX_RELEASE( m_pGaussianBlurPSC );
	MIX_RELEASE( m_pGaussianBlurExPSC );
	MIX_RELEASE( m_pShadowMappingPSC );
	MIX_RELEASE( m_pSsaoPSC );
	MIX_RELEASE( m_pLumTransformPSC );
	MIX_RELEASE( m_pLumAdaptedPSC );
	MIX_RELEASE( m_pLumOperatorPSC );
	MIX_RELEASE( m_pBrightPassPSC );
	MIX_RELEASE( m_pUnderWaterPSC );
	MIX_RELEASE( m_pLSInitPSC );
	MIX_RELEASE( m_pLSBlurPSC );
	MIX_RELEASE( m_pLFImagePSC );
	MIX_RELEASE( m_pLFModifyPSC );
	MIX_RELEASE( m_pFIHablePSC );
	MIX_RELEASE( m_pCAImagePSC );
	MIX_RELEASE( m_pCAFinishPSC );
	MIX_RELEASE( m_pGammaCorrectPSC );
	MIX_RELEASE( m_pCamMotBlurPSC );
	MIX_RELEASE( m_pDofPSC );
	MIX_RELEASE( m_pLensDistPSC );
	MIX_RELEASE( m_pVignettePSC );
	MIX_RELEASE( m_pFxaaPSC );
}

Boolean Renderer::OnInitialize( const Mix::Scene::RENDERER_CONFIG& config )
{
	UInt32 vscSkyDomeSize = max( sizeof( Renderer::VSC_SKYDOME_DEFAULT ), sizeof( Renderer::VSC_SKYDOME_ATMOSPHERE ) );
	UInt32 pscSkyDomeSize = max( sizeof( Renderer::PSC_SKYDOME_DEFAULT ), sizeof( Renderer::PSC_SKYDOME_ATMOSPHERE ) );

	//レンダリング定数( VS )
	if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::VSC_RENDERRING ), True, NULL, &m_pGeneralVSC, L"GeneralVSC" ) == False )
	{
		return False;
	}

	//レンダリング定数( PS )
	if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_RENDERRING ), True, NULL, &m_pGeneralPSC, L"GeneralPSC" ) == False )
	{
		return False;
	}

	//スカイドーム定数( VS )
	if( m_pGraphicsDev->CreateShaderConstant( vscSkyDomeSize, True, NULL, &m_pSkyDomeVSC, L"SkyDomeVSC" ) == False )
	{
		return False;
	}

	//スカイドーム定数( PS )
	if( m_pGraphicsDev->CreateShaderConstant( pscSkyDomeSize, True, NULL, &m_pSkyDomePSC, L"SkyDomePSC" ) == False )
	{
		return False;
	}

	//スカイドーム : パノラマ定数( VS )
	if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::VSC_SKYDOME_PANORAMA ), True, NULL, &m_pPanoramaVSC, L"SkyDome_PanoramaVSC" ) == False )
	{
		return False;
	}

	//スカイドーム : パノラマ定数( PS )
	if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_SKYDOME_PANORAMA ), True, NULL, &m_pPanoramaPSC, L"SkyDome_PanoramaPSC" ) == False )
	{
		return False;
	}

	//トランスフォーム定数( VS )
	if( m_pGraphicsDev->CreateShaderConstant( sizeof( Mix::Matrix4x4 ) * Renderer::WORLD_MAT_MAX, True, NULL, &m_pTransformVSC, L"TransformVSC" ) == False )
	{
		return False;
	}

	//ローカルライト定数( PS )
	if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_LOCAL_LIGHT ), True, NULL, &m_pLocalLightPSC, L"LocalLightPSC" ) == False )
	{
		return False;
	}

	//サンプリング( PS )
	if( m_pGraphicsDev->CreateShaderConstant( sizeof( Mix::Vector4 ), True, NULL, &m_pSamplingPSC, L"SamplingPSC" ) == False )
	{
		return False;
	}

	//アンダーウォーター定数( PS )
	if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_UNDER_WATER ), True, NULL, &m_pUnderWaterPSC, L"UnderWaterPSC" ) == False )
	{
		return False;
	}

	//フィルミック : Hable ( PS )
	if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_FILMIC_HABLE ), True, NULL, &m_pFIHablePSC, L"FilmicHablePSC" ) == False )
	{
		return False;
	}

	//ガンマ補正定数( PS )
	if( m_pGraphicsDev->CreateShaderConstant( sizeof( Mix::Vector4 ), True, NULL, &m_pGammaCorrectPSC, L"GammaCorrectPSC" ) == False )
	{
		return False;
	}

	//カメラモーションブラー定数( PS )
	if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_CAM_MOT_BLUR ), True, NULL, &m_pCamMotBlurPSC, L"CameraMotionBlurPSC" ) == False )
	{
		return False;
	}

	//歪曲収差定数( PS )
	if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_LENS_DIST ), True, NULL, &m_pLensDistPSC, L"LensDistortionPSC" ) == False )
	{
		return False;
	}

	//ヴィネット( PS )
	if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_VIGNETTE ), True, NULL, &m_pVignettePSC, L"VignettePSC" ) == False )
	{
		return False;
	}

	//FXAA( PS )
	if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_FXAA ), True, NULL, &m_pFxaaPSC, L"FxaaPSC" ) == False )
	{
		return False;
	}

	return True;
}

Boolean Renderer::OnUpdateConfig( const Mix::Scene::RENDERER_CONFIG& config )
{
	UInt32 caps = config.caps;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 解放
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_RELEASE( m_pBlurPSC );
	MIX_RELEASE( m_pGaussianBlurVSC );
	MIX_RELEASE( m_pGaussianBlurPSC );
	MIX_RELEASE( m_pGaussianBlurExPSC );

	MIX_RELEASE( m_pBrightPassPSC );

	MIX_RELEASE( m_pSsaoPSC );

	MIX_RELEASE( m_pShadowMappingPSC );

	MIX_RELEASE( m_pLumTransformPSC );
	MIX_RELEASE( m_pLumAdaptedPSC );
	MIX_RELEASE( m_pLumOperatorPSC );

	MIX_RELEASE( m_pLSInitPSC );
	MIX_RELEASE( m_pLSBlurPSC );

	MIX_RELEASE( m_pLFImagePSC );
	MIX_RELEASE( m_pLFModifyPSC );

	MIX_RELEASE( m_pCAImagePSC );
	MIX_RELEASE( m_pCAFinishPSC );

	MIX_RELEASE( m_pDofPSC );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	/*
		ブラー
	*/

	MIX_ASSERT( m_pBlurPSC == NULL );
	MIX_ASSERT( m_pGaussianBlurVSC == NULL );
	MIX_ASSERT( m_pGaussianBlurPSC == NULL );
	MIX_ASSERT( m_pGaussianBlurExPSC == NULL );

	if( ( MIX_TESTBIT( caps, Mix::Scene::RCAP_SHADOW_MAPPING ) == Mix::Scene::RCAP_SHADOW_MAPPING ) ||
		( MIX_TESTBIT( caps, Mix::Scene::RCAP_AMBIENT_OCCLUSION ) == Mix::Scene::RCAP_AMBIENT_OCCLUSION ) ||
		( MIX_TESTBIT( caps, Mix::Scene::RCAP_BLOOM ) == Mix::Scene::RCAP_BLOOM ) ||
		( MIX_TESTBIT( caps, Mix::Scene::RCAP_LENS_FLARE ) == Mix::Scene::RCAP_LENS_FLARE ) ||
		( MIX_TESTBIT( caps, Mix::Scene::RCAP_CHROMATISM ) == Mix::Scene::RCAP_CHROMATISM ) ||
		( MIX_TESTBIT( caps, Mix::Scene::RCAP_DEPTH_OF_FIELD ) == Mix::Scene::RCAP_DEPTH_OF_FIELD ) )
	{
		//カーネルブラー( PS )
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Mix::Vector4 ) * 3, True, NULL, &m_pBlurPSC, L"BlurPSC" ) == False )
		{
			return False;
		}

		//ガウシアンブラー( VS )
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Mix::Vector4 ) * 8, True, NULL, &m_pGaussianBlurVSC, L"GaussianBlurVSC" ) == False )
		{
			return False;
		}

		//ガウシアンブラー( PS )
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_GAUSSIAN_BLUR ), True, NULL, &m_pGaussianBlurPSC, L"GaussianBlurPSC" ) == False )
		{
			return False;
		}

		//ガウシアンブラーEX( PS )
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_GAUSSIAN_BLUR_EX ), True, NULL, &m_pGaussianBlurExPSC, L"GaussianBlurExPSC" ) == False )
		{
			return False;
		}
	}

	/*
		ブライトパス
	*/

	MIX_ASSERT( m_pBrightPassPSC == NULL );

	if( ( MIX_TESTBIT( caps, Mix::Scene::RCAP_BLOOM ) == Mix::Scene::RCAP_BLOOM ) ||
		( MIX_TESTBIT( caps, Mix::Scene::RCAP_LIGHT_SHAFTS ) == Mix::Scene::RCAP_LIGHT_SHAFTS ) ||
		( MIX_TESTBIT( caps, Mix::Scene::RCAP_LENS_FLARE ) == Mix::Scene::RCAP_LENS_FLARE ) )
	{
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_BRIGHT_PASS ), True, NULL, &m_pBrightPassPSC, L"BrightPassPSC" ) == False )
		{
			return False;
		}
	}

	/*
		アンビエントオクルージョン
	*/

	MIX_ASSERT( m_pSsaoPSC == NULL );

	if( MIX_TESTBIT( caps, Mix::Scene::RCAP_AMBIENT_OCCLUSION ) == Mix::Scene::RCAP_AMBIENT_OCCLUSION )
	{
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_SSAO ), True, NULL, &m_pSsaoPSC, L"SsaoPSC" ) == False )
		{
			return False;
		}
	}

	/*
		シャドウマッピング
	*/

	MIX_ASSERT( m_pShadowMappingPSC == NULL );

	if( MIX_TESTBIT( caps, Mix::Scene::RCAP_SHADOW_MAPPING ) == Mix::Scene::RCAP_SHADOW_MAPPING )
	{
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_SM ), True, NULL, &m_pShadowMappingPSC, L"ShadowMappingPSC" ) == False )
		{
			return False;
		}
	}

	/*
		ルミノシティ
	*/

	MIX_ASSERT( m_pLumTransformPSC == NULL );
	MIX_ASSERT( m_pLumAdaptedPSC == NULL );
	MIX_ASSERT( m_pLumOperatorPSC == NULL );

	if( MIX_TESTBIT( caps, Mix::Scene::RCAP_LUMINOSITY ) == Mix::Scene::RCAP_LUMINOSITY )
	{
		//トランスフォーム定数( PS )
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_LUM_TRANSFORM ), True, NULL, &m_pLumTransformPSC, L"LumTransformPSC" ) == False )
		{
			return False;
		}

		//アダプテッド定数( PS )
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_LUM_ADAPTED ), True, NULL, &m_pLumAdaptedPSC, L"LumAdaptedPSC" ) == False )
		{
			return False;
		}

		//オペレーター定数( PS )
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_LUM_OPERATOR ), True, NULL, &m_pLumOperatorPSC, L"LumOperatorPSC" ) == False )
		{
			return False;
		}
	}

	/*
		ライトシャフト
	*/

	MIX_ASSERT( m_pLSBlurPSC == NULL );

	if( MIX_TESTBIT( caps, Mix::Scene::RCAP_LIGHT_SHAFTS ) == Mix::Scene::RCAP_LIGHT_SHAFTS )
	{
		// 初期化定数( PS )
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_LIGHT_SHAFTS_INIT ), True, NULL, &m_pLSInitPSC, L"LightShaftsInitPSC" ) == False )
		{
			return False;
		}

		// ブラー定数( PS )
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_LIGHT_SHAFTS_BLUR ), True, NULL, &m_pLSBlurPSC, L"LightShaftsBlurPSC" ) == False )
		{
			return False;
		}
	}

	/*
		レンズフレア
	*/

	MIX_ASSERT( m_pLFImagePSC == NULL );
	MIX_ASSERT( m_pLFModifyPSC == NULL );

	if( MIX_TESTBIT( caps, Mix::Scene::RCAP_LENS_FLARE ) == Mix::Scene::RCAP_LENS_FLARE )
	{
		// イメージ定数( PS )
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_LF_IMAGE ), True, NULL, &m_pLFImagePSC, L"LensFlareImagePSC" ) == False )
		{
			return False;
		}

		// モディファイ定数( PS )
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_LF_MODIFY ), True, NULL, &m_pLFModifyPSC, L"LensFlareModifyPSC" ) == False )
		{
			return False;
		}
	}

	/*
		色収差
	*/

	MIX_ASSERT( m_pCAImagePSC == NULL );
	MIX_ASSERT( m_pCAFinishPSC == NULL );

	if( MIX_TESTBIT( caps, Mix::Scene::RCAP_CHROMATISM ) == Mix::Scene::RCAP_CHROMATISM )
	{
		// イメージ定数( PS )
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_CA_IMAGE ), True, NULL, &m_pCAImagePSC, L"ChromatismImagePSC" ) == False )
		{
			return False;
		}

		// フィニッシュ定数( PS )
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_CA_FINISH ), True, NULL, &m_pCAFinishPSC, L"ChromatismFinishPSC" ) == False )
		{
			return False;
		}
	}

	/*
		被写界深度
	*/

	MIX_ASSERT( m_pDofPSC == NULL );

	if( MIX_TESTBIT( caps, Mix::Scene::RCAP_DEPTH_OF_FIELD ) == Mix::Scene::RCAP_DEPTH_OF_FIELD )
	{
		if( m_pGraphicsDev->CreateShaderConstant( sizeof( Renderer::PSC_DOF ), True, NULL, &m_pDofPSC, L"DofPSC" ) == False )
		{
			return False;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////

	return True;
}

void Renderer::OnPrepareRendering( const Renderer::PREPARE_REDNERING_EVENT_ARGS& e )
{
	MIX_ASSERT( m_pGeneralVSC != NULL );
	MIX_ASSERT( m_pGeneralPSC != NULL );

	if( m_pGeneralVSC->Lock() == True )
	{
		Renderer::VSC_RENDERRING vsc;

		vsc.viewMat = e.viewMat;
		vsc.viewProjMat = e.viewProjMat;
		vsc.lightMat = e.lightMat;
		vsc.lightBiasMat = e.lightBiasMat;

		m_pGeneralVSC->Write( &vsc, sizeof( vsc ) );
		m_pGeneralVSC->Unlock();
	}

	if( m_pGeneralPSC->Lock() == True )
	{
		Renderer::PSC_RENDERRING psc;

		psc.camParam.Set( e.eyePos.x, e.eyePos.y, e.eyePos.z, e.invFarZ );
		psc.ambientColor = e.globalAmbientColor;
		psc.hsParam.Set( e.hsAxis.x, e.hsAxis.y, e.hsAxis.z, ( e.hsEnabled == True )? 1.0f : 0.0f );
		psc.hsGroundColor = e.hsGroundColor;
		psc.hsSkyColor = e.hsSkyColor;
		psc.sunParam.Set( e.sunDir.x, e.sunDir.y, e.sunDir.z, ( e.sunEnabled == True )? 1.0f : 0.0f );
		psc.sunColor = e.sunColor;
		psc.fogParam.Set( e.fogParam0, e.fogParam1, 0.0f, ( e.fogEnabled == True )? 1.0f : 0.0f );
		psc.fogColor = e.fogColor;
		psc.shadowParam0.Set( e.shadowDepthBias, e.shadowDepthSlopeScale, e.shadowDepthBiasClamp, ( e.shadowEnabled == True )? 1.0f : 0.0f );
		psc.shadowParam1.Set( e.shadowPCFRange, e.shadowPCFMul, e.shadowTexelSize.x, e.shadowTexelSize.y );
		psc.asColor.Set( e.asColor.x, e.asColor.y, e.asColor.z, ( e.asEnabled == True )? 1.0f : 0.0f );
		psc.asSunDir = e.asSunDir;
		psc.asMultipliers = e.asMultipliers;
		psc.asHG = e.asHG;
		psc.asBetaDashR = e.asBetaDashR;
		psc.asBetaDashM = e.asBetaDashM;
		psc.asBetaRM = e.asBetaRM;
		psc.asOneOverBetaRM = e.asOneOverBetaRM;

		m_pGeneralPSC->Write( &psc, sizeof( psc ) );
		m_pGeneralPSC->Unlock();
	}

	m_pGraphicsDev->SetVertexShaderConstant( Renderer::VSCR_GENERAL, m_pGeneralVSC );
	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_GENERAL, m_pGeneralPSC );
}

void Renderer::OnTransform( const Renderer::TRANSFORM_EVENT_ARGS& e )
{
	MIX_ASSERT( e.count <= Renderer::WORLD_MAT_MAX );
	MIX_ASSERT( m_pTransformVSC != NULL );

	if( m_pTransformVSC->Lock() == True )
	{
		m_pTransformVSC->Write( &( e.list[0] ), sizeof( Mix::Matrix4x4 ) * e.count );
		m_pTransformVSC->Unlock();
	}

	m_pGraphicsDev->SetVertexShaderConstant( Renderer::VSCR_TRANSFORM, m_pTransformVSC );
}

void Renderer::OnPlacementLocalLight( const Renderer::LOCALLIGHT_EVENT_ARGS& e )
{
	MIX_ASSERT( m_pLocalLightPSC != NULL );

	if( m_pLocalLightPSC->Lock() == True )
	{
		Renderer::PSC_LOCAL_LIGHT psc;

		for( UInt32 i = 0; i < e.count; i++ )
		{
			const Mix::Scene::Common::LOCAL_LIGHT* src = e.list[i];

			psc.pos[i] = Mix::Vector4( src->pos.x, src->pos.y, src->pos.z, 1.0f );
			psc.atten[i] = src->atten;
			psc.color[i] = src->color;

			if( src->type == Mix::Scene::IRendererObject::SPOT_LIGHT )
			{
				psc.dir[i] = Mix::Vector4( src->dir.x, src->dir.y, src->dir.z, 1.0f );
				psc.misc[i] = Mix::Vector4( src->range, src->innerCos, src->outerCos, src->exp );
			}
			else
			{
				psc.dir[i] = Mix::Vector4( 0.0f, 0.0f, 0.0f, 0.0f );
				psc.misc[i] = Mix::Vector4( src->outerRadius, src->invDiffRadius, 0.0f, 0.0f );
			}
		}

		if( e.count < Renderer::LOCAL_LIGHT_MAX )
		{
			MIX_ASSERT( ( sizeof( psc.pos ) / sizeof( Mix::Vector4 ) ) > e.count );
			psc.pos[e.count].w = 0.0f;
		}

		m_pLocalLightPSC->Write( &psc, sizeof( psc ) );
		m_pLocalLightPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_LOCALLIGHT, m_pLocalLightPSC );
}

void Renderer::OnRenderSkyDome( const Renderer::SKYDOME_DEFAULT_EVENT_ARGS& e )
{
	MIX_ASSERT( m_pSkyDomeVSC != NULL );
	MIX_ASSERT( m_pSkyDomePSC != NULL );

	if( m_pSkyDomeVSC->Lock() == True )
	{
		Renderer::VSC_SKYDOME_DEFAULT vsc;

		vsc.wvpMat = e.wvpMat;

		m_pSkyDomeVSC->Write( &vsc, sizeof( vsc ) );
		m_pSkyDomeVSC->Unlock();
	}

	if( m_pSkyDomePSC->Lock() == True )
	{
		Renderer::PSC_SKYDOME_DEFAULT psc;

		psc.baseColor = e.baseColor;
		psc.baseParam.Set( e.baseParam.texScale, e.baseParam.texOpacity, 0.0f, 0.0f );

		psc.cloudColor = e.cloudColor;

		for( UInt32 i = 0; i < Mix::Scene::Common::SkyDome::CL_MAX; i++ )
		{
			const Renderer::SKYDOME_CLOUD_LAYER& srcLayer = e.cloudLayers[i];
			const Mix::Vector2& texOffset = srcLayer.texOffset;

			psc.cloudLayer[i].Set( texOffset.x, texOffset.y, srcLayer.texScale, srcLayer.texOpacity );
		}

		m_pSkyDomePSC->Write( &psc, sizeof( psc ) );
		m_pSkyDomePSC->Unlock();
	}

	m_pGraphicsDev->SetVertexShaderConstant( Renderer::VSCR_SKYDOME, m_pSkyDomeVSC );
	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_SKYDOME, m_pSkyDomePSC );
}

void Renderer::OnRenderSkyDome( const Renderer::SKYDOME_ATMOSPHERE_EVENT_ARGS& e )
{
	MIX_ASSERT( m_pSkyDomeVSC != NULL );
	MIX_ASSERT( m_pSkyDomePSC != NULL );

	if( m_pSkyDomeVSC->Lock() == True )
	{
		Renderer::VSC_SKYDOME_ATMOSPHERE vsc;

		vsc.wMat = e.worldMat;
		vsc.wvpMat = e.worldViewProjMat;

		m_pSkyDomeVSC->Write( &vsc, sizeof( vsc ) );
		m_pSkyDomeVSC->Unlock();
	}

	if( m_pSkyDomePSC->Lock() == True )
	{
		Renderer::PSC_SKYDOME_ATMOSPHERE psc;

		psc.sunColor = e.sunColor;
		psc.nightColor = e.nightColor;
		psc.baseParam.Set( e.baseParam.texScale, e.baseParam.texOpacity, 0.0f, 0.0f );

		psc.cloudColor = e.cloudColor;

		for( UInt32 i = 0; i < Mix::Scene::Common::SkyDome::CL_MAX; i++ )
		{
			const Renderer::SKYDOME_CLOUD_LAYER& srcLayer = e.cloudLayers[i];
			const Mix::Vector2& texOffset = srcLayer.texOffset;

			psc.cloudLayer[i].Set( texOffset.x, texOffset.y, srcLayer.texScale, srcLayer.texOpacity );
		}

		psc.cloudParams.Set( e.cloudLighting.cornerThreshold, e.cloudLighting.cornerMul, e.cloudLighting.darkness, 0.0f );

		m_pSkyDomePSC->Write( &psc, sizeof( psc ) );
		m_pSkyDomePSC->Unlock();
	}

	m_pGraphicsDev->SetVertexShaderConstant( Renderer::VSCR_SKYDOME, m_pSkyDomeVSC );
	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_SKYDOME, m_pSkyDomePSC );
}

void Renderer::OnRenderPanorama( const Renderer::SKYDOME_PANORAMA_EVENT_ARGS& e )
{
	MIX_ASSERT( m_pPanoramaVSC != NULL );
	MIX_ASSERT( m_pPanoramaPSC != NULL );

	if( m_pPanoramaVSC->Lock() == True )
	{
		Renderer::VSC_SKYDOME_PANORAMA vsc;

		vsc.wvpMat = e.wvpMat;
		vsc.wMat = e.wMat;

		m_pPanoramaVSC->Write( &vsc, sizeof( vsc ) );
		m_pPanoramaVSC->Unlock();
	}

	if( m_pPanoramaPSC->Lock() == True )
	{
		Renderer::PSC_SKYDOME_PANORAMA psc;

		psc.baseColor = e.baseColor;
		psc.param.Set( e.texRepeat, e.dist, e.fogRatio, 0.0f );

		m_pPanoramaPSC->Write( &psc, sizeof( psc ) );
		m_pPanoramaPSC->Unlock();
	}

	m_pGraphicsDev->SetVertexShaderConstant( Renderer::VSCR_PANORAMA, m_pPanoramaVSC );
	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_PANORAMA, m_pPanoramaPSC );
}

void Renderer::OnRenderSampling( const Renderer::RENDER_SAMPLING_ARGS& e )
{
	MIX_ASSERT( m_pSamplingPSC != NULL );

	if( m_pSamplingPSC->Lock() == True )
	{
		Mix::Vector4 psc;

		psc.x = e.texelSize.x;
		psc.y = e.texelSize.y;
		psc.z = e.colorScale;

		m_pSamplingPSC->Write( &psc, sizeof( psc ) );
		m_pSamplingPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_SAMPLING, m_pSamplingPSC );
}

void Renderer::OnRenderBlur( const Renderer::RENDER_BLUR_ARGS& e )
{
	MIX_ASSERT( m_pBlurPSC != NULL );

	if( m_pBlurPSC->Lock() == True )
	{
		m_pBlurPSC->Write( &( e.params ), sizeof( e.params ) );
		m_pBlurPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_BLUR, m_pBlurPSC );
}

void Renderer::OnRenderGaussianBlur( const Renderer::RENDER_GAUSSIAN_BLUR_ARGS& e )
{
	MIX_ASSERT( m_pGaussianBlurVSC != NULL );
	MIX_ASSERT( m_pGaussianBlurPSC != NULL );

	if( m_pGaussianBlurVSC->Lock() == True )
	{
		m_pGaussianBlurVSC->Write( &( e.inOffsets[0] ), sizeof( e.inOffsets ) );
		m_pGaussianBlurVSC->Unlock();
	}

	if( m_pGaussianBlurPSC->Lock() == True )
	{
		Renderer::PSC_GAUSSIAN_BLUR psc;

		psc.offset = e.outOffset;
		Mix::Memory::Copy( &( psc.weights[0] ), &( e.weights[0] ), sizeof( Float32 ) * 8 );

		m_pGaussianBlurPSC->Write( &psc, sizeof( psc ) );
		m_pGaussianBlurPSC->Unlock();
	}

	m_pGraphicsDev->SetVertexShaderConstant( Renderer::VSCR_GAUSSIAN_BLUR, m_pGaussianBlurVSC );
	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_GAUSSIAN_BLUR, m_pGaussianBlurPSC );
}

void Renderer::OnRenderGaussianBlurEx( const Renderer::RENDER_GAUSSIAN_BLUR_EX_ARGS& e )
{
	MIX_ASSERT( m_pGaussianBlurExPSC != NULL );

	if( m_pGaussianBlurExPSC->Lock() == True )
	{
		Renderer::PSC_GAUSSIAN_BLUR_EX psc;

		psc.halfRadius = e.halfRadius;
		psc.inc = e.inc;
		psc.step = e.step;

		Mix::Memory::Zero( psc.reserve0, sizeof( psc.reserve0 ) );
		Mix::Memory::Zero( psc.reserve1, sizeof( psc.reserve1 ) );
		Mix::Memory::Zero( psc.reserve2, sizeof( psc.reserve2 ) );

		m_pGaussianBlurExPSC->Write( &psc, sizeof( psc ) );
		m_pGaussianBlurExPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_GAUSSIAN_BLUR_EX, m_pGaussianBlurExPSC );
}

void Renderer::OnRenderShadowMapping( const Renderer::RENDER_SHADOW_MAPPING_ARGS& e )
{
	MIX_ASSERT( m_pShadowMappingPSC != NULL );

	if( m_pShadowMappingPSC->Lock() == True )
	{
		Renderer::PSC_SM psc;

		//params
		psc.falloutStart = e.falloutStart;
		psc.invFalloutDist = e.invFalloutDist;
		psc.refractFactor = e.refractFactor;
		psc.reserve = 0.0f;

		//color
		psc.color = e.color;

		m_pShadowMappingPSC->Write( &psc, sizeof( psc ) );
		m_pShadowMappingPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_SM, m_pShadowMappingPSC );
}

void Renderer::OnRenderAmbientOcclusion( const Renderer::RENDER_AMBIENT_OCCLUSION_ARGS& e )
{
	MIX_ASSERT( m_pSsaoPSC != NULL );

	if( m_pSsaoPSC->Lock() == True )
	{
		Renderer::PSC_SSAO psc;

		psc.radius = e.radius;
		psc.threshold = e.threshold;
		psc.depth = e.depth;
		psc.intensity = e.intensity;
		psc.ntexAspect = e.ntexAspect;
		psc.reserve[0] = 0.0f;
		psc.reserve[1] = 0.0f;
		psc.color = e.color;

		m_pSsaoPSC->Write( &psc, sizeof( psc ) );
		m_pSsaoPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_SSAO, m_pSsaoPSC );
}

void Renderer::OnRenderBrightPass( const Renderer::RENDER_BRIGHTPASS_ARGS& e )
{
	MIX_ASSERT( m_pBrightPassPSC != NULL );

	if( m_pBrightPassPSC->Lock() == True )
	{
		Renderer::PSC_BRIGHT_PASS psc;

		psc.middleGray = e.middleGray;
		psc.white2Inv = e.invWhite2;
		psc.threshold = e.threshold;
		psc.offset = e.offset;

		m_pBrightPassPSC->Write( &psc, sizeof( psc ) );
		m_pBrightPassPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_BRIGHT_PASS, m_pBrightPassPSC );
}

void Renderer::OnRenderLumTransform( const Renderer::RENDER_LUM_TRANSFORM_ARGS& e )
{
	MIX_ASSERT( m_pLumTransformPSC != NULL );

	if( m_pLumTransformPSC->Lock() == True )
	{
		Renderer::PSC_LUM_TRANSFORM psc;

		psc.texelSize = e.texelSize;
		psc.lumRange = e.lumRange;

		m_pLumTransformPSC->Write( &psc, sizeof( psc ) );
		m_pLumTransformPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_LUM_TRANSFORM, m_pLumTransformPSC );
}

void Renderer::OnRenderLumAdapted( const Renderer::RENDER_LUM_ADAPTED_ARGS& e )
{
	MIX_ASSERT( m_pLumAdaptedPSC != NULL );

	if( m_pLumAdaptedPSC->Lock() == True )
	{
		Renderer::PSC_LUM_ADAPTED psc;

		psc.rods = e.rods;
		psc.cones = e.cones;
		psc.deltaTime = e.deltaTime;
		psc.reserve0 = 0.0f;

		m_pLumAdaptedPSC->Write( &psc, sizeof( psc ) );
		m_pLumAdaptedPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_LUM_ADAPTED, m_pLumAdaptedPSC );
}

void Renderer::OnRenderLumOperator( const Renderer::RENDER_LUM_OPERATOR_ARGS& e )
{
	MIX_ASSERT( m_pLumOperatorPSC != NULL );

	if( m_pLumOperatorPSC->Lock() == True )
	{
		Renderer::PSC_LUM_OPERATOR psc;

		psc.middleGray = e.middleGray;
		psc.white2Inv = e.invWhite2;
		psc.reserve[0] = 0.0f;
		psc.reserve[1] = 0.0f;

		m_pLumOperatorPSC->Write( &psc, sizeof( psc ) );
		m_pLumOperatorPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_LUM_OPERATOR, m_pLumOperatorPSC );
}

void Renderer::OnRenderLightShaftsInit( const Renderer::RENDER_LIGHT_SHAFTS_INIT_ARGS& e )
{
	MIX_ASSERT( m_pLSInitPSC != NULL );

	if( m_pLSInitPSC->Lock() == True )
	{
		Renderer::PSC_LIGHT_SHAFTS_INIT psc;

		psc.whiteness = e.whiteness;
		psc.ntexAspect = e.ntexAspect;
		psc.reserve = 0.0f;

		m_pLSInitPSC->Write( &psc, sizeof( psc ) );
		m_pLSInitPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_LS_INIT, m_pLSInitPSC );
}

void Renderer::OnRenderLightShaftsBlur( const Renderer::RENDER_LIGHT_SHAFTS_BLUR_ARGS& e )
{
	MIX_ASSERT( m_pLSBlurPSC != NULL );

	if( m_pLSBlurPSC->Lock() == True )
	{
		Renderer::PSC_LIGHT_SHAFTS_BLUR psc;

		psc.lightPos = e.lightPos;
		psc.EdotL = e.EdotL;
		psc.reserve0 = 0.0f;
		psc.density = e.density;
		psc.decay = e.decay;
		psc.exposure = e.exposure;
		psc.reserve1 = 0.0f;
		psc.fiStart = e.fiStart;
		psc.fiEnd = e.fiEnd;
		psc.fiInvDist = e.fiInvDist;
		psc.reserve2 = 0.0f;

		m_pLSBlurPSC->Write( &psc, sizeof( psc ) );
		m_pLSBlurPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_LS_BLUR, m_pLSBlurPSC );
}

void Renderer::OnRenderUnderWater( const Renderer::UNDERWATER_EVENT_ARGS& e )
{
	MIX_ASSERT( m_pUnderWaterPSC != NULL );

	if( m_pUnderWaterPSC->Lock() == True )
	{
		Renderer::PSC_UNDER_WATER psc;

		psc.color = e.color;
		psc.density = e.density;
		psc.intensity = e.intensity;
		psc.threshold = e.threshold;
		psc.offset = e.offset;

		m_pUnderWaterPSC->Write( &psc, sizeof( psc ) );
		m_pUnderWaterPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_UNDERWATER, m_pUnderWaterPSC );
}

void Renderer::OnRenderLensFlareImage( const Renderer::RENDER_LENSFLARE_IMAGE_ARGS& e )
{
	MIX_ASSERT( m_pLFImagePSC != NULL );

	if( m_pLFImagePSC->Lock() == True )
	{
		Renderer::PSC_LF_IMAGE psc;

		psc.distoVec = e.distortion;
		psc.numGhost = static_cast<Float32>( e.numGhost );
		psc.ghostWeight = e.ghostWeight;
		psc.ghostDisp = e.ghostDispersion;
		psc.haloWeight = e.haloWeight;
		psc.haloWidth = e.haloWidth;

		m_pLFImagePSC->Write( &psc, sizeof( psc ) );
		m_pLFImagePSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_LF_IMAGE, m_pLFImagePSC );
}

void Renderer::OnRenderLensFlareModify( const Renderer::RENDER_LENSFLARE_MODIFY_ARGS& e )
{
	MIX_ASSERT( m_pLFModifyPSC != NULL );

	if( m_pLFModifyPSC->Lock() == True )
	{
		Renderer::PSC_LF_MODIFY psc;

		psc.dirtInt = e.dirtIntensity;
		psc.dirtExp = e.dirtExposure;
		psc.brustInt = e.brustIntensity;
		psc.brustExp = e.brustExposure;
		psc.camMat = e.camMat;

		m_pLFModifyPSC->Write( &psc, sizeof( psc ) );
		m_pLFModifyPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_LF_MODIFY, m_pLFModifyPSC );
}

void Renderer::OnRenderFilmicHable( const Renderer::RENDER_FILMIC_HABLE_ARGS& e )
{
	MIX_ASSERT( m_pFIHablePSC != NULL );

	if( m_pFIHablePSC->Lock() == True )
	{
		Renderer::PSC_FILMIC_HABLE psc;

		psc.exposureBias = e.exposureBias;
		psc.shoulderStrength = e.shoulderStrength;
		psc.linearStrength = e.linearStrength;
		psc.linearAngle = e.linearAngle;
		psc.toeStrength = e.toeStrength;
		psc.toeNumerator = e.toeNumerator;
		psc.toeDenominator = e.toeDenominator;
		psc.linearWhitePointValue = e.linearWhitePointValue;

		m_pFIHablePSC->Write( &psc, sizeof( psc ) );
		m_pFIHablePSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_FILMIC, m_pFIHablePSC );
}

void Renderer::OnRenderChromatismImage( const Renderer::RENDER_CHROMATISM_IMAGE_ARGS& e )
{
	MIX_ASSERT( m_pCAImagePSC != NULL );

	if( m_pCAImagePSC->Lock() == True )
	{
		Renderer::PSC_CA_IMAGE psc;

		psc.k = e.k;
		psc.kCube = e.kCube;
		psc.scale = e.scale;
		psc.reserve = 0.0f;
		psc.colorFactor = e.colorFactor;

		m_pCAImagePSC->Write( &psc, sizeof( psc ) );
		m_pCAImagePSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_CA_IMAGE, m_pCAImagePSC );
}

void Renderer::OnRenderChromatismFinish( const Renderer::RENDER_CHROMATISM_FINISH_ARGS& e )
{
	MIX_ASSERT( m_pCAFinishPSC != NULL );

	if( m_pCAFinishPSC->Lock() == True )
	{
		Renderer::PSC_CA_FINISH psc;

		psc.weight = e.weight;
		psc.fiStartZ = e.fiStartZ;
		psc.fiInvDist = e.fiInvDist;
		psc.reserve = 0.0f;

		m_pCAFinishPSC->Write( &psc, sizeof( psc ) );
		m_pCAFinishPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_CA_FINISH, m_pCAFinishPSC );
}

void Renderer::OnRenderGammaCorrect( const Renderer::RENDER_GAMMA_ARGS& e )
{
	MIX_ASSERT( m_pGammaCorrectPSC != NULL );

	if( m_pGammaCorrectPSC->Lock() == True )
	{
		m_pGammaCorrectPSC->Write( &( e.invValue ), sizeof( e.invValue ) );
		m_pGammaCorrectPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_GAMMA_CORRECT, m_pGammaCorrectPSC );
}

void Renderer::OnRenderCameraMotionBlur( const Renderer::RENDER_CAMERA_MOTION_BLUR_ARGS& e )
{
	MIX_ASSERT( m_pCamMotBlurPSC != NULL );

	if( m_pCamMotBlurPSC->Lock() == True )
	{
		Renderer::PSC_CAM_MOT_BLUR psc;

		psc.invViewProjMat = e.invViewProjMat;
		psc.preViewProjMat = e.preViewProjMat;

		psc.cp0 = e.cp0;
		psc.cp1 = e.cp1;
		psc.cp2 = e.cp2;
		psc.reserve = 0.0f;

		psc.scale = e.scale;
		psc.intensity = e.intensity;
		psc.invVolume = e.invVolume;
		psc.dist = e.dist;

		m_pCamMotBlurPSC->Write( &psc, sizeof( psc ) );
		m_pCamMotBlurPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_CAM_MOT_BLUR, m_pCamMotBlurPSC );
}

void Renderer::OnRenderDof( const Renderer::RENDER_DOF_ARGS& e )
{
	MIX_ASSERT( m_pDofPSC != NULL );

	if( m_pDofPSC->Lock() == True )
	{
		Renderer::PSC_DOF psc;

		psc.nearZ = e.nearZ;
		psc.farZ = e.farZ;
		psc.invNearDist = e.invNearDist;
		psc.invFarDist = e.invFarDist;

		psc.blurThreshold = e.blurThreshold;
		psc.invBlurThreaholdN = e.invBlurThreaholdN;
		psc.invBlurThreaholdF = e.invBlurThreaholdF;
		psc.reserve = 0.0f;

		Mix::Memory::Copy( psc.samplingTable, e.samplingTable, sizeof( Mix::Vector4 ) * Renderer::DOF_SAMPLING_NUM );

		m_pDofPSC->Write( &psc, sizeof( psc ) );
		m_pDofPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_DOF, m_pDofPSC );
}

void Renderer::OnRenderLensDistortion( const Renderer::RENDER_LENS_DISTORTION_ARGS& e )
{
	MIX_ASSERT( m_pLensDistPSC != NULL );

	if( m_pLensDistPSC->Lock() == True )
	{
		Renderer::PSC_LENS_DIST psc;

		psc.k = e.k;
		psc.kCube = e.kCube;
		psc.scale = e.scale;
		psc.reserve = 0.0f;

		m_pLensDistPSC->Write( &psc, sizeof( psc ) );
		m_pLensDistPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_LENS_DIST, m_pLensDistPSC );
}

void Renderer::OnRenderVignette( const Renderer::RENDER_VIGNETTE_ARGS& e )
{
	MIX_ASSERT( m_pVignettePSC != NULL );

	if( m_pVignettePSC->Lock() == True )
	{
		Renderer::PSC_VIGNETTE psc;

		psc.start = e.start;
		psc.invDist = e.invDist;
		psc.reserve[0] = 0.0f;
		psc.reserve[1] = 0.0f;
		psc.color = e.color;

		m_pVignettePSC->Write( &psc, sizeof( psc ) );
		m_pVignettePSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_LENS_DIST, m_pVignettePSC );
}

void Renderer::OnRenderFXAA( const Renderer::RENDER_FXAA_ARGS& e )
{
	if( m_pFxaaPSC->Lock() == True )
	{
		Renderer::PSC_FXAA psc;

		psc.texCoords[0] = e.texCoords[0];
		psc.texCoords[1] = e.texCoords[1];
		psc.invScreenSize = e.invScreenSize;

		m_pFxaaPSC->Write( &psc, sizeof( psc ) );
		m_pFxaaPSC->Unlock();
	}

	m_pGraphicsDev->SetPixelShaderConstant( Renderer::PSCR_FXAA, m_pFxaaPSC );
}

}}}}
