////clouds 21 0.a009 sdf 2.1
////clouds 21 0.a009 sdf 2.1
//#version 130

#define PI 3.1415926
bool leftside=false;
float fishdx,fishdy;

const int blobcount=120;
uniform float blobx[blobcount];
uniform float bloby[blobcount];
uniform float blobz[blobcount];
uniform float blobr[blobcount];

#define LIGHTING

uniform float iTime;
uniform sampler2D depthMap;
uniform sampler2D colorMap;
uniform sampler2D noiseMap;
uniform samplerCube envMap;

float depth3d, depthrm;
//uniform sampler2D iChannel0; // noise
//uniform sampler2D iChannel1; // floor color
//uniform sampler2D iChannel2; // floor mask
//uniform sampler2D iChannel3; // floor normal map
#define iChannel0 depthMap 
#define iChannel1 depthMap
#define iChannel2 depthMap
#define iChannel3 depthMap
// these are not actually used, they're defined just for compiling

uniform int actionselector; // 1 = helix,  2 = cube, 3 = both
uniform float testvalue;

const float skeyl=1.2;

//float fov=1.2;
///const float fov_ = 65.0f;
///const float fov = 1.0f / tan(fov_ * (6.28f / 360.0f) / 2.0f);//3.5f;


uniform float fov;
uniform vec3 rayorigin;
uniform vec3 raydirection;
uniform vec3 upvector;
///vec3 upvector=vec3(0.0,1.0,0.0);

uniform mat4 rotmatrix;

vec2 rotateVector (vec2 vec, float ang)
{
    vec2 res = vec2(
        vec.x * cos(ang) - vec.y * sin(ang),
        vec.x * sin(ang) + vec.y * cos(ang)
    );
    return res;
}

float Helix (vec3 q)
{   
float sp=4.0*1.25; ///spin
	float l = length(q.xz)*2.0 - 1.7;
	float d = mod((atan(q.z,q.x)-q.y*sp), 6.28) - 3.14;
	return length(vec2(l, d)) - 0.35*0.9;

    ///float l = length(q.xz) - 5.0;
	///float d = mod(atan(q.z,q.x)-q.y, 6.28) - 3.14;
	///return length(vec2(l, d)) - 1.25;
}

float sdBox( vec3 p, vec3 b )
{
    vec3 d = abs(p) - b;
    return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}

float sinussdEllipsoid( in vec3 p, in vec3 r ) // approximated
{
    float k0 = length(p/r);
    float k1 = length(p/(r*r));
    return k0*(k0-1.0)/k1;
}

float sinussdBox( vec3 p, vec3 b )
{
    float time=0.0-iTime*2.1;
    b.y=1.0;
    /*
    const float scale=1505.1;
    b.x=2.0/scale;
    b.z=2.0/scale;
    */
    const float r2=0.55;
    const float r=0.95*r2;
    float h=p.y/0.05/3.1/1.1;
    h+=time;
    p=p+vec3(r*(sin(h)),0.0,r*(cos(h)));
    
    float rcheck=length(vec2(p.x,p.z));//sqrt(pow(p.x,2.0)+pow(p.z,2.0));
    if (rcheck>0.25*r2) p.x=1000.0;//(move it out of range)
    
    return sinussdEllipsoid(p,b);
    
    vec3 d = abs(p) - b;
    return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}

float sdEllipsoid( in vec3 p, in vec3 r ) // approximated
{
    float k0 = length(p/r);
    float k1 = length(p/(r*r));
    return k0*(k0-1.0)/k1;
}

vec2 opU( vec2 d1, vec2 d2 ) { 
if (d1.x<d2.x) return d1; else return d2;
//return min(d1,d2); 
}

float h_=0.0;
vec2 opUsc( vec2 d1, vec2 d2, float k ) {
    float h = clamp( 0.5 + 0.5*(d2.x-d1.x)/k, 0.0, 1.0 );
    h_=clamp((d2.x-d1.x)/k, -1.0, 1.0 );
    //h_+=1.0; h_/=2.0;
    return vec2(mix( d2.x, d1.x, h ) - k*h*(1.0-h), d1.y); 
}

vec2 opSs( vec2 d1, vec2 d2, float k ) {
    float h = clamp( 0.5 + 0.5*(-d2.x-d1.x)/k, 0.0, 1.0 );
    //h_=clamp((-d2.x-d1.x)/k, -1.0, 1.0 );
    return vec2(mix( d1.x, -d2.x,  h ) + k*h*(1.0-h), d1.y);
}

float hash_(vec3 p)  // replace this by something better
{
    p  = fract( p*0.3183099+.1 );
	p *= 17.0;
    return fract( p.x*p.y*p.z*(p.x+p.y+p.z) );
}

float noise_( in vec3 x )
{
    x*=1.3;
    
    float time=iTime/4.0;
    //time=0.0;
    x.y+=time*1.5;
    x.z+=time*1.9;

    vec3 i = floor(x);
    vec3 f = fract(x);
    f = f*f*(3.0-2.0*f);
	
    return mix(mix(mix( hash_(i+vec3(0,0,0)), 
                        hash_(i+vec3(1,0,0)),f.x),
                   mix( hash_(i+vec3(0,1,0)), 
                        hash_(i+vec3(1,1,0)),f.x),f.y),
               mix(mix( hash_(i+vec3(0,0,1)), 
                        hash_(i+vec3(1,0,1)),f.x),
                   mix( hash_(i+vec3(0,1,1)), 
                        hash_(i+vec3(1,1,1)),f.x),f.y),f.z);
}

float sdSphere( vec3 p, float s )
{
    return length( p ) - s;
}


vec3 random3(vec3 c) {
	float j = 4096.0*sin(dot(c,vec3(17.0, 59.4, 15.0)));
	vec3 r;
	r.z = fract(512.0*j);
	j *= .125;
	r.x = fract(512.0*j);
	j *= .125;
	r.y = fract(512.0*j);
	return r-0.5;
}

const float F3 =  0.3333333;
const float G3 =  0.1666667;

float simplex3d(vec3 p) {
	 vec3 s = floor(p + dot(p, vec3(F3)));
	 vec3 x = p - s + dot(s, vec3(G3));
	 
	 vec3 e = step(vec3(0.0), x - x.yzx);
	 vec3 i1 = e*(1.0 - e.zxy);
	 vec3 i2 = 1.0 - e.zxy*(1.0 - e);
	 	
	 vec3 x1 = x - i1 + G3;
	 vec3 x2 = x - i2 + 2.0*G3;
	 vec3 x3 = x - 1.0 + 3.0*G3;
	 
	 vec4 w, d;
	 
	 w.x = dot(x, x);
	 w.y = dot(x1, x1);
	 w.z = dot(x2, x2);
	 w.w = dot(x3, x3);
	 
	 w = max(0.6 - w, 0.0);
	 
	 d.x = dot(random3(s), x);
	 d.y = dot(random3(s + i1), x1);
	 d.z = dot(random3(s + i2), x2);
	 d.w = dot(random3(s + 1.0), x3);
	 
	 w *= w;
	 w *= w;
	 d *= w;
	 
	 return dot(d, vec4(52.0));
}

float LUTnoise( in vec3 x )
{
    vec3 i = floor(x);
    vec3 f = fract(x);
	f = f*f*(3.0-2.0*f);
	vec2 uv = (i.xy+vec2(37.0,17.0)*i.z) + f.xy;
	vec2 rg = textureLod(noiseMap, (uv+0.5)/512.0, 0.0).yx;
	return mix( rg.x, rg.y, f.z );
}


float sdCapsule( vec3 p, vec3 a, vec3 b, float r )
{
    vec3 pa = p - a, ba = b - a;
    float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
    return length( pa - ba*h ) - r;
}

mat4 rotateY(float theta) {
    float c = cos(theta);
    float s = sin(theta);

    return mat4(
        vec4(c, 0, s, 0),
        vec4(0, 1, 0, 0),
        vec4(-s, 0, c, 0),
        vec4(0, 0, 0, 1)
    );
}

mat4 rotateX(float theta) {
    float c = cos(theta);
    float s = sin(theta);

    return mat4(
        vec4(1, 0, 0, 0),
        vec4(0, c, -s, 0),
        vec4(0, s, c, 0),
        vec4(0, 0, 0, 1)
    );
}

mat4 rotateZ(float theta) { ///not tested
    float c = cos(theta);
    float s = sin(theta);

    return mat4(
        vec4(c, -s, 0, 0),
        vec4(s, c, 0, 0),
        vec4(0, 0, 1, 0),
        vec4(0, 0, 0, 1)
    );
}

