--local bgColor = { 0.79653309732353, 0.74187444685202, 0.24326303903317, 1 }
--local bgColor = { 0.80513931699576, 0.53053376873074, 0.066316721091342, 1 }
--local bgColor = { 0.92928861354411, 0.70720542008728, 0.77272865993225, 1 }
local bgColor = { 1, 0.95, 0.85, 1 }
--local bgColor = { 1, 1, 0.8, 1 }

_G.clearColor = { red = bgColor[1], green = bgColor[2], blue = bgColor[3] }
--_G.clearColor = { red = 0.0, green = 0.0, blue = 0.0 }

_G.time = 0
--math.randomSeed(2)
local tunnelScale = 0.01

local model = {
	vs = "pn",
	scale = tunnelScale,
	uniforms = {
		directionalLight = { -1, 1, 0 },
		intensity = 1,
		ambientLight = 1,
		color = { 1, 1, 1, 1 },
	}
}

local superSample = 2

_G.renderTextureTargets = {
	effect1 = { width = config.width, height = config.height },
	effect2 = { width = config.width, height = config.height },
	effect3 = { width = config.width, height = config.height },
	effect4 = { width = config.width, height = config.height },
	effect5 = { width = config.width * superSample, height = config.height * superSample },
	depth = { width = config.width / 16, height = config.height / 16 },
	effect6 = { width = config.width, height = config.height },
	final = { width = config.width, height = config.height },
	lights = { width = config.width / 16, height = config.height / 16 },
	finalBunny = { width = 1024, height = 1024 },
}
_G.graphics.createRenderTargets()

local light = {
	texture = "light",
	layer = "lights",
	scale = 80,
	uniforms = {
		color = { 1 * 1.2, 0.89 * 1.2, 0.75 * 1.2, 1 },
	}
}

local light0 = instance{light, x = -config.width / 8, y = config.height / 2 }

local rays = {
	texture = "effect4",
	fs = "radial_blur_colored",
	layer = "rays",
	--scale = 2,
	light = light0,
	uniforms = {
		source = { function(self) return self.light.x / config.width + 0.5 end, function(self) return self.light.y / config.height + 0.5 end }, --uniform vec2 source;
		decay = 0.01, --uniform float decay;
		samples = 150, --uniform float samples;
		density = 1,
		strength = 2,
		colorRotations = { 0, 0, 0 },
		colorRotationFactors = { 0, 0, 0 },
	},
}

local cameraZ = _G.tween(0.5, -600, 120, 0, false, _G.bezier.make({0.000,0.000,0.091,0.000,0.209,0.009,0.291,0.018,0.291,0.018,0.636,0.055,0.982,0.655,1.000,1.000,}))
--local cameraZ = function() return -_G.time * 0.2 end
--local cameraZ = function() return 0 end --
--,

local indices = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }

local tunnelOffset = { 1.3, 0.4 }
local tunnelPower = 1.5

local flowerTexture = "flowertunnel_FlowersTexture"
local flowerTextureTranslucent = "flowertunnel_FlowersTextureTranslucent"

local flowers = instance{model,
	model = "FlowerTunnel_Flowers01",
	vs = "flowerPath",
	uniforms_depthPerOffsetIndex = 7,
	uniforms_indices = indices,
	uniforms_offset = function() return tunnelOffset end,
	uniforms_cameraZ = cameraZ,
	uniforms_power = function() return tunnelPower end,
	uniforms_divider = 3,
	uniforms_fogColor = function() return bgColor end,
	uniforms_fogDensity = 0.08,
	uniforms_fogMinDistance = 2,
	uniforms_textureSampler = function() return flowerTexture end,
	uniforms_translucentTextureSampler = function() return flowerTextureTranslucent end,
	uniforms_lightsTextureSampler = "lights",
	uniforms_cellThreshold = 100,
	uniforms_screenWidth = config.width * superSample,
	uniforms_screenHeight = config.height * superSample,
	uniforms_translucentStrength = 2,
}

local leavesTexture = "flowertunnel_LeavesTexture"
local leavesTextureTranslucent = "flowertunnel_uvwLeavesTranslucent"

local leaves = instance{flowers,
	model = "FlowerTunnel_Leaves01",
	uniforms_textureSampler = function() return leavesTexture end,
	uniforms_translucentTextureSampler = function() return leavesTextureTranslucent end,
}

local roots = instance{flowers,
	model = "FlowerTunnel_Roots01",
	uniforms_ambientLight = 0.9,
	uniforms_textureSampler = "roots_texture",
	uniforms_translucentTextureSampler = "roots_texture",
	--uniforms_color = { 202/255, 140/255, 105/255, 1 }
}

local zParticles = 	{
	layer = "particles",
	uniforms = {
		color = { 0.3, 0.3, 0.3, 0 },
		power = 1.4,
		divider = 4,
		offset = function() return tunnelOffset end,
	},
	particles = {
		vs = "tunnelParticles",
		fs = "pt-pre",
		sprite = "light",
		frequency = 100,
		uniforms = {
		},
		emit = function()
			local x = math.random() * 400 - 200
			local y = math.random() * 700 - 350
			local z = -2000 + math.random() * 100
			local zSpeed = 2000
			return {
				x = x,
				z = function(t) return z + t * zSpeed end,
				y = y,
				lifeTime = 2,
				scale = 0.2,
				--scale = function(t) return (-math.pow(t * 2 - 1, 4) + 1) * 0.3 end,
			}
		end,
	},
	scale = 0.01,
}

local getPosition = function(channel, offset, t)
	t = t or _G.time * 20 + offset
	local t2 = t - math.floor(t)
	local pixel0 = _G.resources.getColorFromTexture("perlin_noise", math.abs(t) % (512 * 512), channel) / 255
	local pixel1 = _G.resources.getColorFromTexture("perlin_noise", math.abs(t + 1) % (512 * 512), channel) / 255
	return _G.lerp(pixel0, pixel1, t2)
end

local slowParticles = 	{
	layer = "particles",
	uniforms = {
		color = { 0.3, 0.3, 0.3, 0 },
		power = 1.4,
		divider = 4,
		offset = function() return tunnelOffset end,
	},
	particles = {
--		vs = "tunnelParticles",
		fs = "pt-pre",
		sprite = "light",
		frequency = 10,
		uniforms = {
		},
		emit = function()
			local x = math.random() * config.width - config.width / 2
			local y = config.height / 2 - math.random() * 100
			local z = -math.random() * 2000
			local ySpeed = math.random() * 50 + config.height / 2
			return {
				x = function(t) return x + getPosition(0, 0, t * 256) * 100 end,
				z = z,
				y = function(t) return y - t * ySpeed end,
				lifeTime = 10,
				scale = function(t) return math.sin(t * 3.141) * 0.2 end,
			}
		end,
	},
	scale = 0.01,
}


local spacing = 5

local final = { texture = "final", layer = "final" }

local cameraX = function() return 0 + getPosition(0, 0, _G.time * 1) - 0.5 end
local cameraY = function() return 0.7 + getPosition(1, 0, _G.time * 1) - 0.5 end
local cameraRotationX = function() return (getPosition(0, 200, _G.time * 5) - 0.5) * 15 end
local cameraRotationY = function() return (getPosition(1, 200, _G.time * 5) - 0.5) * 15 end

local bunny = {
	texture = "bunny_1024",
	layer = "bunny",
	vs = "tunnelParticles",
	fs = "bunny",
	--z = _G.tween(-20, 0, 4, 0, true),
	scaleY = -0.0015,
	scaleX = -0.0015,
	--y = 0.8,
	--x = 0.2,
	--x = function() return getPosition(0, 500, _G.time * 2) * 400 end,
	--y = function() return getPosition(1, 500, _G.time * 2) * 400 end,
	uniforms = {
		color = { 1.0, 1.0, 1.0, 0.8 },
		power = 1.4,
		divider = 3,
		offset = function() return tunnelOffset end,
		perlinTextureSampler = "perlin_noise",
		perlinStrength = 0.4,
		angleOffsetFactor = 2,
		timeAngleFactor = 4,
		radiusOffsetFactor = _G.tween(0, 5, 4, 0, true, _G.bezier.make({0.000,0.436,0.082,0.927,0.082,1.000,0.127,1.000,0.127,1.000,0.245,1.000,0.255,0.300,0.345,0.000,0.345,0.000,0.573,0.000,0.718,0.000,1.000,0.000,})),
		time = function() return _G.time * 0.1 end,
		suckInFactor = 1.0,
		suckInOffset = 0.0,
	},
}

