#version 450
layout(vertices = 3) out;

struct pn_patch
{
    float b210;
    float b120;
    float b021;
    float b012;
    float b102;
    float b201;
    float b111;
    float n110;
    float n011;
    float n101;
};

layout(binding = 0, std140) uniform uniforms_t
{
    mat4 ProjectionMatrix;
    mat4 ViewMatrix;
    mat4 ModelMatrix;
    vec4 uv_tiling;
    vec4 light_position;
    vec4 tess_params;
} ub;

layout(location = 0) in vec4 v_normal[];
layout(location = 0) out vec4 tcs_normal[3];
layout(location = 3) out vec4 tcs_uv[3];
layout(location = 1) in vec4 v_uv[];
layout(location = 6) out pn_patch tcs_patch[3];

float wij(int i, int j)
{
    return dot(gl_in[j].gl_Position.xyz - gl_in[i].gl_Position.xyz, v_normal[i].xyz);
}

float vij(int i, int j)
{
    vec3 Pj_minus_Pi = gl_in[j].gl_Position.xyz - gl_in[i].gl_Position.xyz;
    vec3 Ni_plus_Nj = v_normal[i].xyz + v_normal[j].xyz;
    return (2.0 * dot(Pj_minus_Pi, Ni_plus_Nj)) / dot(Pj_minus_Pi, Pj_minus_Pi);
}

void main()
{
    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
    tcs_normal[gl_InvocationID] = v_normal[gl_InvocationID];
    tcs_uv[gl_InvocationID] = v_uv[gl_InvocationID];
    float P0 = gl_in[0].gl_Position[gl_InvocationID];
    float P1 = gl_in[1].gl_Position[gl_InvocationID];
    float P2 = gl_in[2].gl_Position[gl_InvocationID];
    float N0 = v_normal[0][gl_InvocationID];
    float N1 = v_normal[1][gl_InvocationID];
    float N2 = v_normal[2][gl_InvocationID];
    int param = 0;
    int param_1 = 1;
    barrier();
    tcs_patch[gl_InvocationID].b210 = (((2.0 * P0) + P1) - (wij(param, param_1) * N0)) / 3.0;
    int param_2 = 1;
    int param_3 = 0;
    tcs_patch[gl_InvocationID].b120 = (((2.0 * P1) + P0) - (wij(param_2, param_3) * N1)) / 3.0;
    int param_4 = 1;
    int param_5 = 2;
    tcs_patch[gl_InvocationID].b021 = (((2.0 * P1) + P2) - (wij(param_4, param_5) * N1)) / 3.0;
    int param_6 = 2;
    int param_7 = 1;
    tcs_patch[gl_InvocationID].b012 = (((2.0 * P2) + P1) - (wij(param_6, param_7) * N2)) / 3.0;
    int param_8 = 2;
    int param_9 = 0;
    tcs_patch[gl_InvocationID].b102 = (((2.0 * P2) + P0) - (wij(param_8, param_9) * N2)) / 3.0;
    int param_10 = 0;
    int param_11 = 2;
    tcs_patch[gl_InvocationID].b201 = (((2.0 * P0) + P2) - (wij(param_10, param_11) * N0)) / 3.0;
    float E = (((((tcs_patch[gl_InvocationID].b210 + tcs_patch[gl_InvocationID].b120) + tcs_patch[gl_InvocationID].b021) + tcs_patch[gl_InvocationID].b012) + tcs_patch[gl_InvocationID].b102) + tcs_patch[gl_InvocationID].b201) / 6.0;
    float V = ((P0 + P1) + P2) / 3.0;
    tcs_patch[gl_InvocationID].b111 = E + ((E - V) * 0.5);
    int param_12 = 0;
    int param_13 = 1;
    tcs_patch[gl_InvocationID].n110 = (N0 + N1) - (vij(param_12, param_13) * (P1 - P0));
    int param_14 = 1;
    int param_15 = 2;
    tcs_patch[gl_InvocationID].n011 = (N1 + N2) - (vij(param_14, param_15) * (P2 - P1));
    int param_16 = 2;
    int param_17 = 0;
    tcs_patch[gl_InvocationID].n101 = (N2 + N0) - (vij(param_16, param_17) * (P0 - P2));
    float tessLevelOuter = ub.tess_params.x;
    float tessLevelInner = ub.tess_params.y;
    gl_TessLevelOuter[gl_InvocationID] = tessLevelOuter;
    gl_TessLevelInner[0] = tessLevelInner;
}

