rend3-routine 0.3.0

Customizable Render Routines for the rend3 rendering library.
Documentation
#version 440

#ifdef GPU_DRIVEN
#extension GL_EXT_nonuniform_qualifier : require
#endif

layout(location = 0) in vec4 i_position;
layout(location = 1) in vec2 i_coords0;
layout(location = 2) in vec4 i_color;
layout(location = 3) flat in uint i_material;

#ifdef ALPHA_CUTOUT

layout(set = 0, binding = 0) uniform sampler primary_sampler;
#ifdef GPU_DRIVEN
layout(set = 1, binding = 1, std430) readonly buffer MaterialBuffer {
    float material_data[];
};
layout(set = 3, binding = 0) uniform texture2D textures[];
#endif
#ifdef CPU_DRIVEN
layout(set = 3, binding = 0, std430) readonly buffer TextureData {
    float material_data[];
};
layout(set = 3, binding = 1) uniform texture2D texture;
#endif
layout(set = 2, binding = 0) uniform DataAbi {
    uint stride; // Stride in offset into a float array (i.e. byte index / 4). Unused when GpuDriven.
    uint texture_offset; // Must be zero when GpuDriven. When GpuDriven, it's the index into the material data with the texture enable bitflag.
    uint cutoff_offset; // Stride in offset into a float array  (i.e. byte index / 4)
    uint uv_transform_offset; // Stride in offset into a float array pointing to a mat3 with the uv transform (i.e. byte index / 4). 0xFFFFFFFF represents "no transform"
};

void main() {
    uint base_material_offset = stride * i_material;
    float cutoff = material_data[base_material_offset + cutoff_offset];

    vec2 coords;
    if (uv_transform_offset != 0xFFFFFFFF) {
        uint base_transform_offset = base_material_offset + uv_transform_offset;
        mat3 transform = mat3(
            material_data[base_transform_offset + 0],
            material_data[base_transform_offset + 1],
            material_data[base_transform_offset + 2],
            material_data[base_transform_offset + 4],
            material_data[base_transform_offset + 5],
            material_data[base_transform_offset + 6],
            material_data[base_transform_offset + 8],
            material_data[base_transform_offset + 9],
            material_data[base_transform_offset + 10]
        );
        coords = vec2(transform * vec3(i_coords0, 1.0));
    } else {
        coords = i_coords0;
    }
    vec2 uvdx = dFdx(coords);
    vec2 uvdy = dFdy(coords);

    #ifdef GPU_DRIVEN
    uint texture_index = floatBitsToUint(material_data[base_material_offset + texture_offset]);
    if (texture_index != 0) {
        float alpha = textureGrad(sampler2D(textures[nonuniformEXT(texture_index - 1)], primary_sampler), coords, uvdx, uvdy).a;

        if (alpha <= cutoff) {
            discard;
        }
    }
    #endif
    #ifdef CPU_DRIVEN
    uint texture_enable_bitflags = floatBitsToUint(material_data[base_material_offset + texture_offset]);
    if (bool(texture_enable_bitflags & 0x1)) {
        float alpha = textureGrad(sampler2D(texture, primary_sampler), coords, uvdx, uvdy).a;

        if (alpha <= cutoff) {
            discard;
        }
    }
    #endif
}
#else // ALPHA_CUTOUT
void main() {}
#endif // ALPHA_CUTOUT