Graphics/Shadows: Add directional shadow mapping (WIP)

It still needs some debug


Former-commit-id: 029872debc1a784712a33802ddd70a2b61e55623
This commit is contained in:
Lynix 2015-08-13 13:54:34 +02:00
parent 75972fec36
commit 835da411c7
9 changed files with 118 additions and 24 deletions

View File

@ -37,11 +37,14 @@ namespace Ndk
void OnEntityRemoved(Entity* entity) override; void OnEntityRemoved(Entity* entity) override;
void OnEntityValidation(Entity* entity, bool justAdded) override; void OnEntityValidation(Entity* entity, bool justAdded) override;
void OnUpdate(float elapsedTime) override; void OnUpdate(float elapsedTime) override;
void UpdateShadowMaps(); void UpdateDirectionalShadowMaps(const NzAbstractViewer& viewer);
void UpdatePointSpotShadowMaps();
EntityList m_cameras; EntityList m_cameras;
EntityList m_drawables; EntityList m_drawables;
EntityList m_directionalLights;
EntityList m_lights; EntityList m_lights;
EntityList m_pointSpotLights;
NzBackgroundRef m_background; NzBackgroundRef m_background;
NzDepthRenderTechnique m_shadowTechnique; NzDepthRenderTechnique m_shadowTechnique;
NzForwardRenderTechnique m_renderTechnique; NzForwardRenderTechnique m_renderTechnique;

View File

