#include <metal_stdlib>
#include <simd/simd.h>

using namespace metal;

struct VertexOut
{
    float2 uv [[user(locn0)]];
    float eyedist [[user(locn1)]];
    float4 gl_Position [[position]];
};

struct VertexIn
{
    float2 pos_attr [[attribute(0)]];
    float2 uv_attr [[attribute(1)]];
    float2 vector_offset_attr [[attribute(2)]];
};

vertex VertexOut vertexShader(VertexIn in [[stage_in]], constant int& projected_tile_size_unif [[buffer(1)]], constant float& meter_scale_unif [[buffer(2)]], constant float4x4& modelview_unif [[buffer(3)]], constant float& edge_width_multiplier [[buffer(4)]], constant float4x4& proj_unif [[buffer(5)]], constant float2& tex_scale_unif [[buffer(6)]], constant float2& tex_offset_unif [[buffer(7)]], texture2d<float> heightmap_unif [[texture(0)]], sampler heightmap_unifSmplr [[sampler(0)]])
{
    VertexOut out = {};
    float elev_range = 4492.0;
    float elev_min = -80.0;
    float elev_offset = 3.0;
    float proj_tile_size = float(projected_tile_size_unif);
    float4 heightmap_pixel = heightmap_unif.sample(heightmap_unifSmplr, (in.pos_attr / float2(proj_tile_size)), level(0.0));
    float z = (heightmap_pixel.w + (heightmap_pixel.z * 255.0)) / 256.0;
    float altitude = elev_offset + ((elev_min + (z * elev_range)) * meter_scale_unif);
    float4 world_pos = modelview_unif * float4(in.pos_attr + (in.vector_offset_attr * edge_width_multiplier), altitude, 1.0);
    out.gl_Position = proj_unif * world_pos;
    out.uv = (in.uv_attr * tex_scale_unif) + tex_offset_unif;
    out.eyedist = -world_pos.z;
    return out;
}

