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

@@ -8,6 +8,7 @@ layout(early_fragment_tests) in;
/********************Entrant********************/
in vec4 vColor;
in vec4 vLightSpacePos[3];
in mat3 vLightToWorld;
in vec3 vNormal;
in vec2 vTexCoord;
@@ -29,10 +30,13 @@ struct Light
vec4 parameters1;
vec4 parameters2;
vec2 parameters3;
bool shadowMapping;
};
// Lumières
uniform Light Lights[3];
uniform samplerCube PointLightShadowMap[3];
uniform sampler2D SpotLightShadowMap[3];
// Matériau
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);
}
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()
{
vec4 diffuseColor = MaterialDiffuse * vColor;
@@ -168,6 +198,10 @@ void main()
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)
{
case LIGHT_DIRECTIONAL:
@@ -175,75 +209,95 @@ void main()
vec3 lightDir = -Lights[i].parameters1.xyz;
// Ambient
lightAmbient += Lights[i].color.rgb * Lights[i].factors.x * (MaterialAmbient.rgb + SceneAmbient.rgb);
lightAmbient += lightColor.rgb * lightAmbientFactor * (MaterialAmbient.rgb + SceneAmbient.rgb);
// Diffuse
float lambert = max(dot(normal, lightDir), 0.0);
lightDiffuse += lambert * Lights[i].color.rgb * Lights[i].factors.y;
lightDiffuse += lambert * lightColor.rgb * lightDiffuseFactor;
// Specular
vec3 reflection = reflect(-lightDir, normal);
float specularFactor = max(dot(reflection, eyeVec), 0.0);
specularFactor = pow(specularFactor, MaterialShininess);
lightSpecular += specularFactor * Lights[i].color.rgb;
lightSpecular += specularFactor * lightColor.rgb;
break;
}
case LIGHT_POINT:
{
vec3 lightDir = Lights[i].parameters1.xyz - vWorldPos;
float lightDirLength = length(lightDir);
lightDir /= lightDirLength; // Normalisation
vec3 lightPos = Lights[i].parameters1.xyz;
float lightAttenuation = Lights[i].parameters1.w;
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
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
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
vec3 reflection = reflect(-lightDir, normal);
float specularFactor = max(dot(reflection, eyeVec), 0.0);
specularFactor = pow(specularFactor, MaterialShininess);
lightSpecular += att * specularFactor * Lights[i].color.rgb;
lightSpecular += att * specularFactor * lightColor.rgb;
break;
}
case LIGHT_SPOT:
{
vec3 lightDir = Lights[i].parameters1.xyz - vWorldPos;
float lightDirLength = length(lightDir);
lightDir /= lightDirLength; // Normalisation
vec3 lightPos = Lights[i].parameters1.xyz;
vec3 lightDir = Lights[i].parameters2.xyz;
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
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
float curAngle = dot(Lights[i].parameters2.xyz, -lightDir);
float outerAngle = Lights[i].parameters3.y;
float innerMinusOuterAngle = Lights[i].parameters3.x - outerAngle;
att *= max((curAngle - outerAngle) / innerMinusOuterAngle, 0.0);
float curAngle = dot(lightDir, -worldToLight);
float innerMinusOuterAngle = lightInnerAngle - lightOuterAngle;
att *= max((curAngle - lightOuterAngle) / innerMinusOuterAngle, 0.0);
// 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
vec3 reflection = reflect(-lightDir, normal);
vec3 reflection = reflect(-worldToLight, normal);
float specularFactor = max(dot(reflection, eyeVec), 0.0);
specularFactor = pow(specularFactor, MaterialShininess);
lightSpecular += att * specularFactor * Lights[i].color.rgb;
lightSpecular += att * specularFactor * lightColor.rgb;
break;
}
@@ -256,61 +310,85 @@ void main()
{
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)
{
case LIGHT_DIRECTIONAL:
{
vec3 lightDir = normalize(-Lights[i].parameters1.xyz);
vec3 lightDir = -Lights[i].parameters1.xyz;
// Ambient
lightAmbient += Lights[i].color.rgb * Lights[i].factors.x * (MaterialAmbient.rgb + SceneAmbient.rgb);
lightAmbient += lightColor.rgb * lightAmbientFactor * (MaterialAmbient.rgb + SceneAmbient.rgb);
// Diffuse
float lambert = max(dot(normal, lightDir), 0.0);
lightDiffuse += lambert * Lights[i].color.rgb * Lights[i].factors.y;
lightDiffuse += lambert * lightColor.rgb * lightDiffuseFactor;
break;
}
case LIGHT_POINT:
{
vec3 lightDir = Lights[i].parameters1.xyz - vWorldPos;
float lightDirLength = length(lightDir);
lightDir /= lightDirLength; // Normalisation
vec3 lightPos = Lights[i].parameters1.xyz;
float lightAttenuation = Lights[i].parameters1.w;
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
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
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;
}
case LIGHT_SPOT:
{
vec3 lightDir = Lights[i].parameters1.xyz - vWorldPos;
float lightDirLength = length(lightDir);
lightDir /= lightDirLength; // Normalisation
vec3 lightPos = Lights[i].parameters1.xyz;
vec3 lightDir = Lights[i].parameters2.xyz;
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
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
float curAngle = dot(Lights[i].parameters2.xyz, -lightDir);
float outerAngle = Lights[i].parameters3.y;
float innerMinusOuterAngle = Lights[i].parameters3.x - outerAngle;
att *= max((curAngle - outerAngle) / innerMinusOuterAngle, 0.0);
float curAngle = dot(lightDir, -worldToLight);
float innerMinusOuterAngle = lightInnerAngle - lightOuterAngle;
att *= max((curAngle - lightOuterAngle) / innerMinusOuterAngle, 0.0);
// 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:
@@ -318,7 +396,7 @@ void main()
}
}
}
lightSpecular *= MaterialSpecular.rgb;
#if SPECULAR_MAPPING
lightSpecular *= texture(MaterialSpecularMap, texCoord).rgb; // Utiliser l'alpha de MaterialSpecular n'aurait aucun sens
@@ -340,3 +418,4 @@ void main()
#endif // LIGHTING
#endif // FLAG_DEFERRED
}

File diff suppressed because one or more lines are too long

View File

@@ -15,6 +15,7 @@ in vec2 VertexTexCoord;
/********************Sortant********************/
out vec4 vColor;
out vec4 vLightSpacePos[3];
out mat3 vLightToWorld;
out vec3 vNormal;
out vec2 vTexCoord;
@@ -23,6 +24,8 @@ out vec3 vWorldPos;
/********************Uniformes********************/
uniform vec3 EyePosition;
uniform mat4 InvViewMatrix;
uniform mat4 LightViewProjMatrix[3];
uniform float VertexDepth;
uniform mat4 ViewProjMatrix;
uniform mat4 WorldMatrix;
@@ -120,6 +123,11 @@ void main()
#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
vTexCoord = VertexTexCoord;
#endif

File diff suppressed because one or more lines are too long