#version 450 const int MAX_LIGHTS = 10; layout(location = 0) in vec3 v_Normal; layout(location = 1) in vec4 v_Position; layout(location = 2) in vec2 v_Uv; layout(location = 0) out vec4 o_Target; struct Light { mat4 proj; vec4 pos; vec4 color; }; layout(set = 0, binding = 0) uniform Globals { mat4 u_ViewProj; uvec4 u_NumLights; }; layout(set = 0, binding = 1) uniform Lights { Light u_Lights[MAX_LIGHTS]; }; layout(set = 0, binding = 2) uniform texture2DArray t_Shadow; layout(set = 0, binding = 3) uniform samplerShadow s_Shadow; layout(set = 1, binding = 0) uniform Entity { mat4 u_World; vec4 u_Color; }; float fetch_shadow(int light_id, vec4 homogeneous_coords) { // homogeneous coords is the depth of the previously rendered // fragment, from the lights perspective. If it's less than 0 // then it's behind the light, so it's obviously in shadow if (homogeneous_coords.w <= 0.0) { return 1.0; } // compensate for the Y-flip difference between the NDC and texture coordinates const vec2 flip_correction = vec2(0.5, -0.5); // compute texture coordinates for shadow lookup vec4 light_local = vec4( // I don't know what kind of jank shit is going on on this line homogeneous_coords.xy * flip_correction/homogeneous_coords.w + 0.5, light_id, homogeneous_coords.z / homogeneous_coords.w ); // do the lookup, using HW PCF and comparison return texture(sampler2DArrayShadow(t_Shadow, s_Shadow), light_local); } void main() { vec3 normal = normalize(v_Normal); vec3 ambient = vec3(0.05, 0.05, 0.05); // accumulate color vec3 color = ambient; for (int i=0; i