#version 450 layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #include layout(set = 0, binding = 0) uniform sampler2D reduced_depth_sampler; layout(std430, set = 0, binding = 1) buffer PointLightData { PointLight point_lights[10]; }point_light_data; layout(std430, set = 0, binding = 2) buffer SpotLightData { SpotLight spot_lights[10]; }spot_light_data; layout(std430, set = 0, binding = 3) buffer AreaLightData { AreaLight area_lights[10]; }area_light_data; layout(std430, set = 0, binding = 4) buffer ReflectionProbeData { ReflectionProbe probes[10]; }reflection_probe_data; const int ntiles_x = 120, ntiles_y = 68; layout(set = 0, binding = 5) buffer TileData { Tile tiles[ntiles_x][ntiles_y]; Item items[81600]; }tile_data; layout(set = 0, binding = 6) uniform NLightsBlock{ivec4 n_lights;} n_lights_block; layout(set = 0, binding = 7) buffer TilingInfo { uvec2 tile_size; uint max_items; uint max_items_tile; } tiling_info; layout(push_constant) uniform ProjectionData { mat4 mv; mat4 p; //vec3 view_pos; } projection_data; vec2 depth_minmax(ivec2 ctile) { return texelFetch(reduced_depth_sampler, ctile, 0).xy; } vec3 world_space_location(ivec2 ctile, float depth, ivec2 ntiles) { ivec2 resolution = ntiles*ivec2(tiling_info.tile_size); vec2 uv = vec2(ctile)/vec2(ntiles); //moves the location at the center og the tile uv += 0.5/vec2(ntiles); //converts from normalized range to -1.0..1.0 vec4 clip_space = vec4(1.0); clip_space.xy = uv*2.0-1.0; clip_space.z = depth; mat4 p = projection_data.p; p[0][3] = 0.0; p[1][3] = 0.0; p[2][3] = -1.0; vec4 homogenous = inverse(p)*clip_space; homogenous /= homogenous.w; vec4 world_space = inverse(projection_data.mv) * homogenous; return world_space.xyz; } float sphere_ray_intersection(vec3 ray_origin, vec3 ray_dir, vec4 sphere, out bool intersected) { vec3 op = sphere.xyz - ray_origin; float t, eps = 1e-3; float b = dot(op, ray_dir); float det = b * b - dot(op, op) + sphere.w * sphere.w; intersected = det >= 0.0; if(det < 0.0) { return 0.0; } else { det = sqrt(det); return (t = b - det) > eps ? t : ((t = b + det) > eps ? t : 0.0); } } bool has_influence(PointLight light, vec3 a, vec3 b) { vec3 ray_dir = normalize(b - a); vec3 ray_origin = a; bool intersected; float dist = sphere_ray_intersection( ray_origin, ray_dir, vec4(light.position.xyz, light.influence_radius), intersected ); return intersected && (dist > 0 || dist < length(b - a)) && dist != 0.0; return length(a-light.position.xyz) < light.influence_radius; } bool has_influence(SpotLight light, vec3 a, vec3 b) { return true; } bool has_influence(AreaLight light, vec3 a, vec3 b) { return false; } bool has_influence(ReflectionProbe light, vec3 a, vec3 b) { return false; } uint global_id(ivec2 ntiles) { /*return gl_GlobalInvocationID.z * gl_WorkGroupSize.x * gl_WorkGroupSize.y + gl_GlobalInvocationID.y * gl_WorkGroupSize.x + gl_GlobalInvocationID.x;*/ return gl_GlobalInvocationID.y*ntiles.x+gl_GlobalInvocationID.x; } void main(){ ivec2 ntiles = textureSize(reduced_depth_sampler, 0); if(gl_GlobalInvocationID.x > ntiles.x || gl_GlobalInvocationID.y > ntiles.y) return; //current til ivec2 ctile = ivec2(gl_GlobalInvocationID.xy); vec2 depth_minmax = depth_minmax(ctile); vec3 world_space_location_a = world_space_location(ctile, depth_minmax.x, ntiles), world_space_location_b = world_space_location(ctile, depth_minmax.y, ntiles); //tiles have fixed length in buffer tile_data.tiles[ctile.x][ctile.y].offset = int(global_id(ntiles)*tiling_info.max_items_tile); //------------------------------iterate over point lights-------------------------------- int current_light = 0, start = int(global_id(ntiles)*tiling_info.max_items_tile); for(int i = 0;i < n_lights_block.n_lights.x && current_light < tiling_info.max_items_tile;i++) { PointLight light = point_light_data.point_lights[i]; if(has_influence(light, world_space_location_a, world_space_location_b)) tile_data.items[start+current_light++].point_spot_offset = i << 16; } //writes count for this type of light tile_data.tiles[ctile.x][ctile.y].point_spot_area_probe_count = current_light; //------------------------------iterate over spot lights-------------------------------- current_light = 0; for(int i = 0;i < n_lights_block.n_lights.y && current_light < tiling_info.max_items_tile;i++) { SpotLight light = spot_light_data.spot_lights[i]; if(has_influence(light, world_space_location_a, world_space_location_b)) tile_data.items[start+current_light++].point_spot_offset |= i & 0x0000ffff; } //writes count for this type of light tile_data.tiles[ctile.x][ctile.y].point_spot_area_probe_count |= current_light << 8; //------------------------------iterate over area lights-------------------------------- current_light = 0; for(int i = 0;i < n_lights_block.n_lights.z && current_light < tiling_info.max_items_tile;i++) { AreaLight light = area_light_data.area_lights[i]; if(has_influence(light, world_space_location_a, world_space_location_b)) tile_data.items[start+current_light++].area_probe_offset = i << 16; } //writes count for this type of light tile_data.tiles[ctile.x][ctile.y].point_spot_area_probe_count |= current_light << 16; //------------------------------iterate over reflection probes-------------------------------- current_light = 0; for(int i = 0;i < n_lights_block.n_lights.w && current_light < tiling_info.max_items_tile;i++) { ReflectionProbe light = reflection_probe_data.probes[i]; if(has_influence(light, world_space_location_a, world_space_location_b)) tile_data.items[start+current_light++].point_spot_offset |= i & 0x0000ffff; } //writes count for this type of light tile_data.tiles[ctile.x][ctile.y].point_spot_area_probe_count |= current_light << 24; }