#version 450

layout(push_constant) uniform constants {
    mat4 lightSpaceMatrix;
    mat4 model;
};

layout(quads, equal_spacing, ccw) in;

layout(location = 0) in vec3 iPos[];
layout(location = 1) flat in int iChunkID[];

layout(binding = 1) uniform uEntity {
    mat4 unusedModel;
    vec4 noiseSize;
    vec4 unusedColor;
};

layout(binding = 2) readonly buffer uHeights {
    float heights[];
};

float height(vec2 id) {
    ivec2 noiseRes = ivec2(noiseSize.xy);
    vec2 gridPos = id * float(noiseRes - 1);

    ivec2 base = ivec2(floor(gridPos));
    vec2 frac = fract(gridPos);

    int idx00 = base.y * noiseRes.y + base.x;
    int idx10 = base.y * noiseRes.y + min(base.x + 1, noiseRes.x - 1);
    int idx01 = min(base.y + 1, noiseRes.y - 1) * noiseRes.x + base.x;
    int idx11 = min(base.y + 1, noiseRes.y - 1) * noiseRes.x + min(base.x + 1, noiseRes.x - 1);

    int offset = iChunkID[0] * noiseRes.x * noiseRes.y;

    float h00 = heights[offset + idx00];
    float h10 = heights[offset + idx10];
    float h01 = heights[offset + idx01];
    float h11 = heights[offset + idx11];

    return mix(mix(h00, h10, frac.x), mix(h01, h11, frac.x), frac.y);
}

void main() {
    vec2 id = gl_TessCoord.xy;
    vec4 p0 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, id.x);
    vec4 p1 = mix(gl_in[3].gl_Position, gl_in[2].gl_Position, id.x);
    vec4 pos = mix(p0, p1, id.y);

    float scale = 1.0;
    float h = height(id); // float(iChunkID[0]) * 0.5;

    pos.y += h * scale;
    gl_Position = lightSpaceMatrix * model * pos;
}
