Graphics: Add shadow mapping

Former-commit-id: ca404bee246991eab98df35396e3010ec5165c43
This commit is contained in:
Lynix 2015-07-05 23:57:54 +02:00
parent 4d07735b85
commit 75972fec36
10 changed files with 206 additions and 58 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
vec3 worldToLight = lightPos - vWorldPos;
float lightDistance = length(worldToLight);
worldToLight /= lightDistance; // Normalisation
float att = max(Lights[i].parameters1.w - Lights[i].parameters2.w*lightDirLength, 0.0); 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;
vec3 worldToLight = lightPos - vWorldPos;
float lightDistance = length(worldToLight);
worldToLight /= lightDistance; // Normalisation
float att = max(Lights[i].parameters1.w - Lights[i].parameters2.w*lightDirLength, 0.0); 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:
@ -318,7 +396,7 @@ void main()
} }
} }
} }
lightSpecular *= MaterialSpecular.rgb; lightSpecular *= MaterialSpecular.rgb;
#if SPECULAR_MAPPING #if SPECULAR_MAPPING
lightSpecular *= texture(MaterialSpecularMap, texCoord).rgb; // Utiliser l'alpha de MaterialSpecular n'aurait aucun sens lightSpecular *= texture(MaterialSpecularMap, texCoord).rgb; // Utiliser l'alpha de MaterialSpecular n'aurait aucun sens
@ -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

View File

@ -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