Graphics: Add shadow mapping
Former-commit-id: ca404bee246991eab98df35396e3010ec5165c43
This commit is contained in:
parent
4d07735b85
commit
75972fec36
|
|
@ -68,6 +68,7 @@ class NAZARA_GRAPHICS_API NzAbstractRenderQueue
|
||||||
{
|
{
|
||||||
NzColor color;
|
NzColor color;
|
||||||
NzVector3f position;
|
NzVector3f position;
|
||||||
|
NzTexture* shadowMap;
|
||||||
float ambientFactor;
|
float ambientFactor;
|
||||||
float attenuation;
|
float attenuation;
|
||||||
float diffuseFactor;
|
float diffuseFactor;
|
||||||
|
|
@ -78,8 +79,10 @@ class NAZARA_GRAPHICS_API NzAbstractRenderQueue
|
||||||
struct SpotLight
|
struct SpotLight
|
||||||
{
|
{
|
||||||
NzColor color;
|
NzColor color;
|
||||||
|
NzMatrix4f transformMatrix;
|
||||||
NzVector3f direction;
|
NzVector3f direction;
|
||||||
NzVector3f position;
|
NzVector3f position;
|
||||||
|
NzTexture* shadowMap;
|
||||||
float ambientFactor;
|
float ambientFactor;
|
||||||
float attenuation;
|
float attenuation;
|
||||||
float diffuseFactor;
|
float diffuseFactor;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ class NAZARA_GRAPHICS_API NzForwardRenderTechnique : public NzAbstractRenderTech
|
||||||
static bool Initialize();
|
static bool Initialize();
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
struct ShaderUniforms;
|
struct ShaderUniforms;
|
||||||
|
|
||||||
void ChooseLights(const NzSpheref& object, bool includeDirectionalLights = true) const;
|
void ChooseLights(const NzSpheref& object, bool includeDirectionalLights = true) const;
|
||||||
|
|
@ -43,7 +43,7 @@ class NAZARA_GRAPHICS_API NzForwardRenderTechnique : public NzAbstractRenderTech
|
||||||
void DrawTransparentModels(const NzSceneData& sceneData) const;
|
void DrawTransparentModels(const NzSceneData& sceneData) const;
|
||||||
const ShaderUniforms* GetShaderUniforms(const NzShader* shader) const;
|
const ShaderUniforms* GetShaderUniforms(const NzShader* shader) const;
|
||||||
void OnShaderInvalidated(const NzShader* shader) const;
|
void OnShaderInvalidated(const NzShader* shader) const;
|
||||||
void SendLightUniforms(const NzShader* shader, const NzLightUniforms& uniforms, unsigned int index, unsigned int uniformOffset) const;
|
void SendLightUniforms(const NzShader* shader, const NzLightUniforms& uniforms, unsigned int index, unsigned int uniformOffset, nzUInt8 availableTextureUnit) const;
|
||||||
|
|
||||||
static float ComputeDirectionalLightScore(const NzSpheref& object, const NzAbstractRenderQueue::DirectionalLight& light);
|
static float ComputeDirectionalLightScore(const NzSpheref& object, const NzAbstractRenderQueue::DirectionalLight& light);
|
||||||
static float ComputePointLightScore(const NzSpheref& object, const NzAbstractRenderQueue::PointLight& light);
|
static float ComputePointLightScore(const NzSpheref& object, const NzAbstractRenderQueue::PointLight& light);
|
||||||
|
|
@ -86,6 +86,7 @@ class NAZARA_GRAPHICS_API NzForwardRenderTechnique : public NzAbstractRenderTech
|
||||||
unsigned int m_maxLightPassPerObject;
|
unsigned int m_maxLightPassPerObject;
|
||||||
|
|
||||||
static NzIndexBuffer s_quadIndexBuffer;
|
static NzIndexBuffer s_quadIndexBuffer;
|
||||||
|
static NzTextureSampler s_shadowSampler;
|
||||||
static NzVertexBuffer s_quadVertexBuffer;
|
static NzVertexBuffer s_quadVertexBuffer;
|
||||||
static NzVertexDeclaration s_billboardInstanceDeclaration;
|
static NzVertexDeclaration s_billboardInstanceDeclaration;
|
||||||
static NzVertexDeclaration s_billboardVertexDeclaration;
|
static NzVertexDeclaration s_billboardVertexDeclaration;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,14 @@
|
||||||
// This file is part of the "Nazara Engine - Graphics module"
|
// This file is part of the "Nazara Engine - Graphics module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
inline void NzForwardRenderTechnique::SendLightUniforms(const NzShader* shader, const NzLightUniforms& uniforms, unsigned int index, unsigned int uniformOffset) const
|
#include <Nazara/Renderer/Renderer.hpp>
|
||||||
|
|
||||||
|
inline void NzForwardRenderTechnique::SendLightUniforms(const NzShader* shader, const NzLightUniforms& uniforms, unsigned int index, unsigned int uniformOffset, nzUInt8 availableTextureUnit) const
|
||||||
{
|
{
|
||||||
|
// If anyone got a better idea..
|
||||||
|
int dummyCubemap = NzRenderer::GetMaxTextureUnits() - 1;
|
||||||
|
int dummyTexture = NzRenderer::GetMaxTextureUnits() - 2;
|
||||||
|
|
||||||
if (index < m_lights.size())
|
if (index < m_lights.size())
|
||||||
{
|
{
|
||||||
const LightIndex& lightIndex = m_lights[index];
|
const LightIndex& lightIndex = m_lights[index];
|
||||||
|
|
@ -30,6 +36,19 @@ inline void NzForwardRenderTechnique::SendLightUniforms(const NzShader* shader,
|
||||||
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.position, light.attenuation));
|
shader->SendVector(uniforms.locations.parameters1 + uniformOffset, NzVector4f(light.position, light.attenuation));
|
||||||
shader->SendVector(uniforms.locations.parameters2 + uniformOffset, NzVector4f(0.f, 0.f, 0.f, light.invRadius));
|
shader->SendVector(uniforms.locations.parameters2 + uniformOffset, NzVector4f(0.f, 0.f, 0.f, light.invRadius));
|
||||||
|
|
||||||
|
shader->SendBoolean(uniforms.locations.shadowMapping + uniformOffset, light.shadowMap != nullptr);
|
||||||
|
if (light.shadowMap)
|
||||||
|
{
|
||||||
|
NzRenderer::SetTexture(availableTextureUnit, light.shadowMap);
|
||||||
|
NzRenderer::SetTextureSampler(availableTextureUnit, s_shadowSampler);
|
||||||
|
|
||||||
|
shader->SendInteger(uniforms.locations.pointLightShadowMap + index, availableTextureUnit);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap);
|
||||||
|
|
||||||
|
shader->SendInteger(uniforms.locations.spotLightShadowMap + index, dummyTexture);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,12 +61,30 @@ inline void NzForwardRenderTechnique::SendLightUniforms(const NzShader* shader,
|
||||||
shader->SendVector(uniforms.locations.parameters1 + uniformOffset, NzVector4f(light.position, light.attenuation));
|
shader->SendVector(uniforms.locations.parameters1 + uniformOffset, NzVector4f(light.position, light.attenuation));
|
||||||
shader->SendVector(uniforms.locations.parameters2 + uniformOffset, NzVector4f(light.direction, light.invRadius));
|
shader->SendVector(uniforms.locations.parameters2 + uniformOffset, NzVector4f(light.direction, light.invRadius));
|
||||||
shader->SendVector(uniforms.locations.parameters3 + uniformOffset, NzVector2f(light.innerAngleCosine, light.outerAngleCosine));
|
shader->SendVector(uniforms.locations.parameters3 + uniformOffset, NzVector2f(light.innerAngleCosine, light.outerAngleCosine));
|
||||||
|
|
||||||
|
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.spotLightShadowMap + index, availableTextureUnit);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
shader->SendInteger(uniforms.locations.spotLightShadowMap + index, dummyTexture);
|
||||||
|
|
||||||
|
shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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.pointLightShadowMap + index, dummyCubemap);
|
||||||
|
shader->SendInteger(uniforms.locations.spotLightShadowMap + index, dummyTexture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float NzForwardRenderTechnique::ComputeDirectionalLightScore(const NzSpheref& object, const NzAbstractRenderQueue::DirectionalLight& light)
|
inline float NzForwardRenderTechnique::ComputeDirectionalLightScore(const NzSpheref& object, const NzAbstractRenderQueue::DirectionalLight& light)
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,6 @@
|
||||||
#include <Nazara/Renderer/RenderTexture.hpp>
|
#include <Nazara/Renderer/RenderTexture.hpp>
|
||||||
#include <Nazara/Renderer/Texture.hpp>
|
#include <Nazara/Renderer/Texture.hpp>
|
||||||
|
|
||||||
class NzLight;
|
|
||||||
struct NzLightUniforms;
|
|
||||||
|
|
||||||
class NAZARA_GRAPHICS_API NzLight : public NzRenderable
|
class NAZARA_GRAPHICS_API NzLight : public NzRenderable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -101,9 +98,13 @@ struct NzLightUniforms
|
||||||
int type;
|
int type;
|
||||||
int color;
|
int color;
|
||||||
int factors;
|
int factors;
|
||||||
|
int lightViewProjMatrix;
|
||||||
int parameters1;
|
int parameters1;
|
||||||
int parameters2;
|
int parameters2;
|
||||||
int parameters3;
|
int parameters3;
|
||||||
|
int pointLightShadowMap;
|
||||||
|
int shadowMapping;
|
||||||
|
int spotLightShadowMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ubo;
|
bool ubo;
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,9 @@ bool NzForwardRenderTechnique::Initialize()
|
||||||
s_billboardInstanceDeclaration.EnableComponent(nzVertexComponent_InstanceData0, nzComponentType_Float3, NzOffsetOf(NzForwardRenderQueue::BillboardData, center));
|
s_billboardInstanceDeclaration.EnableComponent(nzVertexComponent_InstanceData0, nzComponentType_Float3, NzOffsetOf(NzForwardRenderQueue::BillboardData, center));
|
||||||
s_billboardInstanceDeclaration.EnableComponent(nzVertexComponent_InstanceData1, nzComponentType_Float4, NzOffsetOf(NzForwardRenderQueue::BillboardData, size)); // Englobe sincos
|
s_billboardInstanceDeclaration.EnableComponent(nzVertexComponent_InstanceData1, nzComponentType_Float4, NzOffsetOf(NzForwardRenderQueue::BillboardData, size)); // Englobe sincos
|
||||||
s_billboardInstanceDeclaration.EnableComponent(nzVertexComponent_InstanceData2, nzComponentType_Color, NzOffsetOf(NzForwardRenderQueue::BillboardData, color));
|
s_billboardInstanceDeclaration.EnableComponent(nzVertexComponent_InstanceData2, nzComponentType_Color, NzOffsetOf(NzForwardRenderQueue::BillboardData, color));
|
||||||
|
|
||||||
|
s_shadowSampler.SetFilterMode(nzSamplerFilter_Bilinear);
|
||||||
|
s_shadowSampler.SetWrapMode(nzSamplerWrap_Clamp);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
|
@ -475,7 +478,8 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzSceneData& sceneData) co
|
||||||
bool instancing = m_instancingEnabled && (!material->IsLightingEnabled() || noPointSpotLight) && matEntry.instancingEnabled;
|
bool instancing = m_instancingEnabled && (!material->IsLightingEnabled() || noPointSpotLight) && matEntry.instancingEnabled;
|
||||||
|
|
||||||
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
||||||
const NzShader* shader = material->Apply((instancing) ? nzShaderFlags_Instancing : 0);
|
nzUInt8 freeTextureUnit;
|
||||||
|
const NzShader* shader = material->Apply((instancing) ? nzShaderFlags_Instancing : 0, 0, &freeTextureUnit);
|
||||||
|
|
||||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||||
if (shader != lastShader)
|
if (shader != lastShader)
|
||||||
|
|
@ -559,7 +563,7 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzSceneData& sceneData) co
|
||||||
|
|
||||||
// Sends the uniforms
|
// Sends the uniforms
|
||||||
for (unsigned int i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
for (unsigned int i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
||||||
SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, i*shaderUniforms->lightOffset);
|
SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, i*shaderUniforms->lightOffset, freeTextureUnit + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
const NzMatrix4f* instanceMatrices = &instances[0];
|
const NzMatrix4f* instanceMatrices = &instances[0];
|
||||||
|
|
@ -618,7 +622,7 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzSceneData& sceneData) co
|
||||||
|
|
||||||
// Sends the light uniforms to the shader
|
// Sends the light uniforms to the shader
|
||||||
for (unsigned int i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
for (unsigned int i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
||||||
SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, shaderUniforms->lightOffset*i);
|
SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, shaderUniforms->lightOffset*i, freeTextureUnit + i);
|
||||||
|
|
||||||
// Et on passe à l'affichage
|
// Et on passe à l'affichage
|
||||||
drawFunc(meshData.primitiveMode, 0, indexCount);
|
drawFunc(meshData.primitiveMode, 0, indexCount);
|
||||||
|
|
@ -668,7 +672,8 @@ void NzForwardRenderTechnique::DrawTransparentModels(const NzSceneData& sceneDat
|
||||||
const NzMaterial* material = modelData.material;
|
const NzMaterial* material = modelData.material;
|
||||||
|
|
||||||
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
||||||
const NzShader* shader = material->Apply();
|
nzUInt8 freeTextureUnit;
|
||||||
|
const NzShader* shader = material->Apply(0, 0, &freeTextureUnit);
|
||||||
|
|
||||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||||
if (shader != lastShader)
|
if (shader != lastShader)
|
||||||
|
|
@ -687,7 +692,7 @@ void NzForwardRenderTechnique::DrawTransparentModels(const NzSceneData& sceneDat
|
||||||
lightCount = std::min(m_renderQueue.directionalLights.size(), NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U));
|
lightCount = std::min(m_renderQueue.directionalLights.size(), NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U));
|
||||||
|
|
||||||
for (unsigned int i = 0; i < lightCount; ++i)
|
for (unsigned int i = 0; i < lightCount; ++i)
|
||||||
SendLightUniforms(shader, shaderUniforms->lightUniforms, i, shaderUniforms->lightOffset * i);
|
SendLightUniforms(shader, shaderUniforms->lightUniforms, i, shaderUniforms->lightOffset * i, freeTextureUnit++);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastShader = shader;
|
lastShader = shader;
|
||||||
|
|
@ -726,7 +731,7 @@ void NzForwardRenderTechnique::DrawTransparentModels(const NzSceneData& sceneDat
|
||||||
ChooseLights(NzSpheref(position, radius), false);
|
ChooseLights(NzSpheref(position, radius), false);
|
||||||
|
|
||||||
for (unsigned int i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
for (unsigned int i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
||||||
SendLightUniforms(shader, shaderUniforms->lightUniforms, i, shaderUniforms->lightOffset*i);
|
SendLightUniforms(shader, shaderUniforms->lightUniforms, i, shaderUniforms->lightOffset*i, freeTextureUnit++);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzRenderer::SetMatrix(nzMatrixType_World, matrix);
|
NzRenderer::SetMatrix(nzMatrixType_World, matrix);
|
||||||
|
|
@ -758,9 +763,13 @@ const NzForwardRenderTechnique::ShaderUniforms* NzForwardRenderTechnique::GetSha
|
||||||
uniforms.lightUniforms.locations.type = type0Location;
|
uniforms.lightUniforms.locations.type = type0Location;
|
||||||
uniforms.lightUniforms.locations.color = shader->GetUniformLocation("Lights[0].color");
|
uniforms.lightUniforms.locations.color = shader->GetUniformLocation("Lights[0].color");
|
||||||
uniforms.lightUniforms.locations.factors = shader->GetUniformLocation("Lights[0].factors");
|
uniforms.lightUniforms.locations.factors = shader->GetUniformLocation("Lights[0].factors");
|
||||||
|
uniforms.lightUniforms.locations.lightViewProjMatrix = shader->GetUniformLocation("LightViewProjMatrix[0]");
|
||||||
uniforms.lightUniforms.locations.parameters1 = shader->GetUniformLocation("Lights[0].parameters1");
|
uniforms.lightUniforms.locations.parameters1 = shader->GetUniformLocation("Lights[0].parameters1");
|
||||||
uniforms.lightUniforms.locations.parameters2 = shader->GetUniformLocation("Lights[0].parameters2");
|
uniforms.lightUniforms.locations.parameters2 = shader->GetUniformLocation("Lights[0].parameters2");
|
||||||
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.shadowMapping = shader->GetUniformLocation("Lights[0].shadowMapping");
|
||||||
|
uniforms.lightUniforms.locations.spotLightShadowMap = shader->GetUniformLocation("SpotLightShadowMap[0]");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
uniforms.hasLightUniforms = false;
|
uniforms.hasLightUniforms = false;
|
||||||
|
|
@ -777,6 +786,7 @@ void NzForwardRenderTechnique::OnShaderInvalidated(const NzShader* shader) const
|
||||||
}
|
}
|
||||||
|
|
||||||
NzIndexBuffer NzForwardRenderTechnique::s_quadIndexBuffer;
|
NzIndexBuffer NzForwardRenderTechnique::s_quadIndexBuffer;
|
||||||
|
NzTextureSampler NzForwardRenderTechnique::s_shadowSampler;
|
||||||
NzVertexBuffer NzForwardRenderTechnique::s_quadVertexBuffer;
|
NzVertexBuffer NzForwardRenderTechnique::s_quadVertexBuffer;
|
||||||
NzVertexDeclaration NzForwardRenderTechnique::s_billboardInstanceDeclaration;
|
NzVertexDeclaration NzForwardRenderTechnique::s_billboardInstanceDeclaration;
|
||||||
NzVertexDeclaration NzForwardRenderTechnique::s_billboardVertexDeclaration;
|
NzVertexDeclaration NzForwardRenderTechnique::s_billboardVertexDeclaration;
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatri
|
||||||
light.invRadius = m_invRadius;
|
light.invRadius = m_invRadius;
|
||||||
light.position = transformMatrix.GetTranslation();
|
light.position = transformMatrix.GetTranslation();
|
||||||
light.radius = m_radius;
|
light.radius = m_radius;
|
||||||
|
light.shadowMap = m_shadowMap.Get();
|
||||||
|
|
||||||
renderQueue->AddPointLight(light);
|
renderQueue->AddPointLight(light);
|
||||||
break;
|
break;
|
||||||
|
|
@ -76,6 +77,14 @@ void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatri
|
||||||
light.outerAngleTangent = m_outerAngleTangent;
|
light.outerAngleTangent = m_outerAngleTangent;
|
||||||
light.position = transformMatrix.GetTranslation();
|
light.position = transformMatrix.GetTranslation();
|
||||||
light.radius = m_radius;
|
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);
|
renderQueue->AddSpotLight(light);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ layout(early_fragment_tests) in;
|
||||||
|
|
||||||
/********************Entrant********************/
|
/********************Entrant********************/
|
||||||
in vec4 vColor;
|
in vec4 vColor;
|
||||||
|
in vec4 vLightSpacePos[3];
|
||||||
in mat3 vLightToWorld;
|
in mat3 vLightToWorld;
|
||||||
in vec3 vNormal;
|
in vec3 vNormal;
|
||||||
in vec2 vTexCoord;
|
in vec2 vTexCoord;
|
||||||
|
|
@ -29,10 +30,13 @@ struct Light
|
||||||
vec4 parameters1;
|
vec4 parameters1;
|
||||||
vec4 parameters2;
|
vec4 parameters2;
|
||||||
vec2 parameters3;
|
vec2 parameters3;
|
||||||
|
bool shadowMapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Lumières
|
// Lumières
|
||||||
uniform Light Lights[3];
|
uniform Light Lights[3];
|
||||||
|
uniform samplerCube PointLightShadowMap[3];
|
||||||
|
uniform sampler2D SpotLightShadowMap[3];
|
||||||
|
|
||||||
// Matériau
|
// Matériau
|
||||||
uniform sampler2D MaterialAlphaMap;
|
uniform sampler2D MaterialAlphaMap;
|
||||||
|
|
@ -81,6 +85,32 @@ vec4 EncodeNormal(in vec3 normal)
|
||||||
return vec4(vec2(atan(normal.y, normal.x)/kPI, normal.z), 0.0, 0.0);
|
return vec4(vec2(atan(normal.y, normal.x)/kPI, normal.z), 0.0, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float VectorToDepthValue(vec3 vec, float zNear, float zFar)
|
||||||
|
{
|
||||||
|
vec3 absVec = abs(vec);
|
||||||
|
float localZ = max(absVec.x, max(absVec.y, absVec.z));
|
||||||
|
|
||||||
|
float normZ = ((zFar + zNear) * localZ - (2.0*zFar*zNear)) / ((zFar - zNear)*localZ);
|
||||||
|
return (normZ + 1.0) * 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestShadowDirectional()
|
||||||
|
{
|
||||||
|
///TODO
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestShadowPoint(int lightIndex, vec3 lightToWorld, float zNear, float zFar)
|
||||||
|
{
|
||||||
|
return texture(PointLightShadowMap[lightIndex], vec3(lightToWorld.x, -lightToWorld.y, -lightToWorld.z)).x >= VectorToDepthValue(lightToWorld, zNear, zFar);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestShadowSpot(int lightIndex)
|
||||||
|
{
|
||||||
|
vec4 lightSpacePos = vLightSpacePos[lightIndex];
|
||||||
|
return textureProj(SpotLightShadowMap[lightIndex], lightSpacePos.xyw).x >= (lightSpacePos.z - 0.0005)/lightSpacePos.w;
|
||||||
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 diffuseColor = MaterialDiffuse * vColor;
|
vec4 diffuseColor = MaterialDiffuse * vColor;
|
||||||
|
|
@ -168,6 +198,10 @@ void main()
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
{
|
{
|
||||||
|
vec4 lightColor = Lights[i].color;
|
||||||
|
float lightAmbientFactor = Lights[i].factors.x;
|
||||||
|
float lightDiffuseFactor = Lights[i].factors.y;
|
||||||
|
|
||||||
switch (Lights[i].type)
|
switch (Lights[i].type)
|
||||||
{
|
{
|
||||||
case LIGHT_DIRECTIONAL:
|
case LIGHT_DIRECTIONAL:
|
||||||
|
|
@ -175,75 +209,95 @@ void main()
|
||||||
vec3 lightDir = -Lights[i].parameters1.xyz;
|
vec3 lightDir = -Lights[i].parameters1.xyz;
|
||||||
|
|
||||||
// Ambient
|
// Ambient
|
||||||
lightAmbient += Lights[i].color.rgb * Lights[i].factors.x * (MaterialAmbient.rgb + SceneAmbient.rgb);
|
lightAmbient += lightColor.rgb * lightAmbientFactor * (MaterialAmbient.rgb + SceneAmbient.rgb);
|
||||||
|
|
||||||
// Diffuse
|
// Diffuse
|
||||||
float lambert = max(dot(normal, lightDir), 0.0);
|
float lambert = max(dot(normal, lightDir), 0.0);
|
||||||
|
|
||||||
lightDiffuse += lambert * Lights[i].color.rgb * Lights[i].factors.y;
|
lightDiffuse += lambert * lightColor.rgb * lightDiffuseFactor;
|
||||||
|
|
||||||
// Specular
|
// Specular
|
||||||
vec3 reflection = reflect(-lightDir, normal);
|
vec3 reflection = reflect(-lightDir, normal);
|
||||||
float specularFactor = max(dot(reflection, eyeVec), 0.0);
|
float specularFactor = max(dot(reflection, eyeVec), 0.0);
|
||||||
specularFactor = pow(specularFactor, MaterialShininess);
|
specularFactor = pow(specularFactor, MaterialShininess);
|
||||||
|
|
||||||
lightSpecular += specularFactor * Lights[i].color.rgb;
|
lightSpecular += specularFactor * lightColor.rgb;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LIGHT_POINT:
|
case LIGHT_POINT:
|
||||||
{
|
{
|
||||||
vec3 lightDir = Lights[i].parameters1.xyz - vWorldPos;
|
vec3 lightPos = Lights[i].parameters1.xyz;
|
||||||
float lightDirLength = length(lightDir);
|
float lightAttenuation = Lights[i].parameters1.w;
|
||||||
lightDir /= lightDirLength; // Normalisation
|
float lightInvRadius = Lights[i].parameters2.w;
|
||||||
|
|
||||||
float att = max(Lights[i].parameters1.w - Lights[i].parameters2.w*lightDirLength, 0.0);
|
vec3 worldToLight = lightPos - vWorldPos;
|
||||||
|
float lightDirLength = length(worldToLight);
|
||||||
|
vec3 lightDir = worldToLight / lightDirLength; // Normalisation
|
||||||
|
|
||||||
|
float att = max(lightAttenuation - lightInvRadius * lightDirLength, 0.0);
|
||||||
|
|
||||||
// Ambient
|
// Ambient
|
||||||
lightAmbient += att * Lights[i].color.rgb * Lights[i].factors.x * (MaterialAmbient.rgb + SceneAmbient.rgb);
|
lightAmbient += att * lightColor.rgb * lightAmbientFactor * (MaterialAmbient.rgb + SceneAmbient.rgb);
|
||||||
|
|
||||||
|
#if SHADOW_MAPPING
|
||||||
|
if (Lights[i].shadowMapping && !TestShadowPoint(i, vWorldPos - lightPos, 0.1, 50.0))
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Diffuse
|
// Diffuse
|
||||||
float lambert = max(dot(normal, lightDir), 0.0);
|
float lambert = max(dot(normal, lightDir), 0.0);
|
||||||
|
|
||||||
lightDiffuse += att * lambert * Lights[i].color.rgb * Lights[i].factors.y;
|
lightDiffuse += att * lambert * lightColor.rgb * lightDiffuseFactor;
|
||||||
|
|
||||||
// Specular
|
// Specular
|
||||||
vec3 reflection = reflect(-lightDir, normal);
|
vec3 reflection = reflect(-lightDir, normal);
|
||||||
float specularFactor = max(dot(reflection, eyeVec), 0.0);
|
float specularFactor = max(dot(reflection, eyeVec), 0.0);
|
||||||
specularFactor = pow(specularFactor, MaterialShininess);
|
specularFactor = pow(specularFactor, MaterialShininess);
|
||||||
|
|
||||||
lightSpecular += att * specularFactor * Lights[i].color.rgb;
|
lightSpecular += att * specularFactor * lightColor.rgb;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LIGHT_SPOT:
|
case LIGHT_SPOT:
|
||||||
{
|
{
|
||||||
vec3 lightDir = Lights[i].parameters1.xyz - vWorldPos;
|
vec3 lightPos = Lights[i].parameters1.xyz;
|
||||||
float lightDirLength = length(lightDir);
|
vec3 lightDir = Lights[i].parameters2.xyz;
|
||||||
lightDir /= lightDirLength; // Normalisation
|
float lightAttenuation = Lights[i].parameters1.w;
|
||||||
|
float lightInvRadius = Lights[i].parameters2.w;
|
||||||
|
float lightInnerAngle = Lights[i].parameters3.x;
|
||||||
|
float lightOuterAngle = Lights[i].parameters3.y;
|
||||||
|
|
||||||
float att = max(Lights[i].parameters1.w - Lights[i].parameters2.w*lightDirLength, 0.0);
|
vec3 worldToLight = lightPos - vWorldPos;
|
||||||
|
float lightDistance = length(worldToLight);
|
||||||
|
worldToLight /= lightDistance; // Normalisation
|
||||||
|
|
||||||
|
float att = max(lightAttenuation - lightInvRadius * lightDistance, 0.0);
|
||||||
|
|
||||||
// Ambient
|
// Ambient
|
||||||
lightAmbient += att * Lights[i].color.rgb * Lights[i].factors.x * (MaterialAmbient.rgb + SceneAmbient.rgb);
|
lightAmbient += att * lightColor.rgb * lightAmbientFactor * (MaterialAmbient.rgb + SceneAmbient.rgb);
|
||||||
|
|
||||||
|
#if SHADOW_MAPPING
|
||||||
|
if (Lights[i].shadowMapping && !TestShadowSpot(i))
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Modification de l'atténuation pour gérer le spot
|
// Modification de l'atténuation pour gérer le spot
|
||||||
float curAngle = dot(Lights[i].parameters2.xyz, -lightDir);
|
float curAngle = dot(lightDir, -worldToLight);
|
||||||
float outerAngle = Lights[i].parameters3.y;
|
float innerMinusOuterAngle = lightInnerAngle - lightOuterAngle;
|
||||||
float innerMinusOuterAngle = Lights[i].parameters3.x - outerAngle;
|
att *= max((curAngle - lightOuterAngle) / innerMinusOuterAngle, 0.0);
|
||||||
att *= max((curAngle - outerAngle) / innerMinusOuterAngle, 0.0);
|
|
||||||
|
|
||||||
// Diffuse
|
// Diffuse
|
||||||
float lambert = max(dot(normal, lightDir), 0.0);
|
float lambert = max(dot(normal, worldToLight), 0.0);
|
||||||
|
|
||||||
lightDiffuse += att * lambert * Lights[i].color.rgb * Lights[i].factors.y;
|
lightDiffuse += att * lambert * lightColor.rgb * lightDiffuseFactor;
|
||||||
|
|
||||||
// Specular
|
// Specular
|
||||||
vec3 reflection = reflect(-lightDir, normal);
|
vec3 reflection = reflect(-worldToLight, normal);
|
||||||
float specularFactor = max(dot(reflection, eyeVec), 0.0);
|
float specularFactor = max(dot(reflection, eyeVec), 0.0);
|
||||||
specularFactor = pow(specularFactor, MaterialShininess);
|
specularFactor = pow(specularFactor, MaterialShininess);
|
||||||
|
|
||||||
lightSpecular += att * specularFactor * Lights[i].color.rgb;
|
lightSpecular += att * specularFactor * lightColor.rgb;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -256,61 +310,85 @@ void main()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
{
|
{
|
||||||
|
vec4 lightColor = Lights[i].color;
|
||||||
|
float lightAmbientFactor = Lights[i].factors.x;
|
||||||
|
float lightDiffuseFactor = Lights[i].factors.y;
|
||||||
|
|
||||||
switch (Lights[i].type)
|
switch (Lights[i].type)
|
||||||
{
|
{
|
||||||
case LIGHT_DIRECTIONAL:
|
case LIGHT_DIRECTIONAL:
|
||||||
{
|
{
|
||||||
vec3 lightDir = normalize(-Lights[i].parameters1.xyz);
|
vec3 lightDir = -Lights[i].parameters1.xyz;
|
||||||
|
|
||||||
// Ambient
|
// Ambient
|
||||||
lightAmbient += Lights[i].color.rgb * Lights[i].factors.x * (MaterialAmbient.rgb + SceneAmbient.rgb);
|
lightAmbient += lightColor.rgb * lightAmbientFactor * (MaterialAmbient.rgb + SceneAmbient.rgb);
|
||||||
|
|
||||||
// Diffuse
|
// Diffuse
|
||||||
float lambert = max(dot(normal, lightDir), 0.0);
|
float lambert = max(dot(normal, lightDir), 0.0);
|
||||||
|
|
||||||
lightDiffuse += lambert * Lights[i].color.rgb * Lights[i].factors.y;
|
lightDiffuse += lambert * lightColor.rgb * lightDiffuseFactor;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LIGHT_POINT:
|
case LIGHT_POINT:
|
||||||
{
|
{
|
||||||
vec3 lightDir = Lights[i].parameters1.xyz - vWorldPos;
|
vec3 lightPos = Lights[i].parameters1.xyz;
|
||||||
float lightDirLength = length(lightDir);
|
float lightAttenuation = Lights[i].parameters1.w;
|
||||||
lightDir /= lightDirLength; // Normalisation
|
float lightInvRadius = Lights[i].parameters2.w;
|
||||||
|
|
||||||
float att = max(Lights[i].parameters1.w - Lights[i].parameters2.w*lightDirLength, 0.0);
|
vec3 worldToLight = lightPos - vWorldPos;
|
||||||
|
float lightDirLength = length(worldToLight);
|
||||||
|
vec3 lightDir = worldToLight / lightDirLength; // Normalisation
|
||||||
|
|
||||||
|
float att = max(lightAttenuation - lightInvRadius * lightDirLength, 0.0);
|
||||||
|
|
||||||
// Ambient
|
// Ambient
|
||||||
lightAmbient += att * Lights[i].color.rgb * Lights[i].factors.x * (MaterialAmbient.rgb + SceneAmbient.rgb);
|
lightAmbient += att * lightColor.rgb * lightAmbientFactor * (MaterialAmbient.rgb + SceneAmbient.rgb);
|
||||||
|
|
||||||
|
#if SHADOW_MAPPING
|
||||||
|
if (Lights[i].shadowMapping && !TestShadowPoint(i, vWorldPos - lightPos, 0.1, 1.0 / lightInvRadius))
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Diffuse
|
// Diffuse
|
||||||
float lambert = max(dot(normal, lightDir), 0.0);
|
float lambert = max(dot(normal, lightDir), 0.0);
|
||||||
|
|
||||||
lightDiffuse += att * lambert * Lights[i].color.rgb * Lights[i].factors.y;
|
lightDiffuse += att * lambert * lightColor.rgb * lightDiffuseFactor;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LIGHT_SPOT:
|
case LIGHT_SPOT:
|
||||||
{
|
{
|
||||||
vec3 lightDir = Lights[i].parameters1.xyz - vWorldPos;
|
vec3 lightPos = Lights[i].parameters1.xyz;
|
||||||
float lightDirLength = length(lightDir);
|
vec3 lightDir = Lights[i].parameters2.xyz;
|
||||||
lightDir /= lightDirLength; // Normalisation
|
float lightAttenuation = Lights[i].parameters1.w;
|
||||||
|
float lightInvRadius = Lights[i].parameters2.w;
|
||||||
|
float lightInnerAngle = Lights[i].parameters3.x;
|
||||||
|
float lightOuterAngle = Lights[i].parameters3.y;
|
||||||
|
|
||||||
float att = max(Lights[i].parameters1.w - Lights[i].parameters2.w*lightDirLength, 0.0);
|
vec3 worldToLight = lightPos - vWorldPos;
|
||||||
|
float lightDistance = length(worldToLight);
|
||||||
|
worldToLight /= lightDistance; // Normalisation
|
||||||
|
|
||||||
|
float att = max(lightAttenuation - lightInvRadius * lightDistance, 0.0);
|
||||||
|
|
||||||
// Ambient
|
// Ambient
|
||||||
lightAmbient += att * Lights[i].color.rgb * Lights[i].factors.x * (MaterialAmbient.rgb + SceneAmbient.rgb);
|
lightAmbient += att * lightColor.rgb * lightAmbientFactor * (MaterialAmbient.rgb + SceneAmbient.rgb);
|
||||||
|
|
||||||
|
#if SHADOW_MAPPING
|
||||||
|
if (Lights[i].shadowMapping && !TestShadowSpot(i))
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Modification de l'atténuation pour gérer le spot
|
// Modification de l'atténuation pour gérer le spot
|
||||||
float curAngle = dot(Lights[i].parameters2.xyz, -lightDir);
|
float curAngle = dot(lightDir, -worldToLight);
|
||||||
float outerAngle = Lights[i].parameters3.y;
|
float innerMinusOuterAngle = lightInnerAngle - lightOuterAngle;
|
||||||
float innerMinusOuterAngle = Lights[i].parameters3.x - outerAngle;
|
att *= max((curAngle - lightOuterAngle) / innerMinusOuterAngle, 0.0);
|
||||||
att *= max((curAngle - outerAngle) / innerMinusOuterAngle, 0.0);
|
|
||||||
|
|
||||||
// Diffuse
|
// Diffuse
|
||||||
float lambert = max(dot(normal, lightDir), 0.0);
|
float lambert = max(dot(normal, worldToLight), 0.0);
|
||||||
|
|
||||||
lightDiffuse += att * lambert * Lights[i].color.rgb * Lights[i].factors.y;
|
lightDiffuse += att * lambert * lightColor.rgb * lightDiffuseFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -340,3 +418,4 @@ void main()
|
||||||
#endif // LIGHTING
|
#endif // LIGHTING
|
||||||
#endif // FLAG_DEFERRED
|
#endif // FLAG_DEFERRED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -15,6 +15,7 @@ in vec2 VertexTexCoord;
|
||||||
|
|
||||||
/********************Sortant********************/
|
/********************Sortant********************/
|
||||||
out vec4 vColor;
|
out vec4 vColor;
|
||||||
|
out vec4 vLightSpacePos[3];
|
||||||
out mat3 vLightToWorld;
|
out mat3 vLightToWorld;
|
||||||
out vec3 vNormal;
|
out vec3 vNormal;
|
||||||
out vec2 vTexCoord;
|
out vec2 vTexCoord;
|
||||||
|
|
@ -23,6 +24,8 @@ out vec3 vWorldPos;
|
||||||
|
|
||||||
/********************Uniformes********************/
|
/********************Uniformes********************/
|
||||||
uniform vec3 EyePosition;
|
uniform vec3 EyePosition;
|
||||||
|
uniform mat4 InvViewMatrix;
|
||||||
|
uniform mat4 LightViewProjMatrix[3];
|
||||||
uniform float VertexDepth;
|
uniform float VertexDepth;
|
||||||
uniform mat4 ViewProjMatrix;
|
uniform mat4 ViewProjMatrix;
|
||||||
uniform mat4 WorldMatrix;
|
uniform mat4 WorldMatrix;
|
||||||
|
|
@ -120,6 +123,11 @@ void main()
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SHADOW_MAPPING
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
vLightSpacePos[i] = LightViewProjMatrix[i] * WorldMatrix * vec4(VertexPosition, 1.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if TEXTURE_MAPPING
|
#if TEXTURE_MAPPING
|
||||||
vTexCoord = VertexTexCoord;
|
vTexCoord = VertexTexCoord;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue