Graphics/Shadows: Add directional shadow mapping (WIP)
It still needs some debug Former-commit-id: 029872debc1a784712a33802ddd70a2b61e55623
This commit is contained in:
parent
75972fec36
commit
835da411c7
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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>())
|
||||||
|
{
|
||||||
|
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);
|
m_lights.Insert(entity);
|
||||||
|
}
|
||||||
else
|
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] =
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
Loading…
Reference in New Issue