//----------------------------------------------------//
//                                                    //
// This is a free rendering engine. The library and   //
// the source code are free. If you use this code as  //
// is or any part of it in any kind of project or     //
// product, please acknowledge the source and its	  //
// author.											  //
//                                                    //
// For manuals, help and instructions, please visit:  //
// http://graphics.cs.aueb.gr/graphics/               //
//                                                    //
//----------------------------------------------------//
//void DeferredRenderer::DrawSSAO(DRVisual& visual)
	//{
	//	AmbientOcclusion& ambient_occlusion = GetAmbientOcclusion();

	//	AO_PASS_TYPE type = ambient_occlusion.GetAOType();
	//	//ambient_occlusion.SetAOMultiviewMethod(AOM_SAMPLES_BUFFER);
	//	if (ambient_occlusion.IsMultiviewEnabled()) type = ambient_occlusion.GetAOMultiviewType();

	//	glDisable(GL_CULL_FACE);
	//	glBindVertexArray(0);
	//	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
	//	glBindBuffer(GL_ARRAY_BUFFER,0);

	//	glBindVertexArray(m_technique_ssao->m_vao);

	//	glEnable(GL_TEXTURE_2D);
	//	glEnable(GL_TEXTURE_3D);

	//	if (!ambient_occlusion.IsMultiviewEnabled())
	//	{
	//		glActiveTexture( GL_TEXTURE0 );
	//		glBindTexture(GL_TEXTURE_2D, visual.GetDepthBuffer());
	//		glActiveTexture( GL_TEXTURE1 );
	//		glBindTexture(GL_TEXTURE_2D, visual.GetNormalBuffer());
	//		glActiveTexture( GL_TEXTURE2 );
	//		glBindTexture(GL_TEXTURE_3D, noise3D);
	//	}

	//	m_technique_ssao->SetShader(type);
	//	m_technique_ssao->SetMultiviewNumViews(ambient_occlusion.GetMultiviewList().size() + 1);

	//	m_technique_ssao->Start();
	//	Matrix4D Mproj = Matrix4D::Ortho(-1, 1, -1, 1, 1, -1);
	//	m_technique_ssao->SetModelViewProjectionMatrix(Mproj.a);

	//	if (type == APT_SSAO || /*type == APT_SSAO_MULTIVIEW_SAMPLES_BUFFER ||*/ type == APT_SSAO_MULTIVIEW_BUFFERS_SAMPLE_BASIC)
	//	{
	//		m_technique_ssao->SetNumSamples(ambient_occlusion.GetNumPoissonSamples());
	//		m_technique_ssao->SetRange(ambient_occlusion.GetRange());
	//		m_technique_ssao->Set3DSamples(ambient_occlusion.GetPoissonSamples(), ambient_occlusion.GetNumPoissonSamples());
	//	}
	//	else if (type == APT_SSAO_HORIZON_SPLIT || /*type == APT_SSAO_HORIZON_SPLIT_MULTIVIEW_SAMPLES_BUFFER ||*/ type == APT_SSAO_HORIZON_SPLIT_MULTIVIEW_BUFFERS_SAMPLE_BASIC)
	//	{
	//		m_technique_ssao->SetNumSamples(ambient_occlusion.GetNumSamples());
	//		m_technique_ssao->SetNumSlices(ambient_occlusion.GetNumSlices());
	//		m_technique_ssao->SetRange(ambient_occlusion.GetRange());
	//	}
	//	else if (type == APT_SSAO_ALCHEMY || /*type == APT_SSAO_ALCHEMY_MULTIVIEW_SAMPLES_BUFFER ||*/ type == APT_SSAO_ALCHEMY_MULTIVIEW_BUFFERS_SAMPLE_BASIC)
	//	{
	//		m_technique_ssao->SetNumSamples(ambient_occlusion.GetNumPoissonSamples());
	//		m_technique_ssao->SetRange(ambient_occlusion.GetRange());
	//		m_technique_ssao->Set3DSamples(ambient_occlusion.GetPoissonSamples(), ambient_occlusion.GetNumPoissonSamples());
	//	}
	//	else if (type == APT_SSAO_VOLUMETRIC_OBSCURANCE || /*type == APT_SSAO_VOLUMETRIC_OBSCURANCE_MULTIVIEW_SAMPLES_BUFFER ||*/ type == APT_SSAO_VOLUMETRIC_OBSCURANCE_MULTIVIEW_BUFFERS_SAMPLE_BASIC)
	//	{
	//		m_technique_ssao->SetNumSamples(ambient_occlusion.GetNumPoissonSamples());
	//		m_technique_ssao->SetRange(ambient_occlusion.GetRange());
	//		m_technique_ssao->Set2DSamples(ambient_occlusion.GetEquidistantDiskSamples(), ambient_occlusion.GetNumEquidistantDiskSamples());
	//	}

	//	if (!ambient_occlusion.IsMultiviewEnabled())
	//	{
	//		Matrix4D proj = visual.GetProjectionMatrixRef();
	//		proj.transpose();
	//		m_technique_ssao->SetProjMatrix(proj.a);

	//		Matrix4D inv_proj = visual.GetProjectionMatrixInverseRef();
	//		inv_proj.transpose();
	//		m_technique_ssao->SetProjInvMatrix(inv_proj.a);

	//		Matrix4D view = visual.GetViewMatrixRef();
	//		view.transpose();
	//		m_technique_ssao->SetViewMatrix(view.a);

	//		Matrix4D inv_view = visual.GetViewMatrixInverseRef();
	//		inv_view.transpose();
	//		m_technique_ssao->SetViewInvMatrix(inv_view.a);
	//	}
	//	else
	//	{
	//		int current_view = 0;
	//		int total_views = ambient_occlusion.GetMultiviewList().size() + 1;

	//		int* depth_array = new int[total_views];
	//		int* lighting_array = new int[total_views];
	//		float* view_array = new float[total_views * 16];
	//		float* projection_array = new float[total_views * 16];
	//		float* view_inverse_array = new float[total_views * 16];
	//		float* projection_inverse_array = new float[total_views * 16];
	//		float* view_position_array = new float[total_views * 3];

	//		Matrix4D view = visual.GetViewMatrixRef();
	//		view.transpose();

	//		Matrix4D proj = visual.GetProjectionMatrixRef();
	//		proj.transpose();

	//		Matrix4D inv_proj = visual.GetProjectionMatrixInverseRef();
	//		inv_proj.transpose();

	//		Matrix4D inv_view = visual.GetViewMatrixInverseRef();
	//		inv_view.transpose();

	//		for (int array_index = 0; array_index<16; ++array_index)
	//		{
	//			view_array[current_view * 16 + array_index] = view.a[array_index];
	//			projection_array[current_view * 16 + array_index] = proj.a[array_index];
	//			view_inverse_array[current_view * 16 + array_index] = inv_view.a[array_index];
	//			projection_inverse_array[current_view * 16 + array_index] = inv_proj.a[array_index];
	//		}

	//		Vector3D& cam_pos = root->GetActiveCamera()->GetCOP();
	//		view_position_array[current_view * 3] = cam_pos.x;
	//		view_position_array[current_view * 3 + 1] = cam_pos.y;
	//		view_position_array[current_view * 3 + 2] = cam_pos.z;
	//		depth_array[current_view] = visual.GetDepthBuffer();
	//		lighting_array[current_view] = visual.GetLightingBuffer();
	//		++current_view;

	//		for (MULTIVIEW_OBJECT_LIST::iterator i = ambient_occlusion.GetMultiviewList().begin(); i != ambient_occlusion.GetMultiviewList().end(); ++i)
	//		{
	//			MultiViewObject& multiviewobject = *i;

	//			LightManager& light_manager = GetLightManager();
	//			PointLight& light = light_manager.GetPointLight(multiviewobject.light_handle);

	//			proj = light.GetLightProjectionMatrix();
	//			proj.transpose();
	//			inv_proj = light.GetLightProjectionMatrix();
	//			// will remove this later
	//			inv_proj.invert();
	//			inv_proj.transpose();

	//			view = light.GetLightViewMatrix();
	//			inv_view = view;
	//			// will remove this later
	//			inv_view.invert();
	//			view.transpose();
	//			inv_view.transpose();

	//			depth_array[current_view] = light.GetDepthTexture();
	//			if (light.LightingEnabled())
	//				lighting_array[current_view] = light.GetLightingTexture();
	//			else 
	//				lighting_array[current_view] = 0;

	//			for (int array_index = 0; array_index<16; ++array_index)
	//			{
	//				view_array[current_view * 16 + array_index] = view.a[array_index];
	//				projection_array[current_view * 16 + array_index] = proj.a[array_index];
	//				view_inverse_array[current_view * 16 + array_index] = inv_view.a[array_index];
	//				projection_inverse_array[current_view * 16 + array_index] = inv_proj.a[array_index];
	//			}
	//			Vector3D& light_pos = light.GetPosition();
	//			view_position_array[current_view * 3] = light_pos.x;
	//			view_position_array[current_view * 3 + 1] = light_pos.y;
	//			view_position_array[current_view * 3 + 2] = light_pos.z;
	//			++current_view;
	//		}

	//		int32 index = -1;
	//		for (int i = 0; i < total_views; ++i)
	//		{
	//			glActiveTexture( GL_TEXTURE0 + ++index);
	//			glBindTexture(GL_TEXTURE_2D, depth_array[i]);
	//		}
	//		glActiveTexture( GL_TEXTURE0 + ++index);
	//		glBindTexture(GL_TEXTURE_2D, visual.GetNormalBuffer());
	//		glActiveTexture( GL_TEXTURE0 + ++index);
	//		glBindTexture(GL_TEXTURE_3D, noise3D);
	//		for (int i = 0; i < total_views; ++i)
	//		{
	//			glActiveTexture( GL_TEXTURE0 + ++index);
	//			glBindTexture(GL_TEXTURE_2D, lighting_array[i]);
	//		}

	//		m_technique_ssao->SetViewMatrix(view_array, total_views);
	//		m_technique_ssao->SetProjMatrix(projection_array, total_views);
	//		m_technique_ssao->SetProjInvMatrix(projection_inverse_array, total_views);
	//		m_technique_ssao->SetViewInvMatrix(view_inverse_array, total_views);
	//		m_technique_ssao->SetViewPosition(view_position_array, total_views);

	//		SAFE_DELETE_ARRAY_POINTER(depth_array)
	//			SAFE_DELETE_ARRAY_POINTER(lighting_array)
	//			SAFE_DELETE_ARRAY_POINTER(view_array)
	//			SAFE_DELETE_ARRAY_POINTER(projection_array)
	//			SAFE_DELETE_ARRAY_POINTER(projection_inverse_array)
	//			SAFE_DELETE_ARRAY_POINTER(view_inverse_array)
	//			SAFE_DELETE_ARRAY_POINTER(view_position_array)
	//	}

	//	glDrawArrays(GL_QUADS, 0, 4);
	//	m_technique_ssao->Stop();

	//	glBindBuffer(GL_ARRAY_BUFFER, 0);		
	//	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
	//	glBindVertexArray(0);

	//	if (!ambient_occlusion.IsMultiviewEnabled())
	//	{
	//		glActiveTexture( GL_TEXTURE0 );
	//		glBindTexture(GL_TEXTURE_2D,  0);
	//		glActiveTexture( GL_TEXTURE1 );
	//		glBindTexture(GL_TEXTURE_2D,  0);
	//		glActiveTexture( GL_TEXTURE2 );
	//		glBindTexture(GL_TEXTURE_3D,  0);
	//	}
	//	else
	//	{
	//		int total_views = ambient_occlusion.GetMultiviewList().size() + 1;
	//		int32 index = -1;
	//		for (int i = 0; i < total_views; ++i)
	//		{
	//			glActiveTexture( GL_TEXTURE0 + ++index);
	//			glBindTexture(GL_TEXTURE_2D, 0);
	//		}
	//		glActiveTexture( GL_TEXTURE0 + ++index);
	//		glBindTexture(GL_TEXTURE_2D, 0);
	//		glActiveTexture( GL_TEXTURE0 + ++index);
	//		glBindTexture(GL_TEXTURE_3D, 0);
	//		for (int i = 0; i < total_views; ++i)
	//		{
	//			glActiveTexture( GL_TEXTURE0 + ++index);
	//			glBindTexture(GL_TEXTURE_2D, 0);
	//		}
	//	}
	//	glDisable(GL_TEXTURE_2D);
	//	glDisable(GL_TEXTURE_3D);
	//}

	//void DeferredRenderer::DrawSSAO(DRVisual& visual)
	//{
	//	AmbientOcclusion& ambient_occlusion = GetAmbientOcclusion();

	//	AO_PASS_TYPE type = ambient_occlusion.GetAOType();

	//	glDisable(GL_CULL_FACE);
	//	glBindVertexArray(0);
	//	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
	//	glBindBuffer(GL_ARRAY_BUFFER,0);

	//	glBindVertexArray(m_technique_ssao->m_vao);

	//	glEnable(GL_TEXTURE_2D);
	//	glEnable(GL_TEXTURE_3D);

	//	glActiveTexture( GL_TEXTURE0 );
	//	glBindTexture(GL_TEXTURE_2D, visual.GetDepthBuffer());
	//	glActiveTexture( GL_TEXTURE1 );
	//	glBindTexture(GL_TEXTURE_2D, visual.GetNormalBuffer());
	//	glActiveTexture( GL_TEXTURE2 );
	//	glBindTexture(GL_TEXTURE_3D, noise3D);

	//	
	//	ambient_occlusion.SetAOType(APT_SSAO_ALCHEMY);
	//	ambient_occlusion.SetMultiviewStatus(false);
	//	m_technique_ssao->SetShader(type);
	//	m_technique_ssao->SetMultiviewNumViews(ambient_occlusion.GetMultiviewList().size() + 1);
	//	m_technique_ssao->Start();
	//	Matrix4D Mproj = Matrix4D::Ortho(-1, 1, -1, 1, 1, -1);
	//	m_technique_ssao->SetModelViewProjectionMatrix(Mproj.a);

	//	if (type == APT_SSAO || type == APT_SSAO_MULTIVIEW_SAMPLES_BUFFER || type == APT_SSAO_MULTIVIEW_BUFFERS_SAMPLE_BASIC)
	//	{
	//		m_technique_ssao->SetNumSamples(ambient_occlusion.GetNumSamples());
	//		m_technique_ssao->SetRange(ambient_occlusion.GetRange());
	//	}
	//	else if (type == APT_SSAO_HORIZON_SPLIT || type == APT_SSAO_HORIZON_SPLIT_MULTIVIEW_SAMPLES_BUFFER || type == APT_SSAO_HORIZON_SPLIT_MULTIVIEW_BUFFERS_SAMPLE_BASIC)
	//	{
	//		m_technique_ssao->SetNumSamples(ambient_occlusion.GetNumSamples());
	//		m_technique_ssao->SetNumSlices(ambient_occlusion.GetNumSlices());
	//		m_technique_ssao->SetRange(ambient_occlusion.GetRange());
	//	}
	//	else if (type == APT_SSAO_ALCHEMY || type == APT_SSAO_ALCHEMY_MULTIVIEW_SAMPLES_BUFFER || type == APT_SSAO_ALCHEMY_MULTIVIEW_BUFFERS_SAMPLE_BASIC)
	//	{
	//		m_technique_ssao->SetNumSamples(ambient_occlusion.GetNumPoissonSamples());
	//		m_technique_ssao->SetRange(ambient_occlusion.GetRange());
	//		m_technique_ssao->SetSamples(ambient_occlusion.GetPoissonSamples(), ambient_occlusion.GetNumPoissonSamples());
	//	}

	//	Matrix4D proj = visual.GetProjectionMatrixRef();
	//	proj.transpose();
	//	m_technique_ssao->SetProjMatrix(proj.a);

	//	Matrix4D inv_proj = visual.GetProjectionMatrixInverseRef();
	//	inv_proj.transpose();
	//	m_technique_ssao->SetProjInvMatrix(inv_proj.a);

	//	Matrix4D inv_view = visual.GetViewMatrixInverseRef();
	//	inv_view.transpose();
	//	m_technique_ssao->SetViewInvMatrix(inv_view.a);
	//	

	//	glDrawArrays(GL_QUADS, 0, 4);

	//	m_technique_ssao->Stop();

	//	glBindBuffer(GL_ARRAY_BUFFER, 0);		
	//	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
	//	glBindVertexArray(0);

	//	glActiveTexture( GL_TEXTURE0 );
	//	glBindTexture(GL_TEXTURE_2D,  0);
	//	glActiveTexture( GL_TEXTURE1 );
	//	glBindTexture(GL_TEXTURE_2D,  0);
	//	glActiveTexture( GL_TEXTURE2 );
	//	glBindTexture(GL_TEXTURE_3D,  0);
	//	
	//	glDisable(GL_TEXTURE_2D);
	//	glDisable(GL_TEXTURE_3D);


	//	ambient_occlusion.SetMultiviewStatus(true);
	//	if (!ambient_occlusion.IsMultiviewEnabled()) return;
	//
	//	// Multiview
	//	ambient_occlusion.SetAOType(APT_SSAO_ALCHEMY);	
	//	ambient_occlusion.SetAOMultiviewMethod(AOM_BUFFER_SAMPLES_BASIC);

	//	if (ambient_occlusion.IsMultiviewEnabled()) type = ambient_occlusion.GetAOMultiviewType();

	//		visual.StopRendering();
	//		visual.StartRendering(DRVisual::BT_OUT);

	//		glDisable(GL_CULL_FACE);
	//		glBindVertexArray(0);
	//		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
	//		glBindBuffer(GL_ARRAY_BUFFER,0);

	//		glBindVertexArray(m_technique_ssao->m_vao);

	//		glEnable(GL_TEXTURE_2D);
	//		glEnable(GL_TEXTURE_3D);

	//		MultiViewObject& multiviewobject = *ambient_occlusion.GetMultiviewList().begin();

	//		LightManager& light_manager = GetLightManager();
	//		PointLight& light = light_manager.GetPointLight(multiviewobject.light_handle);

	//		glActiveTexture( GL_TEXTURE0 );
	//		glBindTexture(GL_TEXTURE_2D, light.GetDepthTexture());
	//		glActiveTexture( GL_TEXTURE1 );
	//		glBindTexture(GL_TEXTURE_2D, visual.GetDepthBuffer());
	//		glActiveTexture( GL_TEXTURE2 );
	//		glBindTexture(GL_TEXTURE_2D, visual.GetNormalBuffer());
	//		glActiveTexture( GL_TEXTURE3 );
	//		glBindTexture(GL_TEXTURE_2D, visual.GetOcclusionBuffer());
	//		glActiveTexture( GL_TEXTURE4 );
	//		glBindTexture(GL_TEXTURE_3D, noise3D);

	//		m_technique_ssao->SetShader(type);
	//		m_technique_ssao->SetMultiviewNumViews(ambient_occlusion.GetMultiviewList().size() + 1);
	//		m_technique_ssao->Start();
	//		Mproj = Matrix4D::Ortho(-1, 1, -1, 1, 1, -1);
	//		m_technique_ssao->SetModelViewProjectionMatrix(Mproj.a);

	//		if (type == APT_SSAO || type == APT_SSAO_MULTIVIEW_SAMPLES_BUFFER || type == APT_SSAO_MULTIVIEW_BUFFERS_SAMPLE_BASIC)
	//		{
	//			m_technique_ssao->SetNumSamples(ambient_occlusion.GetNumSamples());
	//			m_technique_ssao->SetRange(ambient_occlusion.GetRange());
	//		}
	//		else if (type == APT_SSAO_HORIZON_SPLIT || type == APT_SSAO_HORIZON_SPLIT_MULTIVIEW_SAMPLES_BUFFER || type == APT_SSAO_HORIZON_SPLIT_MULTIVIEW_BUFFERS_SAMPLE_BASIC)
	//		{
	//			m_technique_ssao->SetNumSamples(ambient_occlusion.GetNumSamples());
	//			m_technique_ssao->SetNumSlices(ambient_occlusion.GetNumSlices());
	//			m_technique_ssao->SetRange(ambient_occlusion.GetRange());
	//		}
	//		else if (type == APT_SSAO_ALCHEMY || type == APT_SSAO_ALCHEMY_MULTIVIEW_SAMPLES_BUFFER || type == APT_SSAO_ALCHEMY_MULTIVIEW_BUFFERS_SAMPLE_BASIC)
	//		{
	//			m_technique_ssao->SetNumSamples(ambient_occlusion.GetNumPoissonSamples());
	//			m_technique_ssao->SetRange(ambient_occlusion.GetRange());
	//			m_technique_ssao->SetSamples(ambient_occlusion.GetPoissonSamples(), ambient_occlusion.GetNumPoissonSamples());
	//		}

	//		proj = light.GetLightProjectionMatrix();
	//		proj.transpose();
	//		inv_proj = light.GetLightProjectionMatrix();
	//		// will remove this later
	//		inv_proj.invert();
	//		inv_proj.transpose();

	//		Matrix4D view = light.GetLightViewMatrix();
	//		inv_view = view;
	//		// will remove this later
	//		inv_view.invert();
	//		view.transpose();
	//		inv_view.transpose();

	//		// proj = visual.GetProjectionMatrixRef();
	//		//proj.transpose();
	//		m_technique_ssao->SetProjMatrix(proj.a);

	//		// inv_proj = visual.GetProjectionMatrixInverseRef();
	//		//inv_proj.transpose();
	//		m_technique_ssao->SetProjInvMatrix(inv_proj.a);

	//		// inv_view = visual.GetViewMatrixInverseRef();
	//		//inv_view.transpose();
	//		m_technique_ssao->SetViewInvMatrix(inv_view.a);

	//		m_technique_ssao->SetViewMatrix(view.a);

	//		Matrix4D inv_view_camera = visual.GetViewMatrixInverseRef();
	//		inv_view_camera.transpose();
	//		m_technique_ssao->SetViewInvMatrixView(inv_view_camera.a);

	//		Matrix4D inv_view_proj_camera = visual.GetProjectionMatrixInverseRef();
	//		inv_view_proj_camera.transpose();
	//		m_technique_ssao->SetProjInvMatrixView(inv_view_proj_camera.a);

	//		Matrix4D view_camera = visual.GetViewMatrixRef();
	//		view_camera.transpose();
	//		m_technique_ssao->SetViewMatrixView(view_camera.a);

	//		glDrawArrays(GL_QUADS, 0, 4);

	//		m_technique_ssao->Stop();

	//		glBindBuffer(GL_ARRAY_BUFFER, 0);		
	//		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
	//		glBindVertexArray(0);

	//		glActiveTexture( GL_TEXTURE0 );
	//		glBindTexture(GL_TEXTURE_2D,  0);
	//		glActiveTexture( GL_TEXTURE1 );
	//		glBindTexture(GL_TEXTURE_2D,  0);
	//		glActiveTexture( GL_TEXTURE2 );
	//		glBindTexture(GL_TEXTURE_2D,  0);
	//		glActiveTexture( GL_TEXTURE3 );
	//		glBindTexture(GL_TEXTURE_2D,  0);
	//		glActiveTexture( GL_TEXTURE4 );
	//		glBindTexture(GL_TEXTURE_3D,  0);

	//		glDisable(GL_TEXTURE_2D);
	//		glDisable(GL_TEXTURE_3D);
	//}