#include "DeferredShadowZTiled.h"

#include "ShadowApp.h"
#include "ShadowScene.h"
#include "DirectionalLight.h"

#include "..\DXFunctions\FontManager.h"
#include "..\GameGUI\MenuManager.h"
#include "..\GameGUI\Menu.h"
#include "..\GameGUI\Panel.h"
#include "..\GameGUI\Label.h"
#include "..\GameGUI\Slider.h"
#include "..\GameGUI\CheckBox.h"
#include "..\GameGUI\ComboBox.h"

DeferredShadowZTiled::DeferredShadowZTiled(ShadowApp* const pApp) : DeferredShadowTechnique(pApp)
{
	m_FXConfShadow = m_pApp->GetDevice()->GetShaderManager()->CreateFX("Shaders\\ConfidenceShadow.fx");

	m_TileCount = 5;
	m_MaxTilePasses = 1;
	m_Tiling = 0.5f;
	//m_UseLispSM = false;
	m_JitterType = SMJT_HALTON;

	m_lbAutoTilingTiles = NULL;

	m_AutoTiling = false;
	m_MaxSampleSize = 1;
	m_NoConf = false;
	m_ExactFilter = false;
	m_ExactSize = 2;

	CreateMenu();
}

DeferredShadowZTiled::~DeferredShadowZTiled(void)
{
}

