#pragma once
#include "deferredshadowtechnique.h"
#include "..\DXFunctions\DXVector2.h"
#include "..\GameGUI\GUIElement.h"

class DeferredShadowSMTiled : public DeferredShadowTechnique
{
	ShaderEffect* m_FXSMTiled;

	unsigned	m_Tiling;
	unsigned	m_Xi;
	unsigned	m_ReqResDownSampleSize;
	bool		m_DownSampleReqRes;
	bool		m_UseAvg;

	float** m_pSMTGP;

	DXMatrix m_matInvSMTex;
	DXMatrix m_matLigthProj;

	VertexDeclaration*	m_VDeclSample;
	VertexBuffer*		m_VBSamples;
	unsigned			m_VBRes;
	
	//argb8 with tilex, tiley, resx, resy
	RenderTexture* m_RequiredRes;
	OffscreenRenderTexture* m_RequiredResDownSampled;

	//intermediate x4 rt, rendertexture is sufficient, because no cpu readback is needed
	RenderTexture*	m_RTTileResX_x4;
	RenderTexture*	m_RTTileResY_x4;

	OffscreenRenderTexture*	m_RTTileResX; 
	OffscreenRenderTexture*	m_RTTileResY; 

	static void OnTilingChanged(GUIElement* const sender, const GUIEVENT evnt, void* pData);
	static void OnXiChanged(GUIElement* const sender, const GUIEVENT evnt, void* pData);
	static void OnUseDownSampleReqResChanged(GUIElement* const sender, const GUIEVENT evnt, void* pData);
	static void OnReqResDonwSampleSizeChanged(GUIElement* const sender, const GUIEVENT evnt, void* pData);
	static void OnUseAvgChanged(GUIElement* const sender, const GUIEVENT evnt, void* pData);
	static void OnUseMaxChanged(GUIElement* const sender, const GUIEVENT evnt, void* pData);

	void ProcessPyramid(const unsigned x, const unsigned y, const unsigned level);
	DXVector2 BuildPyramid(const unsigned x, const unsigned y, const unsigned level);
	void RenderRequiredRes(void);
	void RenderTileShadow(const unsigned x, const unsigned y, const unsigned xl, const unsigned yl, const unsigned level);
	void CalculateTileResGPU(void);
	void CalculateTileResCPU(void);
	void CreateRenderTargets(void);
	void CreateMenu(void);

public:
	DeferredShadowSMTiled(ShadowApp* const pApp);
	~DeferredShadowSMTiled(void);

	void SetTiling(const unsigned tiling);
	void SetReqResDownSampleSize(const unsigned size);
	
	void RenderShadowMask(void);

	RenderTexture* GetReqRes(void) const { return m_RequiredRes; }
};