local bunnyUniforms = {
	perlinTextureSampler = "perlin_noise",
	perlinStrength = 0.1,
	angleOffsetFactor = 2,
	timeAngleFactor = 2,
	radiusOffsetFactor = _G.tween(0, 5, 4, 0, true, _G.bezier.make({0.000,0.436,0.082,0.927,0.082,1.000,0.127,1.000,0.127,1.000,0.245,1.000,0.255,0.300,0.345,0.000,0.345,0.000,0.573,0.000,0.718,0.000,1.000,0.000,})),
	time = function() return _G.time * 0.1 end,
	suckInFactor = 1.0,
	suckInOffset = 0.0,
}

local finalBunny = {
	{
		texture = "finalBunny",
		layer = "finalBunny",
		--scaleFunc = function() return 0.5 end,
		--scaleY = function(self) return -self.scaleFunc() end,
		--scaleX = function(self) return self.scaleFunc() end,
		--x = function() return getPosition(0, 500, _G.time * 2) * 400 end,
		--y = function() return getPosition(1, 500, _G.time * 2) * 400 end,
		fs = "bunny",
		uniforms = bunnyUniforms,
		{
			texture = "bunny_eye",
			layer = "finalBunny",
			scale = 0.035,
			x = 110,
			y = -175,
			enabled = false,
			fs = "bunny",
			uniforms = {
				perlinTextureSampler = "perlin_noise",
				perlinStrength = 0.1,
				angleOffsetFactor = 0,
				timeAngleFactor = 0,
				radiusOffsetFactor = 0.1, --_G.tween(0, 5, 4, 0, true, _G.bezier.make({0.000,0.436,0.082,0.927,0.082,1.000,0.127,1.000,0.127,1.000,0.245,1.000,0.255,0.300,0.345,0.000,0.345,0.000,0.573,0.000,0.718,0.000,1.000,0.000,})),
				time = function() return _G.time * 0.1 end,
				suckInFactor = 1.0,
				suckInOffset = 0.0,
			}
		},
	},
	{ texture = "bunny_1024", layer = "bunnyLayout" },
	{ texture = "bunny_eye", layer = "bunnyLayout", scale = 0.035, x = 110, y = -175 },
	{ camera = { layer = "bunnyLayout", fit = "none", width = 1024, height = 1024, target = "finalBunny" } },
	{ camera = { layer = "finalBunny" } },
}

