void RenderSystem::UpdateDirectionalShadowMaps(const Nz::AbstractViewer& /*viewer*/)
	{
		if (!m_shadowRT.IsValid())
			m_shadowRT.Create();

		Nz::SceneData dummySceneData;
		dummySceneData.ambientColor = Nz::Color(0, 0, 0);
		dummySceneData.background = nullptr;
		dummySceneData.viewer = nullptr; //< Depth technique doesn't require any viewer

		for (const Ndk::EntityHandle& light : m_directionalLights)
		{
			LightComponent& lightComponent = light->GetComponent<LightComponent>();
			NodeComponent& lightNode = light->GetComponent<NodeComponent>();

			if (!lightComponent.IsShadowCastingEnabled())
				continue;

			Nz::Vector2ui shadowMapSize(lightComponent.GetShadowMap()->GetSize());

			m_shadowRT.AttachTexture(Nz::AttachmentPoint_Depth, 0, lightComponent.GetShadowMap());
			Nz::Renderer::SetTarget(&m_shadowRT);
			Nz::Renderer::SetViewport(Nz::Recti(0, 0, shadowMapSize.x, shadowMapSize.y));

			Nz::AbstractRenderQueue* renderQueue = m_shadowTechnique.GetRenderQueue();
			renderQueue->Clear();

			///TODO: Culling
			for (const Ndk::EntityHandle& drawable : m_drawables)
			{
				GraphicsComponent& graphicsComponent = drawable->GetComponent<GraphicsComponent>();

				graphicsComponent.AddToRenderQueue(renderQueue);
			}

			///TODO: Cache the matrices in the light?
			Nz::Renderer::SetMatrix(Nz::MatrixType_Projection, Nz::Matrix4f::Ortho(0.f, 100.f, 100.f, 0.f, 1.f, 100.f));
			Nz::Renderer::SetMatrix(Nz::MatrixType_View, Nz::Matrix4f::ViewMatrix(lightNode.GetRotation() * Nz::Vector3f::Forward() * 100.f, lightNode.GetRotation()));

			m_shadowTechnique.Clear(dummySceneData);
			m_shadowTechnique.Draw(dummySceneData);
		}
	}
	void RenderSystem::UpdatePointSpotShadowMaps()
	{
		if (!m_shadowRT.IsValid())
			m_shadowRT.Create();

		Nz::SceneData dummySceneData;
		dummySceneData.ambientColor = Nz::Color(0, 0, 0);
		dummySceneData.background = nullptr;
		dummySceneData.viewer = nullptr; //< Depth technique doesn't require any viewer

		for (const Ndk::EntityHandle& light : m_pointSpotLights)
		{
			LightComponent& lightComponent = light->GetComponent<LightComponent>();
			NodeComponent& lightNode = light->GetComponent<NodeComponent>();

			if (!lightComponent.IsShadowCastingEnabled())
				continue;

			Nz::Vector2ui shadowMapSize(lightComponent.GetShadowMap()->GetSize());

			switch (lightComponent.GetLightType())
			{
				case Nz::LightType_Directional:
					NazaraInternalError("Directional lights included in point/spot light list");
					break;

				case Nz::LightType_Point:
				{
					static Nz::Quaternionf rotations[6] =
					{
						Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(),  Nz::Vector3f::UnitX()), // CubemapFace_PositiveX
						Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitX()), // CubemapFace_NegativeX
						Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitY()), // CubemapFace_PositiveY
						Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(),  Nz::Vector3f::UnitY()), // CubemapFace_NegativeY
						Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitZ()), // CubemapFace_PositiveZ
						Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(),  Nz::Vector3f::UnitZ())  // CubemapFace_NegativeZ
					};

					for (unsigned int face = 0; face < 6; ++face)
					{
						m_shadowRT.AttachTexture(Nz::AttachmentPoint_Depth, 0, lightComponent.GetShadowMap(), face);
						Nz::Renderer::SetTarget(&m_shadowRT);
						Nz::Renderer::SetViewport(Nz::Recti(0, 0, shadowMapSize.x, shadowMapSize.y));

						///TODO: Cache the matrices in the light?
						Nz::Renderer::SetMatrix(Nz::MatrixType_Projection, Nz::Matrix4f::Perspective(Nz::FromDegrees(90.f), 1.f, 0.1f, lightComponent.GetRadius()));
						Nz::Renderer::SetMatrix(Nz::MatrixType_View, Nz::Matrix4f::ViewMatrix(lightNode.GetPosition(), rotations[face]));

						Nz::AbstractRenderQueue* renderQueue = m_shadowTechnique.GetRenderQueue();
						renderQueue->Clear();

						///TODO: Culling
						for (const Ndk::EntityHandle& drawable : m_drawables)
						{
							GraphicsComponent& graphicsComponent = drawable->GetComponent<GraphicsComponent>();

							graphicsComponent.AddToRenderQueue(renderQueue);
						}

						m_shadowTechnique.Clear(dummySceneData);
						m_shadowTechnique.Draw(dummySceneData);
					}
					break;
				}

				case Nz::LightType_Spot:
				{
					m_shadowRT.AttachTexture(Nz::AttachmentPoint_Depth, 0, lightComponent.GetShadowMap());
					Nz::Renderer::SetTarget(&m_shadowRT);
					Nz::Renderer::SetViewport(Nz::Recti(0, 0, shadowMapSize.x, shadowMapSize.y));

					///TODO: Cache the matrices in the light?
					Nz::Renderer::SetMatrix(Nz::MatrixType_Projection, Nz::Matrix4f::Perspective(lightComponent.GetOuterAngle()*2.f, 1.f, 0.1f, lightComponent.GetRadius()));
					Nz::Renderer::SetMatrix(Nz::MatrixType_View, Nz::Matrix4f::ViewMatrix(lightNode.GetPosition(), lightNode.GetRotation()));

					Nz::AbstractRenderQueue* renderQueue = m_shadowTechnique.GetRenderQueue();
					renderQueue->Clear();

					///TODO: Culling
					for (const Ndk::EntityHandle& drawable : m_drawables)
					{
						GraphicsComponent& graphicsComponent = drawable->GetComponent<GraphicsComponent>();

						graphicsComponent.AddToRenderQueue(renderQueue);
					}

					m_shadowTechnique.Clear(dummySceneData);
					m_shadowTechnique.Draw(dummySceneData);
					break;
				}
			}
		}
	}
