#version 450

layout(location = 0) in Fragment {
    vec3 GeoPos;    // Реальная позиция в мире
    uint VoxMTL;    // Материал вокселя
    vec2 LUV;
    uint Place;
} fragment;

layout(location = 0) out vec4 Frame;

struct AtlasEntry {
    vec4 UVMinMax;
    uint Layer;
    uint Flags;
    uint _Pad0;
    uint _Pad1;
};

const uint ATLAS_ENTRY_VALID = 1u;

uniform layout(set = 0, binding = 0) sampler2DArray MainAtlas;
layout(set = 0, binding = 1) readonly buffer MainAtlasLayoutObj {
    AtlasEntry Entries[];
} MainAtlasLayout;

uniform layout(set = 1, binding = 0) sampler2DArray LightMap;
layout(set = 1, binding = 1) readonly buffer LightMapLayoutObj {
    vec3 Color;
} LightMapLayout;

vec4 atlasColor(uint texId, vec2 uv)
{
    uv = mod(uv, 1);

    AtlasEntry entry = MainAtlasLayout.Entries[texId];
    if((entry.Flags & ATLAS_ENTRY_VALID) == 0u)
        return vec4(((int(gl_FragCoord.x / 128) + int(gl_FragCoord.y / 128)) % 2) * vec3(1, 0, 1), 1);

    vec2 baseUV = vec2(uv.x, 1.0f - uv.y);
    vec2 atlasUV = mix(entry.UVMinMax.xy, entry.UVMinMax.zw, baseUV);
    atlasUV = clamp(atlasUV, entry.UVMinMax.xy, entry.UVMinMax.zw);
    return texture(MainAtlas, vec3(atlasUV, entry.Layer));
}

void main() {
    vec2 uv;

    switch(fragment.Place) {
    case 0:
        uv = fragment.GeoPos.xz; break;
    case 1:
        uv = fragment.GeoPos.xy; break;
    case 2:
        uv = fragment.GeoPos.zy; break;
    case 3:
        uv = fragment.GeoPos.xz*vec2(-1, -1); break;
    case 4:
        uv = fragment.GeoPos.xy*vec2(-1, 1); break;
    case 5:
        uv = fragment.GeoPos.zy*vec2(-1, 1); break;
    default:
        uv = vec2(0);
    }

    Frame = atlasColor(fragment.VoxMTL, uv);
}
