frag.gl
, vert.gl
があるページではそれが読み込まれ、表示される window.glsl_frag
window.glsl_vert
window.glsl_vert
は未設定でも化settings.jswindow.glsl_frag = "beam"
// window.glsl_frag = "/api/code/{projectname}/{pagename}/frag.gl"
// window.glsl_vert = "/api/code/{projectname}/{pagename}/vert.gl"
_script.jsimport "/api/code/{projectname}/{username}/settings.js"
import "/api/code/yutaro/background-gl/script.js"
settings.js
は試験的に便利かどうか検討中 window.____
で設定を記述できる import
style.css.grid li.page-list-item a .header {
border-top: rgba(100,255,100, 0.2) solid 3px;
}
.grid li.page-list-item a {
background-color: rgba(0,0,0,0);
}
script.jsimport GlslCanvas from '/api/code/spm/GlslCanvas/script.js'
const frags = ['gradation','smog','blocks','beam', 'fusion', 'mono', 'marin','neon', 'sea']
if( window.glsl_frag === undefined ) {
window.glsl_frag = 'none'
}
const canvas = document.createElement('canvas')
canvas.width = window.parent.screen.width
canvas.height = window.parent.screen.height
canvas.style = `position:fixed; z-index: -1; top: 0; left: 0;`
$('#app-container').append(canvas)
let sandbox = new GlslCanvas(canvas)
function load(frag, vert = undefined ) {
if ( frag === "none" ) return
if ( !frag.includes('/') ) {
frag = `/api/code/yutaro/background_gl/${frag}.gl`
}
return ( async () => {
const fs = await fetch( frag ,
{ credentials: 'same-origin'})
.then( data => data.text())
.catch( err => err )
if( fs.length === 0 ) return false;
if( !vert ) {
sandbox.load(fs)
return false;
}
const vs = await fetch( vert ,
{ credentials: 'same-origin'})
.then( data => data.text())
.catch( err => err )
if( vs.length === 0 ) sandbox.load(fs)
else sandbox.load(fs, vs)
return true;
})()
}
load(window.glsl_frag, window.glsl_vert);
scrapbox.PageMenu.addMenu({
title: 'glsl',
image: 'https://gyazo.com/6bae1fa3ccf6ee0a396dbf23c00e742d/raw'
})
frags.forEach( frag => {
scrapbox.PageMenu('glsl').addItem({
title: frag,
onClick: () => load(frag)
})
})
let url = "/"
let items = []
setInterval( () => {
const path = location.pathname
// ここの例外処理をちゃんと書く
if ( url === path
|| /^\/[\w-]+\/$/.test(path)
|| path.includes('settings')
|| path.includes('stream') ) return
url = path
load(`/api/code${path}/frag.gl`,`/api/code${path}/vert.gl`)
.then( flag => {
if( !flag ) return;
const pageName = path.split('/')[2]
if(items.includes( pageName )) return;
items.push(pageName)
scrapbox.PageMenu('glsl').addItem({
title: pageName,
onClick: () => load(`/api/code${path}/frag.gl`,`/api/code${path}/vert.gl`)
})
});
}, 10)
gradation.gl// Author:
// Title:
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.);
color = vec3(st.x,st.y,abs(sin(u_time)));
gl_FragColor = vec4(color,1.0);
}
beam.gl#ifdef GL_ES
precision mediump float;
#endif
#extension GL_OES_standard_derivatives : enable
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float DEG2RAG = .0174532925199;
float tri2(vec2 pos)
{
float a = dot(pos, vec2(sin( 60.0*DEG2RAG), cos( 60.0*DEG2RAG)));
float b = dot(pos, vec2(sin(-60.0*DEG2RAG), cos(-60.0*DEG2RAG)));
float c = -pos.y;
float d = 0.2*cos(60.0*DEG2RAG);
float u1 = a - d*0.25;
float v1 = b - d*0.25;
float w1 = c - d*0.25;
float u2 = c + d*1.25;
float v2 = b + d*1.25;
float w2 = a + d*1.25;
float t1 = min(u2, min(u1, v1));
float t2 = min(v2, min(w1, u1));
float t3 = min(w2, min(v1, w1));
float res = max(max(t1, t2), t3);
return 0.002/abs(res);
}
float tri(vec2 pos)
{
float a = dot(pos, vec2(sin( 60.0*DEG2RAG), cos( 60.0*DEG2RAG)));
float b = dot(pos, vec2(sin(-60.0*DEG2RAG), cos(-60.0*DEG2RAG)));
float c = -pos.y;
float result = 0.002/abs(min(min(0.05-a,0.05-b), 0.05-c));
return result;
}
void main() {
vec2 pos = (2.0*gl_FragCoord.xy - u_resolution.xy)/max(u_resolution.x, u_resolution.y) / 16.0;
//rotate & zoom
mat2 rot = mat2(cos(u_time),-sin(u_time),
sin(u_time), cos(u_time));
pos *= rot;
float zoom = 1.0/(mod(u_time, 1.0)+1.0)*3.0-1.0;
pos *= zoom;
//effect
vec3 result = vec3(0.0);
for(int i = 0 ; i < 6 ; i++)
{
result += vec3(tri(pos), tri(-pos*0.5), tri2(pos));
pos /= 0.25;
}
gl_FragColor = vec4( mix(vec3(0.0, 0.0, 0.0), vec3(0.5, 0.0,1.0), result.x)
+mix(vec3(0.0, 0.0, 0.0), vec3(0.5,0.25,0.0), result.y)
+mix(vec3(0.0, 0.0, 0.0), vec3(0.0,0.5,0.1), result.z), 1.0 );
}
blocks.gl// @lsdlive
// This was my shader for the shader showdown at Outline demoparty 2018 in Nederland.
// Shader showdown is a live-coding competition where two participants are
// facing each other during 25 minutes.
// (Round 1)
// I don't have access to the code I typed at the event, so it might be
// slightly different.
// Original algorithm on shadertoy from fb39ca4: https://www.shadertoy.com/view/4dX3zl
// I used the implementation from shane: https://www.shadertoy.com/view/MdVSDh
// Thanks to shadertoy community & shader showdown paris.
// This is under CC-BY-NC-SA (shadertoy default licence)
#ifdef GL_ES
precision mediump float;
#endif
uniform float u_time;
uniform vec2 u_mouse;
uniform vec2 u_resolution;
#define iTime u_time
mat2 r2d(float a) {
float c = cos(a), s = sin(a);
return mat2(c, s, -s, c);
}
vec2 path(float t) {
float a = sin(t*.2 + 1.5), b = sin(t*.2);
return vec2(2.*a, a*b);
}
float g = 0.;
float de(vec3 p) {
p.xy -= path(p.z);
float d = -length(p.xy) + 4.;// tunnel (inverted cylinder)
p.xy += vec2(cos(p.z + iTime)*sin(iTime), cos(p.z + iTime));
p.z -= 6. + iTime * 6.;
d = min(d, dot(p, normalize(sign(p))) - 1.); // octahedron (LJ's formula)
// I added this in the last 1-2 minutes, but I'm not sure if I like it actually!
// Trick inspired by balkhan's shadertoys.
// Usually, in raymarch shaders it gives a glow effect,
// here, it gives a colors patchwork & transparent voxels effects.
g += .015 / (.001 + d * d);
return d;
}
void main()
{
vec2 uv = gl_FragCoord.xy / u_resolution.xy - .5;
uv.x *= u_resolution.x / u_resolution.y;
float dt = u_time * 6.;
vec3 ro = vec3(0, 0, -5. + dt);
vec3 ta = vec3(0, 0, dt);
ro.xy += path(ro.z);
ta.xy += path(ta.z);
vec3 fwd = normalize(ta - ro);
vec3 right = cross(fwd, vec3(0, 1, 0));
vec3 up = cross(right, fwd);
vec3 rd = normalize(fwd + uv.x*right + uv.y*up);
rd.xy *= r2d(sin(-ro.x / 3.14)*.3);
// Raycast in 3d to get voxels.
// Algorithm fully explained here in 2D (just look at dde algo):
// http://lodev.org/cgtutor/raycasting.html
// Basically, tracing a ray in a 3d grid space, and looking for
// each voxel (think pixel with a third dimension) traversed by the ray.
vec3 p = floor(ro) + .5;
vec3 mask;
vec3 drd = 1. / abs(rd);
rd = sign(rd);
vec3 side = drd * (rd * (p - ro) + .5);
float t = 0., ri = 0.;
for (float i = 0.; i < 1.; i += .01) {
ri = i;
/*
// sphere tracing algorithm (for comparison)
p = ro + rd * t;
float d = de(p);
if(d<.001) break;
t += d;
*/
if (de(p) < 0.) break;// distance field
// we test if we are inside the surface
mask = step(side, side.yzx) * step(side, side.zxy);
// minimum value between x,y,z, output 0 or 1
side += drd * mask;
p += rd * mask;
}
t = length(p - ro);
vec3 c = vec3(1) * length(mask * vec3(1., .5, .75));
c = mix(vec3(.2, .2, .7), vec3(.2, .1, .2), c);
c += g * .4;
c.r += sin(u_time)*.2 + sin(p.z*.5 - u_time * 6.);// red rings
c = mix(c, vec3(.2, .1, .2), 1. - exp(-.001*t*t));// f
gl_FragColor = vec4(c, 1.0);
}
smog.gl#ifdef GL_ES
precision highp float;
#endif
uniform float u_time;
uniform vec2 u_mouse;
uniform vec2 u_resolution;
#define iterations 4
#define formuparam2 0.89
#define volsteps 10
#define stepsize 0.190
#define zoom 3.900
#define tile 0.450
#define speed2 0.010
#define brightness 0.2
#define darkmatter 0.400
#define distfading 0.560
#define saturation 0.400
#define transverseSpeed 1.1
#define cloud 0.2
float triangle(float x, float a)
{
float output2 = 2.0*abs( 2.0* ( (x/a) - floor( (x/a) + 0.5) ) ) - 1.0;
return output2;
}
float field(in vec3 p)
{
float strength = 7.0 + 0.03 * log(1.e-6 + fract(sin(u_time) * 4373.11));
float accum = 0.0;
float prev = 0.0;
float tw = 0.0;
for (int i = 0; i < 4; ++i)
{
float mag = dot(p, p);
p = abs(p) / mag + vec3(-.5, -.8 + 0.1*sin(u_time*0.2 + 2.0), -1.1+0.3*cos(u_time*0.15));
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 main()
{
vec2 uv2 = 2. * gl_FragCoord.xy / u_resolution.xy - 1.;
vec2 uvs = uv2 * u_resolution.xy / max(u_resolution.x, u_resolution.y);
float time2 = u_time*1.9;
float speed = speed2;
speed = 0.005 * cos(time2*0.02 + 3.1415926/4.0);
//speed = 0.0;
float formuparam = formuparam2;
//get coords and direction
vec2 uv = uvs;
//mouse rotation
float a_xz = 0.9;
float a_yz = -.6;
float a_xy = 0.9 + u_time*0.04;
mat2 rot_xz = mat2(cos(a_xz),sin(a_xz),-sin(a_xz),cos(a_xz));
mat2 rot_yz = mat2(cos(a_yz),sin(a_yz),-sin(a_yz),cos(a_yz));
mat2 rot_xy = mat2(cos(a_xy),sin(a_xy),-sin(a_xy),cos(a_xy));
float v2 =1.0;
vec3 dir=vec3(uv*zoom,1.);
vec3 from=vec3(0.0, 0.0,0.0);
from.x -= .5*(-0.5);
from.y -= .5*(-0.5);
vec3 forward = vec3(0.,0.,1.);
from.x += transverseSpeed*(1.0)*cos(0.01*u_time) + 0.001*u_time;
from.y += transverseSpeed*(1.0)*sin(0.01*u_time) + 0.001*u_time;
from.z += 0.003*u_time;
dir.xy*=rot_xy;
forward.xy *= rot_xy;
dir.xz*=rot_xz;
forward.xz *= rot_xz;
dir.yz*= rot_yz;
forward.yz *= rot_yz;
from.xy*=-rot_xy;
from.xz*=rot_xz;
from.yz*= rot_yz;
//zoom
float zooom = (time2-3311.)*speed;
from += forward* zooom;
float sampleShift = mod( zooom, stepsize );
float zoffset = -sampleShift;
sampleShift /= stepsize; // make from 0 to 1
//volumetric rendering
float s=0.24;
float s3 = s + stepsize/2.0;
vec3 v=vec3(0.);
float t3 = 0.0;
vec3 backCol2 = vec3(0.);
for (int r=0; r<volsteps; r++) {
vec3 p2=from+(s+zoffset)*dir;// + vec3(0.,0.,zoffset);
vec3 p3=(from+(s3+zoffset)*dir )* (1.9/zoom);// + vec3(0.,0.,zoffset);
p2 = abs(vec3(tile)-mod(p2,vec3(tile*2.))); // tiling fold
p3 = abs(vec3(tile)-mod(p3,vec3(tile*2.))); // tiling fold
#ifdef cloud
t3 = field(p3);
#endif
float pa,a=pa=0.;
for (int i=0; i<iterations; i++) {
p2=abs(p2)/dot(p2,p2)-formuparam; // the magic formula
//p=abs(p)/max(dot(p,p),0.005)-formuparam; // another interesting way to reduce noise
float D = abs(length(p2)-pa); // absolute sum of average change
if (i > 2)
{
a += i > 7 ? min( 12., D) : D;
}
pa=length(p2);
}
//float dm=max(0.,darkmatter-a*a*.001); //dark matter
a*=a*a; // add contrast
//if (r>3) fade*=1.-dm; // dark matter, don't render near
// brightens stuff up a bit
float s1 = s+zoffset;
// need closed form expression for this, now that we shift samples
float fade = pow(distfading,max(0.,float(r)-sampleShift));
//t3 += fade;
v+=fade;
//backCol2 -= fade;
// fade out samples as they approach the camera
if( r == 0 )
fade *= (1. - (sampleShift));
// fade in samples as they approach from the distance
if( r == volsteps-1 )
fade *= sampleShift;
v+=vec3(s1,s1*s1,s1*s1*s1*s1)*a*brightness*fade; // coloring based on distance
backCol2 += mix(.4, 1., v2) * vec3(0.20 * t3 * t3 * t3, 0.4 * t3 * t3, t3 * 0.7) * fade;
s+=stepsize;
s3 += stepsize;
}
v=mix(vec3(length(v)),v,saturation); //color adjust
vec4 forCol2 = vec4(v*.01,1.);
#ifdef cloud
backCol2 *= cloud;
#endif
backCol2.r *= 1.80;
backCol2.g *= 0.05;
backCol2.b *= 0.90;
// backCol2.b = 0.5*mix(backCol2.b, backCol2.g, 0.2);
// backCol2.g = 0.0;
//
// backCol2.bg = mix(backCol2.gb, backCol2.bg, 0.5*(cos(u_time*0.01) + 1.0));
gl_FragColor = vec4(backCol2, 1.0);
}
fusion.gl#ifdef GL_ES
precision mediump float;
#endif
#extension GL_OES_standard_derivatives : enable
uniform float u_time;
uniform vec2 u_mouse;
uniform vec2 u_resolution;
void main( void ) {
float dist= 2.7;
vec2 p = gl_FragCoord.xy / u_resolution.xy * 2. - 1.;
p.x *= u_resolution.x/u_resolution.y;
p*=1.5;
p=(p);
float a = sin(atan(p.y,p.x))*cos(atan(p.y,p.x))*2.;
float l = log(length(p))*1.5;
float c = sin((l+cos(a*1.-sin(a*2.-u_time*5.)+u_time*3.2)+a*2.+u_time*0.5));
c*=log(abs(l*dist))/1.5;
//c*=sin(l*dist);
gl_FragColor = vec4((c),c*c,-c,1.0 );
}
mono.gl#ifdef GL_ES
precision mediump float;
#endif
#extension GL_OES_standard_derivatives : enable
uniform float u_time;
uniform vec2 u_mouse;
uniform vec2 u_resolution;
vec2 brickTile(vec2 uv, float zoom)
{
uv *= zoom;
uv.x += step(1., mod(uv.y,2.0)) * -u_time;
return fract(uv);
}
vec2 brickTile2(vec2 uv, float zoom)
{
uv *= zoom;
float t = mod(uv.y,2.0) < 1. ? -u_time : u_time;
uv.x += step(0., mod(uv.y,2.0)) * t;
return fract(uv);
}
vec2 brickTile3(vec2 uv, float zoom)
{
uv *= zoom;
float tx = mod(uv.y,2.0) < 1. ? -u_time : u_time;
float ty = mod(uv.x,2.0) < 1. ? -u_time : u_time;
float b = step(1.,mod(u_time,2.));
if(b < 1.)
{
uv.x += step(0., mod(uv.y,2.0)) * tx;
}
else
{
uv.y += step(0., mod(uv.x,2.0)) * ty;
}
return fract(uv);
}
void main( void ) {
vec2 position = ( gl_FragCoord.xy / u_resolution.xy );
position.x *= u_resolution.x / u_resolution.y;
//position = brickTile(position,5.);
//position = brickTile2(position,10.);
position = brickTile3(position,10.);
float d = distance(position,vec2(.5));
float radius = 0.2;
float s = smoothstep(radius,d + radius, d);
vec3 color = vec3(s * 5.);
color = mix(color,1.- color,sin(u_time) + 1.);
gl_FragColor = vec4( color , 1.0 );
}
marin.gl/*
Iridule ~
shadertoy: iridule
twitter: @iridule
instagram: @the_iridule
email: numinouscranium@gmail.com
*/
#ifdef GL_ES
precision mediump float;
#endif
#extension GL_OES_standard_derivatives : enable
uniform float u_time;
uniform vec2 u_resolution;
vec2 iResolution;
float iTime;
#define repeat(v) mod(p + 1., 2.) -1.
#define un(a, b) min(a, b)
mat3 rotateX(float a) {
return mat3(
1.0, 0.0, 0.0,
0.0, cos(a), sin(a),
0.0, -sin(a), cos(a)
);
}
mat3 rotateY(float a) {
return mat3(
cos(a), 0.0, sin(a),
0.0, 1.0, 0.0,
-sin(a), 0.0, cos(a)
);
}
float sphere_sdf(vec3 p, float r) {
return length(p) - r;
}
float cube_sdf(vec3 p, float s) {
return length(max(abs(p) - s, .0));
}
float ring_sdf(vec3 p) {
float a = sphere_sdf(p + vec3(.2, .0, .0), .1);
float b = sphere_sdf(p + vec3(-.2, .0, .0), .1);
float A = un(a, b);
float c = sphere_sdf(p + vec3(.0, .0, .1), .1);
float d = sphere_sdf(p + vec3(.0, .0, -.1), .1);
float B = un(c, d);
return un(A, B);
}
float shape_sdf(vec3 p) {
vec3 v = rotateY(iTime) * p;
v.y = mod(v.y + 0.2, 0.4) - 0.2;
return un(ring_sdf(v),
sphere_sdf(p * vec3(1., .01, 1.), .11));
}
void mainImage(out vec4 O, in vec2 I) {
vec2 R = iResolution.xy;
vec2 uv = (2. * I - R) / R.y;
vec3 o = vec3(-1., 0., iTime), d = vec3(uv, 1.), p;
float t = 0.;
for (int i = 0; i < 32; i++) {
p = o + d * t;
p = repeat(p);
t += .5 * shape_sdf(p);
}
float l = .8 * dot(normalize(o - p), d);
O = vec4(.5 * vec3(0., uv.y, uv.y) + vec3(.0, .3, 1.) * l * vec3(t * .3), 1.);
}
void main(void) {
iResolution = u_resolution;
iTime = u_time;
mainImage(gl_FragColor, gl_FragCoord.xy);
}
neon.gl#ifdef GL_ES
precision mediump float;
#endif
uniform float u_time;
uniform vec2 u_resolution;
void main( void ) {
vec2 p = ( gl_FragCoord.xy / u_resolution.x );
float scale = 65.0*(1.5+cos(u_time/13.0 + sin(p.x)+ sin(p.y)));
vec3 hue = vec3(p.x,p.y,0.0);
float color = 0.0;
color = (sin(p.x*scale) + sin(p.y*scale) -1.7)*4.0;
gl_FragColor = vec4( color * hue, 1.0 );
}
sea.gl#ifdef GL_ES
precision mediump float;
#endif
uniform float u_time;
uniform vec2 u_mouse;
uniform vec2 u_resolution;
// "Seascape" by Alexander Alekseev aka TDM - 2014
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
const int NUM_STEPS = 16;
const float PI = 3.1415;
const float EPSILON = 1e-3;
float EPSILON_NRM = 0.;
// sea
const int ITER_GEOMETRY = 3;
const int ITER_FRAGMENT = 5;
const float SEA_HEIGHT = 0.6;
const float SEA_CHOPPY = 4.0;
const float SEA_SPEED = 0.8;
const float SEA_FREQ = 0.16;
const vec3 SEA_BASE = vec3(0.2,0.19,0.22);
const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6);
float SEA_TIME = 0.;
mat2 octave_m = mat2(1.6,1.2,-1.2,1.6);
// math
mat3 fromEuler(vec3 ang) {
vec2 a1 = vec2(sin(ang.x),cos(ang.x));
vec2 a2 = vec2(sin(ang.y),cos(ang.y));
vec2 a3 = vec2(sin(ang.z),cos(ang.z));
mat3 m;
m[0] = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
m[2] = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
return m;
}
float hash( vec2 p ) {
float h = dot(p,vec2(127.1,311.7));
return fract(sin(h)*43758.5453123);
}
float noise( in vec2 p ) {
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ),
hash( i + vec2(1.0,0.0) ), u.x),
mix( hash( i + vec2(0.0,1.0) ),
hash( i + vec2(1.0,1.0) ), u.x), u.y);
}
// lighting
float diffuse(vec3 n,vec3 l,float p) {
return pow(dot(n,l) * 0.1 + 0.6,p);
}
float specular(vec3 n,vec3 l,vec3 e,float s) {
float nrm = (s + 8.0) / (3.1415 * 8.0);
return pow(max(dot(reflect(e,n),l),0.0),s) * nrm;
}
// sky
vec3 getSkyColor(vec3 e) {
e.y = max(e.y,0.0);
vec3 ret;
ret.x = pow(1.0-e.y,2.0);
ret.y = 1.0-e.y;
ret.z = 0.6+(1.0-e.y)*0.4;
return ret;
}
// sea
float sea_octave(vec2 uv, float choppy) {
uv += noise(uv);
vec2 wv = 1.0-abs(sin(uv));
vec2 swv = abs(cos(uv));
wv = mix(wv,swv,wv);
return pow(1.0-pow(wv.x * wv.y,0.65),choppy);
}
float map(vec3 p) {
float freq = SEA_FREQ;
float amp = SEA_HEIGHT;
float choppy = SEA_CHOPPY;
vec2 uv = p.xz; uv.x *= 0.75;
float d, h = 0.0;
for(int i = 0; i < ITER_GEOMETRY; i++) {
d = sea_octave((uv+SEA_TIME)*freq,choppy);
d += sea_octave((uv-SEA_TIME)*freq,choppy);
h += d * amp;
uv *= octave_m; freq *= 1.9; amp *= 0.22;
choppy = mix(choppy,1.0,0.2);
}
return p.y - h;
}
float map_detailed(vec3 p) {
float freq = SEA_FREQ;
float amp = SEA_HEIGHT;
float choppy = SEA_CHOPPY;
vec2 uv = p.xz; uv.x *= 0.75;
float d, h = 0.0;
for(int i = 0; i < ITER_FRAGMENT; i++) {
d = sea_octave((uv+SEA_TIME)*freq,choppy);
d += sea_octave((uv-SEA_TIME)*freq,choppy);
h += d * amp;
uv *= octave_m; freq *= 1.9; amp *= 0.22;
choppy = mix(choppy,1.0,0.2);
}
return p.y - h;
}
vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) {
float fresnel = 1.0 - max(dot(n,-eye),0.0);
fresnel = pow(fresnel,3.0) * 0.65;
vec3 reflected = getSkyColor(reflect(eye,n));
vec3 refracted = SEA_BASE + diffuse(n,l,80.0) * SEA_WATER_COLOR * 0.12;
vec3 color = mix(refracted,reflected,fresnel);
float atten = max(1.0 - dot(dist,dist) * 0.001, 0.0);
color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten;
color += vec3(specular(n,l,eye,60.0));
return color;
}
// tracing
vec3 getNormal(vec3 p, float eps) {
vec3 n;
n.y = map_detailed(p);
n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.y;
n.z = map_detailed(vec3(p.x,p.y,p.z+eps)) - n.y;
n.y = eps;
return normalize(n);
}
float heightMapTracing(vec3 ori, vec3 dir, out vec3 p) {
float tm = 0.0;
float tx = 1000.0;
float hx = map(ori + dir * tx);
if(hx > 0.0) return tx;
float hm = map(ori + dir * tm);
float tmid = 0.0;
for(int i = 0; i < NUM_STEPS; i++) {
tmid = mix(tm,tx, hm/(hm-hx));
p = ori + dir * tmid;
float hmid = map(p);
if(hmid < 0.0) {
tx = tmid;
hx = hmid;
} else {
tm = tmid;
hm = hmid;
}
}
return tmid;
}
// main
void main( void ) {
EPSILON_NRM = 0.1 / u_resolution.x;
SEA_TIME = u_time * SEA_SPEED;
vec2 uv = gl_FragCoord.xy / u_resolution.xy;
uv = uv * 2.0 - 1.0;
uv.x *= u_resolution.x / u_resolution.y;
float u_time = u_time * 0.3 + u_mouse.x*0.01;
// ray
vec3 ang = vec3(sin(u_time*3.0)*0.1,sin(u_time)*0.2+0.3,u_time);
vec3 ori = vec3(0.0,3.5,u_time*5.0);
vec3 dir = normalize(vec3(uv.xy,-2.0)); dir.z += length(uv) * 0.15;
dir = normalize(dir) * fromEuler(ang);
// tracing
vec3 p;
heightMapTracing(ori,dir,p);
vec3 dist = p - ori;
vec3 n = getNormal(p, dot(dist,dist) * EPSILON_NRM);
vec3 light = normalize(vec3(0.0,1.0,0.8));
// color
vec3 color = mix(
getSkyColor(dir),
getSeaColor(p,n,light,dir,dist),
pow(smoothstep(0.0,-0.05,dir.y),0.3));
// post
gl_FragColor = vec4(pow(color,vec3(0.75)), 1.0);
}