#version 150 compatibility
#extension GL_EXT_geometry_shader4 : enable

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

in mat3 NM[];
in mat4 PM[];
in vec4 color_gs[];

out vec3 normal;
out vec4 color;
out vec3 position;
flat out int side;

int surface_side_handling(in vec3 position, inout vec3 normal, inout vec4 color);

void emit_face(in vec3 normal_in, in vec4 c0, in vec4 c1, in vec4 c2, in vec4 c3)
{
	color = color_gs[0];
	// compute eye space normal and first corner position
	normal = normal_in;
	position = c0.xyz;

	// determine side in eye space
	side = surface_side_handling(position, normal, color);
	if (side == -1)
		return;

	// emit face
	gl_Position = gl_ProjectionMatrix * c0;
	EmitVertex();
	position = c1.xyz;
	gl_Position = gl_ProjectionMatrix * c1;
	EmitVertex();
	position = c2.xyz;
	gl_Position = gl_ProjectionMatrix * c2;
	EmitVertex();
	position = c3.xyz;
	gl_Position = gl_ProjectionMatrix * c3;
	EmitVertex();
	EndPrimitive();
}

void main()
{
	vec4 C0 = PM[0] * vec4(-0.5, -0.5, -0.5, 1.0);
	vec4 C1 = PM[0] * vec4(0.5, -0.5, -0.5, 1.0);
	vec4 C2 = PM[0] * vec4(-0.5, 0.5, -0.5, 1.0);
	vec4 C3 = PM[0] * vec4(0.5, 0.5, -0.5, 1.0);
	vec4 C4 = PM[0] * vec4(-0.5, -0.5, 0.5, 1.0);
	vec4 C5 = PM[0] * vec4(0.5, -0.5, 0.5, 1.0);
	vec4 C6 = PM[0] * vec4(-0.5, 0.5, 0.5, 1.0);
	vec4 C7 = PM[0] * vec4(0.5, 0.5, 0.5, 1.0);
	emit_face(NM[0] * vec3(-1.0, 0.0, 0.0), C0, C4, C2, C6);
	emit_face(NM[0] * vec3(1.0, 0.0, 0.0), C5, C1, C7, C3);
	emit_face(NM[0] * vec3(0.0, -1.0, 0.0), C0, C1, C4, C5);
	emit_face(NM[0] * vec3(0.0, 1.0, 0.0), C3, C2, C7, C6);
	emit_face(NM[0] * vec3(0.0, 0.0, -1.0), C0, C2, C1, C3);
	emit_face(NM[0] * vec3(0.0, 0.0, 1.0), C6, C4, C7, C5);
}
