
// haha, you bitch!

#define MAX_INSTRUCTIONS 960
//#define FLOOR_FOG
#define LAVA_TEXTURE
#define USE_NORMALMAP
#define EXTRA_LIGHT

varying vec3 Vnormal;
varying vec3 pos;
varying vec3 view;
varying vec4 camn;

uniform sampler2D noiseTex;
uniform sampler2D tex1;
uniform sampler2D tex2;
uniform sampler2D normalTex;
//uniform sampler2D giTex;
uniform sampler2D groundTypeTex;
uniform float tex2CoordMul;
uniform float time;
uniform vec3 light;
uniform vec3 camera;
uniform vec3 amb;
uniform vec3 camdir;
uniform float eruption;
uniform float waterlevel;
uniform float widthDiv;
uniform float heightDiv;

const float mul = 8.0;	// perlin scale
const float mul2 = 16.0;	// perlin scale for ground shadows
const float timeMultiplier = 0.000002;
float crackSize = 0.05;
const float fadeRange = 0.25;
const float texMul = 1.0/512.0;
const float mid = 0.5;
const float intenseRange = 0.15;

const float fogHeightMul = 0.5*5.0;
const float fogVariation = 0.15;

float lavaHeightLimit = 0.0;
const float lavaHeightFade = 0.15;

const float normalDecrease = 120.0;
const float normalExtraMul = 64.0;

//const vec3 fireCol = vec3(0.15, 0.005, 0.005);
//const vec3 groundCol = vec3(0.35, 0.25, 0.05);
const vec3 intenseCol = vec3(0.95, 0.35, 0.125);
const vec3 groundFogCol = vec3(0.25, 0.05, 0.02);

//const float ambient = 0.30;


