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 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;
|
||||
|
|
|
|||
|
|
@ -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] =
|
||||
|
|
|
|||
|
|
@ -59,7 +59,9 @@ class NAZARA_GRAPHICS_API NzAbstractRenderQueue
|
|||
struct DirectionalLight
|
||||
{
|
||||
NzColor color;
|
||||
NzMatrix4f transformMatrix;
|
||||
NzVector3f direction;
|
||||
NzTexture* shadowMap;
|
||||
float ambientFactor;
|
||||
float diffuseFactor;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue