	#version 300 es
 
    in vec3 position;
	
	out vec4 v_position;
	out float v_depth;
	
    uniform mat4 view;
	uniform mat4 viewProjection;
	uniform mat4 world;

    void main(void) {
		vec4 worldPosition = world * vec4(position.xyz, 1.0);
		
		v_position = viewProjection * worldPosition;
		
		v_depth  = v_position.z;
		
		gl_Position = viewProjection * vec4(position.xyz, 1.0);
    }
	
	// #keplerEngine - Split
	
	#version 300 es
	
    precision highp float;

	in vec4 v_position;
	in float v_depth;
	
	out vec4 pixelColor;
	
	uniform float far;
	uniform float near;
	uniform vec3 diffuseColor;
	



	vec4 pack (float depth)
	{
		const vec4 bias = vec4(1.0 / 255.0,
					1.0 / 255.0,
					1.0 / 255.0,
					0.0);

		float r = depth;
		float g = fract(r * 255.0);
		float b = fract(g * 255.0);
		float a = fract(b * 255.0);
		vec4 color = vec4(r, g, b, a);
		
		return color - (color.yzww * bias);
	}
	
	

	vec4 EncodeFloatRGBA( float v ) {
		vec4 enc = vec4(1.0, 255.0, 65025.0, 160581375.0) * v;
		enc = fract(enc);
		enc -= enc.yzww * vec4(1.0/255.0,1.0/255.0,1.0/255.0,0.0);
		return enc;
	}
	
	vec2 packHalf (float depth)
	{
		const vec2 bias = vec2(1.0 / 255.0,
					0.0);
								
		vec2 colour = vec2(depth, fract(depth * 255.0));
		return colour - (colour.yy * bias);
	}

	vec2 ComputeMoments(float depth)  {
		vec2 moments;  
  
		moments.x = depth;  

		float dx = dFdx(depth);  
		float dy = dFdy(depth);  

		moments.y = depth*depth + 0.25 * (dx*dx + dy*dy); 
		
		return moments;  
	}
	
	float normalizeDepth(float depth, float realFar) {
		return (depth) / (realFar);
	}
	
	const float PackUpscale = 256. / 255.; // fraction -> 0..1 (including 1)
	const float UnpackDownscale = 255. / 256.; // 0..1 -> fraction (excluding 1)

	const vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256.,  256. );
	const vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );

	const float ShiftRight8 = 1. / 256.;

	vec4 packDepthToRGBA( const in float v ) {
		vec4 r = vec4( fract( v * PackFactors ), v );
		r.yzw -= r.xyz * ShiftRight8; // tidy overflow
		return r * PackUpscale;
	}

	float unpackRGBAToDepth( const in vec4 v ) {
		return dot( v, UnpackFactors );
	}
	
	
	vec4 DistributePrecision(vec2 Moments)  
	{  
		float g_DistributeFactor = 256.0;  
		float FactorInv = 1.0 / g_DistributeFactor;  
		// Split precision  
		vec2 IntPart;  
		vec2 FracPart = mod(Moments * g_DistributeFactor, IntPart);  
		// Compose outputs to make reconstruction cheap.  
		return vec4(IntPart * FactorInv, FracPart);  
	}  
	float DecodeFloatRGBA( vec4 rgba ) {
		return dot( rgba, vec4(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 160581375.0) );
	}
	
	
	void main() {
		float depth = v_position.z  ;
		
		depth = depth;
		
		float moment1 = depth;
		float moment2 = depth * depth;
		
		float dx = dFdx(depth);  
		float dy = dFdy(depth);  

		moment2 += 0.25 * (dx * dx + dy * dy); 
		
		pixelColor = vec4(depth, moment2, 0.0, 1.0);
		//pixelColor = vec4(diffuseColor, 1.0);
		gl_FragDepth = clamp(depth / far, 0.0, 1.0);
		
	}