_G.world = {
	{ texture = "square", width = _G.config.width, height = _G.config.height, layer = "overlay", uniforms = { color = { 1, 1, 1, _G.tween(1, 0, 3, 2, false) } } },
--	coroutine.create(function() while true do print(cameraZ()); coroutine.yield() end end),
	instance{flowers, fs = "tunnel", layer = "3d", z = function() return math.floor(math.abs(cameraZ()) / spacing) * -spacing end, },
	instance{flowers, fs = "tunnel", layer = "3d", z = function() return math.floor(math.abs(cameraZ()) / spacing + 1.0) * -spacing end, },
	instance{flowers, fs = "tunnel", layer = "3d", z = function() return math.floor(math.abs(cameraZ()) / spacing + 2.0) * -spacing end, },
	instance{leaves, fs = "tunnel", layer = "3d", z = function() return math.floor(math.abs(cameraZ()) / spacing) * -spacing end, },
	instance{leaves, fs = "tunnel", layer = "3d", z = function() return math.floor(math.abs(cameraZ()) / spacing + 1.0) * -spacing end, },
	instance{leaves, fs = "tunnel", layer = "3d", z = function() return math.floor(math.abs(cameraZ()) / spacing + 2.0) * -spacing end, },
	instance{roots, fs = "tunnel", layer = "3d", z = function() return math.floor(math.abs(cameraZ()) / spacing) * -spacing end, },
	instance{roots, fs = "tunnel", layer = "3d", z = function() return math.floor(math.abs(cameraZ()) / spacing + 1.0) * -spacing end, },
	instance{roots, fs = "tunnel", layer = "3d", z = function() return math.floor(math.abs(cameraZ()) / spacing + 2.0) * -spacing end, },
	instance{flowers, layer = "depth", fs = "depth", uniforms_depthFactor = 0.04, z = function() return math.floor(math.abs(cameraZ()) / spacing) * -spacing end, },
	instance{flowers, layer = "depth", fs = "depth", uniforms_depthFactor = 0.04, z = function() return math.floor(math.abs(cameraZ()) / spacing + 1.0) * -spacing end, },
	instance{flowers, layer = "depth", fs = "depth", uniforms_depthFactor = 0.04, z = function() return math.floor(math.abs(cameraZ()) / spacing + 2.0) * -spacing end, },
	instance{leaves, layer = "depth",  fs = "depth", uniforms_depthFactor = 0.04 , z = function() return math.floor(math.abs(cameraZ()) / spacing) * -spacing end, },
	instance{leaves, layer = "depth",  fs = "depth", uniforms_depthFactor = 0.04, z = function() return math.floor(math.abs(cameraZ()) / spacing + 1.0) * -spacing end, },
	instance{leaves, layer = "depth",  fs = "depth", uniforms_depthFactor = 0.04, z = function() return math.floor(math.abs(cameraZ()) / spacing + 2.0) * -spacing end, },
	instance{roots, layer = "depth",  fs = "depth", uniforms_depthFactor = 0.04 , z = function() return math.floor(math.abs(cameraZ()) / spacing) * -spacing end, },
	instance{roots, layer = "depth",  fs = "depth", uniforms_depthFactor = 0.04, z = function() return math.floor(math.abs(cameraZ()) / spacing + 1.0) * -spacing end, },
	instance{roots, layer = "depth",  fs = "depth", uniforms_depthFactor = 0.04, z = function() return math.floor(math.abs(cameraZ()) / spacing + 2.0) * -spacing end, },
	--_G.take(1000, function() return {} end),
	light0,
	rays,
	{ texture = "effect1", layer = "blur1", fs = "pt_blur_horizontal", uniforms = { strength = 1, spread = 1 } },
	{ texture = "effect3", layer = "blur2", fs = "pt_blur_vertical", uniforms = { strength = 1, spread = 1 } },
	{ texture = "effect5", layer = "3d_blur_1", uniforms = { depthTextureSampler = "depth", strength = 1, spread = 2 }, fs = "depthBlurHorizontal", scale = 1 / superSample },
	{ texture = "effect6", layer = "3d_blur_2", uniforms = { depthTextureSampler = "depth", strength = 1, spread = 2 }, fs = "depthBlurVertical" },
	zParticles,
	slowParticles,
	bunny,
	{ camera = { layer = "lights", target = "effect1" } },
	{ camera = { layer = "lights", target = "lights" } },
	{ camera = { layer = "3d", depthTest = true, fov = 66, target = "effect5" }, z = cameraZ, x = cameraX, y = cameraY, rotationX = cameraRotationX, rotationY = cameraRotationY },
	{ texture = "effect5", layer = "mask", scale = 0.5, uniforms = { color = { 0, 0, 0, 1} } },
	{ camera = { layer = "mask", target = "effect1" } },
	{ camera = { layer = "blur1", target = "effect3" } },
	{ camera = { layer = "blur2", target = "effect4" } },
	{ camera = { layer = "lights" } },
	{ camera = { layer = "bunny", fov = 66, target = "effect5", depthTest = true } },
	{ camera = { layer = "depth", fov = 66, target = "depth" }, z = cameraZ, x = cameraX, y = cameraY, rotationX = cameraRotationX, rotationY = cameraRotationY },
	{ camera = { layer = "3d_blur_1", target = "effect6" } },
	{ camera = { layer = "3d_blur_2", target = "final" } },
	{ camera = { layer = "particles", fov = 66, target = "final" } },
	final,
 	{ camera = { layer = "final" } },
	{ camera = { layer = "rays" } },
	--{ texture = "effect1", layer = "foo", scale = 0.5 },
	--{ camera = { layer = "foo" } },
  	{ camera = { layer = "overlay" } },
	finalBunny
}