float feet;
//-------------------------------------------------
float sdXSphere( vec3 p, float s, int i)
{
    vec3 p2 = vec4(p,1.0)*rotateY(i*0.1256)*rotateZ(iTime*6.28*abs(blobr[i])/3.0)*rotateX(i*0.5256+iTime*6.28*abs(blobr[i])/3.0);
    float s_=s*120.0*1.4/feet;

    // bend:
    const float k = 10.0*-3.5; // or some other amount
    float c = cos(k*p2.x);
    float sb = sin(k*p2.x);
    mat2 m = mat2(c,-sb,sb,c);
    vec3 q = vec3(m*p2.xy,p2.z);

    float obj1=sdCapsule(q,0.03/s_,0.0175/s_,0.0175/s_*1.1);
    //float res=opUsc(obj1,obj2,0.02);
    return obj1;

/*
    vec3 p2 = vec4(p,1.0)*rotateY(i*0.1256)*rotateZ(iTime*6.28*blobr[i]/3.0)*rotateX(i*0.5256+iTime*6.28*blobr[i]/3.0);
    vec3 p3 = vec4(p,1.0)*rotateY(i*0.2156)*rotateZ(iTime*6.28*blobr[i]/4.0)*rotateX(i*0.3176+iTime*6.28*blobr[i]/2.25);
    float s_=s*120.0;
    float s2_=s*140.0;
    float obj1=sdCapsule(p2,0.02/s_,0.01/s_,0.01/s_);
    float obj2=sdCapsule(p3,0.02/s2_,0.01/s2_,0.01/s2_);
    float res=opUsc(obj1,obj2,0.02);
    return res;
*/
    float sphere = length(p)-s;
    float noise = simplex3d(p*-0.620000600814819+vec3(i,0.0,0.0));
    sphere = opSs(sphere,noise,0.02);
    //sphere = opU(sphere,noise);

    return sphere;
}

float sdXSphere_( vec3 p, float s, int i)
{
    float sphere = length(p)-s;
    //float noise = LUTnoise(p*-0.620000600814819*testvalue+vec3(0,0,0));
    //float noise = simplex3d(p*-0.620000600814819*testvalue+vec3(0,0,0));
    float noise = sdSphere(p+normalize(noise3(p))/100.0/testvalue,0.01);

    //sphere = opUsc(sphere,noise,0.02*testvalue);
    sphere = opU(sphere,noise);
    return sphere;
}

vec2 cubeshape(vec3 pos){
   float cl=0.75*0.58;
   vec3 pos3=-pos;
   pos+=vec3(0.35*cl,-1000,-0.6*cl);
   //pos.y+=0.26*sin(iTime*6.28/2.5/3.0);
   //pos=(rotmatrix*vec4(pos,1.0)).xyz;

   //float scale=4.25*0.80;
   //scale*=testvalue;
   vec2 res;
   ///res=vec2(100.0,0.0);
   res=vec2(sdBox(pos+vec3(0.0,0.0,0.0),vec3(0.0,0.0,0.0)),0.0);
   vec2 res3 = opU(res,vec2(sdBox(pos,vec3(1.1,1.1,1.1)/21.5),2071.0));

   //float clip=0.56;//testvalue
   //if (pos.x<-(clip) || pos.x>(clip*11.5)) return res3;
   const float clipx=0.56;
   if (pos3.x<-(clipx) || pos3.x>(clipx)) return res3;
   //float clipy=0.56;//0.1 -0.6
   if (pos3.y>0.125||pos3.y<-0.725) return res3;
   if (pos3.z<-0.78||pos3.z>0.4) return res3;

    for (int i=0;i<blobcount;i++){
        const float size=0.7*0.85*1.3;
        ///res3 = opUsc(res3, vec2(sdSphere(pos3+vec3(blobx[i],bloby[i],blobz[i]),size/80.0*1.7/7.2*5.0), 2071.0),0.05/2.7*2.0*0.9/10.0*6.0*blobr[i]*0.6);
        feet = 1.0;
        if (blobr[i]<0.0) {feet = 0.6;}
        res3 = opUsc(res3, vec2(sdXSphere(pos3+vec3(blobx[i],bloby[i],blobz[i]),size*0.01475694,i), 2071.0),abs(blobr[i])*0.012*1.5);
    }

   ///vec2 res3 = opU(res,vec2(sdBox(pos+vec3(0.0,0.032,0.0),vec3(0.0005,0.0005,0.0005)/vec3(scale)),2071.0));
   ///vec2 res3 = opU(res,vec2(sdEllipsoid(pos+vec3(0.0,0.032,0.0),vec3(0.0005,0.0005,0.0005)/vec3(scale)),2071.0));
   return res3;
}

vec2 cloudshape(vec3 pos){
pos.y+=-1.4;
const float scale=4.25*0.80;
   vec2 res;
    //res = vec2(sdBox(pos+vec3(0.0,5.0,0.0), vec3(0.25,4.25,0.25)),26.9);
    res=vec2(100.0,0.0);

    //res = opUsc(res,vec2(sdEllipsoid(pos+vec3(0.0,6.3,0.0), vec3(0.45,4.45,0.45)),26.9),0.01);
    //res = opUsc(res,vec2(sdEllipsoid(pos+vec3(0.0,6.3,0.0), vec3(0.45,4.45,0.45)),26.9),0.01);
    res = opUsc(res,vec2(sdBox(pos+vec3(0.0,0.0,0.0), vec3(4.5,6.5,4.5)/vec3(scale)),26.9),0.06);
    
    //res = opSs(res,vec2(sdBox(pos+vec3(0.0,0.0,0.0), vec3(0.7,0.7,0.7)),26.9),0.32);
    //return h_;

//vec3 q = 3.5*pos;
///float m=1.1;
//float f = 0.75000*noise_( q );
const float f=1.0;
/*
q = m*q*3.01;
f += 0.1500*noise_( q ); 
q = m*q*2.52;
f += 0.0350*noise_( q ); 
*/
//const float r_factor=0.35;
//const float h_factor=1.0;
//float r = 0.1+f*2.35;
//float r2=r_factor/6.0+f*4.55;
//r2=1.0;
vec2 res2=vec2(100.0,0.0);
float sx=iTime*0.9;
//res2 = opUsc(res2,vec2(sdBox(pos+vec3(2.0,1.2*sin(sx),0.0)/vec3(scale),vec3(0.25,0.0025,0.45)*vec3(r2)/vec3(scale)),26.9),0.05);
//res2 = opUsc(res2,vec2(sdBox(pos+vec3(-2.0,1.2*cos(sx),0.0)/vec3(scale),vec3(0.45,0.0025,0.25)*vec3(r2)/vec3(scale)),26.9),0.05);

//res2 = opUsc(res2,vec2(sdBox(pos+vec3(2.0+4.0*sin(sx/2.0),-0.5,0.0)/vec3(scale),vec3(0.25,0.0025,0.45)*vec3(r2)/vec3(scale)),26.9),0.05);
//res2 = opUsc(res2,vec2(sdBox(pos+vec3(-2.0,-0.5,0.0+3.3*cos(sx/1.7))/vec3(scale),vec3(0.45,0.0025,0.25)*vec3(r2)/vec3(scale)),26.9),0.05);
///res2 = opUsc(res2,vec2(sdBox(pos,vec3(0.25,0.0025,0.45)*vec3(r2)/vec3(scale)),26.9),0.05);
//res2 = opUsc(res2,vec2(sdBox(pos+vec3(-2.0,0.0,0.0+3.3*cos(sx/1.7))/vec3(scale),vec3(0.45,0.0025,0.25)*vec3(r2)/vec3(scale)),26.9),0.05);

///res2 = opU(res2,vec2(sinussdBox(pos,vec3(0.0005,0.0005,0.0005)/vec3(scale)),26.9));
///res2 = opU(res2,vec2(sinussdBox(pos+vec3(0.0,0.032,0.0),vec3(0.0005,0.0005,0.0005)/vec3(scale)),26.9));

res2 = opU(res2,vec2(Helix(pos+vec3(0.0,0.0,0.0)),26.9));
res = opSs(res,res2,(1.5+0.02)*0.81+0.6+0.2);

///res = opSs(res,res2,(1.5+0.02)*0.81+0.6);
return vec2(h_,0);
}







float animate=0.0;
float twist=0.0;
float time;

float hash2(vec3 p)  // replace this by something better
{
    p  = fract( p*0.3183099+.1 );
	p *= 17.0;
    return fract( p.x*p.y*p.z*(p.x+p.y+p.z) );
}

