// Alexander Lemke, 2016 // Update 10/12/16: Hash function update to fix artifacts on mobile. const float EPSILON = 0.001; const float PI = 3.14159265359; // noise functions based on iq's https://www.shadertoy.com/view/MslGD8 float Hash(in vec2 p) { return -1.0 + 2.0 * fract(sin(dot(p, vec2(12.0, 78.0))) * 43758.0); } float Noise(in vec2 p) { vec2 n = floor(p); vec2 f = fract(p); vec2 u = f * f * (3.0 - 2.0 * f); return mix(mix(Hash(n), Hash(n + vec2(1.0, 0.0)), u.x), mix(Hash(n + vec2(0.0, 1.0)), Hash(n + vec2(1.0)), u.x), u.y); } float Spiral(in vec2 texCoord, in float rotation) { float spiral = sin(50.0 * (pow(length(texCoord), 0.25) - 0.02 * atan(texCoord.x, texCoord.y) - rotation)); return clamp(spiral, 0.0, 1.0); } vec3 ColoredSpiral(in vec2 texCoord, in float rotation, in vec3 c0, in vec3 c1) { return mix(c0, c1, Spiral(texCoord, rotation)); } void mainImage(out vec4 fragColor, in vec2 fragCoord) { vec2 screenCoord = (fragCoord.xy / iResolution.xy); vec4 finalColor = vec4(1.0); vec2 portalCenter = vec2(sin(iGlobalTime * 2.0), cos(iGlobalTime * 2.0)) * 0.025; vec2 portalTexCoord = portalCenter + vec2((screenCoord.x * 2.0 - 1.0) * (iResolution.x / iResolution.y), (screenCoord.y * 2.0 - 1.0)); vec2 pushDirection = normalize(portalTexCoord + vec2(EPSILON)); float noise = Noise(pushDirection + iGlobalTime) * 0.15 * length(portalTexCoord); portalTexCoord = portalTexCoord + (-noise * pushDirection); float r = length(portalTexCoord); vec3 portalColor = ColoredSpiral(portalTexCoord, 0.1 * iGlobalTime, vec3(0.0, 0.6, 0.0), vec3(0.35, 1.0, 0.0)); finalColor.rgb = mix(finalColor.rgb, mix(portalColor, vec3(0.6, 1.0, 0.35), 0.01 + (r * r)), step(r, 1.0)); fragColor = finalColor; } float getProceduralColors(inout vec3 diffuse, inout vec3 specular, inout float shininess) { vec2 position = _position.xz; position += 0.5; position.y = 1.0 - position.y; vec4 pixelColor; mainImage(pixelColor, position * iWorldScale.xz); }