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

#ifndef USE_NORMALMAP
varying vec3 Vnormal;
#endif
varying vec3 pos;

uniform sampler2D noiseTex;
uniform sampler2D tex1;
uniform sampler2D tex2;
uniform sampler2D normalTex;
uniform float tex2CoordMul;
uniform float time;
uniform vec3 light;

const float mul = 4.0;	// perlin scale
const float mul2 = 8.0;	// perlin scale for ground shadows
const float timeMultiplier = 0.00002;
const float crackSize = 0.5;
//const float crackSize = 0.05;
//const float crackVariation = 0.00001;
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;
const float fogVariation = 0.15;

const float lavaHeightLimit = 0.5;
const float lavaHeightFade = 0.5;

const float normalDecrease = 120.0;
const float normalExtraMul = 16.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.525, 0.55, 0.575);
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 Vnormal = -1.0+2.0*texture2D(normalTex, gl_TexCoord[0].xy).xzy;
#endif
		vec3 normal = Vnormal;

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

		float newTime = time*timeMultiplier;

		vec3 col = getCol(coord, newTime, mul);

		col /= 85.0;

		float alpha = 1.0;

		float wank = sin(time*16.0);

#ifdef EXTRA_LIGHT

		vec3 hdir = getDir(coord*normalExtraMul, 0.89764);

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

		//normal.y = clamp((normal.y-0.75)*4.0, 0.0, 1.0);


		float fade = 0.0;
		fade = clamp(1.0-(abs(col.r-mid))+1.0-(abs(col.g-mid*1.5))+1.0-(abs(col.b-mid*0.5)), 0.0, 1.0)*normal.y;

		//lightMul = 1.0-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
		float sparkle = clamp(noiset(vec3(coord*0.5, newTime*16.0)).r*20.0-19.0,0.0,1.0)+clamp(noiset(vec3(coord*2.0, newTime*32.0)).r*40.0-39.0,0.0,1.0);
		float mul = clamp(abs(normal.y)*5.0-4.0,0.0,1.0);
		sparkle = sparkle*sparkle*sparkle*sparkle*mul;
		vec3 iCol = intenseCol+0.625*intenseCol*sparkle;
#endif

		fade=clamp(fade*5.0,0.0,1.0);

		lightMul = max(1.0-fade, lightMul);


		vec3 snowcol = fade*fade*iCol*(normal.y*0.75+normal.z*1.5+normal.x*0.5); // (clamp(normal.y*normal.y,0.0,1.0));

		col = snowcol +
		      (1.0-fade*fade)*(0.5*texture2D(tex1, gl_TexCoord[0].xy)+0.5*texture2D(tex2, gl_TexCoord[0].xy*tex2CoordMul)).rgb;

		col = col*lightMul;
		vec3 fogCol = gl_Fog.color.rgb;
#ifdef FLOOR_FOG
		float realFog = (gl_Fog.end-gl_FogFragCoord+gl_Fog.start)*gl_Fog.scale;
		float fogMix = pos.y*fogHeightMul + 0.15+fogVariation*(sin(pos.x*1.15+pos.y*1.14+8.0*sin(time))+sin(pos.y*1.58+pos.z*1.0+cos(time)*9.5));
		if (realFog < fogMix) {
			fogMix = realFog;
		} else {
			fogCol = mix(fogCol, groundFogCol, realFog);
		}
#else
		float fogMix = (gl_Fog.end-gl_FogFragCoord+gl_Fog.start)*gl_Fog.scale;
#endif
		fogMix = clamp(fogMix, 0.0, 1.0);

		col = col*0.325 + 0.675*col*fogCol;

		col = mix(fogCol, col, fogMix);

		gl_FragColor = vec4(col, alpha);
	}


#endif