#version 450 struct DirectionalLightStruct { vec3 direction; uint isActive; uint cullingMask; vec4 diffuseColor; mat4 pvMatrix; uint shadowData; }; struct AmbientLightStruct { vec4 ambientColor; float strength; uint isActive; uint cullingMask; }; layout(local_size_x = 16, local_size_y = 16) in; layout(set = 3, binding = 0, rgba32f) uniform image2D positions; layout(set = 3, binding = 1, rgba32f) uniform image2D normals; layout(set = 3, binding = 2, rgba8) uniform image2D albedo; layout(set = 3, binding = 3, r32ui) uniform uimage2D lightLayerData; layout(set = 3, binding = 4, r8) uniform image2D ssaoBlurredImage; layout(set = 3, binding = 5, rgba8) uniform image2D positionWorldSpace; layout(set = 3, binding = 6, rgba8) uniform image2D targetImage; layout(set = 3, binding = 7, rgba8) uniform image2D objectVFXImage; layout (set = 4, binding = 0) uniform sampler2D shadowMaps[]; // for textures (global) layout(set = 1, binding = 0) uniform LightCounts { uint directionalLights; uint pointLights; uint spotLights; uint ambientLights; } lightCounts; layout(std430, set = 1, binding = 1) buffer DirectionalLightData { DirectionalLightStruct dLightData[]; } DirLightData; layout(std430, set = 1, binding = 4) buffer AmbientLightData { AmbientLightStruct aLightData[]; } AmbLightData; float LinStep (float val, float low, float high) { return clamp ((val - low)/(high - low), 0.0f, 1.0f); } float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV) { // clip space for fragment from light view space vec4 fragPosLightPOV = lightPV * worldSpaceFragPos; // Perform perspective division and convert to 0 to 1 range vec3 converted = (fragPosLightPOV.xyz / fragPosLightPOV.w) * vec3(0.5f) + vec3(0.5f); // float sampledDepth = texture(shadowMap, converted.xy).r; // float sampledDepth = texture(shadowMap, converted.xy).z; vec2 moments = texture(shadowMap, converted.xy).xy; if (converted.x < 0.0f || converted.x > 1.0f || converted.y < 0.0f || converted.y > 1.0f) return 1.0f; if (fragPosLightPOV.z > moments.x && fragPosLightPOV.w > 0.0f) { float p = step (fragPosLightPOV.z, moments.x); float variance = max (moments.y - (moments.x * moments.x), 0.00002f); float d = fragPosLightPOV.z - moments.x; float pMax = LinStep (variance / (variance + (d * d)), 0.9f, 1.0f); return min (max (p, pMax), 1.0f); } else if (fragPosLightPOV.z > 1.0f) { return 0.0f; } else return 0.3f; // return step (fragPosLightPOV.z, ); } void main() { // convenient variables ivec2 globalThread = ivec2(gl_GlobalInvocationID); // Get the diffuse color of the pixel vec3 pixelDiffuse = imageLoad (albedo, globalThread).rgb; // Get position of fragment in world space vec4 positionWorld = vec4 (imageLoad (positionWorldSpace, globalThread).rgb, 1.0f); // Get position of fragment in view spacee vec3 positionView = imageLoad (positions, globalThread).rgb; // normal of fragment vec3 normalView = imageLoad(normals, globalThread).rgb; // light layer index uint lightLayer = imageLoad (lightLayerData, globalThread).r; vec3 fragColor = vec3 (0.0f); vec4 shadowMapColor = vec4 (1.0f); for (int i = 0; i < lightCounts.ambientLights; ++i) { if ((lightLayer & AmbLightData.aLightData[i].cullingMask) != 0) { // Just do some add //fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (0.5f); fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (AmbLightData.aLightData[i].strength); } } for (int i = 0; i < lightCounts.directionalLights; ++i) { if ((lightLayer & DirLightData.dLightData[i].cullingMask) != 0) { // get normalized direction of light vec3 dLightNormalized = normalize (DirLightData.dLightData[i].direction); // Get diffuse strength float diffuseStrength = max (0, dot (-dLightNormalized, normalView)); // Calculate the fragment color fragColor += DirLightData.dLightData[i].diffuseColor.rgb * diffuseStrength.rrr * pixelDiffuse; // If the shadow map is enabled (test the bit) if ((DirLightData.dLightData[i].shadowData & uint(1)) == 1) { // calculate shadow map here fragColor *= CalcShadowValue (shadowMaps[0], positionWorld, DirLightData.dLightData[i].pvMatrix).xxx; } } } float ssaoVal = imageLoad (ssaoBlurredImage, globalThread).r; fragColor *= ssaoVal; vec4 objectVFXColor = imageLoad (objectVFXImage, globalThread); fragColor += objectVFXColor.rgb * objectVFXColor.a; // store result into result image imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor.rgb, 1.0f)); // vec2 normTexCoords = vec2 (gl_GlobalInvocationID.xy) / vec2 (1024.0f); // vec4 shadowMapVal = texture(shadowMaps[0], normTexCoords); // if (normTexCoords.x > 1.0f || normTexCoords.y > 1.0f) // shadowMapVal = vec4(0.0f); // imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), shadowMapVal.xxxx); }