#version 130

#pragma vertex_shader

in vec4 vertex;
in vec3 normal;
out vec3 worldNormal;
out vec3 worldPos;
uniform mat4 transform;
void main() {
	gl_Position = transform * vertex;
	worldPos = vertex.xyz;
	worldNormal = normal;
}

#pragma fragment_shader


in vec3 worldNormal;
in vec3 worldPos;
out vec4 fragment;

uniform vec3 lightDirection;
uniform vec4 mapBounds;

uniform sampler2D diffuseMap0;
uniform sampler2D normalMap0;
uniform sampler2D diffuseMap1;
uniform sampler2D normalMap1;



uniform vec2 scale0;
uniform float opacity0;
uniform vec3 autoMin0;
uniform vec3 autoMax0;
uniform vec3 autoBlend0;
uniform vec2 scale1;
uniform float opacity1;
uniform vec3 autoMin1;
uniform vec3 autoMax1;
uniform vec3 autoBlend1;


//Utility functions
float getAutoWeight(vec3 value, vec3 vmin, vec3 vmax, vec3 vblend) {
	vec3 r = smoothstep(vmin-vblend, vmin, value) * smoothstep(vmax+vblend, vmax, value);
	return r.x * r.y * r.z;
}
vec4 sampleNormal(sampler2D map, vec2 coord) {
	vec4 n = texture(map, coord);
	return vec4(n.xyz * 2.0 - 1.0, n.w);
}
vec4 sampleDiffuse(sampler2D map, vec2 coord) {
	return texture(map, coord);
}



// Main shader function
void main() {
	vec4 diffuse = vec4(1.0);
	vec4 normal = vec4(0.0,0.0,1.0,0.0);
	float gloss = 0.0;
	float height;
	float weight;
	vec4 diff, norm;
	vec3 triplanar = max( (abs(worldNormal) - 0.2) * 0.7, 0.0);
	triplanar /= dot(triplanar, vec3(1.0,1.0,1.0));
	vec3 autoValue = vec3(worldPos.y, 1.0 - worldNormal.y, 0.0);
	
	vec3 vertical = vec3(triplanar.x, 0.0, triplanar.z);
	// Layer Procedural layer
	weight = getAutoWeight(autoValue, autoMin0, autoMax0, autoBlend0);
	diff = sampleDiffuse(diffuseMap0, worldPos.xz * scale0);
	norm = sampleNormal(normalMap0, worldPos.xz * scale0);
	diffuse = mix(diffuse, diff, weight * opacity0);
	normal = mix(normal, norm, weight * opacity0);

	// Layer Procedural layer
	weight = getAutoWeight(autoValue, autoMin1, autoMax1, autoBlend1);
	diff = sampleDiffuse(diffuseMap1, worldPos.xz * scale1);
	norm = sampleNormal(normalMap1, worldPos.xz * scale1);
	diffuse = mix(diffuse, diff, weight * opacity1);
	normal = mix(normal, norm, weight * opacity1);


	vec3 nmult = vec3(1.0, 0.0, -1.0);
	vec3 finalNormal = normalize(worldNormal + normal.xzy * nmult);

	// Lighting
	float l = dot(finalNormal, normalize(lightDirection));
	float s = (l+1.0)/1.3 * 0.2 + 0.1;
	fragment = diffuse * max(l, s);
}