float hash2_(vec3 p3) /// looks better (more regular) but less interesting :)
{
	p3  = fract(p3 * .1031);
    p3 += dot(p3, p3.zyx + 31.32);
    return fract((p3.x + p3.y) * p3.z);
}

float noisefast2( in vec3 x )
{
    vec3 i = floor(x);
    vec3 f = fract(x);
    f = f*f*(3.0-2.0*f);
	
    return mix(mix(mix( hash2(i+vec3(0,0,0)), 
                        hash2(i+vec3(1,0,0)),f.x),
                   mix( hash2(i+vec3(0,1,0)), 
                        hash2(i+vec3(1,1,0)),f.x),f.y),
               mix(mix( hash2(i+vec3(0,0,1)), 
                        hash2(i+vec3(1,0,1)),f.x),
                   mix( hash2(i+vec3(0,1,1)), 
                        hash2(i+vec3(1,1,1)),f.x),f.y),f.z);
}

float noisefast_( in vec3 x )
{
    vec3 i = floor(x);
    vec3 f = fract(x);
	f = f*f*(3.0-2.0*f);
	vec2 uv = (i.xy+vec2(37.0,17.0)*i.z) + f.xy;
	vec2 rg = textureLod( iChannel1, (uv+0.5)/256.0, 0.0).yx;
	return mix( rg.x, rg.y, f.z );
}


float noisefast( in vec3 x )
{
    ivec3 i = ivec3(floor(x));
    vec3 f = fract(x);
	f = f*f*(3.0-2.0*f);
	ivec2 uv = i.xy + ivec2(37,17)*i.z;
	vec2 rgA = texelFetch( iChannel1, (uv+ivec2(0,0))&255, 0 ).yx;
    vec2 rgB = texelFetch( iChannel1, (uv+ivec2(1,0))&255, 0 ).yx;
    vec2 rgC = texelFetch( iChannel1, (uv+ivec2(0,1))&255, 0 ).yx;
    vec2 rgD = texelFetch( iChannel1, (uv+ivec2(1,1))&255, 0 ).yx;
    vec2 rg = mix( mix( rgA, rgB, f.x ),
                   mix( rgC, rgD, f.x ), f.y );
    return mix( rg.x, rg.y, f.z );
}

//clouds 21 0.997 rechecking lighting

//
// Description : Array and textureless GLSL 2D/3D/4D simplex 
//               noise functions.
//      Author : Ian McEwan, Ashima Arts.
//  Maintainer : stegu
//     Lastmod : 20110822 (ijm)
//     License : Copyright (C) 2011 Ashima Arts. All rights reserved.
//               Distributed under the MIT License. See LICENSE file.
//               https://github.com/ashima/webgl-noise
//               https://github.com/stegu/webgl-noise
//  

vec4 mod289(vec4 x) {
  return x - floor(x * (1.0 / 289.0)) * 289.0; }

float mod289(float x) {
  return x - floor(x * (1.0 / 289.0)) * 289.0; }

vec4 permute(vec4 x) {
     return mod289(((x*34.0)+10.0)*x);
}

float permute(float x) {
     return mod289(((x*34.0)+10.0)*x);
}

vec4 taylorInvSqrt(vec4 r)
{
  return 1.79284291400159 - 0.85373472095314 * r;
}

float taylorInvSqrt(float r)
{
  return 1.79284291400159 - 0.85373472095314 * r;
}

vec4 grad4(float j, vec4 ip)
  {
  const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);
  vec4 p,s;

  p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;
  p.w = 1.5 - dot(abs(p.xyz), ones.xyz);
  s = vec4(lessThan(p, vec4(0.0)));
  p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; 

  return p;
  }
						
// (sqrt(5) - 1)/4 = F4, used once below
#define F4 0.309016994374947451

float snoise(vec4 v)
  {
  const vec4  C = vec4( 0.138196601125011,  // (5 - sqrt(5))/20  G4
                        0.276393202250021,  // 2 * G4
                        0.414589803375032,  // 3 * G4
                       -0.447213595499958); // -1 + 4 * G4

// First corner
  vec4 i  = floor(v + dot(v, vec4(F4)) );
  vec4 x0 = v -   i + dot(i, C.xxxx);

// Other corners

// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
  vec4 i0;
  vec3 isX = step( x0.yzw, x0.xxx );
  vec3 isYZ = step( x0.zww, x0.yyz );
//  i0.x = dot( isX, vec3( 1.0 ) );
  i0.x = isX.x + isX.y + isX.z;
  i0.yzw = 1.0 - isX;
//  i0.y += dot( isYZ.xy, vec2( 1.0 ) );
  i0.y += isYZ.x + isYZ.y;
  i0.zw += 1.0 - isYZ.xy;
  i0.z += isYZ.z;
  i0.w += 1.0 - isYZ.z;

  // i0 now contains the unique values 0,1,2,3 in each channel
  vec4 i3 = clamp( i0, 0.0, 1.0 );
  vec4 i2 = clamp( i0-1.0, 0.0, 1.0 );
  vec4 i1 = clamp( i0-2.0, 0.0, 1.0 );

  //  x0 = x0 - 0.0 + 0.0 * C.xxxx
  //  x1 = x0 - i1  + 1.0 * C.xxxx
  //  x2 = x0 - i2  + 2.0 * C.xxxx
  //  x3 = x0 - i3  + 3.0 * C.xxxx
  //  x4 = x0 - 1.0 + 4.0 * C.xxxx
  vec4 x1 = x0 - i1 + C.xxxx;
  vec4 x2 = x0 - i2 + C.yyyy;
  vec4 x3 = x0 - i3 + C.zzzz;
  vec4 x4 = x0 + C.wwww;

// Permutations
  i = mod289(i); 
  float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x);
  vec4 j1 = permute( permute( permute( permute (
             i.w + vec4(i1.w, i2.w, i3.w, 1.0 ))
           + i.z + vec4(i1.z, i2.z, i3.z, 1.0 ))
           + i.y + vec4(i1.y, i2.y, i3.y, 1.0 ))
           + i.x + vec4(i1.x, i2.x, i3.x, 1.0 ));

// Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope
// 7*7*6 = 294, which is close to the ring size 17*17 = 289.
  vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ;

  vec4 p0 = grad4(j0,   ip);
  vec4 p1 = grad4(j1.x, ip);
  vec4 p2 = grad4(j1.y, ip);
  vec4 p3 = grad4(j1.z, ip);
  vec4 p4 = grad4(j1.w, ip);

// Normalise gradients
  vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
  p0 *= norm.x;
  p1 *= norm.y;
  p2 *= norm.z;
  p3 *= norm.w;
  p4 *= taylorInvSqrt(dot(p4,p4));

// Mix contributions from the five corners
  vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0);
  vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4)            ), 0.0);
  m0 = m0 * m0;
  m1 = m1 * m1;
  return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 )))
               + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ;

  }


#define AA 0


//Original 2015 version.

vec2 Hash(vec2 P)
{
vec2 val1=texture(iChannel0,P/1000.0+iTime/500.0).xy;
vec2 val2=texture(iChannel0,P/1000.0).xy;
vec2 val=vec2(val1.x,val2.x);
val-=0.5;
val/=1.1;
return val;
 	return fract(cos(P*mat2(-64.2,71.3,81.4,-29.8))*8321.3); 
}


float Hash3d(vec3 uv)
{

    if (uv.x<0.0) uv.x=1.0+uv.x;
    if (uv.y<0.0) uv.y=1.0+uv.y;
    if (uv.z<0.0) uv.z=1.0+uv.z;
    if (uv.x>1.0) uv.x=uv.x-1.0;
    if (uv.y>1.0) uv.y=uv.y-1.0;
    if (uv.z>1.0) uv.z=uv.z-1.0;
    
    //uv=clamp(uv,0.0,1.0);

    float f = uv.x + uv.y * 37.0 + uv.z * 521.0;
    //return fract(sin(f)*110003.9);
    return fract(cos(f)*110003.9);
}

const vec2 zeroOne = vec2(0.0, 1.0);
float mixP(float f0, float f1, float a)
{
    return mix(f0, f1, a);
    return mix(f0, f1, a*a*(3.0-2.0*a));
}
float noiseValue(vec3 uv)
{
    vec3 fr = fract(uv.xyz);
    vec3 fl = floor(uv.xyz);
    float h000 = Hash3d(fl);
    float h100 = Hash3d(fl + zeroOne.yxx);
    float h010 = Hash3d(fl + zeroOne.xyx);
    float h110 = Hash3d(fl + zeroOne.yyx);
    float h001 = Hash3d(fl + zeroOne.xxy);
    float h101 = Hash3d(fl + zeroOne.yxy);
    float h011 = Hash3d(fl + zeroOne.xyy);
    float h111 = Hash3d(fl + zeroOne.yyy);
    return mixP(
        mixP(mixP(h000, h100, fr.x),
             mixP(h010, h110, fr.x), fr.y),
        mixP(mixP(h001, h101, fr.x),
             mixP(h011, h111, fr.x), fr.y)
        , fr.z);
}