void DeferredSpotLightsPass::renderLight(SpotLight* light, IEffect* lightEffect, IViewer* viewer, unsigned int normalMap) {
	GraphicsInterface::beginPerformanceEvent("Lighting");

	light->update();

	GraphicsInterface::setFrameBuffer(spotLightFrameBuffer_);
	GraphicsInterface::clearActiveColorBuffers(Color4::CORNFLOWERBLUE);

	lightEffect->beginDraw();
  
	GraphicsInterface::setRenderState(CULL_MODE_BACK);

	Matrix4x4 viewProjection = viewer->projection() * viewer->viewTransform();
	lightEffect->setUniform(viewer->viewTransform(), "View");
	lightEffect->setUniform(viewProjection, "ViewProj");
	lightEffect->setUniform(viewProjection.inverse(), "ViewProjInv");

	lightEffect->setUniform(viewer->projection().inverse(), "ProjInv");

	lightEffect->setUniform(viewer->position(), "ViewerPosition");

	Matrix4x4 worldViewProj = viewer->projection() * viewer->viewTransform() * light->transform();
	lightEffect->setUniform(worldViewProj, "WorldViewProj");

	Matrix4x4 worldView = viewer->viewTransform() * light->transform();
	lightEffect->setUniform(worldView, "WorldView");

	Matrix3x3 normalMatrix = viewer->viewTransform().inverse().transpose().mat3x3(); // strips out the translation;
	lightEffect->setUniform(normalMatrix, "NormalMatrix");

	Matrix4x4 lightViewProj = light->projection() * light->viewTransform();
	lightEffect->setUniform(lightViewProj, "LightViewProj");
	lightEffect->setUniform(lightViewProj.inverse(), "LightViewProjRaw");

	float lightDistance = light->direction().length();
	float lightDistanceSquared = lightDistance * lightDistance;
	lightEffect->setUniform(1.0f / lightDistanceSquared, "LightDistance");

	lightEffect->setUniform(light->direction().inverse().normalize(), "DirectionToLight");

	lightEffect->setUniform(light->position(), "LightPosition");
	lightEffect->setUniform(light->direction().normalize(), "LightDirection");
	lightEffect->setUniform(light->color(), "LightColor");

	lightEffect->setUniform(light->outerAngle(), "LightOuterAngle");
	lightEffect->setUniform(light->innerAngle(), "LightInnerAngle");

	lightEffect->setUniform(GraphicsInterface::halfBackBufferPixel(), "HalfPixel");

	unsigned int depthBufferId = GraphicsInterface::depthBufferTexture();
	lightEffect->setTexture(depthBufferId, "DepthMap");

	lightEffect->setTexture(normalMap, "NormalMap");

	if (light->castsShadows()) {
		CSize shadowMapResolution = light->shadowMapResolution();
		Vector2 shadowMapSize(1.0f/shadowMapResolution.width, 1.0f/shadowMapResolution.height);
		lightEffect->setUniform(shadowMapSize, "ShadowMapSize");
		lightEffect->setTexture(light->shadowMapTexture(), "ShadowMap");


    lightEffect->setUniform(light->lightBias(), "LightBias");
    lightEffect->setUniform(light->lightBleed(), "LightBleed");
    lightEffect->setUniform(light->shadowBias(), "ShadowBias");
	}

	//GraphicsInterface::setBlendState(IGraphicsInterface::ALPHA);

	lightEffect->commitBuffers();
	GraphicsInterface::drawVertexBuffer(quadVbo_, Geometry::SCREEN_PLANE_VERTEX_COUNT, Geometry::SCREEN_PLANE_VERTEX_FORMAT);
	lightEffect->endDraw();

	GraphicsInterface::endPerformanceEvent();
}