game_kernel 0.1.0

A 3D game engine written entirely in rust
Documentation
#version 450

layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;

#include<light_structs.h>

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;
}