float r(float n)
{
 	return fract(cos(n*89.42)*343.42);
}

vec2 r(vec2 n)
{
 	vec2 result=vec2(r(n.x*23.62-300.0+n.y*34.35),r(n.x*45.13+256.0+n.y*38.89)); 
    ///return result;
    return vec2(noiseValue(vec3(n,iTime/4.0)));//+result;
}

float fade(vec2 n){
    return fract(noiseValue(vec3(n,0.0)));
}

float worley(vec2 n,float s) 
{
    float dis = 1.0;
    for(int x = -1;x<=1;x++)
    {
        for(int y = -1;y<=1;y++)
        {
            vec2 p = floor(n/s)+vec2(x,y);
            float d = length(r(p)+vec2(x,y)-fract(n/s));
            if (dis>d)
            {
             	dis = d;
            }
        }
    }
    return dis;
	
}


vec3 gammaCorrect(vec3 color, float gamma){
    return pow(color, vec3(1.0/gamma));
}

vec3 levelRange(vec3 color, float minInput, float maxInput){
    return min(max(color - vec3(minInput), vec3(0.0)) / (vec3(maxInput) - vec3(minInput)), vec3(1.0));
}

float flevelRange(float color, float minInput, float maxInput){
    return min(max(color - minInput, 0.0) / (maxInput - minInput), 1.0);
}

vec3 finalLevels(vec3 color, float minInput, float gamma, float maxInput){
    return gammaCorrect(levelRange(color, minInput, maxInput), gamma);
}

//use like: vec3 col = finalLevels(someTex.rgb, 34.0/255.0, 1.5, 235.0/255.0);

// The MIT License
// Copyright � 2013 Inigo Quilez
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


// Simplex Noise (http://en.wikipedia.org/wiki/Simplex_noise), a type of gradient noise
// that uses N+1 vertices for random gradient interpolation instead of 2^N as in regular
// latice based Gradient Noise.


// Value    Noise 2D, Derivatives: https://www.shadertoy.com/view/4dXBRH
// Gradient Noise 2D, Derivatives: https://www.shadertoy.com/view/XdXBRH
// Value    Noise 3D, Derivatives: https://www.shadertoy.com/view/XsXfRH
// Gradient Noise 3D, Derivatives: https://www.shadertoy.com/view/4dffRH
// Value    Noise 2D             : https://www.shadertoy.com/view/lsf3WH
// Value    Noise 3D             : https://www.shadertoy.com/view/4sfGzS
// Gradient Noise 2D             : https://www.shadertoy.com/view/XdXGW8
// Gradient Noise 3D             : https://www.shadertoy.com/view/Xsl3Dl
// Simplex  Noise 2D             : https://www.shadertoy.com/view/Msf3WH
// Wave     Noise 2D             : https://www.shadertoy.com/view/tldSRj


vec2 hash( vec2 p ) // replace this by something better
{
	p = vec2( dot(p,vec2(127.1,311.7)), dot(p,vec2(269.5,183.3)) );
	return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}

float noise( in vec2 p )
{
    const float K1 = 0.366025404; // (sqrt(3)-1)/2;
    const float K2 = 0.211324865; // (3-sqrt(3))/6;

	vec2  i = floor( p + (p.x+p.y)*K1 );
    vec2  a = p - i + (i.x+i.y)*K2;
    float m = step(a.y,a.x); 
    vec2  o = vec2(m,1.0-m);
    vec2  b = a - o + K2;
	vec2  c = a - 1.0 + 2.0*K2;
    vec3  h = max( 0.5-vec3(dot(a,a), dot(b,b), dot(c,c) ), 0.0 );
	vec3  n = h*h*h*h*vec3( dot(a,hash(i+0.0)), dot(b,hash(i+o)), dot(c,hash(i+1.0)));
    return dot( n, vec3(70.0) );
}

// -----------------------------------------------

vec2 iResolution = vec2(1920.0,1080.0);
vec2 iResolution2 = vec2(1920.0,1080.0);

vec3 noise_(in vec2 fragCoord )
{
    vec2 p = fragCoord.xy / iResolution.xy;

	vec2 uv = p*vec2(iResolution.x/iResolution.y,1.0) + iTime*0.25;
	
	float f = 0.0;
	
    // left: value noise	
	if( p.x<0.6 )
	{
		f = noise( 16.0*uv );
	}
    // right: fractal noise (4 octaves)
    else	
	{
		uv *= 5.0;
        mat2 m = mat2( 1.6,  1.2, -1.2,  1.6 );
		f  = 0.5000*noise( uv ); uv = m*uv;
		f += 0.2500*noise( uv ); uv = m*uv;
		f += 0.1250*noise( uv ); uv = m*uv;
		f += 0.0625*noise( uv ); uv = m*uv;
	}

	f = 0.5 + 0.5*f;
	
    f *= smoothstep( 0.0, 0.005, abs(p.x-0.6) );	
	
	return vec3( f );
}

const mat3 rot1 = mat3(-0.37, 0.36, 0.85,-0.14,-0.93, 0.34,0.92, 0.01,0.4);
const mat3 rot2 = mat3(-0.55,-0.39, 0.74, 0.33,-0.91,-0.24,0.77, 0.12,0.63);
const mat3 rot3 = mat3(-0.71, 0.52,-0.47,-0.08,-0.72,-0.68,-0.7,-0.45,0.56);

float simplex3d_fractal(vec3 m) {
    return   0.5333333*simplex3d(m*rot1)
			+0.2666667*simplex3d(2.0*m*rot2)
			+0.1333333*simplex3d(4.0*m*rot3)
			+0.0666667*simplex3d(8.0*m);
}

void mainImage_simplex3d( out vec4 fragColor, in vec2 fragCoord )
{
	vec2 p = fragCoord.xy/iResolution.x;
	vec3 p3 = vec3(p, iTime*0.025);
	
	float value;
	
	if (p.x <= 0.6) {
		value = simplex3d(p3*32.0);
	} else {
		value = simplex3d_fractal(p3*8.0+8.0);
	}
	
	value = 0.5 + 0.5*value;
	value *= smoothstep(0.0, 0.005, abs(0.6-p.x)); // hello, iq :)
	
	fragColor = vec4(
			vec3(value),
			1.0);
	return;
}

float fbm_(vec3 x){
    //return 0.5+0.5*simplex3d_fractal(x/32.0*8.0+8.0);
    //float res= 0.5+0.5*snoise(vec4(x,time));

    //float res= 0.5+0.5*simplex3d(x/16.0*8.0+8.0);
    //float res=noisefast(x/4.0);
    float res=noisefast_(x/5.0);
    
    return res;
}
float fbm(vec3 x){
    //return 0.5+0.5*simplex3d_fractal(x/32.0*8.0+8.0);
    //float res= 0.5+0.5*snoise(vec4(x,time));

    //float res= 0.5+0.5*simplex3d(x/16.0*8.0+8.0);
    //float res=noisefast(x/4.0);
    return noisefast2(x);
    ///return noisefast2(x/5.0);
    //float res=noiseValue(x/5.0);
    
    ///return res;
}


float worley3d(vec3 n,float s) 
{
    return simplex3d(n);
}

vec3 v3(float x){return vec3(x,x,0);}


const float scale=0.025;
const float ylimit=122.6*scale;
const float ylimit2=-122.6*scale;
const float border=35.0*scale/1.2; ///0.7
vec3 rotpos;

