///////////////////////////////////////////////
//Shadowing
///////////////////////////////////////////////
AVOID DeferredRenderer::VGenerateShadowMaps()
{
	if (m_bVarianceShadows)
	{
		//m_pVarianceShadowsShaders->VBind();
		//m_pShadowsShaders->VBind();
	}
	else
	{
		//m_pShadowsShaders->VBind();
	}
	m_pShadowCubeShaders->VBind();

	//Set rendering states
	m_pDepthEnableStencilDisableStandard->Set(1);
	for (LightList::iterator lit = m_lights.begin(); lit != m_lights.end(); lit++)
	{
		Light* pLight = (*lit);

		//initialize light if it hasn't been yet 
		if (!pLight->IsInitialized())
			pLight->VInitialize(m_pLayout);

		//clear shadow map before generating new one
		pLight->VClearShadowMap();

		Mesh * pMesh;
		m_queue.Reset();
		while (pMesh = m_queue.Next())
		{
			//pMesh->VPreRender(this, view, viewProj); 
			pLight->VPrepareToGenerateShadowMap(pMesh->GetWorldTransform(), this);
			pMesh->GenerateShadowMap();
		} 

		pLight->VFinishShadowMapGeneration(this);
	}
}
AVOID DeferredRenderer::VRender()
{
	/*** Render Scene For Each Camera ***/
 	//for (CameraPtr pCamera : m_cameras)
	for (Cameras::iterator it = m_cameras.begin(); it != m_cameras.end(); it++)
	{
		CameraPtr pCamera = (*it);
		//Keep track of current view and projection matrices
		Mat4x4 view			= pCamera->GetView();
		Mat4x4 projection	= pCamera->GetProjection();
		Mat4x4 viewProj		= view * projection; //calculate view * projection matrix

		VRenderSky(pCamera, viewProj);

		//	Rendering to g-buffer
		m_gbuffer.BindForWriting(m_pDepthDSV);

		// ===================================================== //
		//	Go through sorted render queue and render each mesh  //
		// ===================================================== //
		PrepareForGeometryPass(pCamera);
		VSetStateForGBuffer();
		m_pDepthEnableStencilDisableStandard->Set(1);
		Mesh * pMesh;
		m_queue.Reset();
		while (pMesh = m_queue.Next())
		{
			//set states needed for rendering current mesh
			pMesh->VPreRender(this, view, viewProj); 

			//finally render it
			pMesh->VRender(this);

			//remove previous states
			pMesh->VPostRender(this);
		} 
		//unbind g-buffer views
		m_gbuffer.UnbindFromWriting();

		// ========================================= //
		//		Generate Shadow Maps				 //
		// ========================================= //
		VGenerateShadowMaps();

		// ========================================= //
		//		Generate velocity map				 //
		// ========================================= //
		//VGenerateVelocityMap(pCamera, this, viewProj);

		//clear meshes queue
		m_queue.Clear();
		//m_pDepthDisableStencilDisable->Set(0);

		//filter variance shadow maps
		if (m_bVarianceShadows)
		{
			for (LightList::iterator lit = m_lights.begin(); lit != m_lights.end(); lit++)
			{
				Light* pLight = (*lit);
				for (int i =0; i < 1; i++)
				{
					//FilterImage(pLight->GetVarianceShadowMapSRV(), pLight->GetVarianceShadowUAV(), pLight->GetTempSRV(), pLight->GetTempUAV(), SCREEN_WIDTH, SCREEN_HEIGHT, FT_Gaussian);
				}
			}
		}

		// ========================================= //
		//	Calculate ambient occlusion				 //
		// ========================================= //
		//CalculateAmbientOcclusion(pCamera);
		//FilterImage(m_pSSAOSRV, m_pSSAOBlurredUAV, FT_Gaussian);

		//m_pSSAOSRV->Set(5, ST_Pixel); 
		// ========================================= //
		//	Time for light pass - Render all lights  //
		// ========================================= //

		//set g-buffer for reading and set back buffer as render target
		m_gbuffer.BindForReading(0);
		//SetRenderTargetView(); 
		m_pTempRTV->Set();

		PrepareForLightPass(pCamera);

		//for (Light * pLight : m_lights)
		for (LightList::iterator lit = m_lights.begin(); lit != m_lights.end(); lit++)
		{
			Light* pLight = (*lit);

			//initialize light if it hasn't been yet 
			if (!pLight->IsInitialized())
				pLight->VInitialize(m_pLayout);

			//set states needed for rendering current light
			pLight->VPreRender(this); 

			//scissor test optimization
			pLight->VSetScissorRect(this, pCamera);

			//finally render it
			pLight->VRender();

			//remove all used states
			pLight->VPostRender(this);
		}
		this->NoBlending()->Set(nullptr);

		//VApplyMotionBlur();
		CopyPostProcessingToBackBuffer();

		//clean lights
		while(!m_lights.empty())
		{
			m_lights.pop_back();
		}

		//unbind g-buffer views
		m_gbuffer.UnbindFromReading(0);
		m_gbuffer.Clear();

		UnbindShaderResourceViews(6, 1, ST_Pixel);
		VFinishPass();
	}
}