#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(binding = 0) uniform UniformBufferObject {
    mat4 normalMat;
    mat4 view;
    mat4 proj;
    uint mode;
    uint angleType;
} ubo;

layout(push_constant) uniform PushConsts {
    uint wallDrawMode;
} pushConstants;

layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec3 inColour;
layout(location = 3) in vec2 inTexCoord;
layout(location = 4) in uint inTexIndex;
layout(location = 5) in vec3 extraColour;
layout(location = 6) in uint extraFlags;
layout(location = 7) in uint inTileIndex;

layout(location = 0) out vec3 fragColour;
layout(location = 1) out vec2 fragTexCoord;
layout(location = 2) out uint fragTexIndex;
layout(location = 3) out vec3 fragExtraColour;
layout(location = 4) out vec3 fragNormal;
layout(location = 5) out uint fragTileIndex;
layout(location = 6) out vec3 fragCoord;

out gl_PerVertex {
    vec4 gl_Position;
};

void main() {
    vec3 pos = inPosition;
    fragTexCoord = inTexCoord;
    // if we do not want to show the *entire* wall length
    // (as it might obstruct the user's view), lower it
    // mode 1 == full wall
    // mode 2 == only full view if in the back depending on camera angle
    // mode == 3 everything is lower
    // the fifth bit indicates if this is the "upper" vertex that might need to get lowered
    // the sixth bit indicates if this is a lower vertex in a portal that may need to vanish altogether
    if (pushConstants.wallDrawMode != 1) {
        if ((pushConstants.wallDrawMode == 3 || (((extraFlags >> ubo.angleType) & 1U) == 0))
            && (((extraFlags >> 5) & 1U) == 1)) {
            pos.y -= 2.22;
            // texture index 2048 means "no texture", do not try to set an offset on nothing
            if (inTexIndex != 2048) {
                fragTexCoord.y = 268;
            }
            if (((extraFlags >> 6) & 1U) == 1) {
                pos.y = -0.1;
            }
        }
    }
    gl_Position = ubo.proj * ubo.view * vec4(pos, 1.0);
    fragColour = inColour;
    // 2048 is a special value that means we want to use the blank texture instead
    fragTexIndex = (inTexIndex != 2048) ? inTexIndex : 0;
    fragExtraColour = extraColour;
    fragTileIndex = inTileIndex;
    // lighting information passed on to the fragment shader
    fragNormal = inNormal;
    fragCoord = inPosition;
}