layout (vertices=3) out;

#include "/lib/settings.glsl"

in DATA {
	#if !defined ENTITIES && !defined HAND && defined SHADER_GRASS && !defined BLOCKENTITIES
		vec4 grassSideCheck;
		vec3 centerPosition;
	#endif

	vec4 color;

    #if defined IRIS_FEATURE_FADE_VARIABLE && VANILLA_CHUNK_FADING > 0 && !defined HAND
		float chunkFade;
	#endif

	vec4 lmtexcoord;
	vec3 normalMat;

	#if defined POM && (defined WORLD && !defined ENTITIES && !defined HAND || defined COLORWHEEL)
		vec4 texcoordam; // .st for add, .pq for mul
		vec2 texcoord;
	#endif

	#ifdef MC_NORMAL_MAP
		vec4 tangent;
	#endif

	flat int blockID;
	vec3 worldPosAbs;
} data_in[];

out DATA {
	#if !defined ENTITIES && !defined HAND && defined SHADER_GRASS && !defined BLOCKENTITIES
		vec4 grassSideCheck;
		vec3 centerPosition;
	#endif

	vec4 color;

    #if defined IRIS_FEATURE_FADE_VARIABLE && VANILLA_CHUNK_FADING > 0 && !defined HAND
		float chunkFade;
	#endif

	vec4 lmtexcoord;
	vec3 normalMat;

	#if defined POM && (defined WORLD && !defined ENTITIES && !defined HAND || defined COLORWHEEL)
		vec4 texcoordam; // .st for add, .pq for mul
		vec2 texcoord;
	#endif

	#ifdef MC_NORMAL_MAP
		vec4 tangent;
	#endif

	flat int blockID;
	vec3 worldPosAbs;
} data_out[];

uniform mat4 gbufferModelViewInverse;
uniform vec3 cameraPosition;

vec3 viewToWorld(vec3 viewPosition) {
    vec4 pos;
    pos.xyz = viewPosition;
    pos.w = 0.0;
    pos = gbufferModelViewInverse * pos;
    return pos.xyz;
}

void main() {

    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;

    data_out[gl_InvocationID].color = data_in[gl_InvocationID].color;
    data_out[gl_InvocationID].lmtexcoord = data_in[gl_InvocationID].lmtexcoord;
    data_out[gl_InvocationID].normalMat = data_in[gl_InvocationID].normalMat;

    #if defined POM && (defined WORLD && !defined ENTITIES && !defined HAND || defined COLORWHEEL)
        data_out[gl_InvocationID].texcoordam = data_in[gl_InvocationID].texcoordam;
        data_out[gl_InvocationID].texcoord = data_in[gl_InvocationID].texcoord;
    #endif

    #if defined IRIS_FEATURE_FADE_VARIABLE && VANILLA_CHUNK_FADING > 0 && !defined HAND
		data_out[gl_InvocationID].chunkFade = data_in[gl_InvocationID].chunkFade;
	#endif

    #ifdef MC_NORMAL_MAP
        data_out[gl_InvocationID].tangent = data_in[gl_InvocationID].tangent;
    #endif

    data_out[gl_InvocationID].blockID = data_in[gl_InvocationID].blockID;
    data_out[gl_InvocationID].worldPosAbs = data_in[gl_InvocationID].worldPosAbs;

    if(gl_InvocationID == 0) {
    #if !defined ENTITIES && !defined HAND && defined SHADER_GRASS && !defined BLOCKENTITIES && defined WORLD

        data_out[gl_InvocationID].grassSideCheck = data_in[gl_InvocationID].grassSideCheck;

        data_out[gl_InvocationID].centerPosition = data_in[gl_InvocationID].centerPosition;

        #ifdef MC_NORMAL_MAP
            vec3 normals = viewToWorld(data_in[0].normalMat);
        #else
            const vec3 normals = vec3(0.0, 1.0, 0.0);
        #endif

        float vDist = length(gl_out[gl_InvocationID].gl_Position.xyz);

        #if REPLACE_SHORT_GRASS == 2
        if (data_in[0].blockID == 85 && normals.y > 0.9 && vDist < GRASS_RANGE && data_in[gl_InvocationID].grassSideCheck.x > 1.5)
        #else
        if (data_in[0].blockID == 85 && normals.y > 0.9 && vDist < GRASS_RANGE)
        #endif
        {
            // This removes the second layer of some texture packs like patrix, otherwise the grass is duplicated
            // float fractYPos = fract(gl_out[gl_InvocationID].gl_Position.y+cameraPosition.y);
            // if(fractYPos > 0.9999 || fractYPos < 0.0001 || abs(fractYPos - 0.5) < 0.0001)
            // {
                #if GRASS_DENSITY == 3
                    int innerDivisions = 8;
                    int outerDivisions = 6;
                    if (vDist > 10) {innerDivisions = 7; outerDivisions = 5;}
                    if (vDist > 20) {innerDivisions = 5; outerDivisions = 3;}
                    if (vDist > 25) {innerDivisions = 4; outerDivisions = 2;}
                #elif GRASS_DENSITY == 2
                    int innerDivisions = 7;
                    int outerDivisions = 5;
                    if (vDist > 13) {innerDivisions = 5; outerDivisions = 3;}
                    if (vDist > 22) {innerDivisions = 4; outerDivisions = 2;}
                #elif GRASS_DENSITY == 1
                    int innerDivisions = 5;
                    int outerDivisions = 6;
                    if (vDist > 10) {innerDivisions = 5; outerDivisions = 3;}
                    if (vDist > 20) {innerDivisions = 4; outerDivisions = 2;}
                #else
                    int innerDivisions = 5;
                    int outerDivisions = 4;
                    if (vDist > 10) {innerDivisions = 4; outerDivisions = 2;}
                    if (vDist > 20) {innerDivisions = 3; outerDivisions = 2;}
                #endif

                gl_TessLevelOuter[0] = outerDivisions;
                gl_TessLevelOuter[1] = outerDivisions;
                gl_TessLevelOuter[2] = outerDivisions;

                gl_TessLevelInner[0] = innerDivisions;
            // } else {
            //     gl_TessLevelOuter[0] = 0;
            //     gl_TessLevelOuter[1] = 0;
            //     gl_TessLevelOuter[2] = 0;

            //     gl_TessLevelInner[0] = 0;
            // }
        } else {
            gl_TessLevelOuter[0] = 1;
            gl_TessLevelOuter[1] = 1;
            gl_TessLevelOuter[2] = 1;

            gl_TessLevelInner[0] = 0;
        }
    #else
        gl_TessLevelOuter[0] = 1;
        gl_TessLevelOuter[1] = 1;
        gl_TessLevelOuter[2] = 1;

        gl_TessLevelInner[0] = 0;
    #endif
    }
}