@ -46,21 +46,40 @@ namespace Ndk
m_drawables.Remove(entity); m_drawables.Remove(entity);
if (entity->HasComponent<LightComponent>() && entity->HasComponent<NodeComponent>()) if (entity->HasComponent<LightComponent>() && entity->HasComponent<NodeComponent>())
m_lights.Insert(entity); {
LightComponent& lightComponent = entity->GetComponent<LightComponent>();
if (lightComponent.GetLightType() == nzLightType_Directional)
{
m_directionalLights.Insert(entity);
m_pointSpotLights.Remove(entity);
}
else else
{
m_directionalLights.Remove(entity);
m_pointSpotLights.Insert(entity);
}
m_lights.Insert(entity);
}
else
{
m_directionalLights.Remove(entity);
m_lights.Remove(entity); m_lights.Remove(entity);
m_pointSpotLights.Remove(entity);
}
} }
void RenderSystem::OnUpdate(float elapsedTime) void RenderSystem::OnUpdate(float elapsedTime)
{ {
NazaraUnused(elapsedTime); NazaraUnused(elapsedTime);
UpdateShadowMaps(); UpdatePointSpotShadowMaps();
for (const Ndk::EntityHandle& camera : m_cameras) for (const Ndk::EntityHandle& camera : m_cameras)
{ {
CameraComponent& camComponent = camera->GetComponent<CameraComponent>(); CameraComponent& camComponent = camera->GetComponent<CameraComponent>();
camComponent.ApplyView();
//UpdateDirectionalShadowMaps(camComponent);
NzAbstractRenderQueue* renderQueue = m_renderTechnique.GetRenderQueue(); NzAbstractRenderQueue* renderQueue = m_renderTechnique.GetRenderQueue();
renderQueue->Clear(); renderQueue->Clear();
@ -81,6 +100,8 @@ namespace Ndk
lightComponent.AddToRenderQueue(renderQueue, lightNode.GetTransformMatrix()); lightComponent.AddToRenderQueue(renderQueue, lightNode.GetTransformMatrix());
} }
camComponent.ApplyView();
NzSceneData sceneData; NzSceneData sceneData;
sceneData.ambientColor = NzColor(25, 25, 25); sceneData.ambientColor = NzColor(25, 25, 25);
sceneData.background = m_background; sceneData.background = m_background;
@ -90,7 +111,7 @@ namespace Ndk
} }
} }
void RenderSystem::UpdateShadowMaps() void RenderSystem::UpdateDirectionalShadowMaps(const NzAbstractViewer& viewer)
{ {
if (!m_shadowRT.IsValid()) if (!m_shadowRT.IsValid())
m_shadowRT.Create(); m_shadowRT.Create();
@ -100,18 +121,66 @@ namespace Ndk
dummySceneData.background = nullptr; dummySceneData.background = nullptr;
dummySceneData.viewer = nullptr; //< Depth technique doesn't require any viewer dummySceneData.viewer = nullptr; //< Depth technique doesn't require any viewer
for (const Ndk::EntityHandle& light : m_lights) for (const Ndk::EntityHandle& light : m_directionalLights)
{ {
LightComponent& lightComponent = light->GetComponent<LightComponent>(); LightComponent& lightComponent = light->GetComponent<LightComponent>();
NodeComponent& lightNode = light->GetComponent<NodeComponent>(); NodeComponent& lightNode = light->GetComponent<NodeComponent>();
if (!lightComponent.IsShadowCastingEnabled() || lightComponent.GetLightType() == nzLightType_Directional) if (!lightComponent.IsShadowCastingEnabled())
continue;
NzVector2ui shadowMapSize(lightComponent.GetShadowMap()->GetSize());
m_shadowRT.AttachTexture(nzAttachmentPoint_Depth, 0, lightComponent.GetShadowMap());
NzRenderer::SetTarget(&m_shadowRT);
NzRenderer::SetViewport(NzRecti(0, 0, shadowMapSize.x, shadowMapSize.y));
NzAbstractRenderQueue* 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?
NzRenderer::SetMatrix(nzMatrixType_Projection, NzMatrix4f::Ortho(0.f, 100.f, 100.f, 0.f, 1.f, 100.f));
NzRenderer::SetMatrix(nzMatrixType_View, NzMatrix4f::ViewMatrix(lightNode.GetRotation() * NzVector3f::Forward() * 100.f, lightNode.GetRotation()));
m_shadowTechnique.Draw(dummySceneData);
}
}
void RenderSystem::UpdatePointSpotShadowMaps()
{
if (!m_shadowRT.IsValid())
m_shadowRT.Create();
NzSceneData dummySceneData;
dummySceneData.ambientColor = NzColor(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; continue;
NzVector2ui shadowMapSize(lightComponent.GetShadowMap()->GetSize()); NzVector2ui shadowMapSize(lightComponent.GetShadowMap()->GetSize());
switch (lightComponent.GetLightType()) switch (lightComponent.GetLightType())
{ {
case nzLightType_Directional:
NazaraInternalError("Directional lights included in point/spot light list");
break;
case nzLightType_Point: case nzLightType_Point:
{ {
static NzQuaternionf rotations[6] = static NzQuaternionf rotations[6] =

View File

@ -59,7 +59,9 @@ class NAZARA_GRAPHICS_API NzAbstractRenderQueue
struct DirectionalLight struct DirectionalLight
{ {
NzColor color; NzColor color;
NzMatrix4f transformMatrix;
NzVector3f direction; NzVector3f direction;
NzTexture* shadowMap;
float ambientFactor; float ambientFactor;
float diffuseFactor; float diffuseFactor;
}; };

View File

@ -25,6 +25,20 @@ inline void NzForwardRenderTechnique::SendLightUniforms(const NzShader* shader,
shader->SendColor(uniforms.locations.color + uniformOffset, light.color); shader->SendColor(uniforms.locations.color + uniformOffset, light.color);
shader->SendVector(uniforms.locations.factors + uniformOffset, NzVector2f(light.ambientFactor, light.diffuseFactor)); shader->SendVector(uniforms.locations.factors + uniformOffset, NzVector2f(light.ambientFactor, light.diffuseFactor));
shader->SendVector(uniforms.locations.parameters1 + uniformOffset, NzVector4f(light.direction)); shader->SendVector(uniforms.locations.parameters1 + uniformOffset, NzVector4f(light.direction));
shader->SendBoolean(uniforms.locations.shadowMapping + uniformOffset, light.shadowMap != nullptr);
if (light.shadowMap)
{
NzRenderer::SetTexture(availableTextureUnit, light.shadowMap);
NzRenderer::SetTextureSampler(availableTextureUnit, s_shadowSampler);
shader->SendMatrix(uniforms.locations.lightViewProjMatrix + index, light.transformMatrix);
shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, availableTextureUnit);
}
else
shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture);
shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap);
break; break;
} }
@ -48,7 +62,7 @@ inline void NzForwardRenderTechnique::SendLightUniforms(const NzShader* shader,
else else
shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap); shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap);
shader->SendInteger(uniforms.locations.spotLightShadowMap + index, dummyTexture); shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture);
break; break;
} }
@ -69,10 +83,10 @@ inline void NzForwardRenderTechnique::SendLightUniforms(const NzShader* shader,
NzRenderer::SetTextureSampler(availableTextureUnit, s_shadowSampler); NzRenderer::SetTextureSampler(availableTextureUnit, s_shadowSampler);
shader->SendMatrix(uniforms.locations.lightViewProjMatrix + index, light.transformMatrix); shader->SendMatrix(uniforms.locations.lightViewProjMatrix + index, light.transformMatrix);
shader->SendInteger(uniforms.locations.spotLightShadowMap + index, availableTextureUnit); shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, availableTextureUnit);
} }
else else
shader->SendInteger(uniforms.locations.spotLightShadowMap + index, dummyTexture); shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture);
shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap); shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap);
break; break;
@ -82,8 +96,8 @@ inline void NzForwardRenderTechnique::SendLightUniforms(const NzShader* shader,
else else
{ {
shader->SendInteger(uniforms.locations.type + uniformOffset, -1); //< Disable the light in the shader shader->SendInteger(uniforms.locations.type + uniformOffset, -1); //< Disable the light in the shader
shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture);
shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap); shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap);
shader->SendInteger(uniforms.locations.spotLightShadowMap + index, dummyTexture);
} }
} }

