#version 150

vec3 frmHex(int u_color) {
	// by Alex Roth
	float rValue = float(u_color / 256 / 256);
	float gValue = float(u_color / 256 - int(rValue * 256.0));
	float bValue = float(u_color - int(rValue * 256.0 * 256.0) - int(gValue * 256.0));
	return vec3(rValue / 255.0, gValue / 255.0, bValue / 255.0);
}
vec3 frmRgbI(int r, int g, int b) {
	return vec3(r/255,g/255,b/255);
}
vec3 toHsv(vec3 inVal) {
	float r = inVal.x;
	float g = inVal.y;
	float b = inVal.z;
	
    // by Sam Hocevar
    float K = 0.0;
    float tmp;
    if (g < b) {
        tmp = g;
        g=b;
        b=tmp;
        K = -1.0;
    }
    if (r < g) {
        tmp = r;
        r=g;
        g=tmp;
        K = -2.0 / 6.0 - K;
    }
    float chroma = r - min(g, b);
    float h = abs(K + (g - b) / (6.0 * chroma + 1e-20));
    float s = chroma / (r + 1e-20);
    float v = r;
    return vec3(h, s, v);
}
bool fzyEql(float inVal, float target, float del) {
	if (distance(inVal,target) < del) {
		return true;
	} else {
		return false;
	}
}
bool rngCheck(float inVal, float target) {
	if (fzyEql(inVal, target, 0.004)) {
		return true;
	} else {
		return false;
	}
}
bool fzyEqlV3(vec3 inVal, vec3 target, float del) {
	if (fzyEql(inVal.x,target.x,del) &&
	    fzyEql(inVal.y,target.y,del) &&
		fzyEql(inVal.z,target.z,del)) {
		return true;
	} else {
		return false;
	}
}
bool rngCheckV3(vec3 inVal, vec3 target) {
	if (rngCheck(inVal.x,target.x) &&
	    rngCheck(inVal.y,target.y) &&
		rngCheck(inVal.z,target.z)) {
		return true;
	} else {
		return false;
	}
}
bool rngCheckV4(vec4 inVal, vec4 target) {
	if (rngCheckV3(inVal.xyz,target.xyz) &&
	    rngCheck(inVal.w,target.w)) {
		return true;
	} else {
		return false;
	}
}

vec4 linear_fog(vec4 inColor, float vertexDistance, float fogStart, float fogEnd, vec4 fogColor) {
	
    // by shmoobalizer
    float fogLength = fogStart / fogEnd;
    //vec4 netherFogColor = vec4(frmHex(0x1D0404),1.0);
    vec4 endFogColor = vec4(frmHex(0x0E0E11),0.9);
    if (fzyEqlV3(fogColor.rgb,frmHex(0x141014),0.01)) { // if end
        fogColor = endFogColor;
    } else if (fogLength > 0.0 && fogLength < 0.2) { // if nether~
        //fogColor = netherFogColor;
		fogStart = fogStart / 1;
		fogEnd = fogEnd * 3;
    } else { // if overworld~~
		fogStart = fogStart / 4;
		fogEnd = fogEnd * 1;
	}

    if (vertexDistance <= fogStart) {
        return inColor;
    }
    float fogValue = vertexDistance < fogEnd ? smoothstep(fogStart, fogEnd, vertexDistance) : 1.0;
    
    return vec4(mix(inColor.rgb, fogColor.rgb, fogValue * fogColor.a), inColor.a);
}

float linear_fog_fade(float vertexDistance, float fogStart, float fogEnd) {
    if (vertexDistance <= fogStart) {
        return 1.0;
    } else if (vertexDistance >= fogEnd) {
        return 0.0;
    }

    return smoothstep(fogEnd, fogStart, vertexDistance);
}
// 1.18.1
float cylindrical_distance(mat4 modelViewMat, vec3 pos) {
    float distXZ = length((modelViewMat * vec4(pos.x, 0.0, pos.z, 1.0)).xyz);
    //float distY = length((modelViewMat * vec4(0.0, pos.y, 0.0, 1.0)).xyz);
    float distY = length((modelViewMat * vec4(pos.x, pos.y, pos.z, 1.0)).xyz);
    return max(distXZ, distY);
}

// 1.18.2 +
float fog_distance(mat4 modelViewMat, vec3 pos, int shape) {
    if (shape == 0) {
        return length((modelViewMat * vec4(pos, 1.0)).xyz);
    } else {
        //float distXZ = length((modelViewMat * vec4(pos.x, 0.0, pos.z, 1.0)).xyz);
        //float distY = length((modelViewMat * vec4(0.0, pos.y, 0.0, 1.0)).xyz);
        //return max(distXZ, distY);
        return length((modelViewMat * vec4(pos, 1.0)).xyz);
    }
}