vec4 map_cloud2(vec3 pos,int lighting){
//float b=cloudshape(pos);        
//    return vec4(b);
        float time=iTime/1.0;
        //pos+=(sin(time),0.0,cos(time));
        vec2 posxz=vec2(pos.x,pos.z);
        posxz=rotateVector(posxz,time);
        pos.x=posxz.x; pos.z=posxz.y;
        rotpos=pos.xyz;

vec2 b2=cloudshape(pos);
//if (b2.y==2071.0) return vec4(2071.0);
float b=b2.x;
if (b<0.1) return vec4(0.0);

    const float slowdown=0.5;
    time=2.0*iTime*2.5*slowdown*1.5+5.0*1000.0;
    ///float time2=0.0;//-iTime*10.0;
    //time=mod(time,100.0);
    //time/=200.0;
    //time=0.0;
    //if (pos.y>ylimit+border) return vec4(0.0);
    //if (pos.y<ylimit2-border) return vec4(0.0);
    
    vec3 uv;
    //if (animate==0.0)
        //uv=pos.xyz*40.0/2.5+vec3(0,0,time);
        uv=pos.xyz*40.0/2.5+vec3(0,-time/1.5,0.0);
    //else
        //uv=pos.xyz*40.0/2.5+vec3(0,0,time/3.0);
    //uv.y*=4.2;
    uv*=3.0*0.9/5.0; //testvalue; //this added specifically for thie effect
    uv*=0.775*1.2;
        float a;
		float f;
        const float m=2.5*1.1;
      /*
		float fbig = fbm( uv/200.0*3.5*3.5*3.5);
        if (fbig<0.45) return vec4(0.0);
      */  
        //vec3 anim;
        //if (animate==0.0) anim=vec3(0.0); else anim=vec3(0.0,0.0,time*2.2*slowdown/2.0); 
        //uv/=2.0;
        ///uv*=0.9;
///f  = 0.5000*fbm( uv ); uv = m*uv; //anim*=1.01;
		f = 0.2500*fbm( uv ); ///uv = m*uv; //anim*=1.01;
        f*=8.0;
//        /*
//#define octaves
#ifdef octaves
        //if (animate==0.0){
        if (lighting!=2){
        uv = m*uv;
		f += 0.1250*fbm( uv ); uv = m*uv; //anim*=1.01;
		    f += 0.0525*fbm( uv ); uv = m*uv; //anim*=1.01; ///0.625
		    f += 0.0425*fbm( uv ); ///0.0325
		    //f += 0.0112*fbm( uv );
        } else {
		    //f += 0.0625*fbm( uv );
        }
#else
		//f += 0.0625*fbm( uv );
#endif        
//        */
        //a=f*fbig;
    
    /*
    float w1 = fbm(uv+vec3(0,time2,time));
    float w2 = fbm(uv*2.0+vec3(0,time2,time)*2.0);
    float w3 = fbm(uv*4.0+vec3(0,time2,time)*4.0)/2.0;
    a=(w1+w2+w3)/2.0/1.2;
    */
///    a=f;
    /*
    if (lighting==0){
        if (pos.y>ylimit) a*=1.0-smoothstep(ylimit,ylimit+border,pos.y);//((pos.y/ylimit))/0.7;
        if (pos.y<ylimit2) a*=1.0-smoothstep(ylimit2,ylimit2-border,pos.y);//(1.0-(pos.y/ylimit2))/0.7;
        a=flevelRange(a,0.25,0.7);
    }
    */
a=f*1.6*0.57*0.9*b;
///a*=1.6*0.57;//1.8;
///a*=b;
    return vec4(a);
    ///return vec4(abs(a));
    ///return vec4(1.0,1.0,1.0,a);
}

vec4 map_cloud2_ref(vec3 pos,int lighting){
return map_cloud2( vec3(pos.x,-pos.y-1.75,pos.z),2);
/*
vec4 res=vec4(0.0);
//if (pos.y<0)
    res=map_cloud2( vec3(pos.x,-pos.y-1.75,pos.z),2);
return res;
*/
}


vec4 map_cloud3(vec3 pos,int lighting){
vec2 b2=cloudshape(pos);
float b=b2.x;
if (b<0.01) return vec4(0.0);
/*
    ylimit=0.6*scale*15.0; //plain clouds
    ylimit2=-0.6*scale*15.0;
*/
    const float slowdown=0.5;
    time=2.0*iTime*2.5*slowdown*1.5;//+5.0*1000.0;
    if (animate==0.0 && twist==0.0) time*=2.0; //plain clouds
    if (twist==1.0) time*=10.0;
    float time2=0.0;//-iTime*10.0;
    //time=mod(time,100.0);
    //time/=200.0;
    //time=0.0;
    vec2 clouduv=vec2(0.0);

    vec3 uv;
    if (animate==0.0)
        uv=(pos.xyz*40.0/2.5+vec3(0,0,time));
    else
        uv=pos.xyz*40.0/2.5+vec3(0,0,time/3.0);

    //uv.y*=4.2;
    //clouduv=uv.xz*testvalue
    /*
    if (testvalue>=1.0)
        clouduv=uv.xz/2000.0/10.0;
    if (testvalue>=1.2)
        clouduv=uv.xy/2000.0/10.0;
    if (testvalue>=1.4)
        clouduv=uv.yz/2000.0/10.0;
        */
        /*
    vec3 cuv=uv; cuv/=2.0;
        float cm=2.5*1.4;
		cuv = cm*cuv; 
		//cuv = cm*cuv; 
		//cuv = cm*cuv; 
    //clouduv=vec2(fbm(cuv*1.05*0.08*0.02*testvalue),fbm(cuv*1.17*0.08*0.02*testvalue));
    clouduv=vec2(fbm(cuv*1.05*0.08*0.02),fbm(cuv*1.17*0.08*0.02));
    clouduv/=12.0;
        */
    /*
    clouduv.x=-clouduv.x;
    clouduv.xy*=34.0;
    clouduv.x-=0.35;
    */

    //if (pos.y>ylimit+border) return vec4(0.0);
    //if (pos.y<ylimit2-border) return vec4(0.0);

		float f,a;
        //mat2 m = mat2( 1.6,  1.2, -1.2,  1.6 );
        float m=2.5*1.4;
		//float fbig = fbmold( uv/200.0*3.5*3.5*3.5*0.25);
        //if (fbig<0.25) return vec4(0.0);
        float fbig=1.0;

        //vec3 anim;
        //if (animate==0.0) anim=vec3(0.0); else anim=vec3(0.0,0.0,time*2.2*slowdown/2.0); 
        uv/=2.0;
		f  = 0.5000*fbm( uv ); uv = m*uv; 
		f *= 0.4+fbm( uv ); uv = m*uv; 
		f -= 0.4*-0.75*fbm( uv*3.5*0.05);
		f += 0.1250*fbm( uv); uv = m*uv; 
#define octaves
#ifdef octaves
        if (animate==0.0){
		    f += 0.0625*fbm( uv ); uv = m*uv; //anim*=1.01;
		    f -= 0.0625*fbm( uv ); uv = m*uv; //anim*=1.01;
		    //f += 0.0112*fbm( uv );
        } else {
		    f += 0.0625*fbm( uv );
        }
#else
		f += 0.0625*fbm( uv );
#endif        
        a=f*fbig;
    
    /*
    float w1 = fbm(uv+vec3(0,time2,time));
    float w2 = fbm(uv*2.0+vec3(0,time2,time)*2.0);
    float w3 = fbm(uv*4.0+vec3(0,time2,time)*4.0)/2.0;
    a=(w1+w2+w3)/2.0/1.2;
    */
    if (lighting==0){
        if (pos.y>ylimit) a*=1.0-smoothstep(ylimit,ylimit+border,pos.y);//((pos.y/ylimit))/0.7;
        if (pos.y<ylimit2) a*=1.0-smoothstep(ylimit2,ylimit2-border,pos.y);//(1.0-(pos.y/ylimit2))/0.7;
        a=flevelRange(a,0.25,0.7);
    }
    
    a*=b;
    
    return vec4(a);
    return vec4(1.0,1.0,1.0,a);
}


