var FXBentPlane = function () {

	FRAME.Module.call( this );

	this.parameters.input = {
		sphere_radius: 10,
		camera_distance: 2,
		color: [1,1,1],
		color2: [0.2,0.2,0.2]
	};

	var width = renderer.domElement.width;
	var height = renderer.domElement.height;

	var scene = new THREE.Scene();
	var camera = new THREE.OrthographicCamera(window.innerWidth / -2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / -2, -10, 10);
	var quadmaterial;
	var quad;

	this.init = function ( parameters ) {
		this.parameters.input = parameters;
	    var quadgeometry = new THREE.PlaneGeometry(window.innerWidth, window.innerHeight);
	    
		this.quadmaterial = new THREE.ShaderMaterial({
	        uniforms: {
	                iGlobalTime: {
	                	type: "f",
	                	value: 1.0
	                },
	                iResolution: {
	                	type: "v2",
	                	value: new THREE.Vector2(renderer.getContext().drawingBufferWidth, renderer.getContext().drawingBufferHeight),
	                },
	                sphere_radius: {
	                	type: "f",
	                	value: parameters.sphere_radius
	                },
	                camera_distance: {
	                	type: "f",
	                	value: parameters.camera_distance
	                },
	                color: {
	                	type: "v3",
	                	value: new THREE.Vector3(parameters.color[0],parameters.color[1],parameters.color[2]),
	                },
	                color2: {
	                	type: "v3",
	                	value: new THREE.Vector3(parameters.color2[0],parameters.color2[1],parameters.color2[2]),
	                }
	        },
	        vertexShader: [

	                "varying vec2 vUv;",

	                "void main() {",

	                "vUv = vec2( uv.x, uv.y );",
	                "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",

	                "}"

	        ].join("\n"),
	        fragmentShader: [
"uniform float time;",
"uniform float iGlobalTime;",
"uniform vec2 iResolution;",
"varying vec2 vUv;",
"",
"",
"////////",
"// paste shadertoy here, begin",
"",
"",
"// as allways, higher is better",
"#define RM_MAX_ITER 2",
"#define DISTANCE 2.",
"",
"const float eps = 0.01;",
"uniform float sphere_radius;",
"uniform vec3 color;",
"uniform vec3 color2;",
"",
"vec3 roty(vec3 v, float a)",
"{",
"    float ca = cos(a);",
"    float sa = sin(a);",
"    return vec3(v.z*sa + v.x*ca, v.y, v.z*ca - v.x*sa);",
"}",
"",
"// raymarching CSG: min = union, max = intersection",
"float sphere(in vec3 p, vec3 c, float r)",
"{",
"    return length(p-c) - r;",
"}",
"",
"float plane(in vec3 p, vec3 n, float d)",
"{",
"    return dot(p,n)-d;",
"}",
"",
"vec4 chessboard(in vec3 p)",
"{",
"    float d = sphere(p,vec3(0.,0.,2.),sphere_radius);",
"    float k = mod(pow(mod(p.x,2.),2.)+pow(mod(-p.z,2.),2.)+pow(mod(p.y,2.),2.)+4.,2.);",
"    k = 1.-abs(k-1.);",
"    return mix(vec4(color,d),vec4(color2,d),k);",
"}",
"",
"vec4 scene(in vec3 p)",
"{",
"    return chessboard(p);",
"}",
"",
"// gradient normal",
"vec3 getNormal(in vec3 p)",
"{",
"    vec3 normal;",
"    vec3 ep = vec3(eps,0,0);",
"    normal.x = scene(p + ep.xyz).w - scene(p - ep.xyz).w;",
"    normal.y = scene(p + ep.yxz).w - scene(p - ep.yxz).w;",
"    normal.z = scene(p + ep.yzx).w - scene(p - ep.yzx).w;",
"    return normalize(normal);",
"}",
"",
"void mainImage( out vec4 fragColor, in vec2 fragCoord )",
"{",
"	vec2 uv = (fragCoord.xy - iResolution.xy*0.5) / iResolution.yy;",
"    ",
"    vec3 rayStart = vec3(0,0,DISTANCE);",
"    vec3 rayDir = normalize(vec3(uv,-1));",
"    vec3 rayDir1 = normalize(vec3(uv+vec2(1.,0.)/iResolution.yy,-1));",
"    vec3 rayDir2 = normalize(vec3(uv+vec2(-1.,0.)/iResolution.yy,-1));",
"    vec3 rayDir3 = normalize(vec3(uv+vec2(0.,1.)/iResolution.yy,-1));",
"    vec3 rayDir4 = normalize(vec3(uv+vec2(0.,-1.)/iResolution.yy,-1));",
"",
"    //float a = 3.14+1.4*iGlobalTime;",
"    float a = 3.14+sin(.1*iGlobalTime);",
"    float ca = cos(a);",
"    float sa = sin(a);",
"    rayStart = vec3(rayStart.z*sa + rayStart.x*ca, rayStart.y, rayStart.z*ca - rayStart.x*sa);",
"    rayDir = vec3(rayDir.z*sa + rayDir.x*ca, rayDir.y, rayDir.z*ca - rayDir.x*sa);",
"    rayDir1 = vec3(rayDir1.z*sa + rayDir1.x*ca, rayDir1.y, rayDir1.z*ca - rayDir1.x*sa);",
"    rayDir2 = vec3(rayDir2.z*sa + rayDir2.x*ca, rayDir2.y, rayDir2.z*ca - rayDir2.x*sa);",
"    rayDir3 = vec3(rayDir3.z*sa + rayDir3.x*ca, rayDir3.y, rayDir3.z*ca - rayDir3.x*sa);",
"    rayDir4 = vec3(rayDir4.z*sa + rayDir4.x*ca, rayDir4.y, rayDir4.z*ca - rayDir4.x*sa);",
"",
"    a = 0.1*sin(.1*iGlobalTime);",
"    //a = 3.14+.4*iGlobalTime;",
"    ca = cos(a);",
"    sa = sin(a);",
"	rayStart = vec3(rayStart.x, rayStart.z*sa + rayStart.y*ca, rayStart.z*ca - rayStart.y*sa);",
"    rayDir = vec3(rayDir.x, rayDir.z*sa + rayDir.y*ca, rayDir.z*ca - rayDir.y*sa);",
"    rayDir1 = vec3(rayDir1.x, rayDir1.z*sa + rayDir1.y*ca, rayDir1.z*ca - rayDir1.y*sa);",
"    rayDir2 = vec3(rayDir2.x, rayDir2.z*sa + rayDir2.y*ca, rayDir2.z*ca - rayDir2.y*sa);",
"    rayDir3 = vec3(rayDir3.x, rayDir3.z*sa + rayDir3.y*ca, rayDir3.z*ca - rayDir3.y*sa);",
"    rayDir4 = vec3(rayDir4.x, rayDir4.z*sa + rayDir4.y*ca, rayDir4.z*ca - rayDir4.y*sa);",
"    ",
"    vec3 p;",
"    float t = 0.0;",
"    vec4 currentColor;",
"    for (int i=0; i<RM_MAX_ITER; ++i)",
"    {",
"        p = rayStart + rayDir*t;",
"        currentColor = scene(p) +",
"            scene(rayStart + rayDir1*t) +",
"            scene(rayStart + rayDir2*t) +",
"            scene(rayStart + rayDir3*t) +",
"            scene(rayStart + rayDir4*t);",
"        currentColor /= 5.;",
"		t += currentColor.w;",
"    }",
"",
"    vec3 finalColor = vec3(0,0,0);",
"    vec3 normal = getNormal(p.xyz);",
"    //vec3 normal = vec3(0,0,1);",
"    vec3 light1 = vec3(sin(iGlobalTime),cos(iGlobalTime),0);",
"    vec3 light2 = vec3(0,0,-1);",
"    //            finalColor = normal;",
"    //            finalColor = vec3(1,0,1) *",
"    //                dot(vec3(1.,sin(iGlobalTime ),cos(iGlobalTime )),normal);",
"    float diffuse1 = 0.1+dot(light1,normal);",
"    float diffuse2 = 0.1+dot(light2,normal);",
"    float specular = pow(max(0.,dot(light1,normal)),21.);",
"    ",
"    #ifdef CLEAN",
"    //if (currentColor.w>100.)",
"    if (currentColor.w>eps)",
"    {",
"        currentColor = vec4(0.,0.,0.,0.);",
"    }",
"    #endif",
"    ",
"    #ifdef EVIL_BIRD_IN_THE_DARK",
"    if (currentColor.w>0.)",
"    {",
"        currentColor = vec4(0.,0.,0.,0.);",
"    }",
"    #endif",
"",
"",
"    //float specular = 0.;",
"    float ambient = 0.2;",
"    finalColor = currentColor.xyz *",
"        (ambient + max(0.,0.5* diffuse1) + 0.5*diffuse2 + specular);",
"    ",
"	fragColor = vec4(finalColor, min(1.,max(0.,1.-currentColor.w) + length(finalColor)));",
"",
"    #ifdef BACKGROUNDTEXTURE",
"    fragColor = mix(vec4(pow(texture2D (iChannel0,fragCoord/iResolution.xy).r,21.)), fragColor, fragColor.a);",
"    #endif",
"}",
"",
"",
"",
"",
"// paste shadertoy here, stop",
"////////",
"",
"void main()",
"{",
"	vec4 fragColor;",
"	vec2 fragCoord = vUv.xy*iResolution;",
"",
"	mainImage(fragColor,fragCoord);",
"    ",
"	gl_FragColor = fragColor;",
"}",
""].join("\n"),
			depthTest: false,
			depthWrite: false,
			blending: THREE.AdditiveBlending 
	    });

		//quad = new THREE.Mesh(quadgeometry, this.quadmaterial, this.compositeShader);
		quad = new THREE.Mesh(quadgeometry, this.quadmaterial);
    	scene.add(quad);

		camera = new THREE.OrthographicCamera(window.innerWidth / -2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / -2, -100, 100);
	};

	this.start = function ( t, parameters ) {

	};

	this.end = function ( ) {
		
	};	

	this.update = function ( t, perc, gt ) {		
	    quad.material.uniforms['iGlobalTime'].value = gt;
	    //quad.material.uniforms['funkyness'].value = 100+Math.sin(t)*100;

		if ( this.renderToTexture )
			renderer.render( scene, camera, this.fbo, this.clearBuffer );
		else
			renderer.render( scene, camera );
	};

};