Merge branch 'NDK-ShadowMapping'
Former-commit-id: e77949168073f06d52d10785afb41bad2f7f86c0
This commit is contained in:
@@ -8,7 +8,9 @@
|
||||
#define NDK_SYSTEMS_RENDERSYSTEM_HPP
|
||||
|
||||
#include <Nazara/Graphics/AbstractBackground.hpp>
|
||||
#include <Nazara/Graphics/DeferredRenderTechnique.hpp>
|
||||
#include <Nazara/Graphics/DepthRenderTechnique.hpp>
|
||||
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
||||
#include <Nazara/Renderer/RenderTexture.hpp>
|
||||
#include <NDK/EntityList.hpp>
|
||||
#include <NDK/System.hpp>
|
||||
#include <unordered_map>
|
||||
@@ -48,13 +50,19 @@ namespace Ndk
|
||||
void OnEntityRemoved(Entity* entity) override;
|
||||
void OnEntityValidation(Entity* entity, bool justAdded) override;
|
||||
void OnUpdate(float elapsedTime) override;
|
||||
void UpdateDirectionalShadowMaps(const Nz::AbstractViewer& viewer);
|
||||
void UpdatePointSpotShadowMaps();
|
||||
|
||||
std::unique_ptr<Nz::AbstractRenderTechnique> m_renderTechnique;
|
||||
EntityList m_cameras;
|
||||
EntityList m_drawables;
|
||||
EntityList m_directionalLights;
|
||||
EntityList m_lights;
|
||||
EntityList m_pointSpotLights;
|
||||
Nz::BackgroundRef m_background;
|
||||
Nz::DepthRenderTechnique m_shadowTechnique;
|
||||
Nz::Matrix4f m_coordinateSystemMatrix;
|
||||
Nz::RenderTexture m_shadowRT;
|
||||
bool m_coordinateSystemInvalidated;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include <NDK/Systems/RenderSystem.hpp>
|
||||
#include <Nazara/Graphics/ColorBackground.hpp>
|
||||
#include <Nazara/Math/Rect.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <NDK/Components/CameraComponent.hpp>
|
||||
#include <NDK/Components/GraphicsComponent.hpp>
|
||||
#include <NDK/Components/LightComponent.hpp>
|
||||
@@ -48,9 +50,27 @@ namespace Ndk
|
||||
m_drawables.Remove(entity);
|
||||
|
||||
if (entity->HasComponent<LightComponent>() && entity->HasComponent<NodeComponent>())
|
||||
{
|
||||
LightComponent& lightComponent = entity->GetComponent<LightComponent>();
|
||||
if (lightComponent.GetLightType() == Nz::LightType_Directional)
|
||||
{
|
||||
m_directionalLights.Insert(entity);
|
||||
m_pointSpotLights.Remove(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_directionalLights.Remove(entity);
|
||||
m_pointSpotLights.Insert(entity);
|
||||
}
|
||||
|
||||
m_lights.Insert(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_directionalLights.Remove(entity);
|
||||
m_lights.Remove(entity);
|
||||
m_pointSpotLights.Remove(entity);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderSystem::OnUpdate(float elapsedTime)
|
||||
@@ -69,10 +89,13 @@ namespace Ndk
|
||||
m_coordinateSystemInvalidated = false;
|
||||
}
|
||||
|
||||
UpdatePointSpotShadowMaps();
|
||||
|
||||
for (const Ndk::EntityHandle& camera : m_cameras)
|
||||
{
|
||||
CameraComponent& camComponent = camera->GetComponent<CameraComponent>();
|
||||
camComponent.ApplyView();
|
||||
|
||||
//UpdateDirectionalShadowMaps(camComponent);
|
||||
|
||||
Nz::AbstractRenderQueue* renderQueue = m_renderTechnique->GetRenderQueue();
|
||||
renderQueue->Clear();
|
||||
@@ -89,12 +112,14 @@ namespace Ndk
|
||||
for (const Ndk::EntityHandle& light : m_lights)
|
||||
{
|
||||
LightComponent& lightComponent = light->GetComponent<LightComponent>();
|
||||
NodeComponent& drawableNode = light->GetComponent<NodeComponent>();
|
||||
NodeComponent& lightNode = light->GetComponent<NodeComponent>();
|
||||
|
||||
///TODO: Cache somehow?
|
||||
lightComponent.AddToRenderQueue(renderQueue, Nz::Matrix4f::ConcatenateAffine(m_coordinateSystemMatrix, drawableNode.GetTransformMatrix()));
|
||||
lightComponent.AddToRenderQueue(renderQueue, Nz::Matrix4f::ConcatenateAffine(m_coordinateSystemMatrix, lightNode.GetTransformMatrix()));
|
||||
}
|
||||
|
||||
camComponent.ApplyView();
|
||||
|
||||
Nz::SceneData sceneData;
|
||||
sceneData.ambientColor = Nz::Color(25, 25, 25);
|
||||
sceneData.background = m_background;
|
||||
@@ -105,5 +130,146 @@ namespace Ndk
|
||||
}
|
||||
}
|
||||
|
||||
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>();
|
||||
NodeComponent& drawableNode = drawable->GetComponent<NodeComponent>();
|
||||
|
||||
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()), // nzCubemapFace_PositiveX
|
||||
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitX()), // nzCubemapFace_NegativeX
|
||||
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitY()), // nzCubemapFace_PositiveY
|
||||
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), Nz::Vector3f::UnitY()), // nzCubemapFace_NegativeY
|
||||
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitZ()), // nzCubemapFace_PositiveZ
|
||||
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), Nz::Vector3f::UnitZ()) // nzCubemapFace_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>();
|
||||
NodeComponent& drawableNode = drawable->GetComponent<NodeComponent>();
|
||||
|
||||
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>();
|
||||
NodeComponent& drawableNode = drawable->GetComponent<NodeComponent>();
|
||||
|
||||
graphicsComponent.AddToRenderQueue(renderQueue);
|
||||
}
|
||||
|
||||
m_shadowTechnique.Clear(dummySceneData);
|
||||
m_shadowTechnique.Draw(dummySceneData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SystemIndex RenderSystem::systemIndex;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user