--_G.world = {}

bunny.enabled = false
zParticles.enabled = false
slowParticles.enabled = true
finalBunny.enabled = false

--finalBunny[1].uniforms.perlinStrength = 0
--finalBunny[1].uniforms.angleOffsetFactor = 0
--finalBunny[1].uniforms.timeAngleFactor = 0
--finalBunny[1].uniforms.radiusOffsetFactor = 0--_G.tween(0, 5, 4, 0, true, _G.bezier.make({0.000,0.436,0.082,0.927,0.082,1.000,0.127,1.000,0.127,1.000,0.245,1.000,0.255,0.300,0.345,0.000,0.345,0.000,0.573,0.000,0.718,0.000,1.000,0.000,}))

--final.fs = "tunnelEffect2"
--final.uniforms = { cellThreshold = _G.tween(2, 50, 5, 0, true, _G.bezier.make({0.000,1.000,0.000,0.000,0.600,0.000,1.000,0.000,})) }
--final.uniforms = { cellThreshold = _G.tween(50, 2, 1, 0, true) }
local flowerTextures = {
	"flowertunnel_FlowersTexture",
	"flowertunnel_uvwFlowers_B",
	"flowertunnel_FlowersTexture_BW",
	"flowertunnel_uvwFlowers_WIREFRAME",
}

local flowerTexturesTranslucent = {
	"flowertunnel_FlowersTextureTranslucent",
	"flowertunnel_uvwFlowers_B_Translucent",
	"flowertunnel_FlowersTextureTranslucent_BW",
	"flowertunnel_FlowersTexture_BW",
	"flowertunnel_uvwFlowers_WIREFRAME",
}

local leafTextures = {
	"flowertunnel_LeavesTexture",
	"flowertunnel_LeavesTexture_BW",
	"flowertunnel_uvwLeaves_WIREFRAME",
}

local leafTexturesTranslucent = {
	"flowertunnel_uvwLeavesTranslucent",
	"flowertunnel_LeavesTexture_BW",
	"flowertunnel_uvwLeavesTranslucent_BW",
	"flowertunnel_uvwLeaves_WIREFRAME",
}


local changeTunnelDirection = function(offset, _flowerTexture, _flowerTranslucentTexture, _leavesTexture, _leavesTranslucentTexture, delay, strength, enableBunny)
	if delay > 1 then _G.wait(delay - 1) end
	bunny.enabled = enableBunny
	bunny.z = _G.tween(-15, 0, math.min(1, delay), 0, false)
	final.fs = "tunnelEffect1"
	final.uniforms = { offsetR = { 1, 1 }, offsetG = { 0, 0 }, offsetB = { -1, -1 }, strength = _G.tween(0, strength, math.min(1.0, delay), 0, false, _G.bezier.make({0.000,0.000,0.509,0.045,0.873,0.291,1.000,1.000,})) }
	_G.wait(math.min(delay, 1.0))
	bunny.enabled = false
	final.uniforms = { offsetR = { 1, 1 }, offsetG = { 0, 0 }, offsetB = { -1, -1 }, strength = _G.tween(0, strength * 2, math.min(1.0, delay), 0, false, _G.bezier.make({0.000,1.000,0.000,0.000,0.600,0.000,1.000,0.000,})) }
	if _flowerTexture then flowerTexture = flowerTextures[_flowerTexture] end
	if _flowerTranslucentTexture then flowerTextureTranslucent = flowerTexturesTranslucent[_flowerTranslucentTexture] end
	if _leavesTexture then leavesTexture = leafTextures[_leavesTexture] end
	if _leavesTranslucentTexture then leavesTextureTranslucent = leafTexturesTranslucent[_leavesTranslucentTexture] end

	tunnelOffset = offset
end

--_G.timeScale = 60
_G.wait(3)
_G.audio.playMusic("tunnel.mp3")
_G.wait(8)
changeTunnelDirection({ -1.3, 0.3 }, 2, 2, 1, 1, 8, 0.004, false)
tunnelPower = 1.6
changeTunnelDirection({ 1.2, 0.3 }, 1, 1, 1, 1, 8, 0.004, false)

