#version 450

layout(points) in;
layout(triangle_strip, max_vertices=12) out;

layout(binding = 0) uniform UniformBufferObject {
    mat4 model;
    mat4 geom_rot;
    mat4 view;
    mat4 proj;
    bool[16] use_geom_shader;
} ubo;

layout(location = 0) in vec3 geoColor[];
layout(location = 1) in vec2 geoTexCoord[];

layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTexCoord;

bool ignore_scalars = false;

void main () {
    mat4 geom_rotation = ubo.geom_rot;
    //back
    vec4 normal_back = geom_rotation * vec4(0, 0, -1, 0);
    float scalar_back = dot(normal_back, vec4(1, 0, 0, 0));

    if (scalar_back <= 0 || ignore_scalars){
        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(0.5, -0.5, -0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();
    
        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(-0.5, -0.5, -0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(0.5, 0.5, -0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(-0.5, 0.5, -0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();
        EndPrimitive();
    }

    //front
    vec4 normal_front = geom_rotation * vec4(0, 0, 1, 0);
    float scalar_front = dot(normal_front, vec4(1, 0, 0, 0));
    if (scalar_front <= 0 || ignore_scalars) {
        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(-0.5, 0.5, 0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(-0.5, -0.5, 0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(0.5, 0.5, 0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(0.5, -0.5, 0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();
        EndPrimitive();
    }
    //up
    vec4 normal_up = geom_rotation * vec4(0, 1, 0, 0);
    float scalar_up = dot(normal_up, vec4(1, 0, 0, 0));

    if (scalar_up <= 0 || ignore_scalars) {
        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(0.5, 0.5, -0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(-0.5, 0.5, -0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(0.5, 0.5, 0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(-0.5, 0.5, 0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();
        EndPrimitive();
    }
    //down
    vec4 normal_down = geom_rotation * vec4(0, -1, 0, 0);
    float scalar_down = dot(normal_down, vec4(1, 0, 0, 0));

    if (scalar_down <= 0 || ignore_scalars) {
        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(-0.5, -0.5, 0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(-0.5, -0.5, -0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(0.5, -0.5, 0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(0.5, -0.5, -0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();
        EndPrimitive();
    }
    //left
    vec4 normal_left = geom_rotation * vec4(-1, 0, 0, 0);
    float scalar_left = dot(normal_left, vec4(1, 0, 0, 0));

    if (scalar_left <= 0 || ignore_scalars) {
        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(-0.5, 0.5, -0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(-0.5, -0.5, -0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(-0.5, 0.5, 0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(-0.5, -0.5, 0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();
        EndPrimitive();
    }
    //right
    vec4 normal_right = geom_rotation * vec4(1, 0, 0, 0);
    float scalar_right = dot(normal_right, vec4(1, 0, 0, 0));

    if (scalar_right <= 0 || ignore_scalars) {
        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(0.5, -0.5, 0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(0.5, -0.5, -0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(0.5, 0.5, 0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();

        gl_Position = ubo.proj * ubo.view * (gl_in[0].gl_Position + geom_rotation * vec4(0.5, 0.5, -0.5, 0));
        fragColor = geoColor[0];
        fragTexCoord = geoTexCoord[0];
        EmitVertex();
        EndPrimitive();
    }
}