void DeferredShadowZTiled::RenderShadowMask(void)
{
	if (m_FXConfShadow->IsCompiled())
	{
		m_FXConfShadow->SetMatrix("g_matInvProj", DXMatrix::InvertMatrix(m_pApp->GetActiveCam().GetProjMatrix()));
		m_FXConfShadow->SetMatrix("g_matInvView", DXMatrix::InvertMatrix(m_pApp->GetActiveCam().GetViewMatrix()));
		m_FXConfShadow->SetMatrix("g_matInvViewProj",  DXMatrix::InvertMatrix(m_pApp->GetActiveCam().GetViewProjMatrix()));
		m_FXConfShadow->SetMatrix("g_matView", m_pApp->GetActiveCam().GetViewMatrix());

		m_FXConfShadow->SetTexture("g_texNormal", m_pApp->m_DSNormal->GetSurface());
		m_FXConfShadow->SetTexture("g_texDiffuse", m_pApp->m_DSDiffuse->GetSurface());

		if (m_pApp->GetWorldPosType() == WPT_WORLDPOS)
			m_FXConfShadow->SetTexture("g_texWorld", m_pApp->m_DSWorld->GetSurface());
		else
			m_FXConfShadow->SetTexture("g_texDepth", m_pApp->m_DSDepth->GetSurface());

		if (m_pApp->GetUseIDBuffer())
			m_FXConfShadow->SetTexture("g_texID", m_pApp->m_DSID->GetSurface());
		
		m_FXConfShadow->SetTexture("SM_ShadowMap", m_pApp->GetShadowMapping()->GetShadowMap());
		m_FXConfShadow->SetTexture("SM_IDBuffer", m_pApp->m_SM->GetIDBuffer());
		m_FXConfShadow->SetFloat("SM_ShadowMapSize", m_pApp->GetShadowMapping()->GetShadowMapSize());
		m_FXConfShadow->SetMatrix("SM_matSM", m_pApp->GetShadowMapping()->GetSMMatrix());
		
		m_FXConfShadow->SetFloat("SM_DetphBias", m_pApp->GetConstBias());
		m_FXConfShadow->SetFloat("SM_SlopeBias", m_pApp->GetSlopeBias());

		float rtsize[2] = {m_pApp->GetDevice()->GetViewPort()->GetWidth(), m_pApp->GetDevice()->GetViewPort()->GetHeight()};
		m_FXConfShadow->SetFloatArray("g_RTSize", rtsize, 2);

		m_FXConfShadow->SetFloatArray("g_LightDir", m_pApp->GetActiveScene()->GetLight()->GetDirection(), 3);

		m_FXConfShadow->SetFloat("g_MaxPasses", m_pApp->m_Config.MaxJitter + 1);

		IDirect3DQuery9* pOcclusionQuery;
		m_pApp->GetDevice()->GetDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &pOcclusionQuery);

		m_pApp->GetDevice()->SetStencilEnalbe(false);

		if (m_ExactFilter)
		{
			m_pApp->RenderOptConf(1);
			
			m_FXConfShadow->SetTexture("g_texOptConf", m_pApp->m_OptConf->GetSurface());
			m_FXConfShadow->SetFloat("g_ConfScale", 1);
			m_FXConfShadow->SetFloat("g_ExactFilterSize", m_ExactSize);
		}

		m_FXConfShadow->SetFloat("g_ShadowConfT", 0);

		//camera for a tile
		Camera c = m_pApp->GetActiveScene()->GetCamera();
		
		/*BoundingMesh bm = BoundingMesh(ViewFrustum(c));
		
		bm.ClipByAABB(m_pApp->GetActiveScene()->GetSceneBound());
		bm.TransformPoints(c.GetViewMatrix());
		AABB asdf = bm.BuildAABB();
		float hnf = bm.BuildAABB().GetE().z * 2;*/

		//now iterate the tiles from back to front
				
		float n = 1;
		float f = _min(2000, m_pApp->GetActiveScene()->GetLight()->GetShadowFar());

		float autofar = f;

		unsigned cnt = 0;
		unsigned tile = 0;

		int inext = 0;

		m_pApp->m_SM->SetJitterType(m_JitterType);
//		m_pApp->m_SM->SetLispSMEnable(m_UseLispSM);

		float smsize0;
		
		while(true)
		{
			unsigned nochange = 0;
			unsigned ijitter = 0;

			float ntile, ftile; //near and farplane of tile

			if (m_AutoTiling)
			{
				//far * screensize / shadowmapsize / fragsize = dist, 
				//gives the distance where a sample of a planar projeceted shadow map is "fragsize" in screenspace
				//to get the tile nearplane, the double size of the actual shadow map is used in the equation above
				
				if (tile == m_TileCount - 1)
				{
					ntile = n;
				}
				else if (tile == m_TileCount - 2)
				{
					//render tiles from back to front
					float tn = 0.5f;

					float slog = n * pow(autofar / n, tn);
					float suniform = n + (autofar - n) * tn;

					ntile = slog * m_Tiling + suniform * (1 - m_Tiling);

				//	ntile = max(n, autofar * m_pApp->GetDevice()->GetViewPort()->GetHeight() / (m_pApp->GetSMSize() * 2 * m_MaxSampleSize));
				}
				else
				{
					float sigma = 1;
					float fw = autofar * sigma;
					float dw = fw / m_pApp->GetSMSize();

					float resavg = (m_pApp->GetDevice()->GetViewPort()->GetWidth() + m_pApp->GetDevice()->GetViewPort()->GetHeight()) * 0.5f;

					ntile = dw * resavg / m_MaxSampleSize; 

					float fx = sigma * resavg / m_MaxSampleSize / m_pApp->GetSMSize(); 
					fx = fx;

					float fx2 = ntile / autofar;
					fx2 = fx2;

				//	ntile = max(n, autofar * m_pApp->GetDevice()->GetViewPort()->GetHeight() / (m_pApp->GetSMSize() * 2 * m_MaxSampleSize));
				}
				ftile = autofar;

				if (ftile <= n)
					break;

				autofar = ntile;
			}
			else
			{
				//render tiles from back to front
				float tn = (m_TileCount - tile - 1) / (float)m_TileCount;
				float tf = (m_TileCount - tile) / (float)m_TileCount;

				float nlog = n * pow(f / n, tn);
				float nuniform = n + (f - n) * tn;

				float flog = n * pow(f / n, tf);
				float funiform = n + (f - n) * tf;

				ntile = nlog * m_Tiling + nuniform * (1 - m_Tiling);
				ftile = flog * m_Tiling + funiform * (1 - m_Tiling);
			}

			//set camera for this tile
			c.SetPerspectiveProj(m_pApp->GetActiveScene()->GetCamera().GetAspectRatio(), 1, ntile, ftile); 

			m_pApp->GetShadowMapping()->Update(m_pApp->GetActiveScene()->GetSceneBound(), c, m_pApp->GetActiveScene()->GetLight()->GetDirection());

			m_pApp->GetActiveScene()->UpdateVisibleMesh(c);
			m_pApp->GetActiveScene()->GetLight()->UpdateShadowBound(c);

			//ViewFrustum lvf(Camera(m_pApp->GetShadowMapping()->GetLightView(), m_pApp->GetShadowMapping()->GetLightProj()));

			//build frustum to cull shadow caster
			//Frustum sf;

			//push antilightplanes from viewfrustum
			//for (int i = 0; i <C->GetLightFrustum().planes.size() - 6; i++)
			//	sf.planes.push_back(m_pApp->GetActiveScene()->GetLight()->GetLightFrustum().planes[i]);
					
			//for (int i = 0; i < 6; i++)
			//	sf.planes.push_back(lvf.ClipPlanes[i]);

			//first input comes from whole lightfrustum, it is spittet in Curr (farest tile) and Next (the first part, which are all other tiles)
			//for tiles > 0, input is always old Next which is split to Curr und new Next
			//GetTileShadowCasters(sf, cnt == 0 ? m_pApp->GetActiveScene()->GetLight()->GetShadowCasters() : m_RLNext[!inext], m_RLCurr, m_RLNext[inext]);
			
			//GetTileShadowCasters(m_pApp->GetActiveScene()->GetLight()->GetLightFrustum(), true/*cnt == 0*/ ? m_pApp->GetActiveScene()->GetLight()->GetShadowCasters() : m_RLNext[!inext], m_RLCurr, m_RLNext[inext]);

			m_pApp->GetActiveScene()->GetLight()->ClearRenderList();
			m_pApp->GetActiveScene()->GetSpatialPartitioningTree()->TraverseVisibleObjects(m_pApp->GetActiveScene()->GetLight()->GetLightFrustum(), DirectionalLight::GatherShadowCasters, m_pApp->GetActiveScene()->GetLight());

			if (!cnt)
			{
				m_FXConfShadow->SetFloat("g_ConfScale", 1);
				smsize0 = m_pApp->GetShadowMapping()->GetSMWorldSize();
			}
			else
			{
				m_FXConfShadow->SetFloat("g_ConfScale", smsize0 / m_pApp->GetShadowMapping()->GetSMWorldSize());
			}

			//wlog("%f",smsize0 / m_pApp->GetShadowMapping()->GetSMWorldSize());

			while(true && m_pApp->GetShadowMapping()->GetSMWorldSize() > 0)
			{
				m_pApp->m_SM->Jitter(ijitter++);

				//m_pApp->GetActiveScene()->GetLight()->RenderShadowMap(m_RLCurr);
				m_pApp->GetActiveScene()->GetLight()->RenderShadowMap();

				//m_Device->SetStencilEnalbe(true);
				
				//m_FXDS->SetMatrix("SM_matSMTex", m_SM->GetSMTexMatrix());

				//needs  to be set each iteration, because of jitter
				m_FXConfShadow->SetMatrix("SM_matSM", m_pApp->m_SM->GetSMMatrix());

				//if(!cnt && m_SampleVis)
				if(m_pApp->m_VisType == VIS_SAMPLE)
				{
					m_pApp->DrawSampleVis();
				}

				//D3DXSaveTextureToFile("bla.dds",D3DXIFF_DDS,m_DSTest->GetSurface()->GetSurface(),NULL);

				if(m_pApp->m_BenchType == BT_CONVERGENCE && m_pApp->m_RenderRef)
					m_pApp->m_DSShadowRef->StartRender(0);
				else
					m_pApp->m_DSShadow[0]->StartRender(0);
 
				if(!cnt)  
				{
					m_pApp->GetDevice()->Clear(D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, 0, 0, 0);
				}

				XString tech = "RenderShadow_Tile";

				if (m_NoConf)
				{
					tech.appand("_Select");
					m_FXConfShadow->SetFloat("g_TileNear", ntile);
					m_FXConfShadow->SetFloat("g_TileFar", ftile);
				}

				if (m_pApp->GetWorldPosType() == WPT_DEPTH)
					tech.appand("_Depth");
				else if (m_pApp->GetWorldPosType() == WPT_LINEARDEPTH)
					tech.appand("_LinearDepth");
				else if (m_pApp->GetWorldPosType() == WPT_WORLDPOS)
					tech.appand("_World");

				if (m_pApp->GetSMFiltering())
				{
					tech.appand("_Filter");

					if (m_ExactFilter)
						tech.appand("Ex");
				}
				else if (m_pApp->GetUseIDBuffer())
				{
					tech.appand("_ID");
				}

				m_FXConfShadow->SetTechnique(tech);

				m_FXConfShadow->SetFloat("g_BiasScale", m_pApp->GetShadowMapping()->GetSMWorldSize() / smsize0);

				m_FXConfShadow->SetFloat("g_iPass", cnt);
				
				pOcclusionQuery->Issue(D3DISSUE_BEGIN);

				m_pApp->RenderFSQuad(m_FXConfShadow);

				pOcclusionQuery->Issue(D3DISSUE_END);

				// Force the driver to execute the commands from the command buffer.
				// Empty the command buffer and wait until the GPU is idle.
				while(S_FALSE == pOcclusionQuery->GetData(&m_pApp->m_LastPixelDrawed, sizeof(DWORD), D3DGETDATA_FLUSH ));

				int drawT = 100;
				if(m_pApp->m_LastPixelDrawed < drawT)
					nochange++;
				else
					nochange = 0;
				m_pApp->m_PixelSet[cnt] = m_pApp->m_LastPixelDrawed;
			

				//end rendering of dsshadowref after testconfidence because the depth surface is needed
				//m_DSPass->EndRender();
				if(m_pApp->m_BenchType == BT_CONVERGENCE && m_pApp->m_RenderRef)
					m_pApp->m_DSShadowRef->EndRender();
				else
					m_pApp->m_DSShadow[0]->EndRender();
				
				cnt++; 

				//int ScreenPixels = m_Device->GetViewPort()->Width * m_Device->GetViewPort()->Height;
				if (ijitter >= m_MaxTilePasses) 
					break;

				//if(!usebrandnew)
				int drawTPasses = 2;
				if(nochange >= drawTPasses)
					break;
			}

			inext = !inext;
			tile++;
			
			if (tile >= m_TileCount)
				break;
		}

		m_lbAutoTilingTiles->SetText(XString((int)tile));
		
		pOcclusionQuery->Release();
		
	}
}