#if MAX_INSTRUCTIONS > 96

	vec3 noiset(vec2 xy) { return texture2D(noiseTex, xy).rgb; }
	vec3 noiset(vec3 xyz) { return texture2D(noiseTex, vec2(xyz.x+xyz.z*17.0, xyz.y+xyz.z*37.0)).rgb; }

	vec3 getCol(vec2 coord, float newTime, float octave) {
		return //noiset(vec3(coord*octave*0.0078125, newTime))*128.0+
		       noiset(vec3(coord*octave*0.015625, newTime))*64.0+
		       //noiset(vec3(coord*octave*0.03125, newTime))*32.0+
		       noiset(vec3(coord*octave*0.0625, newTime))*16.0+
		       //noiset(vec3(coord*octave*0.125, newTime))*8.0+
		       noiset(vec3(coord*octave*0.25, newTime))*4.0+
		       //noiset(vec3(coord*octave*0.5, newTime))*2.0+
		       noiset(vec3(coord*octave, newTime));

/*		return noiset(vec3(coord*octave*0.0078125, newTime))*128.0+
		       noiset(vec3(coord*octave*0.015625, newTime))*64.0+
		       noiset(vec3(coord*octave*0.03125, newTime))*32.0+
		       noiset(vec3(coord*octave*0.0625, newTime))*16.0+
		       noiset(vec3(coord*octave*0.125, newTime))*8.0+
		       noiset(vec3(coord*octave*0.25, newTime))*4.0+
		       noiset(vec3(coord*octave*0.5, newTime))*2.0+
		       noiset(vec3(coord*octave, newTime));
*/
	}

	float getHeight(vec2 coord, float time) {
		return clamp(getCol(coord, time, mul2).r, -85.0, 85.0);
	}

	vec3 getDir(vec2 coord, float newTime) {
		float sx = getHeight(vec2(coord.x-texMul, coord.y), newTime) - getHeight(vec2(coord.x+texMul, coord.y), newTime);
		float sy = getHeight(vec2(coord.x, coord.y-texMul), newTime) - getHeight(vec2(coord.x, coord.y+texMul), newTime);
		return normalize(vec3(sx, normalDecrease, sy));
	}

	void main() {
#ifdef USE_NORMALMAP
		vec3 Nnormal = -1.0+2.0*texture2D(normalTex, gl_TexCoord[0].xy).xzy;
#else
		vec3 Nnormal = Vnormal;
#endif
		vec3 normal = Nnormal;

//		vec3 pos = possi*0.2;
//		vec3 possi = pos*0.2;
		vec3 possi = vec3(0.0, 0.2, 0.0);

		vec2 coord = vec2(gl_TexCoord[0].xy);
		vec3 normLight = normalize(light);

		float newTime = time*timeMultiplier;

		vec3 col = getCol(coord, newTime, mul);
		vec3 col2;
//		vec3 lmap = vec3(clamp(texture2D(giTex, gl_TexCoord[0].xy)*10.0-7.5,0.0,1.0));
//		vec3 lmap = vec3(1.0-2.0*clamp(texture2D(giTex, gl_TexCoord[0].xy)*1.5-0.5,0.0,1.0));
//		vec3 lmap = vec3(1.5*texture2D(giTex, gl_TexCoord[0].xy));

		col /= 85.0;

		float alpha = 1.0;

		float sizer = clamp(sin(possi.y*normal.y*33.77+time*5.3),0.0,1.0);
		lavaHeightLimit = lavaHeightLimit*(1.0-eruption*0.65);

		crackSize = (crackSize*eruption*clamp(possi.y-1.0,0.0,1.0)*eruption*0.25+clamp(possi.y-0.75,0.0,1.0)*eruption);

		float minSize = crackSize;//-crackVariation*abs(sin(coord.x*4.06839+time*17.0*3.14159));
		float maxSize = crackSize;//+crackVariation*abs(sin(coord.y*3.43678+time*13.0*3.14159));

#ifdef EXTRA_LIGHT
//		vec3 hdir = getDir(coord*normalExtraMul, 0.89764);
		vec3 hdir = getDir(vec2(coord.x*normalExtraMul, coord.y*normalExtraMul*4.0), 0.89764);

		vec3 xz = vec3(Nnormal.x, 0.0, Nnormal.z);
		float s = length(xz);
		xz = normalize(xz);
		vec3 zx = vec3(xz.z, 0.0, -xz.x);
		hdir = (hdir*zx)*zx + ((hdir*Nnormal)*Nnormal.y+(hdir*xz)*s)*Nnormal + ((hdir*xz)*Nnormal.y-(hdir*Nnormal)*s)*xz;
#else
		vec3 hdir = Vnormal;
#endif
		hdir = hdir*0.5+0.5*normal;
		float lightMul = dot(hdir, normLight);

		normal.y = clamp((normal.y-0.85)*6.66, 0.0, 1.0);



		float fade = 0.0;
//		fade = clamp(1.0-((abs(col.r-mid)-crackSize)*(1.0/intenseRange)), 0.0, 1.0)*normal.y;
		fade = clamp(1.0-((abs(col.g-mid)-crackSize)*(1.0/intenseRange)), 0.0, 1.0)*(1.0-normal.y+sizer*0.005);

		//lightMul = lightMul*(1.0-normal.y) + normal.y*ambient ;//+ (1.0-ambient)*dot(normalize(hdir), normLight);

		//lightMul = lightMul;//max(fade, lightMul);

#ifdef LAVA_TEXTURE
		float v = 1.0+0.75*(getCol(coord, newTime*16.0, mul*8.0).r/85.0);
		vec3 iCol = intenseCol*vec3(v, v, v);
#else
		vec3 iCol = intenseCol;
#endif

//		fade = fade*(clamp((possi.y-lavaHeightLimit-0.35)/lavaHeightFade, 0.0, 1.0));
//		fade = texture2D(groundTypeTex, gl_TexCoord[0].xy).r;
//		fade = 0.0;

		float realFade = texture2D(groundTypeTex, gl_TexCoord[0].xy).r;
		realFade = 1.0-((1.0-realFade)*(1.0-realFade));

/*		float c1 = texture2D(groundTypeTex, vec2(gl_TexCoord[0].x-widthDiv, gl_TexCoord[0].y)).r;
		float c2 = texture2D(groundTypeTex, vec2(gl_TexCoord[0].x+widthDiv, gl_TexCoord[0].y)).r;
		float c3 = texture2D(groundTypeTex, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y+heightDiv)).r;
		float c4 = texture2D(groundTypeTex, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y-heightDiv)).r;
		float rf2 = max(c1, max(c2, max(c3, c4)));*/
		float rf2 = realFade;

//		float snfade = clamp((1.0-fade)*(1.0-abs(normal.y*1.125))*1.0+10.0*clamp(possi.y-lavaHeightLimit-0.2,0.0,0.1),0.0,1.0);
		//float snfade = clamp((1.0-fade)*(1.0-abs(normal.y*1.125))*1.0+10.0 * clamp(possi.y-lavaHeightLimit-0.2, 0.0, 0.1), 0.0, 1.0);
float snfade = abs(normal.y*1.125);
snfade = 1.0-(snfade*snfade);
		float snfade2 = clamp(possi.y*14.0*5.0-1.0,0.0,1.0);
		// snow
/*		snfade = 0.0;
		float snfade2 = 0.0;*/
/*		snfade = 1.0;
		float snfade2 = 0.0;*/
//		snfade = realFade;
//		float snfade2 = 0.0;
		fade = min(realFade, fade);

		float doth = getCol(coord*8.0*5.0, 1.0, 1.0).r/85.0;
		vec3 ldot = fract(25.0*possi*5.0+9.0*doth+0.15*view);
		ldot *= 1.0-ldot;
		float sparkle = clamp(1.0-4.1*(ldot.x+ldot.y+ldot.z), 0.0, 1.0);
		sparkle = sparkle*sparkle;
		float dotsi = (1.0-realFade)*clamp(dot(reflect(-normalize(view), normalize(Nnormal)), camera), 0.0, 1.0);
		sparkle = sparkle*dotsi;
//		float ht = 0.1625;
/*		if(possi.y<waterlevel) {
			iCol=vec3(0.0,0.0,0.0);//vec3(1.0-clamp(-(possi.y-waterlevel)*10.0,0.0,1.0),1.0-clamp(-(possi.y-waterlevel)*5.0,0.0,1.0),1.0-clamp(-(possi.y-waterlevel)*3.5,0.0,1.0));
			sparkle=0.0;
		}*/
		vec3 snCol = vec3(0.525+sparkle, 0.55+sparkle*1.25, 0.575+sparkle*2.0);


		// edge shit
		float shade = max(dot(view, camn.xyz), 0.0);
//		shade = clamp(sqrt(shade)*2.0, 0.0, 1.0);
		shade = clamp(sqrt(shade)*2.0, 0.0, 1.0);

		vec3 stonetex = (texture2D(tex1, gl_TexCoord[0].xy*8.0)+texture2D(tex2, gl_TexCoord[0].xy*tex2CoordMul)).rgb;
		col2 = (1.0-fade)*(snCol*(1.0-snfade*snfade) + (0.5+0.5*shade)*(snfade)*(stonetex*(0.5+0.5*lightMul)));

//		col = shade*fade*iCol + snCol*(1.0-snfade2)+shade*snfade2*1.5*col2;
		vec3 snowshit = /*shade*fade*iCol + */snCol*(1.0-snfade2)+shade*snfade2*1.5*col2;
		col = (1.0-realFade)*snowshit+ realFade*(fade*iCol) + rf2*(0.5*col2+0.5*stonetex);
		col *= (0.2+0.8*(1.0-realFade))*(0.6+0.4*lightMul);

		// fog
		vec3 fogCol = gl_Fog.color.rgb;
#ifdef FLOOR_FOG
		float realFog = (gl_Fog.end-gl_FogFragCoord+gl_Fog.start)*gl_Fog.scale;
		float fogMix = possi.y*fogHeightMul + 0.15+fogVariation*(sin(possi.x*1.15+possi.y*1.14+8.0*sin(time*0.5))+sin(possi.y*1.58+possi.z*1.0+cos(time*0.5)*9.5));

		fogMix = min(realFog, fogMix);
		fogCol = mix(fogCol, fogCol, clamp(realFog, 0.0, 1.0));

		fogMix = clamp(fogMix, 0.0, 1.0) + clamp((fade-0.75)*4.0, 0.0, 1.0);
#else
		float fogMix = (gl_Fog.end-gl_FogFragCoord+gl_Fog.start)*gl_Fog.scale;
		fogMix = clamp(fogMix, 0.0, 1.0) + clamp((fade-0.75)*4.0, 0.0, 1.0);
#endif

		col = mix(fogCol, col*(0.75+0.25*lightMul)+iCol*fade, fogMix);
		col += clamp((1.0-shade)*(1.0-shade)*amb*2.0,0.0,0.15);

/*		if(possi.y<waterlevel) {
			col *= vec3(1.0-clamp(-(possi.y-waterlevel)*10.0,0.0,1.0),1.0-clamp(-(possi.y-waterlevel)*5.0,0.0,1.0),1.0-clamp(-(possi.y-waterlevel)*3.5,0.0,1.0));
		}*/

		gl_FragColor = vec4(col, alpha);
	}


#endif