vec4 map_cloud(vec3 pos){
    float time=iTime*2.3;
    float time2=iTime*2.1;
    time=mod(time,100.0);
    time2=mod(time,100.0);
    time/=200.0;
    time2/=200.0;
    //time=0.0; time2=100.0;
    
    vec3 uv=pos*48.0;//32.0
    
    vec3 uv2=uv*2.25;
    vec3 uv3=uv*10.0;
    //float dis = worley(uv+iTime*32.0,32.0);
    //float dis = (worley(uv+iTime*32.0,332.0));
    float w1 = (worley3d(uv+time*v3(102.0),332.0));
    vec3 w1_=finalLevels(vec3(w1),32.0/255.0,1.5,240.0/255.0);
    //vec3 dis3=vec3(dis);
    float w2 = (worley3d(uv+time*v3(112.0),232.0));
    vec3 w2_=finalLevels(vec3(w2),32.0/255.0,1.5,240.0/255.0);
    
    ///float p1 = noise_(vec2(uv*2.0+iTime*3.0)).x;
    ///float p1 = noiseValue(vec3(uv/6.0+iTime*3.0,iTime));
    float p1 = fbm(vec3(time2/2.0,uv3/600.0+time*v3(1.0/1.5)));
    vec3 p1_=vec3(p1);
    p1_=finalLevels(p1_,64.0/255.0,1.5,190.0/255.0);
    float p2 = fbm(vec3(time2/2.0,uv3/2000.0+time*v3(1.0/1.5)));
    vec3 p2_=vec3(p2);

    //vec3 result=p2_;
    
    //tiniest detail:
    
    float p3 = fbm(vec3(time2/2.0,uv3/200.0+time*v3(1.0/1.5)));
    vec3 p3_=vec3(p3);
    float w3 = (1.0-(worley3d(uv+time*v3(32.0),134.0)))/1.2;
    vec3 w3_=finalLevels(vec3(w3),62.0/255.0,0.5,230.0/255.0);
    
    float m = 1.0-fbm(vec3(time2/5.5,uv2/300.0+time/10.0));
    vec3 m_=finalLevels(vec3(m),130.0/255.0,1.5,190.0/255.0);

    vec3 fin=w1_*w2_/2.0;
	vec3 result = (((vec3(1.0)-fin)*p1_+p2_/2.0+w3_)*p3_*m_+(1.0-w1_)/16.0);
    result=finalLevels(result,40.0/255.0,1.5,255.0/255.0);
    
	///fragColor = vec4(m_,1.0);

    //vec4 col_res = vec4(vec3(1.0),result.x);
    vec4 col_res = vec4(result.xyz,result.x);
    
    return col_res;
}

const float normaleps=0.005;
vec3 calcNormal( in vec3 pos )
{
    vec3 eps = vec3( normaleps, 0.0, 0.0 );

    vec3 nor = vec3(
        fbm(pos+eps.xyy) - fbm(pos-eps.xyy),
        fbm(pos+eps.yxy) - fbm(pos-eps.yxy),
        fbm(pos+eps.yyx) - fbm(pos-eps.yyx) );
    return normalize(nor);

}

vec2 map(vec3 pos){return cubeshape(pos);}
vec3 cubeshapenormal;
vec3 calcNormal_( in vec3 pos )
{
    /*
    vec2 e = vec2(1.0,-1.0)*0.5773*0.0005;
    return normalize( e.xyy*map( pos + e.xyy ).x +
                      e.yyx*map( pos + e.yyx ).x +
                      e.yxy*map( pos + e.yxy ).x +
                      e.xxx*map( pos + e.xxx ).x );
    */
    vec3 eps = vec3( normaleps, 0.0, 0.0 );
    ///vec3 eps = vec3( 0.0005, 0.0, 0.0 );

    vec3 nor = vec3(
        map(pos+eps.xyy).x - map(pos-eps.xyy).x,
        map(pos+eps.yxy).x - map(pos-eps.yxy).x,
        map(pos+eps.yyx).x - map(pos-eps.yyx).x );
    ///cubeshapenormal=normalize(nor);
    return normalize(nor);

}

// A simple way to bend 2D space
vec2 bend( in vec2 p, in float l, in float a )
{
    if( abs(a)<0.001 ) return p;  // if perfectly straight
    
    float ra = 0.5*l/a;
    p.x -= ra;
    
    vec2 sc = vec2(sin(a),cos(a));
    vec2 q = p - 2.0*sc*max(0.0,dot(sc,p));
    
    float s = sign(a);
    return vec2( (p.y>0.0) ? ra-s*length(q)        : sign(-s*p.x)*(q.x+ra),
                 (p.y>0.0) ? ra*atan(s*p.y,-s*p.x) : (s*p.x<0.0)?p.y:l-p.y );
}


float pack_normal(vec2 n) {
    vec2 s = sign(n);
    return (n.y*s.x - s.y*(n.x + s.x - 2.0)) * 0.25;
}

vec2 unpack_normal(float x) {
    float a = x * 2.0;
    vec2 s;
    s.x = sign(a);
    s.y = sign(1.0 - a*s.x);
    vec2 q;
    q.y = fract(a) - 0.5;
    q.x = sqrt(0.5 - q.y*q.y);
    return q*mat2(s.y,-s.x,s.xy);
}

// returns factors of PI (-1..1) and radius
vec2 pseudopolar(vec2 p) {
	float r = length(p);
    return vec2(pack_normal(p / r), r);
}

vec2 invpseudopolar(vec2 pl) {
    return pl.y*unpack_normal(pl.x);
}