changeTunnelDirection({ -1.1, 0.2 }, 1, 1, 1, 1, 8, 0.01, false)
rays.uniforms.strength = _G.tween(2, 4, 0.5, 0, true, _G.bezier.make({0.000,0.000,0.282,1.000,0.455,1.000,0.600,0.000,0.600,0.000,0.873,0.000,0.836,0.000,1.000,0.000,}))
rays.uniforms.decay = _G.tween(5, 0.01, 0.5, 0, true, _G.bezier.make({0.000,0.000,0.282,1.000,0.455,1.000,0.600,0.000,0.600,0.000,0.873,0.000,0.836,0.000,1.000,0.000,}))
zParticles.enabled = true
slowParticles.enabled = false
changeTunnelDirection({ -1.1, 0.2 }, 1, 2, 2, 1, 2, 0.004, false)
changeTunnelDirection({ -1.1, 0.2 }, 2, 1, 2, 1, 2, 0.004, false)
changeTunnelDirection({ -1.1, 0.2 }, 1, 2, 2, 1, 2, 0.004, false)

changeTunnelDirection({ 1.4, 0.35 }, 1, 1, 1, 1, 2, 0.01, false)
changeTunnelDirection({ 1.4, 0.35 }, 1, 3, 1, 3, 2, 0.004, false)
changeTunnelDirection({ 1.4, 0.35 }, 1, 1, 1, 1, 2, 0.004, false)
changeTunnelDirection({ 1.4, 0.35 }, 3, 1, 2, 1, 2, 0.004, false)

changeTunnelDirection({ -1.6, 0.7 }, 2, 2, 1, 1, 2, 0.01, false)
rays.uniforms.colorRotations = { 10, 4, 7 }
rays.uniforms.colorRotationFactors = { -1, 2, 2 }
changeTunnelDirection({ -1.6, 0.7 }, 1, 1, 1, 1, 2, 0.004, false)
changeTunnelDirection({ -1.6, 0.7 }, 2, 2, 1, 1, 2, 0.004, false)
changeTunnelDirection({ -1.6, 0.7 }, 1, 1, 1, 1, 2, 0.004, false)

tunnelPower = 1.6
changeTunnelDirection({ 1.3, 0.3 }, 1, 4, 1, 2, 2, 0.01, false)
changeTunnelDirection({ -1.3, 0.3 }, 1, 4, 1, 2, 2, 0.01, false)

tunnelPower = 1.5
changeTunnelDirection({ 1.2, 0.5 }, 1, 1, 1, 2, 1, 0.01, false)
changeTunnelDirection({ 1.3, 0.3 }, 4, 2, 1, 1, 1, 0.01, false)
changeTunnelDirection({ -1.3, 0.5 }, 2, 2, 3, 4, 1, 0.01, false)
changeTunnelDirection({ -1.1, 0.7 }, 1, 4, 1, 2, 1, 0.01, false)
changeTunnelDirection({ -1.6, 0.5 }, 4, 2, 3, 1, 1, 0.01, true)
changeTunnelDirection({ 1.3, 0.5 }, 4, 2, 1, 1, 1, 0.01, true)
changeTunnelDirection({ -1.3, 0.6 }, 4, 5, 3, 4, 1, 0.01, true)
changeTunnelDirection({ -1.1, 0.8 }, 1, 2, 3, 2, 1, 0.01, true)
changeTunnelDirection({ 1.3, 0.3 }, 4, 2, 1, 1, 1, 0.01, false)
changeTunnelDirection({ -1.6, 0.5 }, 4, 2, 3, 1, 1, 0.01, true)