void DeferredShadowZTiled::UpdateInput(void)
{
}

void DeferredShadowZTiled::GetTileShadowCasters(const Frustum& f, const RenderList& all, RenderList& curr, RenderList& next)
{
	next.Clear();
	curr.Clear();

	for (int i = 0; i < all.GetJobCount(); i++)
	{
		RenderJob* job = all.GetJobs()[i];

		CONTAINMENTTESTRESULT test = Cont_OBS_In_Frustum(*((OBS*)(job->UserData)), f);

		if (test != CTR_DISJOINT)
			curr.AddRJ(job);

		if (test != CTR_CONTAINS)
			next.AddRJ(job);
	}
}

void DeferredShadowZTiled::CreateMenu(void)
{
	m_pMenu = new Menu(m_pApp->GetMenuManager(), 122);

	Panel* pnBack = new Panel(m_pApp->GetMenuManager(), 1111);
	pnBack->SetPosition(300, 85);
	pnBack->SetSize(250, 380);
	pnBack->SetOpacity(0.8f);
	pnBack->SetTexture(m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\ck.png", FMT_A8R8G8B8, POOL_MANAGED));
	pnBack->SetAlphaBlend(true);
	pnBack->SetFixedBorder(4);

	m_pMenu->AddChild(pnBack);

	FontParam fp;
	fp.m_Height = 16;
	Font* font = m_pApp->GetDevice()->GetFontManager()->Create(fp);

	int y = 20;

	//CheckBox* ckUseLispSM = new CheckBox(m_pApp->GetMenuManager(), 2);
	//ckUseLispSM->SetUserData(this);
	//ckUseLispSM->SetPosition(20, y);
	//ckUseLispSM->SetSize(100, 20);
	//ckUseLispSM->SetChecked(m_UseLispSM);
	//ckUseLispSM->SetText("Use LispSM [F2]");
	//ckUseLispSM->SetTexture(m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\ck.png", FMT_A8R8G8B8, POOL_MANAGED), 
	//				m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\ckc.png", FMT_A8R8G8B8, POOL_MANAGED));
	//ckUseLispSM->SetAlphaBlend(true);
	//ckUseLispSM->SetFont(font);
	//ckUseLispSM->SetEventHandler(GE_VALUECHANGED, OnLispSMCheck);

	//pnBack->AddChild(ckUseLispSM);

	//y += 30;

	Label *lbjitter = new Label(m_pApp->GetMenuManager(), 2);
	lbjitter->SetPosition(10, y);
	lbjitter->SetSize(100, 20);
	lbjitter->SetText("Jitter Type: ");
	lbjitter->SetFont(font);
	
	pnBack->AddChild(lbjitter);

	ComboBox* cbJitterType = new ComboBox(m_pApp->GetMenuManager(), 12344);
	cbJitterType->SetUserData(this);
	cbJitterType->SetPosition(100, y);
	cbJitterType->SetSize(130, 22);
	cbJitterType->SetDropDownHeight(104);
	cbJitterType->SetDropDownItemHeight(19);
	cbJitterType->AddItem("None");
	cbJitterType->AddItem("Random");
	cbJitterType->AddItem("Halton");
	cbJitterType->AddItem("Rotation");
	cbJitterType->AddItem("LispSM N");
	cbJitterType->SetTexture(m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\input.png", FMT_A8R8G8B8, POOL_MANAGED), false, 3, 
					m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\combo.png", FMT_A8R8G8B8, POOL_MANAGED), true,
					m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\list.png", FMT_A8R8G8B8, POOL_MANAGED), 
					m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\listsel.png", FMT_A8R8G8B8, POOL_MANAGED), false, 4);
	cbJitterType->SetTextColor(D3DXCOLOR(0,0,0,1), D3DXCOLOR(1,1,1,1));
	cbJitterType->SetFont(font);
	cbJitterType->SetClientBorder(5);
	cbJitterType->SetSelectedIndex((int)m_JitterType);
	cbJitterType->SetEventHandler(GE_VALUECHANGED, OnJitterTypeChanged);

	y += 30;

	Label* lbTiles = new Label(m_pApp->GetMenuManager(), 0);
	lbTiles->SetSize(110, 20);
	lbTiles->SetPosition(10, y);
	lbTiles->SetFont(font);
	lbTiles->SetText("Tiles:");

	pnBack->AddChild(lbTiles);

	Label* lbTilesValue = new Label(m_pApp->GetMenuManager(), 0);
	lbTilesValue->SetUserData(this);
	lbTilesValue->SetSize(40, 20);
	lbTilesValue->SetPosition(60, y);
	lbTilesValue->SetFont(font);
	lbTilesValue->SetText("xxx");
	lbTilesValue->SetTextAlign(AL_RIGHTBOTTOM);

	pnBack->AddChild(lbTilesValue);

	Slider* slTiles = new Slider(m_pApp->GetMenuManager(), 345);
	slTiles->SetUserData(lbTilesValue);
	slTiles->SetPosition(100, y+2);
	slTiles->SetSize(130, 20);
	slTiles->SetRange(1, 10);
	slTiles->SetSliderSize(10, 20, 20, 10);
	slTiles->SetTexture(m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\slider.png", FMT_A8R8G8B8, POOL_MANAGED), 
					m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\nob.png", FMT_A8R8G8B8, POOL_MANAGED));
	slTiles->SetAlphaBlend(true);

	pnBack->AddChild(slTiles);
	slTiles->SetEventHandler(GE_VALUECHANGED, OnTilesChanged);
	slTiles->SetValue(m_TileCount);

	y += 30;

	Label* lbTilePasses = new Label(m_pApp->GetMenuManager(), 0);
	lbTilePasses->SetSize(110, 20);
	lbTilePasses->SetPosition(10, y);
	lbTilePasses->SetFont(font);
	lbTilePasses->SetText("TilePasses:");

	pnBack->AddChild(lbTilePasses);

	Label* lbTilePassesValue = new Label(m_pApp->GetMenuManager(), 0);
	lbTilePassesValue->SetUserData(this);
	lbTilePassesValue->SetSize(40, 20);
	lbTilePassesValue->SetPosition(60, y);
	lbTilePassesValue->SetFont(font);
	lbTilePassesValue->SetText("xxx");
	lbTilePassesValue->SetTextAlign(AL_RIGHTBOTTOM);

	pnBack->AddChild(lbTilePassesValue);

	Slider* slTilePasses = new Slider(m_pApp->GetMenuManager(), 345);
	slTilePasses->SetUserData(lbTilePassesValue);
	slTilePasses->SetPosition(100, y+2);
	slTilePasses->SetSize(130, 20);
	slTilePasses->SetRange(1, 10);
	slTilePasses->SetSliderSize(10, 20, 20, 10);
	slTilePasses->SetTexture(m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\slider.png", FMT_A8R8G8B8, POOL_MANAGED), 
					m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\nob.png", FMT_A8R8G8B8, POOL_MANAGED));
	slTilePasses->SetAlphaBlend(true);

	pnBack->AddChild(slTilePasses);
	slTilePasses->SetEventHandler(GE_VALUECHANGED, OnMaxTilePassesChanged);
	slTilePasses->SetValue(m_MaxTilePasses);

	
	y += 30;

	Label* lbTiling = new Label(m_pApp->GetMenuManager(), 0);
	lbTiling->SetSize(110, 20);
	lbTiling->SetPosition(10, y);
	lbTiling->SetFont(font);
	lbTiling->SetText("Uni<->Log:");

	pnBack->AddChild(lbTiling);

	Label* lbTilingValue = new Label(m_pApp->GetMenuManager(), 0);
	lbTilingValue->SetUserData(this);
	lbTilingValue->SetSize(40, 20);
	lbTilingValue->SetPosition(60, y);
	lbTilingValue->SetFont(font);
	lbTilingValue->SetText("xxx");
	lbTilingValue->SetTextAlign(AL_RIGHTBOTTOM);

	pnBack->AddChild(lbTilingValue);

	Slider* slTiling = new Slider(m_pApp->GetMenuManager(), 345);
	slTiling->SetUserData(lbTilingValue);
	slTiling->SetPosition(100, y+2);
	slTiling->SetSize(130, 20);
	slTiling->SetRange(0, 100);
	slTiling->SetSliderSize(10, 20, 20, 10);
	slTiling->SetTexture(m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\slider.png", FMT_A8R8G8B8, POOL_MANAGED), 
					m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\nob.png", FMT_A8R8G8B8, POOL_MANAGED));
	slTiling->SetAlphaBlend(true);

	pnBack->AddChild(slTiling);
	slTiling->SetEventHandler(GE_VALUECHANGED, OnTilingChanged);
	slTiling->SetValue((int)(m_Tiling * 100));

	y += 30;

	CheckBox* ckAutoTile = new CheckBox(m_pApp->GetMenuManager(), 24);
	ckAutoTile->SetUserData(this);
	ckAutoTile->SetPosition(10, y);
	ckAutoTile->SetSize(100, 20);
	ckAutoTile->SetChecked(m_AutoTiling);
	ckAutoTile->SetText("AutoTiling");
	ckAutoTile->SetTexture(m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\ck.png", FMT_A8R8G8B8, POOL_MANAGED), 
					m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\ckc.png", FMT_A8R8G8B8, POOL_MANAGED));
	ckAutoTile->SetAlphaBlend(true);
	ckAutoTile->SetFont(font);
	ckAutoTile->SetEventHandler(GE_VALUECHANGED, OnAutoTilingChanged);

	pnBack->AddChild(ckAutoTile);

	Label* lbAutoTiles = new Label(m_pApp->GetMenuManager(), 0);
	lbAutoTiles->SetSize(110, 20);
	lbAutoTiles->SetPosition(100, y-2);
	lbAutoTiles->SetFont(font);
	lbAutoTiles->SetText("Tiles:");

	pnBack->AddChild(lbAutoTiles);

	m_lbAutoTilingTiles = new Label(m_pApp->GetMenuManager(), 0);
	m_lbAutoTilingTiles->SetSize(110, 20);
	m_lbAutoTilingTiles->SetPosition(140, y-2);
	m_lbAutoTilingTiles->SetFont(font);
	m_lbAutoTilingTiles->SetText("xx");

	pnBack->AddChild(m_lbAutoTilingTiles);

	y += 30;

	CheckBox* ckNoConfidence = new CheckBox(m_pApp->GetMenuManager(), 24);
	ckNoConfidence->SetUserData(this);
	ckNoConfidence->SetPosition(10, y);
	ckNoConfidence->SetSize(100, 20);
	ckNoConfidence->SetChecked(m_AutoTiling);
	ckNoConfidence->SetText("No Confidence (select slice only)");
	ckNoConfidence->SetTexture(m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\ck.png", FMT_A8R8G8B8, POOL_MANAGED), 
					m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\ckc.png", FMT_A8R8G8B8, POOL_MANAGED));
	ckNoConfidence->SetAlphaBlend(true);
	ckNoConfidence->SetFont(font);
	ckNoConfidence->SetEventHandler(GE_VALUECHANGED, OnNoConfidence);

	pnBack->AddChild(ckNoConfidence);

	y += 30;

	Label* lbMaxSample = new Label(m_pApp->GetMenuManager(), 0);
	lbMaxSample->SetSize(110, 20);
	lbMaxSample->SetPosition(10, y);
	lbMaxSample->SetFont(font);
	lbMaxSample->SetText("FragSize:");

	pnBack->AddChild(lbMaxSample);

	Label* lbMaxSampleValue = new Label(m_pApp->GetMenuManager(), 0);
	lbMaxSampleValue->SetUserData(this);
	lbMaxSampleValue->SetSize(40, 20);
	lbMaxSampleValue->SetPosition(75, y);
	lbMaxSampleValue->SetFont(font);
	lbMaxSampleValue->SetText("xxx");
	lbTilingValue->SetTextAlign(AL_RIGHTBOTTOM);

	pnBack->AddChild(lbMaxSampleValue);

	Slider* slMaxSample = new Slider(m_pApp->GetMenuManager(), 345);
	slMaxSample->SetUserData(lbMaxSampleValue);
	slMaxSample->SetPosition(100, y+2);
	slMaxSample->SetSize(130, 20);
	slMaxSample->SetRange(50, 400);
	slMaxSample->SetSliderSize(10, 20, 20, 10);
	slMaxSample->SetTexture(m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\slider.png", FMT_A8R8G8B8, POOL_MANAGED), 
					m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\nob.png", FMT_A8R8G8B8, POOL_MANAGED));
	slMaxSample->SetAlphaBlend(true);

	pnBack->AddChild(slMaxSample);
	slMaxSample->SetEventHandler(GE_VALUECHANGED, OnMaxSampleSizeChanged);
	slMaxSample->SetValue((int)(m_MaxSampleSize * 100));

	y += 30;

	CheckBox* ckExactFilter = new CheckBox(m_pApp->GetMenuManager(), 24);
	ckExactFilter->SetUserData(this);
	ckExactFilter->SetPosition(10, y);
	ckExactFilter->SetSize(100, 20);
	ckExactFilter->SetChecked(m_ExactFilter);
	ckExactFilter->SetText("ExactFilter");
	ckExactFilter->SetTexture(m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\ck.png", FMT_A8R8G8B8, POOL_MANAGED), 
					m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\ckc.png", FMT_A8R8G8B8, POOL_MANAGED));
	ckExactFilter->SetAlphaBlend(true);
	ckExactFilter->SetFont(font);
	ckExactFilter->SetEventHandler(GE_VALUECHANGED, OnExactFilterChanged);

	pnBack->AddChild(ckExactFilter);

	Label* lbSize = new Label(m_pApp->GetMenuManager(), 0);
	lbSize->SetSize(110, 20);
	lbSize->SetPosition(110, y-3);
	lbSize->SetFont(font);
	lbSize->SetText("Size:");

	pnBack->AddChild(lbSize);

	Label* lbExactSize = new Label(m_pApp->GetMenuManager(), 0);
	lbExactSize->SetUserData(this);
	lbExactSize->SetSize(40, 20);
	lbExactSize->SetPosition(122, y-3);
	lbExactSize->SetFont(font);
	lbExactSize->SetText("xxx");
	lbExactSize->SetTextAlign(AL_RIGHTBOTTOM);

	pnBack->AddChild(lbExactSize);

	Slider* slExactSize = new Slider(m_pApp->GetMenuManager(), 345);
	slExactSize->SetUserData(lbExactSize);
	slExactSize->SetPosition(170, y-1);
	slExactSize->SetSize(60, 20);
	slExactSize->SetRange(10, 30);
	slExactSize->SetSliderSize(10, 20, 20, 10);
	slExactSize->SetTexture(m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\slider.png", FMT_A8R8G8B8, POOL_MANAGED), 
					m_pApp->GetDevice()->GetTextureManager()->CreateTexture("GUI\\nob.png", FMT_A8R8G8B8, POOL_MANAGED));
	slExactSize->SetAlphaBlend(true);

	pnBack->AddChild(slExactSize);
	slExactSize->SetEventHandler(GE_VALUECHANGED, OnExactSizeChanged);
	slExactSize->SetValue((int)(m_ExactSize * 10));

	pnBack->AddChild(cbJitterType);
}

//void DeferredShadowZTiled::OnLispSMCheck(GUIElement* const sender, const GUIEVENT evnt, void* pData)
//{
//	CheckBox* ck = dynamic_cast<CheckBox*>(sender);
//	DeferredShadowZTiled* me = (DeferredShadowZTiled*)ck->GetUserData();
//
//	if (ck && me)
//	{
//		me->m_UseLispSM = ck->IsChecked();
//	}
//}

void DeferredShadowZTiled::OnJitterTypeChanged(GUIElement* const sender, const GUIEVENT evnt, void* pData)
{
	ComboBox* cb = dynamic_cast<ComboBox*>(sender);
	DeferredShadowZTiled* me = (DeferredShadowZTiled*)cb->GetUserData();

	if (me && cb && cb->GetSelectedIndex() >= 0)
	{
		me->m_JitterType = ((SMJITTERTYPE)cb->GetSelectedIndex());
	}
}

void DeferredShadowZTiled::OnAutoTilingChanged(GUIElement* const sender, const GUIEVENT evnt, void* pData)
{
	CheckBox* ck = dynamic_cast<CheckBox*>(sender);
	DeferredShadowZTiled* me = (DeferredShadowZTiled*)ck->GetUserData();

	if (me && ck)
	{
		me->m_AutoTiling = ck->IsChecked();
	}
}

void DeferredShadowZTiled::OnTilesChanged(GUIElement* const sender, const GUIEVENT evnt, void* pData)
{
	Slider* sl = dynamic_cast<Slider*>(sender);
	Label* lb = (Label*)sl->GetUserData();
	DeferredShadowZTiled* me = (DeferredShadowZTiled*)lb->GetUserData();

	if (me && sl && lb)
	{
		lb->SetText(XString(sl->GetValue()));
		me->m_TileCount = sl->GetValue();
	}
}

void DeferredShadowZTiled::OnMaxTilePassesChanged(GUIElement* const sender, const GUIEVENT evnt, void* pData)
{
	Slider* sl = dynamic_cast<Slider*>(sender);
	Label* lb = (Label*)sl->GetUserData();
	DeferredShadowZTiled* me = (DeferredShadowZTiled*)lb->GetUserData();

	if (me && sl && lb)
	{
		lb->SetText(XString(sl->GetValue()));
		me->m_MaxTilePasses = sl->GetValue();
	}
}

void DeferredShadowZTiled::OnTilingChanged(GUIElement* const sender, const GUIEVENT evnt, void* pData)
{
	Slider* sl = dynamic_cast<Slider*>(sender);
	Label* lb = (Label*)sl->GetUserData();
	DeferredShadowZTiled* me = (DeferredShadowZTiled*)lb->GetUserData();

	if (me && sl && lb)
	{
		float t = sl->GetValue() / 100.0f;
		lb->SetText(XString(t));
		me->m_Tiling = t;
	}
}

void DeferredShadowZTiled::OnMaxSampleSizeChanged(GUIElement* const sender, const GUIEVENT evnt, void* pData)
{
	Slider* sl = dynamic_cast<Slider*>(sender);
	Label* lb = (Label*)sl->GetUserData();
	DeferredShadowZTiled* me = (DeferredShadowZTiled*)lb->GetUserData();

	if (me && sl && lb)
	{
		float s = sl->GetValue() / 100.0f;
		lb->SetText(XString(s));
		me->m_MaxSampleSize = s;
	}
}

void DeferredShadowZTiled::OnNoConfidence(GUIElement* const sender, const GUIEVENT evnt, void* pData)
{
	CheckBox* ck = dynamic_cast<CheckBox*>(sender);
	DeferredShadowZTiled* me = (DeferredShadowZTiled*)ck->GetUserData();

	if (me && ck)
	{
		me->m_NoConf = ck->IsChecked();
	}
}

void DeferredShadowZTiled::OnExactFilterChanged(GUIElement* const sender, const GUIEVENT evnt, void* pData)
{
	CheckBox* ck = dynamic_cast<CheckBox*>(sender);
	DeferredShadowZTiled* me = (DeferredShadowZTiled*)ck->GetUserData();

	if (me && ck)
	{
		me->m_ExactFilter = ck->IsChecked();
	}
}

void DeferredShadowZTiled::OnExactSizeChanged(GUIElement* const sender, const GUIEVENT evnt, void* pData)
{
	Slider* sl = dynamic_cast<Slider*>(sender);
	Label* lb = (Label*)sl->GetUserData();
	DeferredShadowZTiled* me = (DeferredShadowZTiled*)lb->GetUserData();

	if (me && sl && lb)
	{
		float s = sl->GetValue() / 10.0f;
		lb->SetText(XString(s));
		me->m_ExactSize = s;
	}
}