// G-BUFFER // - Normal buffer uniform sampler2DRect normalBuffer; // - Color + objectId buffer uniform sampler2DRect colorBuffer; // - Specular color + Specular exponent buffer uniform sampler2DRect specularBuffer; // - Position in view space uniform sampler2DRect positionBuffer; // - depth buffer uniform sampler2DRect depthBuffer; // LIGHT ATTRIBUTES uniform vec3 lightColor; #ifdef SHADOWMAP #ifdef POINT_LIGHT uniform samplerCubeShadow shadowMap; uniform mat3 inverseViewMatrix; #else uniform sampler2DShadow shadowMap; uniform mat4 viewToLightMatrix; #endif #endif #if defined POINT_LIGHT uniform vec3 pointLight; uniform float range; #elif defined DIRECTIONNAL_LIGHT uniform vec3 dirLight; #elif defined SPOT_LIGHT uniform vec3 pointLight; uniform float attenuation; uniform vec3 dirLight; uniform float cutoff; #endif // FRAGMENT POSITIONNING in vec2 screenPos; uniform mat4 inverseProjectionMatrix; // OUTPUT LIGHT layout(location = 0)out vec4 outColor; // FUNCTIONS const float CELL_SHADING = 0.3333; vec3 phongLighting(in vec3 kd, in vec3 ks, in float ns, in vec3 color, in vec3 normal, in vec3 lightDir, in vec3 halfVec, in vec3 viewDir){ float diffuseComponent = max(dot(normal, lightDir), 0); float specularComponent = max(dot(halfVec, normal), 0); return color*diffuseComponent*(kd+ks*pow(specularComponent, ns)); } vec3 CookTorranceSpecularHighlight(in vec3 ks, in float ns, in vec3 normal, in vec3 lightDir, in vec3 halfVec, in vec3 viewDir){ float HN = dot(halfVec, normal); float VN = dot(viewDir, normal); float VH = dot(viewDir, halfVec); float LN = dot(lightDir, normal); HN = max(HN, 0); VN = max(VN, 0); LN = max(LN, 0); // GGX normal distribution : float roughness = 2/(ns+2); float denom = mix(1, roughness, HN*HN); float D = roughness/(3.1416*denom*denom); //D = pow(HN, ns); // Fresnel term with Schlick's approximation vec3 F = mix(ks, vec3(1), pow(1 - VH, 5)); VH = max(VH, 0); // Geometric attenuation float G = min(1, min(2*HN*VN/VH, 2*HN*LN/VH)); return D * F * G; } vec3 testLighting(in vec3 kd, in vec3 ks, in float ns, in vec3 color, in vec3 normal, in vec3 lightDir, in vec3 halfVec, in vec3 viewDir){ float diffuseComponent = max(dot(normal, lightDir), 0); return color*diffuseComponent*(kd+ks*CookTorranceSpecularHighlight(ks, ns, normal, lightDir, halfVec, viewDir)); } // MAIN PROGRAM void main(void) { ivec2 texCoord = ivec2(gl_FragCoord.xy); vec3 normal = texelFetch(normalBuffer, texCoord).xyz; vec4 diffuseTexel = texelFetch(colorBuffer, texCoord); vec3 diffuse = diffuseTexel.rgb; vec4 specularTexel = texelFetch(specularBuffer, texCoord); vec3 specular = specularTexel.rgb; float shininess = specularTexel.w*255; vec4 fragPos = texelFetch(positionBuffer, texCoord); float depth = texelFetch(depthBuffer, texCoord).r; #ifdef SHADOWMAP #ifdef POINT_LIGHT float shadow = 1; #else vec4 fragInLightSpace = viewToLightMatrix * fragPos; fragInLightSpace.z = fragInLightSpace.z - 0.002; float shadow = texture(shadowMap, fragInLightSpace.xyz/fragInLightSpace.w); #endif #else float shadow = 1; #endif float att = 1; #ifdef POINT_LIGHT vec3 dirLight = pointLight - fragPos.xyz; vec4 pointShadowParam = vec4(inverseViewMatrix * dirLight, length(dirLight)); att = texture(shadowMap, pointShadowParam); //outColor = vec4(vec3(texture(shadowMap, vec4(inverseViewMatrix * dirLight, length(dirLight))).r), 1); //return; att = clamp(att, 0, 1); dirLight = normalize(dirLight); #endif #ifdef AMBIENT_LIGHT outColor = vec4(diffuse*lightColor, 1); #else vec3 viewDir = normalize(-fragPos.xyz); vec3 halfVec = normalize(viewDir + dirLight); vec3 light = testLighting(diffuse, specular, shininess, lightColor, normal, dirLight, halfVec, viewDir); outColor = vec4(mix(vec3(0.0), light*shadow, att*att), 1); #endif }