rend3-pbr 0.0.6

Type definitions for rend3
Documentation
#version 440

#include "structures.glsl"

layout(local_size_x = 256) in;

struct CullingUniforms {
    mat4 view;
    mat4 view_proj;
    Frustum frustum;
    uint object_count;
};

layout(set = 0, binding = 0, std430) restrict readonly buffer ObjectInputDataBuffer {
    CullingUniforms uniforms;
    ObjectInputData object_input[];
};
layout(set = 0, binding = 1, std430) restrict buffer ObjectOutputDataBuffer {
    ObjectOutputData object_output[];
};
layout(set = 0, binding = 2, std430) buffer IndirectBuffer {
    uint draw_call_count;
    uint _2;
    uint _3;
    uint _4;
    IndirectCall indirect_call[];
};

float plane_distance(Plane plane, vec3 location) {
    return dot(plane.inner.xyz, location) + plane.inner.w;
}

bool frustum_contains_sphere(Frustum frustum, vec4 sphere) {
    vec3 location = sphere.xyz;
    float neg_radius = -sphere.w;

    if (!(plane_distance(frustum.left, location) >= neg_radius)) {
        return false;
    }
    if (!(plane_distance(frustum.right, location) >= neg_radius)) {
        return false;
    }
    if (!(plane_distance(frustum.top, location) >= neg_radius)) {
        return false;
    }
    if (!(plane_distance(frustum.bottom, location) >= neg_radius)) {
        return false;
    }
    if (!(plane_distance(frustum.near, location) >= neg_radius)) {
        return false;
    }

    return true;
}

vec4 transform_sphere(vec4 sphere, mat4 transform) {
    float max_scale = max(max(length(transform[0].xyz), length(transform[1].xyz)), length(transform[2].xyz));
    vec4 center = transform * vec4(sphere.xyz, 1.0);

    return vec4(center.xyz, sphere.w * max_scale);
}

void main() {
    uint input_idx = gl_GlobalInvocationID.x;

    if (input_idx >= uniforms.object_count) {
        return;
    }

    ObjectInputData in_data = object_input[input_idx];

    mat4 model_view = uniforms.view * in_data.transform;
    vec4 mesh_sphere = transform_sphere(in_data.bounding_sphere, model_view);

    bool visible = frustum_contains_sphere(uniforms.frustum, mesh_sphere);

    if (!visible) {
        return;
    }

    uint output_idx = atomicAdd(draw_call_count, 1);

    ObjectOutputData out_data;

    out_data.model_view = uniforms.view * in_data.transform;
    out_data.model_view_proj = uniforms.view_proj * in_data.transform;
    out_data.inv_trans_model_view = inverse(transpose(mat3(uniforms.view * in_data.transform)));
    out_data.material_idx = in_data.material_idx;

    object_output[output_idx] = out_data;

    IndirectCall call;
    call.vertex_count = in_data.count;
    call.instance_count = 1;
    call.base_index = in_data.start_idx;
    call.vertex_offset = in_data.vertex_offset;
    call.base_instance = output_idx;
    indirect_call[output_idx] = call;
}