float rand( float3 _at )
{
	int3 pos = int3(floor(_at));
	//int hash = ((pos.x * 171880647) ^ (pos.y * 14374924) ^ (pos.z * 96916029)) % 10000;
	int hash = (
			  (pos.x * 0x9E3719B1 - (pos.z >> 17))
			^ (pos.y * 0xAFFE3141 - (pos.x >> 17))
			^ (pos.z * 0x27f161e8 - (pos.y >> 17))
			) % 18973;
	return hash / 18973.0;
}

float randsmooth( float3 _at )
{
	// Split into integer and fractional part
	float3 p0 = floor(_at);
	float3 f = _at - p0;
	// Smootherstep for interpolant
	f = f*f*f*(f*(f*6 - 15) + 10);
	// Trilinear interpolation
	return lerp(
		   lerp(lerp(rand(p0+float3(0,0,0)), rand(p0+float3(1,0,0)), f.x),
				lerp(rand(p0+float3(0,1,0)), rand(p0+float3(1,1,0)), f.x), f.y),
		   lerp(lerp(rand(p0+float3(0,0,1)), rand(p0+float3(1,0,1)), f.x),
				lerp(rand(p0+float3(0,1,1)), rand(p0+float3(1,1,1)), f.x), f.y),
			f.z);
}

float randlin( float3 _at )
{
	// Split into integer and fractional part
	float3 p0 = floor(_at);
	float3 f = _at - p0;
	// Trilinear interpolation
	return lerp(
		   lerp(lerp(rand(p0+float3(0,0,0)), rand(p0+float3(1,0,0)), f.x),
				lerp(rand(p0+float3(0,1,0)), rand(p0+float3(1,1,0)), f.x), f.y),
		   lerp(lerp(rand(p0+float3(0,0,1)), rand(p0+float3(1,0,1)), f.x),
				lerp(rand(p0+float3(0,1,1)), rand(p0+float3(1,1,1)), f.x), f.y),
			f.z);
}

float3 procTexture( float3 _at, float _light )
{
	float whiteNoise1 = randsmooth(6*_at + float3(123,52,35));
	float valueNoise1 = (0.25 * randsmooth(32*_at) + 0.5 * randsmooth(16*_at) + randsmooth(8*_at)) / 1.75;
	float valueNoise2 = (0.25 * randsmooth(24*_at + float3(123,52,35)) + 0.5 * randsmooth(12*_at + float3(123,52,35)) + whiteNoise1) / 1.75;
	// Moon surface with craters
	float moon = 1 - abs(sin(whiteNoise1 * 1.570796327) - 0.4)/0.7;
	moon *= moon;
	moon += valueNoise1 + 0.5;
	moon *= 0.5;
	// Put some lava-lines on the surface by remapping the valueNoise
	float lavaLight = 1-saturate(abs(valueNoise2 * 4.0 - 2.0));
	lavaLight *= 0.5 + 0.7 * randlin( float3(_at.xy * 30, c_time * 0.5) );
	float lava = saturate(lavaLight * 3 - 2) * 0.5;

	moon *= _light + lavaLight * 0.3;
	return float3(moon+lava, moon + lava*lava*0.3, moon);
}


float4 PS( float2 _texCoord: TEXCOORD0 ) : SV_TARGET
{
	_texCoord *= 1.4;
	// Circle center distance
	float len = length(_texCoord);
	if( len > 1 )
	{
		float r = rand(float3(_texCoord * 500.0, 2.7));
		r = r > 0.99 ? r : 0;
		r = r * 100.0 - 99.0;
		return float4(r.rrr, 1);
	}

	// Compute normal from trigonometry
	float3 n = float3(_texCoord.x, _texCoord.y, sqrt(1 - len * len));
	
	float3 pos = mul(n, (float3x3)c_rotation);

	float light = saturate(dot(n, float3(0.707, 0.707, 0)));
	return float4(procTexture(pos, light), 1);
}