tunnelPower = 1.4
changeTunnelDirection({ 1.2, 0.5 }, 1, 1, 1, 4, 0.5, 0.01, false)
changeTunnelDirection({ 1.3, 0.3 }, 4, 1, 1, 1, 0.5, 0.01, true)
changeTunnelDirection({ -1.3, 0.5 }, 1, 5, 1, 1, 0.5, 0.01, false)
changeTunnelDirection({ 1.1, 0.7 }, 1, 1, 3, 1, 0.5, 0.01, true)
changeTunnelDirection({ -1.6, 0.5 }, 1, 1, 1, 4, 0.5, 0.01, false)
changeTunnelDirection({ 1.3, 0.3 }, 4, 1, 1, 1, 0.5, 0.01, true)
changeTunnelDirection({ -1.3, 0.5 }, 1, 5, 1, 1, 0.5, 0.01, false)
changeTunnelDirection({ 1.1, 0.7 }, 1, 1, 3, 1, 0.5, 0.01, true)
changeTunnelDirection({ 1.2, 0.5 }, 1, 1, 1, 4, 0.5, 0.01, false)
changeTunnelDirection({ 1.3, 0.3 }, 4, 1, 1, 1, 0.5, 0.01, true)
changeTunnelDirection({ -1.3, 0.5 }, 1, 5, 1, 1, 0.5, 0.01, false)
changeTunnelDirection({ 1.1, 0.7 }, 1, 1, 3, 1, 0.5, 0.01, true)
changeTunnelDirection({ 1.2, 0.5 }, 1, 1, 1, 4, 0.5, 0.01, false)
changeTunnelDirection({ 1.3, 0.3 }, 4, 1, 1, 1, 0.5, 0.01, true)
changeTunnelDirection({ -1.3, 0.5 }, 1, 5, 1, 1, 0.5, 0.01, false)
changeTunnelDirection({ 1.1, 0.7 }, 1, 1, 3, 1, 0.5, 0.01, true)

for i = 2, 20 do
	_G.world[i].z = _G.get(_G.world[i].z)
end

changeTunnelDirection({0, 0}, 1, 1, 1, 4, 0.25, 0.01, true)
changeTunnelDirection({0, 0}, 2, 2, 2, 3, 0.25, 0.01, true)
changeTunnelDirection({0, 0}, 3, 3, 3, 2, 0.25, 0.01, true)
changeTunnelDirection({0, 0}, 4, 4, 1, 1, 0.25, 0.01, true)
changeTunnelDirection({0, 0}, 1, 5, 2, 4, 0.25, 0.01, true)
changeTunnelDirection({0, 0}, 2, 1, 3, 3, 0.25, 0.01, true)
changeTunnelDirection({0, 0}, 3, 2, 1, 2, 0.25, 0.01, true)
changeTunnelDirection({0, 0}, 4, 3, 2, 1, 0.25, 0.01, true)

light0.uniforms.color = { function() return bgColor[1] * 1.2 end, function() return bgColor[2] * 1.2 end, function() return bgColor[3] * 1.2 end, _G.tween(1, 0, 1, 0, false) }

_G.wait(1)
finalBunny.enabled = true
local bunnyScaleCurve = {0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.982,0.000,0.509,0.836,1.000,1.000,}
local targetScale = 30
finalBunny[1].scale = _G.tween(-0.5, -targetScale, 1, 0, false, _G.bezier.make(bunnyScaleCurve))
finalBunny[1].x = _G.tween(0, 110 * targetScale, 1, 0, false, _G.bezier.make(bunnyScaleCurve))
finalBunny[1].y = _G.tween(0, -174 * targetScale, 1, 0, false, _G.bezier.make(bunnyScaleCurve))
finalBunny[1][1].enabled = true
finalBunny[3].enabled = false
finalBunny[1][1].uniforms.suckInOffset = 0.83
finalBunny[1][1].uniforms.suckInFactor = _G.tween(1, 1.06, 0.5, 0, true, _G.bezier.make({0.000,0.000,0.218,0.964,0.864,0.809,1.000,0.000,}))
finalBunny[1][1].uniforms.perlinStrength = 0.3
finalBunny[1][1].uniforms.radiusOffsetFactor = _G.tween(0, 5, 1, 0, true, _G.bezier.make({0.000,0.436,0.082,0.927,0.082,1.000,0.127,1.000,0.127,1.000,0.245,1.000,0.255,0.300,0.345,0.000,0.345,0.000,0.573,0.000,0.718,0.000,1.000,0.000,}))
_G.wait(9)
finalBunny[1][1].uniforms.perlinStrength = 0
finalBunny[1][1].uniforms.radiusOffsetFactor = 0
finalBunny[1][1].uniforms.suckInFactor = _G.tween(1, 3, 0.5, 0, false, _G.bezier.make({0.000,0.000,0.209,0.909,0.464,0.945,1.000,1.000,}))
finalBunny[1].scale = _G.tween(-targetScale, -targetScale*2, 4, 0, false, _G.bezier.make({0.000,0.000,0.209,0.909,0.464,0.945,1.000,1.000,}))
finalBunny[1].x = _G.tween(110 * targetScale, 110 * targetScale*2, 4, 0, false, _G.bezier.make({0.000,0.000,0.209,0.909,0.464,0.945,1.000,1.000,}))
finalBunny[1].y = _G.tween(-174 * targetScale, -174 * targetScale*2, 4, 0, false, _G.bezier.make({0.000,0.000,0.209,0.909,0.464,0.945,1.000,1.000,}))
table.insert(_G.world, { { texture = "square", width = _G.config.width, height = _G.config.height, layer = "overlay", uniforms = { color = { 0, 0, 0, _G.tween(0, 1, 1, 0, false) } } }, { camera = { layer = "overlay" } } })
_G.wait(1)
_G.loadLevel("credits.lua")

--[[
finalBunny[1].uniforms.perlinStrength = _G.tween(0.4, 0.01, 0.5, 0, false, _G.bezier.make({0.000,0.000,0.164,0.982,0.255,0.955,1.000,1.000,}))
_G.wait(1)
finalBunny[1].uniforms.perlinStrength = _G.tween(0.1, 0.4, 3, 0, false, _G.bezier.make({0.000,0.000,0.164,0.982,0.255,0.955,1.000,1.000,}))
_G.wait(3)
finalBunny[1].uniforms.perlinStrength = _G.tween(0.4, 0.02, 2, 0, false, _G.bezier.make({0.000,0.000,0.164,0.982,0.255,0.955,1.000,1.000,}))
_G.wait(3)
]]
--[[
while true do
	wait(1)
	--tunnelOffset[1] = math.random() * 2 - 1
	--tunnelOffset[2] = math.random() * 2 - 1
	bgColor[1] = math.random()
	bgColor[2] = math.random()
	bgColor[3] = math.random()
	_G.clearColor = { red = bgColor[1], green = bgColor[2], blue = bgColor[3] }
	print(bgColor[1] .. " " .. bgColor[2] .. " " ..  bgColor[3])
end
wait(1)
final.fs = "tunnelEffect1"
final.uniforms = { offsetR = { 1, 1 }, offsetG = { 0, 0 }, offsetB = { -1, -1 }, strength = _G.tween(0, 0.02, 1, 0, true, _G.bezier.make({0.000,1.000,0.000,0.000,0.600,0.000,1.000,0.000,})) }
final.fs = "tunnelEffect2"
final.uniforms = { cellThreshold = _G.tween(2, 20, 1, 0, true, _G.bezier.make({0.000,0.000,0.609,0.000,0.845,0.300,1.000,1.000,})) }
final.fs = "tunnelEffect2"
wait(1)
wait(1)
]]
--[[
	{
		texture = "bunny_1024",
		layer = "bunny",
		scaleFunc = function() return 0.5 end,
		scaleY = function(self) return -self.scaleFunc() end,
		scaleX = function(self) return self.scaleFunc() end,
		x = function() return getPosition(0, 500, _G.time * 2) * 400 end,
		y = function() return getPosition(1, 500, _G.time * 2) * 400 end,
		fs = "bunny",
		uniforms = {
			perlinTextureSampler = "perlin_noise",
			perlinStrength = 0.4,
			angleOffsetFactor = 2,
			radiusOffsetFactor = _G.tween(0, 5, 4, 0, true, _G.bezier.make({0.000,0.436,0.082,0.927,0.082,1.000,0.127,1.000,0.127,1.000,0.245,1.000,0.255,0.300,0.345,0.000,0.345,0.000,0.573,0.000,0.718,0.000,1.000,0.000,})),
			time = function() return _G.time * 0.1 end
		}
	},
]]
