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 OnEntityValidation(Entity* entity, bool justAdded) override;
void OnUpdate(float elapsedTime) override;
void UpdateShadowMaps();
void UpdateDirectionalShadowMaps(const NzAbstractViewer& viewer);
void UpdatePointSpotShadowMaps();
EntityList m_cameras;
EntityList m_drawables;
EntityList m_directionalLights;
EntityList m_lights;
EntityList m_pointSpotLights;
NzBackgroundRef m_background;
NzDepthRenderTechnique m_shadowTechnique;
NzForwardRenderTechnique m_renderTechnique;

View File

@ -46,21 +46,40 @@ namespace Ndk
m_drawables.Remove(entity);
if (entity->HasComponent<LightComponent>() && entity->HasComponent<NodeComponent>())
{
LightComponent& lightComponent = entity->GetComponent<LightComponent>();
if (lightComponent.GetLightType() == nzLightType_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)
{
NazaraUnused(elapsedTime);
UpdateShadowMaps();
UpdatePointSpotShadowMaps();
for (const Ndk::EntityHandle& camera : m_cameras)
{
CameraComponent& camComponent = camera->GetComponent<CameraComponent>();
camComponent.ApplyView();
//UpdateDirectionalShadowMaps(camComponent);
NzAbstractRenderQueue* renderQueue = m_renderTechnique.GetRenderQueue();
renderQueue->Clear();
@ -81,6 +100,8 @@ namespace Ndk
lightComponent.AddToRenderQueue(renderQueue, lightNode.GetTransformMatrix());
}
camComponent.ApplyView();
NzSceneData sceneData;
sceneData.ambientColor = NzColor(25, 25, 25);
sceneData.background = m_background;
@ -90,7 +111,7 @@ namespace Ndk
}
}
void RenderSystem::UpdateShadowMaps()
void RenderSystem::UpdateDirectionalShadowMaps(const NzAbstractViewer& viewer)
{
if (!m_shadowRT.IsValid())
m_shadowRT.Create();
@ -100,18 +121,66 @@ namespace Ndk
dummySceneData.background = nullptr;
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>();
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;
NzVector2ui shadowMapSize(lightComponent.GetShadowMap()->GetSize());
switch (lightComponent.GetLightType())
{
case nzLightType_Directional:
NazaraInternalError("Directional lights included in point/spot light list");
break;
case nzLightType_Point:
{
static NzQuaternionf rotations[6] =

View File

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

View File

@ -25,6 +25,20 @@ inline void NzForwardRenderTechnique::SendLightUniforms(const NzShader* shader,
shader->SendColor(uniforms.locations.color + uniformOffset, light.color);
shader->SendVector(uniforms.locations.factors + uniformOffset, NzVector2f(light.ambientFactor, light.diffuseFactor));
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;
}
@ -48,7 +62,7 @@ inline void NzForwardRenderTechnique::SendLightUniforms(const NzShader* shader,
else
shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap);
shader->SendInteger(uniforms.locations.spotLightShadowMap + index, dummyTexture);
shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture);
break;
}
@ -69,10 +83,10 @@ inline void NzForwardRenderTechnique::SendLightUniforms(const NzShader* shader,
NzRenderer::SetTextureSampler(availableTextureUnit, s_shadowSampler);
shader->SendMatrix(uniforms.locations.lightViewProjMatrix + index, light.transformMatrix);
shader->SendInteger(uniforms.locations.spotLightShadowMap + index, availableTextureUnit);
shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, availableTextureUnit);
}
else
shader->SendInteger(uniforms.locations.spotLightShadowMap + index, dummyTexture);
shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture);
shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap);
break;
@ -82,8 +96,8 @@ inline void NzForwardRenderTechnique::SendLightUniforms(const NzShader* shader,
else
{
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.spotLightShadowMap + index, dummyTexture);
}
}

View File

@ -97,6 +97,7 @@ struct NzLightUniforms
{
int type;
int color;
int directionalSpotLightShadowMap;
int factors;
int lightViewProjMatrix;
int parameters1;
@ -104,7 +105,6 @@ struct NzLightUniforms
int parameters3;
int pointLightShadowMap;
int shadowMapping;
int spotLightShadowMap;
};
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.pointLightShadowMap = shader->GetUniformLocation("PointLightShadowMap[0]");
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
uniforms.hasLightUniforms = false;

View File

@ -33,6 +33,11 @@ m_shadowMapUpdated(false)
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)
{
case nzLightType_Directional:
@ -42,6 +47,8 @@ void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatri
light.color = m_color;
light.diffuseFactor = m_diffuseFactor;
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);
break;
@ -78,12 +85,6 @@ void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatri
light.position = transformMatrix.GetTranslation();
light.radius = m_radius;
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;
renderQueue->AddSpotLight(light);

View File

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

File diff suppressed because one or more lines are too long