View File

@ -97,6 +97,7 @@ struct NzLightUniforms
{ {
int type; int type;
int color; int color;
int directionalSpotLightShadowMap;
int factors; int factors;
int lightViewProjMatrix; int lightViewProjMatrix;
int parameters1; int parameters1;
@ -104,7 +105,6 @@ struct NzLightUniforms
int parameters3; int parameters3;
int pointLightShadowMap; int pointLightShadowMap;
int shadowMapping; int shadowMapping;
int spotLightShadowMap;
}; };
bool ubo; bool ubo;

View File

@ -769,7 +769,7 @@ const NzForwardRenderTechnique::ShaderUniforms* NzForwardRenderTechnique::GetSha
uniforms.lightUniforms.locations.parameters3 = shader->GetUniformLocation("Lights[0].parameters3"); uniforms.lightUniforms.locations.parameters3 = shader->GetUniformLocation("Lights[0].parameters3");
uniforms.lightUniforms.locations.pointLightShadowMap = shader->GetUniformLocation("PointLightShadowMap[0]"); uniforms.lightUniforms.locations.pointLightShadowMap = shader->GetUniformLocation("PointLightShadowMap[0]");
uniforms.lightUniforms.locations.shadowMapping = shader->GetUniformLocation("Lights[0].shadowMapping"); uniforms.lightUniforms.locations.shadowMapping = shader->GetUniformLocation("Lights[0].shadowMapping");
uniforms.lightUniforms.locations.spotLightShadowMap = shader->GetUniformLocation("SpotLightShadowMap[0]"); uniforms.lightUniforms.locations.directionalSpotLightShadowMap = shader->GetUniformLocation("DirectionalSpotLightShadowMap[0]");
} }
else else
uniforms.hasLightUniforms = false; uniforms.hasLightUniforms = false;

View File

@ -33,6 +33,11 @@ m_shadowMapUpdated(false)
void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatrix4f& transformMatrix) const void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatrix4f& transformMatrix) const
{ {
static NzMatrix4f biasMatrix(0.5f, 0.f, 0.f, 0.f,
0.f, 0.5f, 0.f, 0.f,
0.f, 0.f, 0.5f, 0.f,
0.5f, 0.5f, 0.5f, 1.f);
switch (m_type) switch (m_type)
{ {
case nzLightType_Directional: case nzLightType_Directional:
@ -42,6 +47,8 @@ void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatri
light.color = m_color; light.color = m_color;
light.diffuseFactor = m_diffuseFactor; light.diffuseFactor = m_diffuseFactor;
light.direction = transformMatrix.Transform(NzVector3f::Forward(), 0.f); light.direction = transformMatrix.Transform(NzVector3f::Forward(), 0.f);
light.shadowMap = m_shadowMap.Get();
light.transformMatrix = NzMatrix4f::ViewMatrix(transformMatrix.GetRotation() * NzVector3f::Forward() * 100.f, transformMatrix.GetRotation()) * NzMatrix4f::Ortho(0.f, 100.f, 100.f, 0.f, 1.f, 100.f) * biasMatrix;
renderQueue->AddDirectionalLight(light); renderQueue->AddDirectionalLight(light);
break; break;
@ -78,12 +85,6 @@ void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatri
light.position = transformMatrix.GetTranslation(); light.position = transformMatrix.GetTranslation();
light.radius = m_radius; light.radius = m_radius;
light.shadowMap = m_shadowMap.Get(); light.shadowMap = m_shadowMap.Get();
static NzMatrix4f biasMatrix(0.5f, 0.f, 0.f, 0.f,
0.f, 0.5f, 0.f, 0.f,
0.f, 0.f, 0.5f, 0.f,
0.5f, 0.5f, 0.5f, 1.f);
light.transformMatrix = NzMatrix4f::ViewMatrix(transformMatrix.GetTranslation(), transformMatrix.GetRotation()) * NzMatrix4f::Perspective(m_outerAngle*2.f, 1.f, 0.1f, m_radius) * biasMatrix; light.transformMatrix = NzMatrix4f::ViewMatrix(transformMatrix.GetTranslation(), transformMatrix.GetRotation()) * NzMatrix4f::Perspective(m_outerAngle*2.f, 1.f, 0.1f, m_radius) * biasMatrix;
renderQueue->AddSpotLight(light); renderQueue->AddSpotLight(light);

View File

@ -36,7 +36,7 @@ struct Light
// Lumières // Lumières
uniform Light Lights[3]; uniform Light Lights[3];
uniform samplerCube PointLightShadowMap[3]; uniform samplerCube PointLightShadowMap[3];
uniform sampler2D SpotLightShadowMap[3]; uniform sampler2D DirectionalSpotLightShadowMap[3];
// Matériau // Matériau
uniform sampler2D MaterialAlphaMap; uniform sampler2D MaterialAlphaMap;
@ -94,10 +94,10 @@ float VectorToDepthValue(vec3 vec, float zNear, float zFar)
return (normZ + 1.0) * 0.5; return (normZ + 1.0) * 0.5;
} }
bool TestShadowDirectional() bool TestShadowDirectional(int lightIndex)
{ {
///TODO vec4 lightSpacePos = vLightSpacePos[lightIndex];
return true; return texture(DirectionalSpotLightShadowMap[lightIndex], lightSpacePos.xy).x >= (lightSpacePos.z - 0.0005);
} }
bool TestShadowPoint(int lightIndex, vec3 lightToWorld, float zNear, float zFar) bool TestShadowPoint(int lightIndex, vec3 lightToWorld, float zNear, float zFar)
@ -108,7 +108,7 @@ bool TestShadowPoint(int lightIndex, vec3 lightToWorld, float zNear, float zFar)
bool TestShadowSpot(int lightIndex) bool TestShadowSpot(int lightIndex)
{ {
vec4 lightSpacePos = vLightSpacePos[lightIndex]; vec4 lightSpacePos = vLightSpacePos[lightIndex];
return textureProj(SpotLightShadowMap[lightIndex], lightSpacePos.xyw).x >= (lightSpacePos.z - 0.0005)/lightSpacePos.w; return textureProj(DirectionalSpotLightShadowMap[lightIndex], lightSpacePos.xyw).x >= (lightSpacePos.z - 0.0005)/lightSpacePos.w;
} }
void main() void main()
@ -211,6 +211,11 @@ void main()
// Ambient // Ambient
lightAmbient += lightColor.rgb * lightAmbientFactor * (MaterialAmbient.rgb + SceneAmbient.rgb); lightAmbient += lightColor.rgb * lightAmbientFactor * (MaterialAmbient.rgb + SceneAmbient.rgb);
#if SHADOW_MAPPING
if (Lights[i].shadowMapping && !TestShadowDirectional(i))
break;
#endif
// Diffuse // Diffuse
float lambert = max(dot(normal, lightDir), 0.0); float lambert = max(dot(normal, lightDir), 0.0);

File diff suppressed because one or more lines are too long