glsl fragment shader how to get non-interpolated data from each vertex
<p><strong>tl;dr:</strong>
What is the best method for accessing data from each individual vertex whilst in the fragment shader? </p>

<p><strong>e.g.</strong> 
The triangle in this fragment is made up from vertices v0,v1 and v2 and I want to give each vertex a specific integer which I can use to pick a texture and then fade between the 3 in the fragment shader; I don't want these ids to be interpolated and it is important that I can access each vertex's id.</p>

<p><strong>Current Situation:</strong>
I am currently writing a shader for rendering terrain; I have a function in my fragment shader which will return the appropriate texture colour from uvs for a given ID (By means of a texture atlas). I can then fade between the 3 textures to give the give smoothly textured terrain</p>

<p><strong>Current Code</strong></p>

<p>Vertex Shader:</p>

<pre><code>#version 330 core

layout(location = 0) in vec3 in_position;
layout(location = 1) in vec2 in_uv_coords;
layout(location = 2) in vec3 in_normal;
layout(location = 3) in float in_texture_id;

uniform mat4 view_matrix;
uniform mat4 projection_matrix;

out vec2 pass_uv_coords;
out vec3 pass_normal;

out vec3 texture_ratio;
out float pass_fake_brightness;

out float pass_id0;
out float pass_id1;
out float pass_id2;


void CalculateFakeLighting()
{
    const vec3 light_direction = normalize(vec3(1,-1,1));
    vec3 unit_normal = normalize(in_normal);

    float normal_dot_light = dot(unit_normal, -light_direction);
    pass_fake_brightness = max(0.2, normal_dot_light);
}


void main()
{
    pass_uv_coords = in_uv_coords;
    pass_normal = in_normal;

    gl_Position = projection_matrix * view_matrix * vec4(in_position, 1.0);

    int tile_track = int(mod(gl_VertexID, 3));

    switch(tile_track)
    {
        case 0:
            texture_ratio = vec3(1,0,0);
            pass_id0 = in_texture_id;
            break;
        case 1:
            texture_ratio = vec3(0,1,0);
            pass_id1 = in_texture_id;
            break;
        case 2:
            texture_ratio = vec3(0,0,1);
            pass_id0 = in_texture_id;
            break;
    };

    CalculateFakeLighting();
}
</code></pre>

<p>Fragment Shader:</p>

<pre><code>#version 330 core

in vec2 pass_uv_coords;
in vec3 pass_normal;

in vec3 texture_ratio;
in float pass_fake_brightness;

in float pass_id0;
in float pass_id1;
in float pass_id2;

const int HORIZONTAL_IDS = 8;
const int VERTICAL_IDS = 8;

uniform sampler2D texture0_sampler;

out vec4 colour;


void UseFakeLighting()
{
    colour *= pass_fake_brightness;
}

vec2 CorrectUVs(vec2 uvs)
{
    vec2 corrected_uvs = uvs;
    const float cushion = 0.001;

    //Correct UV scale
    while(corrected_uvs.x &gt;= 1)
        corrected_uvs.x--;
    while(corrected_uvs.y &gt;= 1)
        corrected_uvs.y--;

    if(corrected_uvs.x &lt; cushion)
        corrected_uvs.x = cushion;
    if(corrected_uvs.x &gt; 1 - cushion)
        corrected_uvs.x = 1 - cushion;

    if(corrected_uvs.y &lt; cushion)
        corrected_uvs.y = cushion;
    if(corrected_uvs.y &gt; 1 - cushion)
        corrected_uvs.y = 1 - cushion;

    return corrected_uvs;
}


vec4 GetTexture(float id, vec2 uv_coords)
{
    vec2 step = vec2(
        1.0/HORIZONTAL_IDS,
        1.0/VERTICAL_IDS
    );


    uv_coords.x/=HORIZONTAL_IDS;
    uv_coords.y/=VERTICAL_IDS;

    uv_coords.x += step.x * mod(id, HORIZONTAL_IDS);
    uv_coords.y += step.y * floor(id/VERTICAL_IDS);
    //Texture is upsidedown
    uv_coords.y = 1.0 - uv_coords.y;

    return texture(texture0_sampler, uv_coords);
}


void main()
{
    vec2 corrected_uvs = CorrectUVs(pass_uv_coords);
    vec3 correct_ratio = normalize(texture_ratio);

    colour = GetTexture(pass_id0, corrected_uvs) * correct_ratio.x +
    GetTexture(pass_id1, corrected_uvs) * correct_ratio.y +
    GetTexture(pass_id2, corrected_uvs) * correct_ratio.z;

    if(colour.a == 0)
        discard;

    UseFakeLighting();
}
</code></pre>