uniform sampler2D tDiffuse;
uniform float iTime;
uniform vec2 iResolution;
varying vec2 sv;
highp float;
//common Math region #########################################################
#define pi acos(-1.)
float remap01(float value, float minimum, float maximum)
{
return (value - minimum)/(maximum - minimum);
}
vec2 remap01(vec2 value, vec2 minimum, vec2 maximum)
{
return (value - minimum)/(maximum - minimum);
}
float atan2(in float y, in float x)
{
float s = ceil(sign(abs(x) - abs(y)));
return mix(pi/2.0 - atan(x,y), atan(y,x), s);
}
float atan3(in float y, in float x)
{
return pi-pi/2.*(1.+sign(x))* (1.-sign(y*y))-pi/4.*(2.+sign(x))*sign(y)-sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)));
}
vec2 rot2d(vec2 pos, float theta)
{
float c = cos(theta);
float s = sin(theta);
mat2 m = mat2(c,-s,s,c);
return m * pos;
}
//retruns the distance of a ray to point if the ray is starting in ro
float DistanceFromPoinToLine0(vec3 ray, vec3 ro, vec3 point)
{
//https://www.qc.edu.hk/math/Advanced%20Level/Point_to_line.htm 2. method
float d = length(cross(point - ro, ray))/length(ray);
return d;
}
//retruns the distance of a ray to point if the ray is starting in ro
float DistanceFromPoinToLine(vec3 ray, vec3 ro, vec3 point)
{
//https://www.qc.edu.hk/math/Advanced%20Level/Point_to_line.htm 2. method
float d = length(cross(point - ro, ray))/length(ray);
return mix(200.0, d, step(0.0, dot(point - ro, ray)));
}
float hash00(float p)
{
p = fract(p * .1031);
p *= p + 33.33;
p *= p + p;
return fract(p);
}
float hash0(vec3 p)
{
float a = dot(p,vec3(127.1,311.7, 74.7));
return -1.0 + 2.0 * fract(sin(a)*43758.5453123);
}
vec3 hash( vec3 p ) // replace this by something better
{
p = vec3( dot(p,vec3(127.1,311.7, 74.7)),
dot(p,vec3(269.5,183.3,246.1)),
dot(p,vec3(113.5,271.9,124.6)));
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec3 p )
{
vec3 i = floor( p );
vec3 f = fract( p );
vec3 u = f*f*(3.0-2.0*f);
return mix( mix( mix( dot( hash( i + vec3(0.0,0.0,0.0) ), f - vec3(0.0,0.0,0.0) ),
dot( hash( i + vec3(1.0,0.0,0.0) ), f - vec3(1.0,0.0,0.0) ), u.x),
mix( dot( hash( i + vec3(0.0,1.0,0.0) ), f - vec3(0.0,1.0,0.0) ),
dot( hash( i + vec3(1.0,1.0,0.0) ), f - vec3(1.0,1.0,0.0) ), u.x), u.y),
mix( mix( dot( hash( i + vec3(0.0,0.0,1.0) ), f - vec3(0.0,0.0,1.0) ),
dot( hash( i + vec3(1.0,0.0,1.0) ), f - vec3(1.0,0.0,1.0) ), u.x),
mix( dot( hash( i + vec3(0.0,1.0,1.0) ), f - vec3(0.0,1.0,1.0) ),
dot( hash( i + vec3(1.0,1.0,1.0) ), f - vec3(1.0,1.0,1.0) ), u.x), u.y), u.z );
}
vec3 opTwist(in vec3 p)
{
float k = 0.65; // or some other amount
k *= sin(p.y);
float c = cos(k*p.y);
float s = sin(k*p.y);
mat2 m = mat2(c,-s,s,c);
vec3 q = vec3(m*p.xz,p.y);
return q;
}
float opSmoothUnion(float d1, float d2, float k)
{
float h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 );
return mix( d2, d1, h ) - k*h*(1.0-h);
}
float opSmoothSubtraction(float d1, float d2, float k)
{
float h = clamp( 0.5 - 0.5*(d2+d1)/k, 0.0, 1.0 );
return mix( d2, -d1, h ) + k*h*(1.0-h);
}
//end of common Math region ##################################################
float sdSphere( vec3 p, float s )
{
return length(p)-s;
}
float sdTorus( vec3 p, vec2 t )
{
vec2 q = vec2(length(p.xz)-t.x,p.y);
return length(q)-t.y;
}
float sdRoundedCylinder( vec3 p, float ra, float rb, float h )
{
vec2 d = vec2( length(p.xz)-2.0*ra+rb, abs(p.y) - h );
return min(max(d.x,d.y),0.0) + length(max(d,0.0)) - rb;
}
#define PlanetCenter vec3(0.0, 0.0, 0.0)
#define PlanetRad 2.0
#define RingRad vec2(0.9 + PlanetRad, 0.05)
float map( in vec3 pos, out float id)
{
pos = pos - PlanetCenter;
float planet = sdSphere( pos, PlanetRad);
vec2 ringRadIterative = RingRad;
float ringHoles = sdTorus(pos, vec2(2.5, 0.5));
ringHoles = min(ringHoles, sdTorus(pos, vec2(3.5, 0.09)));
ringHoles = min(ringHoles, sdTorus(pos, vec2(3.8, 0.07)));
ringHoles = min(ringHoles, sdTorus(pos, vec2(4.7, 0.04)));
float ring = sdRoundedCylinder(pos, 2.5, 0.004, 0.00005);
ring = opSmoothSubtraction(ringHoles, ring, 0.02);
float dist = min(planet, ring);
id = step(planet - ring, 0.0);
return min(planet, ring);
}
float map( in vec3 pos)
{
float id;
return map(pos, id);
}
#define MAX_STEPS 200; //Dosnt work, rewrite manualy
#define SURFACE_DIST 0.001;
#define MAX_DIST 50.0;
#define MIN_DIST 0.00;
float castRay( in vec3 ro, in vec3 rd, out float id)
{
vec2 res = vec2(-1.0,-1.0);
float tmin = MIN_DIST;
float tmax = MAX_DIST;
float surfDistMin = SURFACE_DIST;
float t = tmin;
for( int i=0; i<150; i++ )
{
float h = map( ro+rd*t, id);
if( abs(h)tmax ) t=-1.0;
return t;
}
vec3 calcNormal( in vec3 pos)
{
vec2 e = vec2(0.0005,0.0);
return normalize( vec3(
map( pos + e.xyy) - map( pos - e.xyy),
map( pos + e.yxy) - map( pos - e.yxy),
map( pos + e.yyx) - map( pos - e.yyx) ) );
}
vec2 getSphericCoord(vec3 pos)
{
vec3 nor = calcNormal(pos);
float lon = atan(nor.x,nor.z)/pi;
float lat = acos(nor.y)/pi;
vec2 r = vec2(lat, lon);
return r;
}
//Texturing region $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
float fbm(vec3 x, float H, vec3 layers)
{
float G = exp2(-H);
float f = 1.2;
float a = 0.5;
float t = 0.05;
for( int i=0; i<6; i++ )
{
t += a*noise(f*x + layers);
f *= 2.0;
a *= G;
}
return t;
}
float paternAtmosphere(vec3 p, float H)
{
vec3 layers = vec3(0.16 * iTime, 0.0, 0.0);
vec3 a = vec3( 0.0, 0.0, 0.0);
vec3 b = vec3( 5.2, 1.3, 1.1);
vec3 c = vec3(-1.7, 9.2, 3.2);
vec3 d = vec3( 3.7, -1.1, 0.0);
vec3 e = vec3( 8.2, 1.6, -1.9);
vec3 f = vec3(-1.7, 6.2, -3.2);
vec3 q = vec3(fbm(p + a, H, layers),
fbm(p + b, H, layers),
fbm(p + c, H, layers) );
vec3 r = vec3(fbm(p + 4.0 * q + d, H, layers),
fbm(p + 4.0 * q + e, H, layers),
fbm(p + 4.0 * q + f, H, layers) );
return fbm(p + 4.0*r, H, layers);
}
vec3 paternAtmosphere(vec3 p, vec3 col1, vec3 col2)
{
float grad = paternAtmosphere(opTwist(p), 1.1);
return mix(col1, col2, grad);
}
// Traditional gradient noise
float gnoise( in float p )
{
float i = floor(p);
float f = fract(p);
float u = f*f*(3.0-2.0*f);
float g0 = hash00(i + 0.0 * u);
float g1 = hash00(i + 1.0 * u);
return mix( g0*(f-0.0), g1*(1.0-f), u);
}
float fbm( in float x)
{
float n = 0.0;
float s = 1.0;
for( int i=0; i<9; i++ )
{
n += s*gnoise(x);
s *= 0.5;
x *= 2.0;
x += 0.131;
}
return n;
}
vec3 paternRing(float dist, vec3 col1, vec3 col2)
{
return mix(col1, col2, fbm(8.5 * dist));
}
//End Texturing region $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
float getLight(vec3 pos, vec3 lightPos, float intensity)
{
vec3 lightDir = normalize(lightPos - pos);
vec3 normal = calcNormal(pos);
float nDotL = dot(normal, lightDir);
float botomClamp = 0.01;
float diffuseLight = intensity * clamp(nDotL, botomClamp , 1.);
float surfDistMin = SURFACE_DIST;
//shadows
//raymarch to light pos if hit its shadow
float id;
float distToHit = castRay(pos + normal * surfDistMin, lightDir, id);
//if distToHit less then lightPos - pos then dif *= 0.1;
float isShadow = step(distToHit, length(lightPos - pos)) * step(0.0, nDotL);
diffuseLight = mix(diffuseLight, intensity * botomClamp, isShadow);
return diffuseLight;
}
float GetFlare0(vec3 ro, vec3 rd, vec3 lightPos, float dist, float flareAmp, float fallOff)
{
return mix(0.0, flareAmp/pow(DistanceFromPoinToLine0(rd, ro, lightPos), fallOff), step(length(lightPos - ro), dist));
}
float GetFlare(vec3 ro, vec3 rd, vec3 lightPos, float dist, float flareAmp, float fallOff)
{
return mix(0.0, flareAmp/pow(DistanceFromPoinToLine(rd, ro, lightPos), fallOff), step(length(lightPos - ro), dist));
}
vec3 stars(vec3 ro, vec3 rd, float dist) {
float r = 20.0;
float random0 = 0.1578;
vec3 starsCol = vec3(0.0, 0.0, 0.0);
for(float i=0.; i<200.; i++ )
{
// random0 = hash00(i);
// float random1 = hash00(random0);
// float random2 = hash00(random0 * 2.342);
// float random3 = hash00(random0 * 3.687);
random0 = hash00(i);
float random1 = hash00(i);
float random2 = hash00(i * 2.342);
float random3 = hash00(i * 3.687);
float theta = 0.8 + random1 * 0.5 * pi;
float phi = random2 * 2.0 * pi;
vec3 lightPos = vec3(r * sin(theta) * cos(phi),
r * sin(theta) * sin(phi),
r * cos(theta));
vec3 lightCol = vec3(1.0) - 0.5 * vec3(random1, 0.0, random3);
starsCol += lightCol * GetFlare(ro, rd, lightPos, dist, 0.00001 + 0.0002 * random2, 2.5);
}
return starsCol;
}
//Returns the RayDirection for a pixel given the ray origin, the look at vector and a zoom factor.
vec3 cameraRayDirection(vec2 uv, vec3 rayOrigin, vec3 lookAt, float zoom)
{
vec3 forwardDir = normalize(lookAt - rayOrigin);
vec3 rightDir = normalize(cross(normalize(vec3(0.2, 1, 0)), forwardDir));
vec3 upDir = cross(forwardDir, rightDir);
vec3 centerOfScreen = rayOrigin + forwardDir * zoom;
vec3 intersectionOfScreen = centerOfScreen + uv.x * rightDir + uv.y * upDir;
return intersectionOfScreen - rayOrigin;
}
vec3 orbitCamera(float radius, float baseFreq)
{
float time = iTime * baseFreq;
vec3 pos = vec3(sin(time), 0.8 * cos(0.5 * time), cos(time));
//pos = vec3(pos.x, rot2d(pos.yz, -40.));
return radius * normalize(pos);
}
vec3 render(vec2 uv, float time)
{
vec3 rayOrigin = orbitCamera(10.0, 0.3); //vec3(0.0, 10.0, 0.0);
vec3 lookAt = PlanetCenter;
vec3 lightPos = vec3(+20.0, 3.2, -10.0);
vec3 lightCol = vec3(0.7, 1.0, 1.0);
vec3 rayDirection = cameraRayDirection(uv, rayOrigin, lookAt, 1.);
float id = 0.0;
float dist = castRay(rayOrigin, rayDirection, id);
vec3 pos = rayOrigin + rayDirection * dist;
vec3 posSphereOS = pos - PlanetCenter;
float flare = GetFlare(rayOrigin, rayDirection, lightPos, dist, 0.09, 2.8);
vec3 planetCol = vec3(paternAtmosphere(posSphereOS, vec3(0.6, 0.25, 0.25), vec3(0.8, 0.65, 0.8)));
vec3 ringCol = paternRing(length(posSphereOS.xz), vec3(0.05, 0.05, 0.05), vec3(0.95, 0.75, 0.8));
vec3 albedo = planetCol * id + step(id, 0.5) * ringCol;
albedo = clamp(albedo, 0.0, 1.0);
//sphericPosCol = vec3(noise(posSphereOS));
//vec3 normal = calcNormal(pos);
float light = getLight(pos, 4.0 * lightPos, 3.2);
float maxDist = MAX_DIST - 1.0;
//dist negative for to far fields
vec3 background = vec3(0, 0, 0) + flare * lightCol + stars(rayOrigin, rayDirection, dist);
vec3 finalCol = mix(albedo * light * lightCol, background, step(maxDist - dist, 0.));
return finalCol;//vec3(length(pos * 0.2));
}
void main()
{
// Normalized pixel coordinates (from 0 to 1)
vec2 uv = (sv - 0.5) * iResolution.xy / iResolution.y;
// Time varying pixel color
vec3 col = render(uv, iTime);
//col = vec3(gnoise(length(uv)));
//Gama correction
col = pow( col, vec3(0.4545));
// Output to screen
gl_FragColor = vec4(col ,1.0);
}