vec3 hue2rgb(float hue) {
    return clamp( 
        abs(mod(hue * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 
        0.0, 1.0);
}

vec3 twister(vec3 p){
    p.x+=0.5*sin(iTime/2.3+p.z/2.7);
    p.y+=0.5*sin(iTime/2.7+p.z/2.5);
    float d=sin(iTime/2.0+p.z/3.0)*3.14*2.0;
    float co = cos(d);
    float si = sin(d);
    p.xy = mat2(co,-si,si,co)*p.xy;
	///vec2 p = (fragCoord.xy / iResolution.xy)*2.0-1.0;	
	///p.x *= iResolution.x/iResolution.y;
	
    vec2 pl = pseudopolar(p.xy);
     
    // compute equivalent normalized (accurate) angle for comparison
    float n=1.2;
    float ra = atan(p.x, p.y) / 3.1415926535898;
    
    float fade=1.0;
    const float fadeangle=1.0/16.0;
    float fra=(ra+1.0)/2.0;
    if (fra<fadeangle) fade=fra/fadeangle;
    else if (fra>1.0-fadeangle) fade=(1.0-fra)/fadeangle;
    
    ///float va = (p.x < 0.0)?pl.x:ra;
    float va = ra;
    
    // logarithmic scaling of radius for zoom effect
    /*
    float rs = log(pl.y);
    vec2 uv = vec2(
       abs(mod(va * 3.0 + rs * 1.0,2.0) - 1.0), 
		abs(mod(rs - iTime * 0.5, 2.0) - 1.0));
    */
    
    float rs = log(pl.y);
    return vec3(va,rs,fade);
    vec2 uv = vec2(
       abs(mod(va * 1.0 + rs * 0.25,2.0) ), 
		abs(mod(rs - time/8.0 * 0.5, 2.0) - 1.0));

    return vec3(uv.x,uv.y,fade);
    
    vec3 color = texture(iChannel0, uv).rgb * min(abs(p.x)*64.0, 1.0);
    // uncomment to see error margin
    //color = vec3(abs(pl.x - ra) * 1000.0, 0.0, 0.0);
    // uncomment for hue spiral
    //color = hue2rgb(pl.x + pl.y*2.0);
    //vec2 unq = invpseudopolar(pl);
    //color = vec3(abs(p - unq)*10000.0, 0.0);
    //color = vec3(unq*0.5+0.5, 0.0);
    //color = hue2rgb(pl.x * 4.0) * (pl.x * 0.5 + 0.5);
    
	///fragColor = vec4(color, 1.0);
}

vec2 iBox( in vec3 ro, in vec3 rd, in vec3 rad ) 
{
    vec3 m = 1.0/rd;
    vec3 n = m*ro;
    vec3 k = abs(m)*rad;
    vec3 t1 = -n - k;
    vec3 t2 = -n + k;
	return vec2( max( max( t1.x, t1.y ), t1.z ),
	             min( min( t2.x, t2.y ), t2.z ) );
}

vec2 map_bkgnd(in vec3 pos){
   vec2 res;
    res = vec2( sdBox(    pos-vec3(0.0,-0.25-1.75/2.0, 0.0), vec3(15,0.25,15)), 1.0 );
    return res;
}
vec2 raycast_bkgnd( in vec3 ro, in vec3 rd )
{
    vec2 res = vec2(-1.0,-1.0);

    float tmin = 1.0;
    float tmax = 20.0;

    
    // raymarch primitives   
    //vec2 tb = iBox( ro-vec3(0.0,0.4,-0.5), rd, vec3(2.5,0.41,3.0) );
    vec2 tb = iBox( ro-vec3(0.0,0.0,0.0), rd, vec3(1000.0,1000.0,1000.0) );
    //if( tb.x<tb.y && tb.y>0.0 && tb.x<tmax)
    {
        //tmin = max(tb.x,tmin);
        //tmax = min(tb.y,tmax);

        float t = tmin;
        for( int i=0; i<int(70.0*0.6) && t<tmax*0.6; i++ )
        {
            vec2 h = map_bkgnd( ro+rd*t );
            if( abs(h.x)<(0.0001*t) )
            { 
                res = vec2(t,h.y);
                break;
            }
            //t += h.x;
            t += h.x;
        }
    }
    
    return res;
}

float calcAO( in vec3 pos, in vec3 nor )
{
    return 1.0;
const int ZERO=0;
	float occ = 0.0;
    float sca = 1.0;
    for( int i=ZERO; i<5; i++ )
    {
        float h = 0.01 + 0.12*float(i)/4.0;
        float d = map_bkgnd( pos + h*nor ).x;
        occ += (h-d)*sca;
        sca *= 0.95;
        if( occ>0.35 ) break;
    }
    return clamp( 1.0 - 3.0*occ, 0.0, 1.0 ) * (0.5+0.5*nor.y);
}

vec4 renderbkgnd( in vec3 ro, in vec3 rd, in vec2 fragCoord)
{ 
///return vec3(0.0);

vec4 col_bkgnd;
vec4 col;
    vec3 pos;

        //vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal( pos );
        vec3 nor = vec3(0.0,1.0,0.0);

        vec3 ref = reflect( rd, nor );

    vec2 res = raycast_bkgnd(ro,rd);
    float t = res.x;
	float m = res.y;
        pos = ro + t*rd;
        //pos+=pos_cloud/4.0;
#ifdef LIGHTING
        pos+=nor/4.0;
#endif
        //vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal( pos );
        //vec3 ref = reflect( rd, nor );
        
        // material
        nor+=texture(iChannel3,pos.xz/2.0/1.24/skeyl).xyz;
        //nor=normalize(nor);
        col_bkgnd=texture(iChannel0,pos.xz/2.0/1.24/skeyl).rgba;
        //col_bkgnd=texture2D(iChannel0,pos.xz/2.0).rgb;



        //if (m<1.5) col=col_bkgnd.rgb; 
        col=col_bkgnd.rgba; 


        //else// col=vec3(cloud_a,0,0);
        //col=mix(col_bkgnd,vec3(1.0),cloud_a);
        //col=mix(col_bkgnd,col2,cloud_a);

        // lighting

        float occ = 1.0; // *testvalue; // calcAO( pos, nor );
        occ = calcAO( pos, nor );
        
		vec3 lin = vec3(0.0);
        float dim=1.1;
        dim/=1.2;

        float ks = 1.0;

        // sun
        {
            vec3  lig = normalize( vec3(-0.5, 0.4*1.46, -0.6) );
            vec3  hal = normalize( lig-rd );
            float dif = clamp( dot( nor, lig ), 0.0, 1.0 );
                  dif /= dim;
          //if( dif>0.0001 )
              //float h=smoothstep(-1.0,1.0,h_);

        	      //dif *= smoothstep(0.3,1.0,calcSoftshadow( pos, lig, 0.02, 2.5 ));
			float spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0);
                  spe *= dif;
                  spe *= 0.04;//+0.96*pow(clamp(1.0-dot(hal,lig),0.0,1.0),5.0);
                  spe /= dim;
            lin += col.rgb*2.20*dif*vec3(1.30,1.00,1.70);
            lin +=     5.00*spe*vec3(1.30,1.00,1.70)*ks;
        }
        // sky
        {
            float dif = sqrt(clamp( 0.5+0.5*nor.y, 0.0, 1.0 ));
                  dif *= occ;
                  dif /= dim;
            float spe = smoothstep( -0.2, 0.2, ref.y );
                  spe *= dif;
                  spe *= 0.04;//+0.96*pow(clamp(1.0+dot(nor,rd),0.0,1.0), 5.0 );
                  spe /= dim;
          //if( spe>0.001 )
                  //spe *= smoothstep(0.3,1.0,calcSoftshadow( pos, ref, 0.02, 2.5 ));
            lin += col.rgb*0.60*dif*vec3(0.40,0.60,1.15);
            lin +=     2.00*spe*vec3(0.40,0.60,1.30)*ks;
        }
        // back
        {
        	float dif = clamp( dot( nor, normalize(vec3(0.5,0.0,0.6))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0);
                  dif *= occ;
        	lin += col.rgb*0.55*dif*vec3(0.25,0.25,0.25);
        }
        // sss
        {
            float dif = pow(clamp(1.0+dot(nor,rd),0.0,1.0),2.0);
                  dif *= occ;
        	lin += col.rgb*0.25*dif*vec3(1.00,1.00,1.00);
        }
     
		//col = lin;
#ifdef LIGHTING
        col=vec4(mix(col_bkgnd.rgb,lin,-dot(normalize(nor),normalize(rd-ro))),col_bkgnd.a);
#endif
        //if (m==1.0) col=lin; else
        //col=mix(col,lin,smoothstep(0.0,0.4,dot(normalize(nor),normalize(rd-ro))/4.0)); //dot is 0 when angle is 90
        //col=mix(col_bkgnd,col_bkgnd+col*5.0,smoothstep(0.0,0.5,-dot(normalize(nor),normalize(rd-ro))/4.0)); //dot is 0 when angle is 90
        //col=mix(col,col_bkgnd+col*5.0,smoothstep(0.0,0.5,dot(normalize(nor),normalize(rd-ro))/4.0)); //dot is 0 when angle is 90
        //col=smoothstep(0.1,0.4,col_bkgnd+col*1.5);

        //col = mix( col, vec3(0.7,0.7,0.9), 1.0-exp( -0.0001*t*t*t ) );

//col=vec3(h,0,0);//test
    col.a=1.0;
	return vec4( clamp(col,0.0,1.0) );
}

vec4 renderbkgnd2( in vec3 ro, in vec3 rd, in vec2 fragCoord)
{ 
///return vec3(0.0);

//vec4 col_bkgnd;
vec4 col;
    vec3 pos;

        //vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal( pos );
        //vec3 nor = vec3(0.0,1.0,0.0);
        ///vec3 ref = reflect( rd, nor );

    vec2 res = raycast_bkgnd(ro,rd);
    float t = res.x;
	//float m = res.y;
        pos = ro + t*rd;
        //pos+=pos_cloud/4.0;
#ifdef LIGHTING
        ///pos+=nor/4.0;
#endif
        //vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal( pos );
        //vec3 ref = reflect( rd, nor );
        
        // material
        col=texture(iChannel2,pos.xz/2.0/1.24/skeyl).rgba;
        //col_bkgnd=texture2D(iChannel0,pos.xz/2.0).rgb;

	return col;
}

















vec2 castRay( in vec3 ro, in vec3 rd )
{
float steps_;
    steps_=60/1.33; //e logo twist
    //steps_=45; //bouncer
    //steps_=60; //ddc gray
    vec2 res = vec2(-1.0,-1.0);

    ///float tmin = 1.0;
    ///float tmin = 0.0000001;
    ///float tmax = 20.0;

    /// raytrace floor plane
    /*
    float tp1 = (0.0-ro.y)/rd.y;
    if( tp1>0.0 )
    {
        tmax = min( tmax, tp1 );
        res = vec2( tp1, 1.0 );
    }
    */
    ///else return res;

    // raymarch primitives
    ///vec2 tb = iBox( ro-vec3(0.5,0.4,-0.5), rd, vec3(2.0,0.41,3.0) );
    ///if( tb.x<tb.y && tb.y>0.0 && tb.x<tmax)
    {
        ///tmin = max(tb.x,tmin);
        ///tmax = min(tb.y,tmax);
        float tmin = 0.0000001;//+(1.71-1.0);
        float t = tmin;
        ///for( int i=0; i<70 /*&& t<tmax*/; i++ )
        for( int i=0; i<steps_ /*&& t<tmax*/; i++ )
        {
            vec2 h = cubeshape( ro+rd*t );
            ///if( abs(h.x)<(0.0001*t) )
            float precision_= 0.001+(1.5-1.0)/1000.0;
            if( abs(h.x)<(precision_*t) )
            {
                res = vec2(t,h.y);
                cubeshapenormal=calcNormal_(ro+rd*t);
                break;
            }
            t += h.x*0.85;
        }
    }

    return res;
}














vec4 render( in vec3 ro, in vec3 rd, in vec2 fragCoord){

    vec2 rendercube=castRay(ro,rd); 
    vec4 col_=vec4(0.0);
    if (rendercube.y==2071.0) {
        vec3 e=rd;
        vec3 n=cubeshapenormal;

        vec3 r = reflect(e,n);
        float m = 2.1 * sqrt( pow( r.x, 2. ) + pow( r.y, 2. ) + pow( r.z, 2. ) );
        vec2 vN = r.xy / m + .5;
        //vec2 vN = r.xy/2.1+0.5;
        //vN.y*=-1.0;

        vec3 base = texture2D( colorMap, vN ).rgb;
        base += texture( envMap, r ).rgb;
        col_ += vec4( base, 1. );
    }

  return col_;

/*
vec4 col;
    vec2 rendercube=castRay(ro,rd); 
    if (rendercube.y==2071.0) {
        vec3 nor=cubeshapenormal;
        float diff=clamp(dot(nor,normalize(vec3(1.5,2.0,-0.5))),0.0,1.0)+0.33;
        col+=vec4(vec3(1.0,0.5,0.05)*diff,1.0);
    }
    return col;
    */
}



mat3 setCamera( in vec3 ro, in vec3 ta, float cr )
{
	vec3 cw = normalize(ta-ro);
	vec3 cp = upvector;//vec3(sin(cr), cos(cr),0.0);
	vec3 cu = normalize( cross(cw,cp) );
	vec3 cv =          ( cross(cu,cw) );
    return mat3( cu, cv, cw );
}

mat3 setCamera2( in vec3 ro, in vec3 ta, float cr )
{
    vec3 cw = normalize(ta-ro);
    vec3 cp = upvector;
    vec3 cu = normalize( cross(cw,cp) );
    vec3 cv = normalize( cross(cu,cw) );
    return mat3( cu, cv, cw );
}



vec2 iMouse=vec2(0.0);

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec3 pos;
    vec2 mo = iMouse.xy/iResolution.xy;
	float time = 32.0 + iTime*1.5*2.5/1.33;

    // camera	
    //vec3 ta = vec3( 0.5, -0.5, -0.6 );
    vec3 ta = vec3( 0.0, -0.5, -0.0 );
    vec3 ro = ta + vec3( 1.0*cos(0.1*time + 7.0*mo.x), 1.3 + 2.0*mo.y - 0.1, 1.0*sin(0.1*time + 7.0*mo.x) );
    ro*=1.25; //1.37
    // camera-to-world transformation
    mat3 ca = setCamera( ro, ta, 0.0 );

    vec2 uv = fragCoord.xy/iResolution.xy;
	vec2 p = uv-1.0;
	p.x*=(iResolution.x/iResolution.y);
    vec3 rd = ca * normalize( vec3(p.x,p.y,fov ) );

    vec4 col;

//if (actionselector==2)
//     col = vec4(renderbkgnd( ro, rd, fragCoord).rgb,1.0);
//else
     col = render( ro, rd, fragCoord);

    fragColor = col;
}

vec3 rotateAxis(vec3 p, vec3 axis, float angle) {
return mix(dot(axis, p)*axis, p, cos(angle)) + cross(axis,p)*sin(angle);
}

void mainImage_c3( out vec4 fragColor, in vec2 fragCoord, in vec2 fragCoord2 ) /// from crawl.frag
{
    vec2 iResolution = vec2(1920,1080);

    //vec2 fragCoord=gl_FragCoord;
    vec2 uv = fragCoord/iResolution.xy;
	vec2 p = uv*2.0-1.0;
	p.x*=(iResolution.x/iResolution.y);
	//vec4 col = vec4(0.05);

    vec3 ro = vec3(0.0,0.0,-1.0);
    vec3 rd = normalize(vec3(p,0.0)-ro);

    vec3 rp = ro;
    

    //const float fl = 2.5; 
    ro=rayorigin;
    vec3 ta=raydirection;
    
    mat3 ca = setCamera2( ro, ta, 0.0 );
    
    float fov_=fov;
    rd = ca * normalize( vec3(p.x,p.y,fov_ ) );


vec4 col;
//if (actionselector==2)
//     col = renderbkgnd( ro, rd, fragCoord);
//else
     col = render( ro, rd, fragCoord);

    fragColor = col;
}

void mainImage_c( out vec4 fragColor, in vec2 fragCoord ) /// from crawl.frag
{
//float yoff=1.75/2.0/200.0;
const float yoff=0.0;

    vec2 mo = iMouse.xy/iResolution.xy;
	float time = 32.0 + iTime*1.5*2.5/1.33;

    // camera	
    //vec3 ta = vec3( 0.5, -0.5, -0.6 );
    vec3 ta = vec3( 0.0, -0.5-yoff, -0.0 );
    vec3 ro = ta + vec3( 1.0*cos(0.1*time + 7.0*mo.x), 1.3 + 2.0*mo.y-yoff, 1.0*sin(0.1*time + 7.0*mo.x) );
    // camera-to-world transformation
    mat3 ca = setCamera( ro, ta, 0.0 );

    vec2 uv = fragCoord.xy/iResolution.xy;
	vec2 p = uv-1.0;
	p.x*=(iResolution.x/iResolution.y);

            //ro=rayorigin;// /vec3(20.0);
            //ta=raydirection;// /vec3(20.0);
            ca = setCamera( ro, ta, 0.0 );
            vec3 rd = ca * normalize( vec3(p.x,p.y,fov ) );

vec4 col;
if (actionselector==2)
     col = renderbkgnd( ro, rd, fragCoord);
else
     col = render( ro, rd, fragCoord);

    fragColor = col;
}

void mainImage_c2( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 mo = iMouse.xy/iResolution.xy;
    float time = 15.0 + iTime;


    vec2 p = (-iResolution.xy + 2.0*fragCoord)/iResolution.y;

            // camera
            vec3 ro = vec3( -0.5+3.5*cos(0.1*time + 6.0*mo.x), 3.0 + 2.0*mo.y, 0.5 + 4.0*sin(0.1*time + 6.0*mo.x) );
            vec3 ta = vec3( -0.5, -0.4, 0.5 );

//dm installed camera control:
            //ro=rayorigin;// /vec3(20.0);
            //ta=raydirection;// /vec3(20.0);
            
            //fully working camera based fish eye distortion effect
            //vec3 cameran=normalize(rotateAxis(normalize(ta-ro), normalize(upvector), PI/2.0));
            //ta+=cameran.xyz*fishdx*10.0;
            const float st=10.0; //strength
            if (leftside){
                vec3 cameran=normalize(rotateAxis(normalize(ta-ro), normalize(upvector), PI/2.0));
                //vec3 cameran=normalize(rotateAxis(normalize(ta-ro), vec3(0,1,0), PI/2.0));
                ta+=cameran.xyz*fishdx*st;
                ro+=cameran.xyz*fishdx*st;
            } else {
                vec3 cameran=normalize(rotateAxis(normalize(ta-ro), normalize(upvector), -PI/2.0));
                //vec3 cameran=normalize(rotateAxis(normalize(ta-ro), vec3(0,1,0), -PI/2.0));
                ta+=cameran.xyz*fishdx*st;
                ro+=cameran.xyz*fishdx*st;
            }


            ro = vec3( -0.5+3.5*cos(0.1*time + 6.0*mo.x), 3.0 + 2.0*mo.y, 0.5 + 4.0*sin(0.1*time + 6.0*mo.x) );
            ta = vec3( -0.5, -0.4, 0.5 );

            ///naive approach that works for default cam position:
            //ta.x+=fishdx*5.0*3.0;

            // camera-to-world transformation
            mat3 ca = setCamera( ro, ta, 0.0 );
            //mat3 ca = mat3cam;


            // ray direction
            //vec3 rd = ca * normalize( vec3(p.x,p.y+1.0,2.0) );
    //vec3 rd = ca * normalize( vec3(p.x,p.y,2.0) );
      vec3 rd = ca * normalize( vec3(p.x,p.y,fov ) );


            //vec4 rd1= ca * vec4(normalize( vec3(p.xy,2.0) ),1.0);
            //vec3 rd = vec3(rd1.xyz);

            // render
vec4 col;
if (actionselector==2)
     col = renderbkgnd( ro, rd, fragCoord);
else
     col = render( ro, rd, fragCoord);

    fragColor = col;
}

const float pioffset=1.0;

void main()
{
    vec2 iResolution = vec2(1920,1080);

    vec2 fragCoord=gl_FragCoord;
    vec2 uv = fragCoord/iResolution.xy;
	vec2 p = uv*2.0-1.0;
	p.x*=(iResolution.x/iResolution.y);
	vec4 col = vec4(0.0);

    vec3 ro = vec3(0.0,0.0,-1.0);
    vec3 rd = normalize(vec3(p,0.0)-ro);

    vec3 rp = ro;

    //const float fl = 2.5; 
    ro=rayorigin;
    vec3 ta=raydirection;
    
    
    mat3 ca = setCamera2( ro, ta, 0.0 );
    

    float fov_=fov;
    rd = ca * normalize( vec3(p.x,p.y,fov_ ) );


    
    col=render(ro,rd,fragCoord);
    //float powf=0.75;
    //col.r=pow(col.r,powf);
    //col.g=pow(col.g,powf);
    //col.b=pow(col.b,powf);
    
    if (actionselector==1) col=vec4(0.0);
	
    gl_FragColor = col;
    
}