162 lines
4.7 KiB
HTML
162 lines
4.7 KiB
HTML
<canvas id="c" style="position:fixed;top:0;left:0;width:100%;height:100%;z-index:1;"></canvas>
|
|
<script>
|
|
var canvas = document.getElementById('c');
|
|
var gl = canvas.getContext('webgl2') || canvas.getContext('webgl');
|
|
|
|
var mouseX = 0, mouseY = 0, lastMove = 0;
|
|
var clickX = 0, clickY = 0, clickTime = 0;
|
|
|
|
document.addEventListener('mousemove', function(e) {
|
|
mouseX = e.clientX / window.innerWidth;
|
|
mouseY = 1.0 - e.clientY / window.innerHeight;
|
|
lastMove = performance.now();
|
|
});
|
|
document.addEventListener('click', function(e) {
|
|
clickX = e.clientX / window.innerWidth;
|
|
clickY = 1.0 - e.clientY / window.innerHeight;
|
|
clickTime = performance.now();
|
|
});
|
|
|
|
var vsSrc = 'attribute vec2 a_pos;void main(){gl_Position=vec4(a_pos,0.0,1.0);}';
|
|
var fsSrc = `
|
|
precision highp float;
|
|
uniform float u_time;
|
|
uniform vec2 u_resolution;
|
|
uniform vec2 u_mouse;
|
|
uniform float u_click;
|
|
uniform vec2 u_clickPos;
|
|
|
|
vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}
|
|
vec2 mod289(vec2 x){return x-floor(x*(1.0/289.0))*289.0;}
|
|
vec3 permute(vec3 x){return mod289(((x*34.0)+1.0)*x);}
|
|
|
|
float snoise(vec2 v){
|
|
const vec4 C=vec4(0.211324865405187,0.366025403784439,-0.577350269189626,0.024390243902439);
|
|
vec2 i=floor(v+dot(v,C.yy));
|
|
vec2 x0=v-i+dot(i,C.xx);
|
|
vec2 i1=(x0.x>x0.y)?vec2(1.0,0.0):vec2(0.0,1.0);
|
|
vec4 x12=x0.xyxy+C.xxzz;
|
|
x12.xy-=i1;
|
|
i=mod289(i);
|
|
vec3 p=permute(permute(i.y+vec3(0.0,i1.y,1.0))+i.x+vec3(0.0,i1.x,1.0));
|
|
vec3 m=max(0.5-vec3(dot(x0,x0),dot(x12.xy,x12.xy),dot(x12.zw,x12.zw)),0.0);
|
|
m=m*m;m=m*m;
|
|
vec3 x=2.0*fract(p*C.www)-1.0;
|
|
vec3 h=abs(x)-0.5;
|
|
vec3 ox=floor(x+0.5);
|
|
vec3 a0=x-ox;
|
|
m*=1.79284291400159-0.85373472095314*(a0*a0+h*h);
|
|
vec3 g;
|
|
g.x=a0.x*x0.x+h.x*x0.y;
|
|
g.yz=a0.yz*x12.xz+h.yz*x12.yw;
|
|
return 130.0*dot(m,g);
|
|
}
|
|
|
|
void main(){
|
|
vec2 uv=gl_FragCoord.xy/u_resolution;
|
|
vec2 p=uv*2.0-1.0;
|
|
p.x*=u_resolution.x/u_resolution.y;
|
|
float t=u_time*0.3;
|
|
|
|
vec2 mp=u_mouse*2.0-1.0;
|
|
mp.x*=u_resolution.x/u_resolution.y;
|
|
float mouseDist=length(p-mp);
|
|
float mouseInfluence=smoothstep(0.8,0.0,mouseDist)*0.3;
|
|
|
|
float ripple=0.0;
|
|
if(u_click>0.0){
|
|
vec2 cp=u_clickPos*2.0-1.0;
|
|
cp.x*=u_resolution.x/u_resolution.y;
|
|
float d=length(p-cp);
|
|
ripple=sin(d*30.0-u_click*8.0)*exp(-d*3.0)*exp(-u_click*2.0)*0.15;
|
|
}
|
|
|
|
float n1=snoise(p*1.5+vec2(t*0.5,t*0.3))*0.5+0.5;
|
|
float n2=snoise(p*3.0+vec2(-t*0.7,t*0.5))*0.5+0.5;
|
|
float n3=snoise(p*0.8+vec2(t*0.2,-t*0.4)+mouseInfluence)*0.5+0.5;
|
|
|
|
vec3 c1=vec3(0.05,0.2,0.4);
|
|
vec3 c2=vec3(0.0,0.8,0.5);
|
|
vec3 c3=vec3(0.3,0.1,0.6);
|
|
vec3 c4=vec3(0.1,0.5,0.9);
|
|
|
|
float aurora=smoothstep(0.3,0.7,n3)*smoothstep(0.8,0.4,n1);
|
|
vec3 auroraColor=mix(c2,c4,n2)*aurora*1.2;
|
|
vec3 bg=mix(c1,c3,uv.y*0.5+n1*0.3);
|
|
bg+=auroraColor;
|
|
|
|
float stars=pow(snoise(p*20.0),12.0)*0.8;
|
|
bg+=vec3(stars);
|
|
bg+=vec3(ripple*2.0,ripple*3.0,ripple*4.0);
|
|
bg+=vec3(0.1,0.3,0.5)*mouseInfluence;
|
|
|
|
float vignette=1.0-smoothstep(0.5,1.5,length(p*0.7));
|
|
bg*=vignette*0.9+0.1;
|
|
|
|
gl_FragColor=vec4(bg,1.0);
|
|
}
|
|
`;
|
|
|
|
function mkShader(type,src){
|
|
var s=gl.createShader(type);
|
|
gl.shaderSource(s,src);
|
|
gl.compileShader(s);
|
|
if(!gl.getShaderParameter(s,gl.COMPILE_STATUS)){gl.deleteShader(s);return null;}
|
|
return s;
|
|
}
|
|
|
|
var vs=mkShader(gl.VERTEX_SHADER,vsSrc);
|
|
var fs=mkShader(gl.FRAGMENT_SHADER,fsSrc);
|
|
var prog=gl.createProgram();
|
|
gl.attachShader(prog,vs);
|
|
gl.attachShader(prog,fs);
|
|
gl.linkProgram(prog);
|
|
gl.useProgram(prog);
|
|
|
|
var buf=gl.createBuffer();
|
|
gl.bindBuffer(gl.ARRAY_BUFFER,buf);
|
|
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),gl.STATIC_DRAW);
|
|
var aPos=gl.getAttribLocation(prog,'a_pos');
|
|
gl.enableVertexAttribArray(aPos);
|
|
gl.vertexAttribPointer(aPos,2,gl.FLOAT,false,0,0);
|
|
|
|
var uTime=gl.getUniformLocation(prog,'u_time');
|
|
var uRes=gl.getUniformLocation(prog,'u_resolution');
|
|
var uMouse=gl.getUniformLocation(prog,'u_mouse');
|
|
var uClick=gl.getUniformLocation(prog,'u_click');
|
|
var uClickPos=gl.getUniformLocation(prog,'u_clickPos');
|
|
|
|
function resize(){
|
|
var dpr=window.devicePixelRatio||1;
|
|
canvas.width=window.innerWidth*dpr;
|
|
canvas.height=window.innerHeight*dpr;
|
|
gl.viewport(0,0,canvas.width,canvas.height);
|
|
}
|
|
window.addEventListener('resize',resize);
|
|
resize();
|
|
|
|
var lastFrame=0, targetFPS=30;
|
|
|
|
function render(now){
|
|
requestAnimationFrame(render);
|
|
if(window._paused||window._fullscreen)return;
|
|
|
|
var interval=1000/targetFPS;
|
|
if(now-lastFrame<interval)return;
|
|
lastFrame=now;
|
|
|
|
if(now-lastMove>5000){targetFPS=10;}else{targetFPS=30;}
|
|
|
|
var t=now/1000.0;
|
|
var clickElapsed=clickTime>0?(now-clickTime)/1000.0:0.0;
|
|
|
|
gl.uniform1f(uTime,t);
|
|
gl.uniform2f(uRes,canvas.width,canvas.height);
|
|
gl.uniform2f(uMouse,mouseX,mouseY);
|
|
gl.uniform1f(uClick,clickElapsed>3.0?0.0:clickElapsed);
|
|
gl.uniform2f(uClickPos,clickX,clickY);
|
|
gl.drawArrays(gl.TRIANGLE_STRIP,0,4);
|
|
}
|
|
requestAnimationFrame(render);
|
|
</script>
|