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

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

uniform float fisheyefactor;

#define LIGHTING
#define noisetexturea noisetexture2
uniform sampler2D noisetexture2;
uniform sampler2D floorNormalMap;
//uniform sampler2D terraincolor;
//uniform sampler2D waternormal;
//uniform samplerCube env;

#define iChannel0 noisetexture2
#define iChannel2 noisetexture2

uniform float iTime;
#define iChannel0 noisetexture2
#define iChannel1 noisetexture2
#define iChannel2 noisetexture2
#define iChannel3 noisetexture2
//uniform int actionselector; // 1 = cloud,  2 = background
int actionselector=2;
uniform float testvalue;

float skeyl=1.2*1.6;

//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 vec3 rayorigin;
uniform vec3 raydirection;
//uniform vec3 upvector;
vec3 upvector=vec3(0.0,1.0,0.0);

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 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;
}

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_=h;
    h_=clamp((-d2.x-d1.x)/k, -1.0, 1.0 );
    //h_+=1.0; h_/=2.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 cloudshape(vec3 pos){
const float scale=4.25;
   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,4.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 );
/*
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(2.0+4.0*sin(sx/2.0),0.0,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.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);
res = opSs(res,res2,1.5);    

return h_;
}







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 );
}

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));
}

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

vec4 map_cloud2(vec3 pos,int lighting){
//float b=cloudshape(pos);        
//    return vec4(b);

float b=cloudshape(pos);
//if (b<0.01) 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,0,time/6.5);
    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
    
        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*=4.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){
float b=cloudshape(pos);
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);

}

// 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;
   float scale=100.0;//testvalue;
    res = vec2( sdBox_(    pos-vec3(0.0,-0.25-1.75/2.0, 0.0), vec3(15*scale,0.25,15*scale)), 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) );
    //float scale=testvalue;
    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<70*0.6 && t<tmax*0.6*4.0; i++ )
        {
            vec2 h = map_bkgnd_( ro+rd*t );
            if( abs(h.x)<(0.0001*t/0.21) )
            { 
                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+=texture2D(iChannel3,pos.xz/2.0/1.24/skeyl).xyz;
        //nor=normalize(nor);
        col_bkgnd=texture2D(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);
        const float dim=1.1;

        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=texture2D(iChannel2,pos.xz/2.0/1.24/skeyl).rgba;
        //col_bkgnd=texture2D(iChannel0,pos.xz/2.0).rgb;

	return col;
}

vec4 render_( in vec3 ro, in vec3 rd, in vec2 fragCoord){
vec4 col_bkgnd;
vec3 ro2=ro,rd2=rd;
{
vec4 col=vec4(0.0);
vec4 col2=vec4(0.0); //reflection
///float tfade=1.0;
    //--------------------------------------
    // raymarch
    //--------------------------------------
    vec4 sum = vec4( 0.0 );
    vec4 sum1 = vec4( 0.0 );
    vec4 sum2 = vec4( 0.0 );
    // dithering
    //float t = 0.1*(texture(iChannel0, fragCoord.xy/1024.0).r);
    float t = 0.1;
    //float t = 0.1*(texture2D(noisetexture2, fragCoord.xy/1024.0).r)/4.0;
    //float t=0.01;
    
    vec3 pos;
    float lighting;
    for( int i=0; i<1800; i++ )
    {
        if( sum.a > 1.05 ) break;
        pos = ro + t*rd;
        
    
        col = map_cloud2( pos.xyz, 1 );// /1.2;
        ///col2 = map_cloud2_ref( pos.xyz, 1 );

        float a=col.a;
        //float a2=col2.a; ///if (a2>0.3) a2=1.0;
        //float a2=col2.a;//*colbkg.a;
        //if (pos.y>ylimit) {a1=1.0-smoothstep(ylimit,ylimit+border,pos.y); a*=a1;}
        //else if (pos.y<ylimit2) {a1=1.0-smoothstep(ylimit2,ylimit2-border,pos.y); a*=a1;}
///float mapa = a;
a=flevelRange(a,0.25,0.7);
//a2=flevelRange(a2,0.25,0.7);
        col=vec4(a); ///col/=1.2;
        //col2=vec4(a2); ///col2/=1.2;

        //const vec3 sundir = normalize( vec3(1.5,2.0,-1.0) );
        //float mapasun=map_cloud2(pos+sundir,1).a*a1;
        const float dim=1.85;

        if (col.a<0.15 ) {
            lighting=0.0; 
        }
        else {
            lighting=0.01;
        }
            col.a*=0.05;
            //col2.a*=0.05;
            col.rgb = col.rgb/40.0/dim;
            if (lighting!=0.0)
                col.rgb+=vec3(0.1,0.1,0.1)*(lighting)*12.0;
            //col2.rgb /= (40.0/dim/7.0*25.0/3.3);
            //col2.a /= (4.0*7.0*0.64);//*testvalue;
            sum1 = sum1 + col*(1.0 - sum1.a);
            //if (col2.a>0) 
            //{
              //  col = col + col2*(1.0 - col.a);
              //  sum2 = sum2 + col2*(1.0 - sum2.a);
            //}
            ///col2.rgb/=7.0;


        sum = sum + col*(1.0 - sum.a);
        t += 0.002;
    }

    t = 0.1;
    for( int i=0; i<1800*0.85; i++ )
    {
        if( sum2.a > 1.05 ) break;
        pos = ro + t*rd;
        
    
        ///col2 = map_cloud2( pos.xyz, 1 );// /1.2;
        col2 = map_cloud2_ref( pos.xyz, 1 );

        float a2=col2.a;
        //float a2=col2.a; ///if (a2>0.3) a2=1.0;
        //float a2=col2.a;//*colbkg.a;
        //if (pos.y>ylimit) {a1=1.0-smoothstep(ylimit,ylimit+border,pos.y); a*=a1;}
        //else if (pos.y<ylimit2) {a1=1.0-smoothstep(ylimit2,ylimit2-border,pos.y); a*=a1;}
///float mapa = a;
a2=flevelRange(a2,0.25,0.7);
//a2=flevelRange(a2,0.25,0.7);
        col2=vec4(a2); ///col/=1.2;
        //col2=vec4(a2); ///col2/=1.2;

        //const vec3 sundir = normalize( vec3(1.5,2.0,-1.0) );
        //float mapasun=map_cloud2(pos+sundir,1).a*a1;
        const float dim=1.85;

        if (col2.a<0.15 ) {
            lighting=0.0; 
        }
        else {
            lighting=0.01;
        }
            col2.a*=0.05;
            //col2.a*=0.05;
            col2.rgb = col2.rgb/40.0/dim;
            if (lighting!=0.0)
                col2.rgb+=vec3(0.1,0.1,0.1)*(lighting)*12.0;
            //col2.rgb /= (40.0/dim/7.0*25.0/3.3);
            //col2.a /= (4.0*7.0*0.64);//*testvalue;
            //sum2 = sum2 + col2*(1.0 - sum2.a);
            //if (col2.a>0) 
            //{
              //  col = col + col2*(1.0 - col.a);
              //  sum2 = sum2 + col2*(1.0 - sum2.a);
            //}
            ///col2.rgb/=7.0;


        sum2 = sum2 + col2*(1.0 - sum2.a);
        t += 0.002;
    }

    if (sum2.a>0.0){
        vec4 colbkgmask;
        colbkgmask = renderbkgnd2(ro2, rd2, fragCoord);
        sum2.rgb *= colbkgmask.r/2.0; // /2.1
        sum2.r += 0.35;
        sum2.a *= colbkgmask.r; // /2.1
    }

    vec3 cloudcol2 = mix(vec3(80.0/255.0,105.0/255.0,209.0/255.0)/0.85/1.89,
    vec3(100.0/255.0,105.0/255.0,200.0/255.0)*2.4,(sum2.r-0.2)/1.75/1.5);
    sum2.a*=1.0/1.1;

    //sum+=sum2*(1.0-sum.a);
    
    //vec3 bg = mix(vec3(90.0/255.0,120.0/255.0,191.0/255.0),
    //vec3(120.0/255.0,130.0/255.0,230.0/255.0)*1.6/1.4*1.1,clamp(-pos.y,0.0,1.0));
    //vec3 bg=col_bkgnd;

    vec3 cloudcol = mix(vec3(80.0/255.0,105.0/255.0,209.0/255.0)/0.85/1.89,
    vec3(100.0/255.0,105.0/255.0,200.0/255.0)*2.4,(sum.r-0.2)/1.75/1.5);
    sum.a*=1.0/1.1;

    col=vec4(cloudcol,1.0)*sum.a;
    col.a=sum.a;
    
    col+=vec4(cloudcol2,sum2.a)*(1.0-col.a);
    //col.a*=2.0;

    //float border=0.3/0.4;
    //if (sum2.a>0.0 && sum1.a<=border){
        //float correction=sum1.a/border;
        //vec4 colbkgmask;
        //colbkgmask = renderbkgnd2(ro, rd, fragCoord);
        //col.r += 0.125*(1.0-correction);
        //col.a *= colbkgmask.r/2.2*(1.0-correction);
    //}

    //col=sum+vec4(bg,1.0)*(1.0-sum.a);
    //col=texture(iChannel1,vec2(1.0-sum.a,0.0))*sum.a+vec4(bg,1.0)*(1.0-sum.a);

    //col=vec4(cloudcol,1.0)*sum.a+vec4(bg,1.0)*(1.0-sum.a);

    //col=sum+vec4(1.2,0.9,0.3,1.0)*lsum*sum.a;
    //vec3 col = clamp( mix( bg, sum.xyz/(0.001+sum.w), sum.w ), 0.0, 1.0 );
    //col=col*vec4(smoothstep(0.1,0.7,sum.x));
    return col;
}
}


mat3 setCamera( in vec3 ro, in vec3 ta, float cr )
{
	vec3 cw = normalize(ta-ro);
	vec3 cp = vec3(sin(cr), cos(cr),0.0);
	vec3 cu = normalize( cross(cw,cp) );
	vec3 cv =          ( 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);
     col = vec4(render_( ro, rd, fragCoord).rgb,1.0);
else
     col = render_( ro, rd, fragCoord);

    fragColor = col;
}

























































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 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); 
}

//===============================================================================================
//===============================================================================================
//===============================================================================================
//===============================================================================================
//===============================================================================================

// 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.

// A list of useful distance function to simple primitives. All
// these functions (except for ellipsoid) return an exact
// euclidean distance, meaning they produce a better SDF than
// what you'd get if you were constructing them from boolean
// operations.

// List of other 3D SDFs: https://www.shadertoy.com/playlist/43cXRl
//
// and http://iquilezles.org/www/articles/distfunctions/distfunctions.htm


//#define AA 1
//#else
//#define AA 2   // make this 2 or 3 for antialiasing
//#endif

//------------------------------------------------------------------
float dot2( in vec2 v ) { return dot(v,v); }
float dot2( in vec3 v ) { return dot(v,v); }
float ndot( in vec2 a, in vec2 b ) { return a.x*b.x - a.y*b.y; }

float sdPlane( vec3 p )
{
	return p.y;
}

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

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 sdBoundingBox( vec3 p, vec3 b, float e )
{
       p = abs(p  )-b;
  vec3 q = abs(p+e)-e;

  return min(min(
      length(max(vec3(p.x,q.y,q.z),0.0))+min(max(p.x,max(q.y,q.z)),0.0),
      length(max(vec3(q.x,p.y,q.z),0.0))+min(max(q.x,max(p.y,q.z)),0.0)),
      length(max(vec3(q.x,q.y,p.z),0.0))+min(max(q.x,max(q.y,p.z)),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;
}

float sdTorus( vec3 p, vec2 t )
{
    return length( vec2(length(p.xz)-t.x,p.y) )-t.y;
}

float sdCappedTorus(in vec3 p, in vec2 sc, in float ra, in float rb)
{
    p.x = abs(p.x);
    float k = (sc.y*p.x>sc.x*p.y) ? dot(p.xy,sc) : length(p.xy);
    return sqrt( dot(p,p) + ra*ra - 2.0*ra*k ) - rb;
}

float sdHexPrism( vec3 p, vec2 h )
{
    vec3 q = abs(p);

    const vec3 k = vec3(-0.8660254, 0.5, 0.57735);
    p = abs(p);
    p.xy -= 2.0*min(dot(k.xy, p.xy), 0.0)*k.xy;
    vec2 d = vec2(
       length(p.xy - vec2(clamp(p.x, -k.z*h.x, k.z*h.x), h.x))*sign(p.y - h.x),
       p.z-h.y );
    return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}

float sdOctogonPrism( in vec3 p, in float r, float h )
{
  const vec3 k = vec3(-0.9238795325,   // sqrt(2+sqrt(2))/2 
                       0.3826834323,   // sqrt(2-sqrt(2))/2
                       0.4142135623 ); // sqrt(2)-1 
  // reflections
  p = abs(p);
  p.xy -= 2.0*min(dot(vec2( k.x,k.y),p.xy),0.0)*vec2( k.x,k.y);
  p.xy -= 2.0*min(dot(vec2(-k.x,k.y),p.xy),0.0)*vec2(-k.x,k.y);
  // polygon side
  p.xy -= vec2(clamp(p.x, -k.z*r, k.z*r), r);
  vec2 d = vec2( length(p.xy)*sign(p.y), p.z-h );
  return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}

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;
}

float sdRoundCone( in vec3 p, in float r1, float r2, float h )
{
    vec2 q = vec2( length(p.xz), p.y );
    
    float b = (r1-r2)/h;
    float a = sqrt(1.0-b*b);
    float k = dot(q,vec2(-b,a));
    
    if( k < 0.0 ) return length(q) - r1;
    if( k > a*h ) return length(q-vec2(0.0,h)) - r2;
        
    return dot(q, vec2(a,b) ) - r1;
}

float sdRoundCone(vec3 p, vec3 a, vec3 b, float r1, float r2)
{
    // sampling independent computations (only depend on shape)
    vec3  ba = b - a;
    float l2 = dot(ba,ba);
    float rr = r1 - r2;
    float a2 = l2 - rr*rr;
    float il2 = 1.0/l2;
    
    // sampling dependant computations
    vec3 pa = p - a;
    float y = dot(pa,ba);
    float z = y - l2;
    float x2 = dot2( pa*l2 - ba*y );
    float y2 = y*y*l2;
    float z2 = z*z*l2;

    // single square root!
    float k = sign(rr)*rr*rr*x2;
    if( sign(z)*a2*z2 > k ) return  sqrt(x2 + z2)        *il2 - r2;
    if( sign(y)*a2*y2 < k ) return  sqrt(x2 + y2)        *il2 - r1;
                            return (sqrt(x2*a2*il2)+y*rr)*il2 - r1;
}

float sdTriPrism( vec3 p, vec2 h )
{
    const float k = sqrt(3.0);
    h.x *= 0.5*k;
    p.xy /= h.x;
    p.x = abs(p.x) - 1.0;
    p.y = p.y + 1.0/k;
    if( p.x+k*p.y>0.0 ) p.xy=vec2(p.x-k*p.y,-k*p.x-p.y)/2.0;
    p.x -= clamp( p.x, -2.0, 0.0 );
    float d1 = length(p.xy)*sign(-p.y)*h.x;
    float d2 = abs(p.z)-h.y;
    return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.);
}

// vertical
float sdCylinder( vec3 p, vec2 h )
{
    vec2 d = abs(vec2(length(p.xz),p.y)) - h;
    return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}

// arbitrary orientation
float sdCylinder(vec3 p, vec3 a, vec3 b, float r)
{
    vec3 pa = p - a;
    vec3 ba = b - a;
    float baba = dot(ba,ba);
    float paba = dot(pa,ba);

    float x = length(pa*baba-ba*paba) - r*baba;
    float y = abs(paba-baba*0.5)-baba*0.5;
    float x2 = x*x;
    float y2 = y*y*baba;
    float d = (max(x,y)<0.0)?-min(x2,y2):(((x>0.0)?x2:0.0)+((y>0.0)?y2:0.0));
    return sign(d)*sqrt(abs(d))/baba;
}

// vertical
float sdCone( in vec3 p, in vec2 c, float h )
{
    vec2 q = h*vec2(c.x,-c.y)/c.y;
    vec2 w = vec2( length(p.xz), p.y );
    
	vec2 a = w - q*clamp( dot(w,q)/dot(q,q), 0.0, 1.0 );
    vec2 b = w - q*vec2( clamp( w.x/q.x, 0.0, 1.0 ), 1.0 );
    float k = sign( q.y );
    float d = min(dot( a, a ),dot(b, b));
    float s = max( k*(w.x*q.y-w.y*q.x),k*(w.y-q.y)  );
	return sqrt(d)*sign(s);
}


float sdCappedCone(vec3 p, vec3 a, vec3 b, float ra, float rb)
{
    float rba  = rb-ra;
    float baba = dot(b-a,b-a);
    float papa = dot(p-a,p-a);
    float paba = dot(p-a,b-a)/baba;

    float x = sqrt( papa - paba*paba*baba );

    float cax = max(0.0,x-((paba<0.5)?ra:rb));
    float cay = abs(paba-0.5)-0.5;

    float k = rba*rba + baba;
    float f = clamp( (rba*(x-ra)+paba*baba)/k, 0.0, 1.0 );

    float cbx = x-ra - f*rba;
    float cby = paba - f;
    
    float s = (cbx < 0.0 && cay < 0.0) ? -1.0 : 1.0;
    
    return s*sqrt( min(cax*cax + cay*cay*baba,
                       cbx*cbx + cby*cby*baba) );
}

// c is the sin/cos of the desired cone angle
float sdSolidAngle(vec3 pos, vec2 c, float ra)
{
    vec2 p = vec2( length(pos.xz), pos.y );
    float l = length(p) - ra;
	float m = length(p - c*clamp(dot(p,c),0.0,ra) );
    return max(l,m*sign(c.y*p.x-c.x*p.y));
}

float sdOctahedron(vec3 p, float s)
{
    p = abs(p);
    float m = p.x + p.y + p.z - s;

    // exact distance
    #if 0
    vec3 o = min(3.0*p - m, 0.0);
    o = max(6.0*p - m*2.0 - o*3.0 + (o.x+o.y+o.z), 0.0);
    return length(p - s*o/(o.x+o.y+o.z));
    #endif
    
    // exact distance
    #if 1
 	vec3 q;
         if( 3.0*p.x < m ) q = p.xyz;
    else if( 3.0*p.y < m ) q = p.yzx;
    else if( 3.0*p.z < m ) q = p.zxy;
    else return m*0.57735027;
    float k = clamp(0.5*(q.z-q.y+s),0.0,s); 
    return length(vec3(q.x,q.y-s+k,q.z-k)); 
    #endif
    
    // bound, not exact
    #if 0
	return m*0.57735027;
    #endif
}

float sdPyramid( in vec3 p, in float h )
{
    float m2 = h*h + 0.25;
    
    // symmetry
    p.xz = abs(p.xz);
    p.xz = (p.z>p.x) ? p.zx : p.xz;
    p.xz -= 0.5;
	
    // project into face plane (2D)
    vec3 q = vec3( p.z, h*p.y - 0.5*p.x, h*p.x + 0.5*p.y);
   
    float s = max(-q.x,0.0);
    float t = clamp( (q.y-0.5*p.z)/(m2+0.25), 0.0, 1.0 );
    
    float a = m2*(q.x+s)*(q.x+s) + q.y*q.y;
	float b = m2*(q.x+0.5*t)*(q.x+0.5*t) + (q.y-m2*t)*(q.y-m2*t);
    
    float d2 = min(q.y,-q.x*m2-q.y*0.5) > 0.0 ? 0.0 : min(a,b);
    
    // recover 3D and scale, and add sign
    return sqrt( (d2+q.z*q.z)/m2 ) * sign(max(q.z,-p.y));;
}

// la,lb=semi axis, h=height, ra=corner
float sdRhombus(vec3 p, float la, float lb, float h, float ra)
{
    p = abs(p);
    vec2 b = vec2(la,lb);
    float f = clamp( (ndot(b,b-2.0*p.xz))/dot(b,b), -1.0, 1.0 );
	vec2 q = vec2(length(p.xz-0.5*b*vec2(1.0-f,1.0+f))*sign(p.x*b.y+p.z*b.x-b.x*b.y)-ra, p.y-h);
    return min(max(q.x,q.y),0.0) + length(max(q,0.0));
}

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

vec2 opU( vec2 d1, vec2 d2 )
{
	return (d1.x<d2.x) ? d1 : d2;
}

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

#define ZERO 0

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


vec2 map_bkgnd(in vec3 pos){
    vec2 res;
    //res = vec2( sdBox(    pos-vec3(0.0,-0.25, 0.0), vec3(5,0.25,5)), 1.0 );
    //res = vec2( sdBox(    pos-vec3(0.0,-0.25, 0.0), vec3(100.0,0.25,100.0)), 1.0 );
    //res = vec2( sdBox(    pos-vec3(0.0,-0.25, 0.0), vec3(150.0,0.25,150.0)), 1.0 );
    res = vec2( sdBox(    pos-vec3(0.0,-0.25-1.75/2.0, 0.0), vec3(15,0.25,15)), 1.0 );
    return res;
}

float h_factor=0.7;
float r_factor=1.1;
vec2 map( in vec3 pos )
{
    vec2 res;
    //vec2 res = vec2( 1e10, 0.0 );

    {
      //res = opU( res, vec2( sdSphere(    pos-vec3(-2.0,0.25, 0.0), 0.25 ), 26.9 ) );
      //float r = noise(pos/1.5*4.0)*2.5;
      
vec3 q = 1.5*pos;
float m=1.1;
float f = 0.75000*noise( q );
//if (layer>totallayers-2)
{
q = m*q*3.01;
f += 0.1500*noise( q ); 
q = m*q*2.52;
f += 0.0350*noise( q ); 
//q = m*q*2.03;
//f += 0.0625*noise( q ); 
//q = m*q*2.01;
}
r_factor=0.35;
h_factor=1.0;
      //float r = 0.4+noise(pos/1.5*12.0)*1.35;
      float r = 0.1+f*2.35;
      float r2=r_factor/6.0+f*2.55*1.15;
      //res = opU( res, vec2( sdEllipsoid(    pos-vec3(0.0,0.25, 0.0), vec3(0.25,0.15,0.25 )*r), 26.9 ) );
      res = vec2( sdEllipsoid(    pos-vec3(0.0,0.25+0.02, 0.0), vec3(0.25,0.15,0.45 )*r2), 26.9 );
      res = opUsc(res,vec2( sdEllipsoid(    pos-vec3(0.75,0.25+0.02, 0.0), vec3(0.45,0.15,0.25 )*r2), 26.9 ),0.75);
      //res = opUsc( res, vec2( sdEllipsoid(    pos-vec3(0.0,0.25, 0.0), vec3(0.25,0.15,0.45 )*(r_factor+0.3)),26.9 ),h_factor ); //tweak last number to get onion layers
      //res = vec2( sdEllipsoid(    pos-vec3(0.0,0.25, 0.0), vec3(0.25,0.15,0.25 )*r*(1.0-h_)), 26.9 );
      
    }
    return res;
}

// http://iquilezles.org/www/articles/boxfunctions/boxfunctions.htm
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 ) );
}

float cloud_a=0.0;
vec2 res_bkgnd=vec2(0.0);
vec3 pos_bkgnd;
vec3 ro_bkgnd;
vec3 rd_bkgnd;

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<70 && t<tmax; 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;
}

vec2 raycast( in vec3 ro, in vec3 rd )
{
    vec2 res = vec2(-1.0,-1.0);

    float tmin = 1.0;
    float tmax = 20.0;

    // raytrace floor plane
    float tp1 = (0.0-ro.y)/rd.y;
    if( tp1>0.0 )
    {
        tmax = min( tmax, tp1 );
        res_bkgnd=res = vec2( tp1, 1.0 );
        pos_bkgnd=ro+rd;
        ro_bkgnd=ro;
        rd_bkgnd=rd;
    }
    //else return res;
    
    // raymarch primitives   
    vec2 tb = iBox( ro-vec3(0.0,0.4,-0.5), rd, vec3(2.5,0.41,3.0) );
    if( tb.x<tb.y && tb.y>0.0 && tb.x<tmax)
    {
        //return vec2(tb.x,2.0);
        tmin = max(tb.x,tmin);
        tmax = min(tb.y,tmax);

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

// http://iquilezles.org/www/articles/rmshadows/rmshadows.htm
float calcSoftshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax )
{
    // bounding volume
    float tp = (0.8-ro.y)/rd.y; if( tp>0.0 ) tmax = min( tmax, tp );

    float res = 1.0;
    float t = mint;
    for( int i=ZERO; i<24; i++ )
    {
		float h = map( ro + rd*t ).x;
        float s = clamp(8.0*h/t,0.0,1.0);
        res = min( res, s*s*(3.0-2.0*s) );
        t += clamp( h, 0.02, 0.2 );
        if( res<0.004 || t>tmax ) break;
    }
    return clamp( res, 0.0, 1.0 );
}

// http://iquilezles.org/www/articles/normalsSDF/normalsSDF.htm
vec3 calcNormal( in vec3 pos )
{
#if 0
    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 );
#else
    // inspired by tdhooper and klems - a way to prevent the compiler from inlining map() 4 times
    vec3 n = vec3(0.0);
    for( int i=ZERO; i<4; i++ )
    {
        vec3 e = 0.5773*(2.0*vec3((((i+3)>>1)&1),((i>>1)&1),(i&1))-1.0);
        n += e*map(pos+0.0005*e).x;
      //if( n.x+n.y+n.z>100.0 ) break;
    }
    return normalize(n);
#endif    
}

float calcAO( in vec3 pos, in vec3 nor )
{
	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( 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);
}

// http://iquilezles.org/www/articles/checkerfiltering/checkerfiltering.htm
float checkersGradBox( in vec2 p, in vec2 dpdx, in vec2 dpdy )
{
    // filter kernel
    vec2 w = abs(dpdx)+abs(dpdy) + 0.001;
    // analytical integral (box filter)
    vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w;
    // xor pattern
    return 0.5 - 0.5*i.x*i.y;                  
}

int layer;
//const int totallayers=4;
const int totallayers=1;

vec3 render( in vec3 ro, in vec3 rd, in vec2 fragCoord)
{ 
    vec3 pos;
    
    // background
    vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3;
    
    // raycast scene
    vec3 col2=vec3(0.0); 
    float a=0.0;
    int layers=0;
    cloud_a=0.0;

    for (layer=0;layer<totallayers;layer++){
        r_factor=1.1+float(layer)*0.2;
        h_factor=0.1+float(layer)*0.1;
        vec2 res = raycast(ro,rd);
        float t = res.x;
        pos = ro + t*rd;
        if (res.y==26.9)
        {
            layers++;
            vec3 q = 10.0*pos;
            float f  = 0.5000*noise( q +vec3(layer*10)); //q = m*q*2.01;
            //f += 0.2500*noise( q ); q = m*q*2.02;
            //f += 0.1250*noise( q ); q = m*q*2.03;
            //f += 0.0625*noise( q ); q = m*q*2.01;

            f = smoothstep( -0.3, 2.0, f );
            col = vec3(f*1.2)*5.0;
            //col = vec3(1.2);
            col2+=col;
            cloud_a+=(float(totallayers-layer)*(1.0/float(totallayers)))*(f*mix(35.0,1.0,float(layer)/float(totallayers)))*1.4;
        }
    }
    col2/=float(layers);
    cloud_a/=500.0;//float(layers);

    h_factor=0.6;
    r_factor=1.5;
    vec2 temp=map(pos);
    float h=smoothstep(-1.0,1.0,h_);
    //h=0.5-h;
    h*=4.0; //use this value as alpha
    
    r_factor=1.1;
    cloud_a*=h;
    cloud_a*=2.3;
    
    
    vec3 pos_cloud=vec3(0.0);
    vec2 res = raycast(ro,rd);
    float t = res.x;
	float m = res.y;
    if( m>-0.5 )
    {
        vec3 pos = ro + t*rd;
        pos_cloud=pos;
        vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal( pos );
        vec3 ref = reflect( rd, nor );
        
        // material        
        col = 0.2 + 0.2*sin( m*2.0 + vec3(0.0,1.0,2.0) );
        float ks = 1.0;
        
        
        
        
col=col2;
vec3 col_bkgnd;//=vec3(0.0);        
        
    {
    vec2 res = raycast_bkgnd_(ro,rd);
    float t = res.x;
	float m = res.y;
        vec3 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
        if (m<1.5) nor+=texture2D(floorNormalMap,pos.xz/2.0/skeyl).xyz;

        col_bkgnd=texture2D(iChannel0,pos.xz/2.0/skeyl).xyz;
        }



        if (m<1.5) col=col_bkgnd; 
        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;
        occ = calcAO( pos, nor );
        //occ+=0.2;
        if (m<1.5) {
                //occ+=testvalue; //floor
            
            //float boostlow = 16.0-testvalue; ///increase to darken image
            //float boosthigh = 219.0; /// decrease to brighten image
            //#define const_1 (boostlow / 255.0)
            //#define const_2 (255.0 / boosthigh)
            //occ = ((occ - const_1) * const_2);
            occ+=((1.0-occ)*0.4*1.5);
            //occ=
        }
        else
            occ=1.0;
        
		vec3 lin = vec3(0.0);
        float dim=1.1;
        if (!(m<1.5)) dim*=1.375; // blob be darker than floor
        else dim/=1.05;
        dim/=1.2;
        // sun
        {
            vec3  lig = normalize( vec3(-0.5, 0.4*1.46*1.12, -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*0.05);
                  spe *= dif;
                  spe *= 0.04+0.96*pow(clamp(1.0-dot(hal,lig),0.0,1.0),5.0)+0.02;
                  spe /= dim;
            lin += col*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/1.25;
            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*0.60*dif*vec3(0.50,0.55,1.20);
            lin +=     2.00*spe*vec3(0.50,0.55,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*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*0.25*dif*vec3(1.00,1.00,1.00);
        }
        float testvalue2=0.85*1.13*1.21;
        if (m>=1.5) {
            testvalue2*=0.6;
            lin/=1.6;
            lin.b*=1.4;
        }
        lin.x=pow(lin.x,testvalue2);
        lin.y=pow(lin.y,testvalue2);
        lin.z=pow(lin.z,testvalue2);
        lin=clamp(lin,0.08,1.0);
		//col = lin;
#ifdef LIGHTING
        //col=mix(col_bkgnd,lin,-dot(normalize(nor),normalize(rd-ro)));
        col=mix(col_bkgnd,lin,1.4);
#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
	return vec3( clamp(col,0.0,1.0) );
}































































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
{
//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) )*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);
    

            //ro=rayorigin;// /vec3(20.0);
            //ta=raydirection;// /vec3(20.0);

//-----------------------------------------------
    ///p = (-iResolution.xy + 2.0*fragCoord)/iResolution.y;
    p = (-iResolution2.xy + 2.0*fragCoord2)/iResolution2.y;
    if (actionselector==1) p = (-iResolution.xy + fragCoord)/iResolution.y;

            float st=10.0*0.29*0.71; //strength
            //if (false)
            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*=testvalue;
            ca = setCamera( ro, ta, 0.0 );
            vec3 rd = ca * normalize( vec3(p.x,p.y,fov ) );

//====================================================
//rd = normalize( vec3( p,-1.0+0.5*length( p ) ) );
//====================================================
//if (actionselector==2) p=fragCoord.xy/iResolution.xy; else p=fragCoord.xy/(iResolution.xy/2.0);
//p=fragCoord.xy;
vec2 p2 = p*0.5;
//rd = ca*normalize( vec3( p2,-1.0*(-1.0+0.5*length( p2 ))) ); //punched out look
//rd = ca*normalize( vec3( p2,-1.0*(-1.0-0.5*length( p2 ))) ); //pinched in look
vec3 rd2 = ca*normalize( vec3( p2,-1.0*(-1.0+0.5*length( p2 ))) ); //punched out look
rd=mix(rd,rd2,fisheyefactor);
//====================================================


vec4 col;
if (actionselector==2)
     //col = renderbkgnd( ro, rd, fragCoord);
     col = vec4(render( ro, rd, fragCoord),1.0);
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()
{
    vec4 color=vec4(0.0, 0.0, 0.0, 1.0);
    vec2 coos;//=gl_FragCoord.xy*2.0;


    if (actionselector==2){
        coos=gl_FragCoord.xy*2.0;
        iResolution = vec2(1920.0,1080.0); //background
    } else {
        coos=gl_FragCoord.xy*2.0;
        iResolution = vec2(1920.0/4,1080.0/4); //cloud
    }
    //float xc=coos.x/iResolution.x;
    //float dim=0.9;
    float xc=coos.x/iResolution.x;
    float yc=coos.y/iResolution.y;

    vec2 coos2=gl_FragCoord.xy;
    float xc2=coos2.x/iResolution.x;
    float yc2=coos2.y/iResolution.y;














    //vec2 coos=gl_FragCoord.xy;
    //float xc=coos.x/iResolution.x;
    //float yc=coos.y/iResolution.y;
    float dim=0.9*2.0;
    if (xc2<0.40) { //0,0.5
        fishdx=sin(xc2*PI*pioffset+PI/2); //1,0
        fishdx=mix(fishdx/dim,0,xc2*(1.0/0.40));
        leftside=true;
    } else if (xc2>0.60){
        xc2-=0.5;
        xc2=0.5-xc2; //0.5,0
        //fishdx=sin(xc*PI+PI/2+pioffset); //0,1
        fishdx=sin(xc2*PI*pioffset+PI/2); //1,0
        fishdx=mix(fishdx/dim,0,xc2*(1.0/0.40));
        leftside=false;
    } else { 
        fishdx=0;
    }
    if (yc2>0.5) {
        yc2=1.0-yc2;
        yc2=0.5-yc2; 
        yc2=yc2*2.0; yc2*=-1;
    } else {
        yc2=0.5-yc2; 
        yc2=yc2*2.0;
    }
    // 0 -- 0.5 -- 0
    // 1 -- 0 -- -1
    fishdx*=yc2;















    mainImage_c3(color,coos,coos2);

    //color.a/=testvalue;

    gl_FragColor = color;
}
// 1920/4=480
// 1080/4=270
