Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
rvGRaV
/*
start of fragment shader playground in THREEjs
work with https://www.shadertoy.com/ and http://glslsandbox.com/
fragments shader ... isint finished at moment.
ES6
*/
Object.defineProperty( window,'log',{ set: p => console.log(p) , get: ()=>'log = ...'} )
var camera, scene, renderer
var uniforms, material, mesh
const VERTEXSHADER_2D = 'void main(){ gl_Position = vec4( position, 1.0 ); }'
window.onload = function()
{
console.clear()
new ThreeShader( )
}
class ThreeShader
{
constructor( holder )
{
holder = holder || document.body
scene = new THREE.Scene()
renderer = new THREE.WebGLRenderer()
camera = new THREE.Camera()
holder.appendChild( renderer.domElement )
this.start = +new Date()
this.shaderSetup()
}
shaderSetup()
{
const VEC2 = 'v2'
const FLOAT = 'f'
//
uniforms = {
iGlobalTime: { type: FLOAT , value: 1.0 },
time: { type: FLOAT , value: 1.0 },
iResolution: { type: VEC2 , value: new THREE.Vector2() },
resolution: { type: VEC2 , value: new THREE.Vector2() },
iMouse: { type: VEC2 , value: new THREE.Vector2() },
mouse: { type: VEC2 , value: new THREE.Vector2() }
}
// this.geometry = new THREE.PlaneBufferGeometry( 1,1 )
material = new THREE.ShaderMaterial({
uniforms: uniforms,
// attributes: { vertexOpacity: { value: [] } },
vertexShader: VERTEXSHADER_2D ,
fragmentShader: this.galaxy
})
mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry ( 2 , 2 ) , material )
scene.add( mesh )
window.addEventListener( 'resize' , this.onResize.bind(this) , false )
this.onResize()
this.onRender()
}
onRender()
{
const SPEED = .1
requestAnimationFrame( this.onRender.bind( this ) )
uniforms.time.value = uniforms.iGlobalTime.value = ( new Date() - this.start ) * 0.001 * SPEED
renderer.render( scene , camera )
}
onResize()
{
let width = window.innerWidth
let height = window.innerHeight
uniforms.resolution.value.x = uniforms.iResolution.value.x = width
uniforms.resolution.value.y = uniforms.iResolution.value.y = height
renderer.setSize( width , height )
}
shaderToyFragment( fragment ){
return `
uniform float iGlobalTime;
uniform vec2 iResolution;
uniform vec2 iMouse;
${fragment}
void main(void) {
//uv is between 0 and 1
vec2 uv = gl_FragCoord.xy / iResolution.xy;
vec2 delta = 1.0 / iResolution.xy;
mainImage(gl_FragColor,gl_FragCoord.xy);
}
`
}
get minFragment()
{
return `
uniform float iGlobalTime;
uniform vec2 iResolution;
void main() {
float x = mod(iGlobalTime + gl_FragCoord.x, 20.) < 10. ? 1. : 0.;
float y = mod(iGlobalTime + gl_FragCoord.y, 20.) < 10. ? 1. : 0.;
gl_FragColor = vec4(vec3(min(x, y)), 1.);
}
`}
get vertexShader()
{
let vertex = `
uniform float iGlobalTime;
uniform vec2 iResolution;
void main() {
gl_Position = vec4( position, 1.0 );
}
`
return vertex
}
get simpleFshader()
{
let fragment = `
uniform float iGlobalTime;
uniform vec2 iResolution;
float field(in vec3 p) {
float strength = 7. + .03 * log(1.e-6 + fract(sin(iGlobalTime) * 4373.11));
float accum = 0.;
float prev = 0.;
float tw = 0.;
for (int i = 0; i < 32; ++i) {
float mag = dot(p, p);
p = abs(p) / mag + vec3(-.5, -.4, -1.5);
float w = exp(-float(i) / 7.);
accum += w * exp(-strength * pow(abs(mag - prev), 2.3));
tw += w;
prev = mag;
}
return max(0., 5. * accum / tw - .7);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
vec2 uv = 2. * fragCoord.xy / iResolution.xy - 1.;
vec2 uvs = uv * iResolution.xy / max(iResolution.x, iResolution.y);
vec3 p = vec3(uvs / 4., 0) + vec3(1., -1.3, 0.);
p += .2 * vec3(sin(iGlobalTime / 16.), sin(iGlobalTime / 12.), sin(iGlobalTime / 128.));
float t = field(p);
float v = (1. - exp((abs(uv.x) - 1.) * 6.)) * (1. - exp((abs(uv.y) - 1.) * 6.));
fragColor = mix(.4, 1., v) * vec4(1.8 * t * t * t, 1.4 * t * t, t, 1.0);
}
void main(void) {
//uv is between 0 and 1
vec2 uv = gl_FragCoord.xy / iResolution.xy;
vec2 delta = 1.0 / iResolution.xy;
// gl_FragColor = vec4(sin(iGlobalTime), uv.x, uv.y ,1.0);
mainImage(gl_FragColor,gl_FragCoord.xy);
}
`
return fragment
}
get galaxyCloud()
{
let fragment = `
//CBS
//Parallax scrolling fractal galaxy.
//Inspired by JoshP's Simplicity shader: https://www.shadertoy.com/view/lslGWr
// http://www.fractalforums.com/new-theories-and-research/very-simple-formula-for-fractal-patterns/
float field(in vec3 p,float s) {
float strength = 7. + .03 * log(1.e-6 + fract(sin(iGlobalTime) * 4373.11));
float accum = s/4.;
float prev = 0.;
float tw = 0.;
for (int i = 0; i < 26; ++i) {
float mag = dot(p, p);
p = abs(p) / mag + vec3(-.5, -.4, -1.5);
float w = exp(-float(i) / 7.);
accum += w * exp(-strength * pow(abs(mag - prev), 2.2));
tw += w;
prev = mag;
}
return max(0., 5. * accum / tw - .7);
}
// Less iterations for second layer
float field2(in vec3 p, float s) {
float strength = 5. + .03 * log(1.e-6 + fract(sin(iGlobalTime) * 4373.11));
//float strength = 7. + .03 * log(1.e-6 + fract(sin(iGlobalTime) * 4373.11));
float accum = s/4.;
float prev = 0.;
float tw = 0.;
for (int i = 0; i < 18; ++i) {
float mag = dot(p, p);
p = abs(p) / mag + vec3(-.5, -.4, -1.5);
float w = exp(-float(i) / 7.);
accum += w * exp(-strength * pow(abs(mag - prev), 2.2));
tw += w;
prev = mag;
}
return max(0., 5. * accum / tw - .7);
}
vec3 nrand3( vec2 co )
{
vec3 a = fract( cos( co.x*8.3e-3 + co.y )*vec3(1.3e5, 4.7e5, 2.9e5) );
vec3 b = fract( sin( co.x*0.3e-3 + co.y )*vec3(8.1e5, 1.0e5, 0.1e5) );
vec3 c = mix(a, b, 0.5);
return c;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
vec2 uv = 2. * fragCoord.xy / iResolution.xy - 1.;
vec2 uvs = uv * iResolution.xy / max(iResolution.x, iResolution.y);
vec3 p = vec3(uvs / 4., 0) + vec3(1., -1.3, 0.);
p += .2 * vec3(sin(iGlobalTime / 16.), sin(iGlobalTime / 12.), sin(iGlobalTime / 128.));
float freqs[4];//=float[4](0.2,0.5,0.1,0.7);
freqs[0]=0.2;
freqs[1]=0.5;
freqs[2]=0.1;
freqs[3]=0.7;
//Sound
/*
freqs[0] = texture2D( iChannel0, vec2( 0.01, 0.25 ) ).x;
freqs[1] = texture2D( iChannel0, vec2( 0.07, 0.25 ) ).x;
freqs[2] = texture2D( iChannel0, vec2( 0.15, 0.25 ) ).x;
freqs[3] = texture2D( iChannel0, vec2( 0.30, 0.25 ) ).x;
*/
float t = field(p,freqs[2]);
float v = (1. - exp((abs(uv.x) - 1.) * 6.)) * (1. - exp((abs(uv.y) - 1.) * 6.));
//Second Layer
vec3 p2 = vec3(uvs / (4.+sin(iGlobalTime*0.11)*0.2+0.2+sin(iGlobalTime*0.15)*0.3+0.4), 1.5) + vec3(2., -1.3, -1.);
p2 += 0.25 * vec3(sin(iGlobalTime / 16.), sin(iGlobalTime / 12.), sin(iGlobalTime / 128.));
float t2 = field2(p2,freqs[3]);
vec4 c2 = mix(.4, 1., v) * vec4(1.3 * t2 * t2 * t2 ,1.8 * t2 * t2 , t2* freqs[0], t2);
//Let's add some stars
//Thanks to http://glsl.heroku.com/e#6904.0
vec2 seed = p.xy * 2.0;
seed = floor(seed * iResolution.x);
vec3 rnd = nrand3( seed );
vec4 starcolor = vec4(pow(rnd.y,40.0));
//Second Layer
vec2 seed2 = p2.xy * 2.0;
seed2 = floor(seed2 * iResolution.x);
vec3 rnd2 = nrand3( seed2 );
starcolor += vec4(pow(rnd2.y,40.0));
fragColor = mix(freqs[3]-.3, 1., v) * vec4(1.5*freqs[2] * t * t* t , 1.2*freqs[1] * t * t, freqs[3]*t, 1.0)+c2+starcolor;
}
`
return this.shaderToyFragment( fragment )
}
get another()
{
var fragment = `
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy / iResolution.xy;
fragColor = vec4(uv,0.5+0.5*sin(iGlobalTime),1.0);
}
`; return this.shaderToyFragment( fragment )
}
get ibilinear()
{
var fragment = `
// https://www.shadertoy.com/view/MscXDS
// Created by inigo quilez - iq/2014
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// Inverse bilienar interpolation: given four points defining a quadrilateral, compute the
// uv coordinates of any point in the plane that would give result to that point as a
// bilinear interpolation of the four points.
//
// The problem resolves through a quadratic equation. More information in this article:
//
// http://www.iquilezles.org/www/articles/ibilinear/ibilinear.htm
vec2 sincos( const in float x )
{
return vec2(sin(x), cos(x));
}
vec3 rotatez( const in vec3 vPos, const in vec2 vSinCos )
{
return vec3( vSinCos.y * vPos.x + vSinCos.x * vPos.y, -vSinCos.x * vPos.x + vSinCos.y * vPos.y, vPos.z);
}
vec3 rotatez( const in vec3 vPos, const in float fAngle )
{
return rotatez( vPos, sincos(fAngle) );
}
vec2 rotatez( const in vec2 vPos, const in float fAngle )
{
return rotatez( vec3(vPos, 0.0), sincos(fAngle) ).xy;
}
mat4 rotatez( const in mat4 vPos, const in float fAngle )
{
return mat4(rotatez( vec3(vPos[0].xy, 0.0), sincos(fAngle) ).xy, 0.0, 0.0,
rotatez( vec3(vPos[1].xy, 0.0), sincos(fAngle) ).xy, 0.0, 0.0,
rotatez( vec3(vPos[2].xy, 0.0), sincos(fAngle) ).xy, 0.0, 0.0,
rotatez( vec3(vPos[3].xy, 0.0), sincos(fAngle) ).xy, 0.0, 0.0);
}
float cross( in vec2 a, in vec2 b ) { return a.x*b.y - a.y*b.x; }
#define PI 3.14159265359
#define E 2.7182818284
#define GR 1.61803398875
#define EPS (.01*(1.0+saw(time)))
#define time (float(__LINE__)+iGlobalTime/PI)
float saw(float x)
{
return acos(cos(x))/3.14;
}
vec2 saw(vec2 x)
{
return acos(cos(x))/3.14;
}
vec3 saw(vec3 x)
{
return acos(cos(x))/3.14;
}
vec4 saw(vec4 x)
{
return acos(cos(x))/3.14;
}
vec3 phase(float map)
{
return vec3(saw(map),
saw(4.0*PI/3.0+map),
saw(2.0*PI/3.0+map));
}
//a is up
//b is center
//d is right
vec3 invBilinear( in vec3 p, in vec3 a, in vec3 b, in vec3 c)
{
vec3 duv = p-b;
vec3 xdir = c-b;
vec3 ydir = a-b;
float theta = PI/2.0;//time;
xdir = rotatez(xdir, theta);
ydir = rotatez(ydir, theta);
float w = length(cross(xdir, ydir));
return vec3(dot(duv, xdir), dot(duv, ydir), w);
}
float sdSegment( in vec2 p, in vec2 a, in vec2 b )
{
vec2 pa = p - a;
vec2 ba = b - a;
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
return length( pa - ba*h );
}
vec3 hash3( float n ) { return fract(sin(vec3(n,n+1.0,n+2.0))*43758.5453123); }
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec3 p = vec3((-iResolution.xy + 2.0*fragCoord.xy)/iResolution.y, 0.0);
// background
vec3 col = vec3( 0.35 + 0.1*p.y );
vec2 r = (.5*cos(1.06*iGlobalTime))*vec2(cos(iGlobalTime), sin(iGlobalTime));
float s = .5;
// move points
vec3 a = vec3(r+s*cos( 1.11*iGlobalTime + vec2(0.1,4.0) ), 0.0);
vec3 b = vec3(r+s*cos( 1.12*iGlobalTime + vec2(1.0,3.0) ), 0.0);
vec3 c = vec3(r+s*cos( 1.13*iGlobalTime + vec2(2.0,2.0) ), 0.0);
// area of the quad
vec3 uv = invBilinear( p, a, b, c );
// quad borders
float h = GR/iResolution.y;
float axis = 1.0-smoothstep(h,2.0*h,sdSegment(p.xy,a.xy,b.xy));
axis += 1.0-smoothstep(h,2.0*h,sdSegment(p.xy,c.xy,b.xy));
axis += 1.0-smoothstep(h,2.0*h,sdSegment(p.xy,a.xy,c.xy));
fragColor = vec4( col, 1.0 );
fragColor.rgb = vec3(saw(abs(uv.x/uv.z)*PI), saw(abs(uv.y/uv.z)*PI), axis);
fragColor.a = 1.0;
}
`; return this.shaderToyFragment( fragment )
}
get galaxy()
{
var fragment = `
// http://glslsandbox.com/e#18021.0
#ifdef GL_ES
precision mediump float;
#endif
uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;
#define iterations 17
#define formuparam 0.53
#define volsteps 20
#define stepsize 0.1
#define zoom 0.800
#define tile 0.850
#define speed 0.010
#define brightness 0.0015
#define darkmatter 0.300
#define distfading 0.730
#define saturation 0.850
void main(void)
{
//get coords and direction
vec2 uv=gl_FragCoord.xy/resolution.xy-.5;
uv.y*=resolution.y/resolution.x;
vec3 dir=vec3(uv*zoom,1.);
float time=time*speed+.25;
//mouse rotation
float a1=.5+mouse.x/resolution.x*2.;
float a2=.8+mouse.y/resolution.y*2.;
mat2 rot1=mat2(cos(a1),sin(a1),-sin(a1),cos(a1));
mat2 rot2=mat2(cos(a2),sin(a2),-sin(a2),cos(a2));
dir.xz*=rot1;
dir.xy*=rot2;
vec3 from=vec3(1.,.5,0.5);
from+=vec3(time*2.,time,-2.);
from.xz*=rot1;
from.xy*=rot2;
//volumetric rendering
float s=0.1,fade=1.;
vec3 v=vec3(0.);
for (int r=0; r<volsteps; r++) {
vec3 p=from+s*dir*.5;
p = abs(vec3(tile)-mod(p,vec3(tile*2.))); // tiling fold
float pa,a=pa=0.;
for (int i=0; i<iterations; i++) {
p=abs(p)/dot(p,p)-formuparam; // the magic formula
a+=abs(length(p)-pa); // absolute sum of average change
pa=length(p);
}
float dm=max(0.,darkmatter-a*a*.001); //dark matter
a*=a*a; // add contrast
if (r>6) fade*=1.-dm; // dark matter, don't render near
//v+=vec3(dm,dm*.5,0.);
v+=fade;
v+=vec3(s,s*s,s*s*s*s)*a*brightness*fade; // coloring based on distance
fade*=distfading; // distance fading
s+=stepsize;
}
v=mix(vec3(length(v)),v,saturation); //color adjust
gl_FragColor = vec4(v*.01,1.);
}
` ; return fragment
}
get closeToNeuron()
{
var fragment = `
#ifdef GL_ES
precision mediump float;
#endif
#extension GL_OES_standard_derivatives : enable
uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;
#define PI 3.14159
float hash(float n) {
return fract(sin(n)*43758.5435);
}
float noise(vec3 x) {
vec3 p = floor(x);
vec3 f = fract(x);
f = f*f*(3.0 - 2.0*f);
float n = p.x + p.y*57.0 + p.z*113.0;
return mix(
mix(
mix(hash(n + 000.0), hash(n + 001.0), f.x),
mix(hash(n + 057.0), hash(n + 058.0), f.x),
f.y),
mix(
mix(hash(n + 113.0), hash(n + 114.0), f.x),
mix(hash(n + 170.0), hash(n + 171.0), f.x),
f.y),
f.z);
}
float map(vec3 p) {
p.z += time*0.5;
float n = abs(dot(cos(p*PI), sin(p.yzx*PI)));
return .45 - n*.33 + 0.02*smoothstep(0.7, 1.0, noise(10.0*p)) + 0.01*noise(40.0*p);
}
float march(vec3 ro, vec3 rd) {
float t = 0.0;
for(int i = 0; i < 100; i++) {
float h = map(ro + rd*t);
if(abs(h) < 0.001 || t >= 10.0) break;
t += h*0.5;
}
return t;
}
vec3 normal(vec3 p) {
vec2 h = vec2(0.001, 0.0);
vec3 n = vec3(
map(p + h.xyy) - map(p - h.xyy),
map(p + h.yxy) - map(p - h.yxy),
map(p + h.yyx) - map(p - h.yyx)
);
return normalize(n);
}
float shadow(vec3 p, vec3 l) {
float res = 1.0;
float t = 0.002;
for(int i = 0; i < 100; i++) {
float h = map(p + l*t);
if(abs(h) < 0.0 || t >= 7.0) break;
t += h;
res = min(res, 16.0*h/t);
}
return clamp(res, 0.0, 1.0);
}
mat3 camera(vec3 eye, vec3 lat) {
vec3 ww = normalize(lat - eye);
vec3 uu = normalize(cross(vec3(0, 1, 0), ww));
vec3 vv = normalize(cross(ww, uu));
return mat3(uu, vv, ww);
}
void main( void ) {
vec2 uv = -1.0 + 2.0*(gl_FragCoord.xy/resolution);
uv.x *= resolution.x/resolution.y;
vec2 mo = -1.5 + 3.0*mouse;
vec3 col = vec3(0);
vec3 ro = vec3(0, 0, -3);
vec3 rd = camera(ro, vec3(4.0*mo.x, 2.0*mo.y, 0.0))*normalize(vec3(uv, 1.97));
float i = march(ro, rd);
if(i < 10.0) {
vec3 pos = ro + rd*i;
vec3 nor = normal(pos);
vec3 ref = reflect(rd, nor);
vec3 lig = normalize(vec3(0.8, 0.7, -0.6));
vec3 bli = -lig;
float amb = 0.5 + 0.5*nor.y;
float dif = clamp(dot(lig, nor), 0.0, 1.0);
float bac = clamp(dot(bli, nor), 0.0, 1.0);
float spe = pow(clamp(dot(ref, lig), 0.0, 1.0), 8.0);
float fre = pow(clamp(1.0 + dot(rd, nor), 0.0, 1.0), 2.0);
float sha = shadow(pos, lig);
col = 0.2*amb*vec3(1);
col += 1.2*dif*vec3(1)*sha;
col += 0.15*bac*vec3(1);
vec3 mat = vec3(0.4, 0.7, 0.3);
pos.z += time*0.5;
float f = smoothstep(0.7, 1.0, noise(10.0*pos));
mat = mix(mat, vec3(1.0, 0.2, 0.2), smoothstep(0.0, 1.0, 100.0*f));
col *= mat;
col += 0.2*spe*vec3(1)*dif*sha;
col += 0.2*fre*vec3(1);
}
col = mix(col, vec3(0.9, 1.0, 0.9), 1.0 - exp(-i*0.5));
gl_FragColor = vec4(col, 1);
}
`;return fragment
}
get tejut()
{
var frag = `
#ifdef GL_ES
precision mediump float;
#endif
uniform float time;
uniform vec2 resolution;
#define FORMUPARAM 0.599
#define ITERATIONS 105
#define INNER_ITERS 10
#define ZOOM 1.2
void main()
{
vec2 uv = (gl_FragCoord.xy/resolution.xy)-.5;
uv *= ZOOM;
//uv += vec2(.15 * sin(time * .2), .1 * cos(time * .1));
float t = time * .1 + ((.25+.05*sin(time*.1))/(length(uv.xy)+.07))* 2.2;
float si = sin(t);
float co = cos(t);
mat2 ma = mat2(co, si, -si, co);
float c = 0.0;
float v1 = 0.0;
float v2 = 0.0;
for (int i = 0; i < ITERATIONS; i++)
{
float s = float(i) * .035;
vec3 p = s * vec3(uv, 1.0 + sin(time * .015));
p.xy *= ma;
p += vec3(.22,.3, s-1.5-sin(t*.13)*.1);
for (int i = 0; i < INNER_ITERS; i++)
{
p = abs(p) / dot(p,p) - FORMUPARAM;
}
v1 += dot(p,p)*.0015 * (2.8+sin(length(uv.xy*18.0)+.5-t*.7));
v2 += dot(p,p)*.0025 * (1.5+sin(length(uv.xy*13.5)+1.21-t*.3));
c = length(p.xy*.3) * .85;
}
float len = length(uv);
v1 *= smoothstep(.7, .0, len);
v2 *= smoothstep(.6, .0, len);
float re = clamp(c, 0.0, 1.0);
float gr = clamp((v1+c)*.25, 0.0, 1.0);
float bl = clamp(v2, 0.0, 1.0);
vec3 col = vec3(re, gr, bl) + smoothstep(0.15, .0, len) * .9;
gl_FragColor=vec4(col, 1.0);
}
`; return frag
}
// earth with clouds
// https://www.shadertoy.com/view/ldyXRw
get earth()
{
var frag = `
#define SHADERTOY
#ifdef __cplusplus
#define _in(T) const T &
#define _inout(T) T &
#define _out(T) T &
#define _begin(type) type {
#define _end }
#define _mutable(T) T
#define _constant(T) const T
#define mul(a, b) (a) * (b)
#endif
#if defined(GL_ES) || defined(GL_SHADING_LANGUAGE_VERSION)
#define _in(T) const in T
#define _inout(T) inout T
#define _out(T) out T
#define _begin(type) type (
#define _end )
#define _mutable(T) T
#define _constant(T) const T
#define mul(a, b) (a) * (b)
precision mediump float;
#endif
#ifdef HLSL
#define _in(T) const in T
#define _inout(T) inout T
#define _out(T) out T
#define _begin(type) {
#define _end }
#define _mutable(T) static T
#define _constant(T) static const T
#define vec2 float2
#define vec3 float3
#define vec4 float4
#define mat2 float2x2
#define mat3 float3x3
#define mat4 float4x4
#define mix lerp
#define fract frac
#define mod fmod
#pragma pack_matrix(row_major)
#endif
#ifdef HLSLTOY
cbuffer uniforms : register(b0) {
float2 u_res;
float u_time;
float2 u_mouse;
};
void mainImage(_out(float4) fragColor, _in(float2) fragCoord);
float4 main(float4 uv : SV_Position) : SV_Target{ float4 col; mainImage(col, uv.xy); return col; }
#endif
#if defined(__cplusplus) || defined(SHADERTOY)
#define u_res iResolution
#define u_time iGlobalTime
#define u_mouse iMouse
#endif
#ifdef GLSLSANDBOX
uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;
#define u_res resolution
#define u_time time
#define u_mouse mouse
void mainImage(_out(vec4) fragColor, _in(vec2) fragCoord);
void main() { mainImage(gl_FragColor, gl_FragCoord.xy); }
#endif
#ifdef UE4
_constant(vec2) u_res = vec2(0, 0);
_constant(vec2) u_mouse = vec2(0, 0);
_mutable(float) u_time = 0;
#endif
#define PI 3.14159265359
struct ray_t {
vec3 origin;
vec3 direction;
};
#define BIAS 1e-4 // small offset to avoid self-intersections
struct sphere_t {
vec3 origin;
float radius;
int material;
};
struct plane_t {
vec3 direction;
float distance;
int material;
};
struct hit_t {
float t;
int material_id;
vec3 normal;
vec3 origin;
};
#define max_dist 1e8
_constant(hit_t) no_hit = _begin(hit_t)
float(max_dist + 1e1), // 'infinite' distance
-1, // material id
vec3(0., 0., 0.), // normal
vec3(0., 0., 0.) // origin
_end;
// ----------------------------------------------------------------------------
// Various 3D utilities functions
// ----------------------------------------------------------------------------
ray_t get_primary_ray(
_in(vec3) cam_local_point,
_inout(vec3) cam_origin,
_inout(vec3) cam_look_at
){
vec3 fwd = normalize(cam_look_at - cam_origin);
vec3 up = vec3(0, 1, 0);
vec3 right = cross(up, fwd);
up = cross(fwd, right);
ray_t r = _begin(ray_t)
cam_origin,
normalize(fwd + up * cam_local_point.y + right * cam_local_point.x)
_end;
return r;
}
_constant(mat3) mat3_ident = mat3(1, 0, 0, 0, 1, 0, 0, 0, 1);
#ifndef HLSL
mat3 transpose(
_in(mat3) m
){
return mat3(
m[0][0], m[1][0], m[2][0],
m[0][1], m[1][1], m[2][1],
m[0][2], m[1][2], m[2][2]);
}
#endif
mat2 rotate_2d(
_in(float) angle_degrees
){
float angle = radians(angle_degrees);
float _sin = sin(angle);
float _cos = cos(angle);
return mat2(_cos, -_sin, _sin, _cos);
}
mat3 rotate_around_z(
_in(float) angle_degrees
){
float angle = radians(angle_degrees);
float _sin = sin(angle);
float _cos = cos(angle);
return mat3(_cos, -_sin, 0, _sin, _cos, 0, 0, 0, 1);
}
mat3 rotate_around_y(
_in(float) angle_degrees
){
float angle = radians(angle_degrees);
float _sin = sin(angle);
float _cos = cos(angle);
return mat3(_cos, 0, _sin, 0, 1, 0, -_sin, 0, _cos);
}
mat3 rotate_around_x(
_in(float) angle_degrees
){
float angle = radians(angle_degrees);
float _sin = sin(angle);
float _cos = cos(angle);
return mat3(1, 0, 0, 0, _cos, -_sin, 0, _sin, _cos);
}
// http://http.developer.nvidia.com/GPUGems3/gpugems3_ch24.html
vec3 linear_to_srgb(
_in(vec3) color
){
const float p = 1. / 2.2;
return vec3(pow(color.r, p), pow(color.g, p), pow(color.b, p));
}
vec3 srgb_to_linear(
_in(vec3) color
){
const float p = 2.2;
return vec3(pow(color.r, p), pow(color.g, p), pow(color.b, p));
}
#ifdef __cplusplus
vec3 faceforward(
_in(vec3) N,
_in(vec3) I,
_in(vec3) Nref
){
return dot(Nref, I) < 0 ? N : -N;
}
#endif
float checkboard_pattern(
_in(vec2) pos,
_in(float) scale
){
vec2 pattern = floor(pos * scale);
return mod(pattern.x + pattern.y, 2.0);
}
float band (
_in(float) start,
_in(float) peak,
_in(float) end,
_in(float) t
){
return
smoothstep (start, peak, t) *
(1. - smoothstep (peak, end, t));
}
// from https://www.shadertoy.com/view/4sSSW3
// original http://orbit.dtu.dk/fedora/objects/orbit:113874/datastreams/file_75b66578-222e-4c7d-abdf-f7e255100209/content
void fast_orthonormal_basis(
_in(vec3) n,
_out(vec3) f,
_out(vec3) r
){
float a = 1. / (1. + n.z);
float b = -n.x*n.y*a;
f = vec3(1. - n.x*n.x*a, b, -n.x);
r = vec3(b, 1. - n.y*n.y*a, -n.y);
}
// ----------------------------------------------------------------------------
// Analytical surface-ray intersection routines
// ----------------------------------------------------------------------------
// geometrical solution
// info: http://www.scratchapixel.com/old/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-sphere-intersection/
void intersect_sphere(
_in(ray_t) ray,
_in(sphere_t) sphere,
_inout(hit_t) hit
){
vec3 rc = sphere.origin - ray.origin;
float radius2 = sphere.radius * sphere.radius;
float tca = dot(rc, ray.direction);
if (tca < 0.) return;
float d2 = dot(rc, rc) - tca * tca;
if (d2 > radius2) return;
float thc = sqrt(radius2 - d2);
float t0 = tca - thc;
float t1 = tca + thc;
if (t0 < 0.) t0 = t1;
if (t0 > hit.t) return;
vec3 impact = ray.origin + ray.direction * t0;
hit.t = t0;
hit.material_id = sphere.material;
hit.origin = impact;
hit.normal = (impact - sphere.origin) / sphere.radius;
}
// ----------------------------------------------------------------------------
// Volumetric utilities
// ----------------------------------------------------------------------------
struct volume_sampler_t {
vec3 origin; // start of ray
vec3 pos; // current pos of acccumulation ray
float height;
float coeff_absorb;
float T; // transmitance
vec3 C; // color
float alpha;
};
volume_sampler_t begin_volume(
_in(vec3) origin,
_in(float) coeff_absorb
){
volume_sampler_t v = _begin(volume_sampler_t)
origin, origin, 0.,
coeff_absorb, 1.,
vec3(0., 0., 0.), 0.
_end;
return v;
}
float illuminate_volume(
_inout(volume_sampler_t) vol,
_in(vec3) V,
_in(vec3) L
);
void integrate_volume(
_inout(volume_sampler_t) vol,
_in(vec3) V,
_in(vec3) L,
_in(float) density,
_in(float) dt
){
// change in transmittance (follows Beer-Lambert law)
float T_i = exp(-vol.coeff_absorb * density * dt);
// Update accumulated transmittance
vol.T *= T_i;
// integrate output radiance (here essentially color)
vol.C += vol.T * illuminate_volume(vol, V, L) * density * dt;
// accumulate opacity
vol.alpha += (1. - T_i) * (1. - vol.alpha);
}
// ----------------------------------------------------------------------------
// Noise function by iq from https://www.shadertoy.com/view/4sfGzS
// ----------------------------------------------------------------------------
float hash(
_in(float) n
){
return fract(sin(n)*753.5453123);
}
float noise_iq(
_in(vec3) x
){
vec3 p = floor(x);
vec3 f = fract(x);
f = f*f*(3.0 - 2.0*f);
#if 1
float n = p.x + p.y*157.0 + 113.0*p.z;
return mix(mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x),
mix( hash(n+157.0), hash(n+158.0),f.x),f.y),
mix(mix( hash(n+113.0), hash(n+114.0),f.x),
mix( hash(n+270.0), hash(n+271.0),f.x),f.y),f.z);
#else
vec2 uv = (p.xy + vec2(37.0, 17.0)*p.z) + f.xy;
vec2 rg = texture2D(iChannel0, (uv + 0.5) / 256.0, -100.0).yx;
return mix(rg.x, rg.y, f.z);
#endif
}
#define noise(x) noise_iq(x)
// ----------------------------------------------------------------------------
// Fractional Brownian Motion
// depends on custom basis function
// ----------------------------------------------------------------------------
#define DECL_FBM_FUNC(_name, _octaves, _basis) float _name(_in(vec3) pos, _in(float) lacunarity, _in(float) init_gain, _in(float) gain) { vec3 p = pos; float H = init_gain; float t = 0.; for (int i = 0; i < _octaves; i++) { t += _basis * H; p *= lacunarity; H *= gain; } return t; }
DECL_FBM_FUNC(fbm, 4, noise(p))
// ----------------------------------------------------------------------------
// Planet
// ----------------------------------------------------------------------------
_constant(sphere_t) planet = _begin(sphere_t)
vec3(0, 0, 0), 1., 0
_end;
#define max_height .4
#define max_ray_dist (max_height * 4.)
vec3 background(
_in(ray_t) eye
){
#if 0
return vec3(.15, .3, .4);
#else
_constant(vec3) sun_color = vec3(1., .9, .55);
float sun_amount = dot(eye.direction, vec3(0, 0, 1));
vec3 sky = mix(
vec3(.0, .05, .2),
vec3(.15, .3, .4),
1.0 - eye.direction.y);
sky += sun_color * min(pow(sun_amount, 30.0) * 5.0, 1.0);
sky += sun_color * min(pow(sun_amount, 10.0) * .6, 1.0);
return sky;
#endif
}
void setup_scene()
{
}
void setup_camera(
_inout(vec3) eye,
_inout(vec3) look_at
){
#if 0
eye = vec3(.0, 0, -1.93);
look_at = vec3(-.1, .9, 2);
#else
eye = vec3(0, 0, -2.5);
look_at = vec3(0, 0, 2);
#endif
}
// ----------------------------------------------------------------------------
// Clouds
// ----------------------------------------------------------------------------
#define CLOUDS
#define anoise (abs(noise(p) * 2. - 1.))
DECL_FBM_FUNC(fbm_clouds, 4, anoise)
#define vol_coeff_absorb 30.034
_mutable(volume_sampler_t) cloud;
float illuminate_volume(
_inout(volume_sampler_t) cloud,
_in(vec3) V,
_in(vec3) L
){
return exp(cloud.height) / .055;
}
void clouds_map(
_inout(volume_sampler_t) cloud,
_in(float) t_step
){
float dens = fbm_clouds(
cloud.pos * 3.2343 + vec3(.35, 13.35, 2.67),
2.0276, .5, .5);
#define cld_coverage .29475675 // higher=less clouds
#define cld_fuzzy .0335 // higher=fuzzy, lower=blockier
dens *= smoothstep(cld_coverage, cld_coverage + cld_fuzzy, dens);
dens *= band(.2, .35, .65, cloud.height);
integrate_volume(cloud,
cloud.pos, cloud.pos, // unused dummies
dens, t_step);
}
void clouds_march(
_in(ray_t) eye,
_inout(volume_sampler_t) cloud,
_in(float) max_travel,
_in(mat3) rot
){
const int steps = 75;
const float t_step = max_ray_dist / float(steps);
float t = 0.;
for (int i = 0; i < steps; i++) {
if (t > max_travel || cloud.alpha >= 1.) return;
vec3 o = cloud.origin + t * eye.direction;
cloud.pos = mul(rot, o - planet.origin);
cloud.height = (length(cloud.pos) - planet.radius) / max_height;
t += t_step;
clouds_map(cloud, t_step);
}
}
void clouds_shadow_march(
_in(vec3) dir,
_inout(volume_sampler_t) cloud,
_in(mat3) rot
){
const int steps = 5;
const float t_step = max_height / float(steps);
float t = 0.;
for (int i = 0; i < steps; i++) {
vec3 o = cloud.origin + t * dir;
cloud.pos = mul(rot, o - planet.origin);
cloud.height = (length(cloud.pos) - planet.radius) / max_height;
t += t_step;
clouds_map(cloud, t_step);
}
}
// ----------------------------------------------------------------------------
// Terrain
// ----------------------------------------------------------------------------
#define TERR_STEPS 120
#define TERR_EPS .005
#define rnoise (1. - abs(noise(p) * 2. - 1.))
DECL_FBM_FUNC(fbm_terr, 3, noise(p))
DECL_FBM_FUNC(fbm_terr_r, 3, rnoise)
DECL_FBM_FUNC(fbm_terr_normals, 7, noise(p))
DECL_FBM_FUNC(fbm_terr_r_normals, 7, rnoise)
vec2 sdf_terrain_map(_in(vec3) pos)
{
float h0 = fbm_terr(pos * 2.0987, 2.0244, .454, .454);
float n0 = smoothstep(.35, 1., h0);
float h1 = fbm_terr_r(pos * 1.50987 + vec3(1.9489, 2.435, .5483), 2.0244, .454, .454);
float n1 = smoothstep(.6, 1., h1);
float n = n0 + n1;
return vec2(length(pos) - planet.radius - n * max_height, n / max_height);
}
vec2 sdf_terrain_map_detail(_in(vec3) pos)
{
float h0 = fbm_terr_normals(pos * 2.0987, 2.0244, .454, .454);
float n0 = smoothstep(.35, 1., h0);
float h1 = fbm_terr_r_normals(pos * 1.50987 + vec3(1.9489, 2.435, .5483), 2.0244, .454, .454);
float n1 = smoothstep(.6, 1., h1);
float n = n0 + n1;
return vec2(length(pos) - planet.radius - n * max_height, n / max_height);
}
vec3 sdf_terrain_normal(_in(vec3) p)
{
#define F(t) sdf_terrain_map_detail(t).x
vec3 dt = vec3(0.001, 0, 0);
return normalize(vec3(
F(p + dt.xzz) - F(p - dt.xzz),
F(p + dt.zxz) - F(p - dt.zxz),
F(p + dt.zzx) - F(p - dt.zzx)
));
#undef F
}
// ----------------------------------------------------------------------------
// Lighting
// ----------------------------------------------------------------------------
vec3 setup_lights(
_in(vec3) L,
_in(vec3) normal
){
vec3 diffuse = vec3(0, 0, 0);
// key light
vec3 c_L = vec3(7, 5, 3);
diffuse += max(0., dot(L, normal)) * c_L;
// fill light 1 - faked hemisphere
float hemi = clamp(.25 + .5 * normal.y, .0, 1.);
diffuse += hemi * vec3(.4, .6, .8) * .2;
// fill light 2 - ambient (reversed key)
float amb = clamp(.12 + .8 * max(0., dot(-L, normal)), 0., 1.);
diffuse += amb * vec3(.4, .5, .6);
return diffuse;
}
vec3 illuminate(
_in(vec3) pos,
_in(vec3) eye,
_in(mat3) local_xform,
_in(vec2) df
){
// current terrain height at position
float h = df.y;
//return vec3 (h);
vec3 w_normal = normalize(pos);
#define LIGHT
#ifdef LIGHT
vec3 normal = sdf_terrain_normal(pos);
float N = dot(normal, w_normal);
#else
float N = w_normal.y;
#endif
// materials
#define c_water vec3(.015, .110, .455)
#define c_grass vec3(.086, .132, .018)
#define c_beach vec3(.153, .172, .121)
#define c_rock vec3(.080, .050, .030)
#define c_snow vec3(.600, .600, .600)
// limits
#define l_water .05
#define l_shore .17
#define l_grass .211
#define l_rock .351
float s = smoothstep(.4, 1., h);
vec3 rock = mix(
c_rock, c_snow,
smoothstep(1. - .3*s, 1. - .2*s, N));
vec3 grass = mix(
c_grass, rock,
smoothstep(l_grass, l_rock, h));
vec3 shoreline = mix(
c_beach, grass,
smoothstep(l_shore, l_grass, h));
vec3 water = mix(
c_water / 2., c_water,
smoothstep(0., l_water, h));
#ifdef LIGHT
vec3 L = mul(local_xform, normalize(vec3(1, 1, 0)));
shoreline *= setup_lights(L, normal);
vec3 ocean = setup_lights(L, w_normal) * water;
#else
vec3 ocean = water;
#endif
return mix(
ocean, shoreline,
smoothstep(l_water, l_shore, h));
}
// ----------------------------------------------------------------------------
// Rendering
// ----------------------------------------------------------------------------
vec3 render(
_in(ray_t) eye,
_in(vec3) point_cam
){
mat3 rot_y = rotate_around_y(27.);
mat3 rot = mul(rotate_around_x(u_time * -12.), rot_y);
mat3 rot_cloud = mul(rotate_around_x(u_time * 8.), rot_y);
sphere_t atmosphere = planet;
atmosphere.radius += max_height;
hit_t hit = no_hit;
intersect_sphere(eye, atmosphere, hit);
if (hit.material_id < 0) {
return background(eye);
}
float t = 0.;
vec2 df = vec2(1, max_height);
vec3 pos;
float max_cld_ray_dist = max_ray_dist;
for (int i = 0; i < TERR_STEPS; i++) {
if (t > max_ray_dist) break;
vec3 o = hit.origin + t * eye.direction;
pos = mul(rot, o - planet.origin);
df = sdf_terrain_map(pos);
if (df.x < TERR_EPS) {
max_cld_ray_dist = t;
break;
}
t += df.x * .4567;
}
#ifdef CLOUDS
cloud = begin_volume(hit.origin, vol_coeff_absorb);
clouds_march(eye, cloud, max_cld_ray_dist, rot_cloud);
#endif
if (df.x < TERR_EPS) {
vec3 c_terr = illuminate(pos, eye.direction, rot, df);
vec3 c_cld = cloud.C;
float alpha = cloud.alpha;
float shadow = 1.;
#ifdef CLOUDS // clouds ground shadows
pos = mul(transpose(rot), pos);
cloud = begin_volume(pos, vol_coeff_absorb);
vec3 local_up = normalize(pos);
clouds_shadow_march(local_up, cloud, rot_cloud);
shadow = mix(.7, 1., step(cloud.alpha, 0.33));
#endif
return mix(c_terr * shadow, c_cld, alpha);
} else {
return mix(background(eye), cloud.C, cloud.alpha);
}
}
#define FOV tan(radians(30.))
// ----------------------------------------------------------------------------
// Main Rendering function
// depends on external defines: FOV
// ----------------------------------------------------------------------------
void mainImage(
_out(vec4) fragColor,
#ifdef SHADERTOY
vec2 fragCoord
#else
_in(vec2) fragCoord
#endif
){
// assuming screen width is larger than height
vec2 aspect_ratio = vec2(u_res.x / u_res.y, 1);
vec3 color = vec3(0, 0, 0);
vec3 eye, look_at;
setup_camera(eye, look_at);
setup_scene();
vec2 point_ndc = fragCoord.xy / u_res.xy;
#ifdef HLSL
point_ndc.y = 1. - point_ndc.y;
#endif
vec3 point_cam = vec3(
(2.0 * point_ndc - 1.0) * aspect_ratio * FOV,
-1.0);
ray_t ray = get_primary_ray(point_cam, eye, look_at);
color += render(ray, point_cam);
fragColor = vec4(linear_to_srgb(color), 1);
}
`; return this.shaderToyFragment( frag )
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r75/three.min.js"></script>
body
width: 100%
height: 100%
background: #333
font-family: arial
color: #999
margin: 0
padding: 0
overflow: hidden
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment