SOURCE

console 命令行工具 X clear

                    
>
console
class ShaderPen {
  constructor(shaderString, noRender) {
    // shadertoy differences
    const ioTest = /\(\s*out\s+vec4\s+(\S+)\s*,\s*in\s+vec2\s+(\S+)\s*\)/;
    const io = shaderString.match(ioTest);
    shaderString = shaderString.replace('mainImage', 'main');
    shaderString = shaderString.replace(ioTest, '()');

    // shadertoy built in uniforms
    const uniforms = this.uniforms = {
      iResolution: {
        type: 'vec3',
        value: [window.innerWidth, window.innerHeight, 0],
      },
      iTime: {
        type: 'float',
        value: 0,
      },
      iTimeDelta: {
        type: 'float',
        value: 0,
      },
      iFrame: {
        type: 'int',
        value: 0,
      },
      iMouse: {
        type: 'vec4',
        value: [0, 0, 0, 0],
      },
    };

    // create default string values
    shaderString = (io ? `#define ${io[1]} gl_FragColor\n#define ${io[2]} gl_FragCoord.xy\n` : '') + shaderString;
    shaderString = Object.keys(uniforms)
      .map((key) => ({
      name: key,
      type: uniforms[key].type,
    }))
      .reduce((a, uniform) => (
      a + `uniform ${uniform.type} ${uniform.name};\n`
    ), '') + shaderString;
    shaderString = 'precision highp float;\n' + shaderString;

    // create, position, and add canvas
    const canvas = this.canvas = document.createElement('canvas');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    canvas.style.position = 'fixed';
    canvas.style.left = 0;
    canvas.style.top = 0;
    document.body.append(canvas);

    // get webgl context and set clearColor
    const gl = this.gl = canvas.getContext('webgl');
    gl.clearColor(0, 0, 0, 0);

    // compile basic vertex shader to make rect fill screen
    const vertexShader = this.vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader, `
      attribute vec2 position;
      void main() {
      gl_Position = vec4(position, 0.0, 1.0);
      }
    `);
    gl.compileShader(vertexShader);

    // compile fragment shader from string passed in
    const fragmentShader = this.fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader, shaderString);
    gl.compileShader(fragmentShader);

    // make program from shaders
    const program = this.program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);

    // vertices for basic rectangle to fill screen
    const vertices = this.vertices = new Float32Array([
      -1, 1, 1, 1, 1, -1,
      -1, 1, 1, -1, -1, -1,
    ]);

    const buffer = this.buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

    gl.useProgram(program);

    program.position = gl.getAttribLocation(program, 'position');
    gl.enableVertexAttribArray(program.position);
    gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0);

    // get all uniform locations from shaders
    Object.keys(uniforms).forEach((key, i) => {
      uniforms[key].location = gl.getUniformLocation(program, key);
    });

    // report webgl errors
    this.reportErrors();

    // bind contexts
    this._bind(
      'mouseDown',
      'mouseMove',
      'mouseUp',
      'render',
      'resize'
    );

    // add event listeners
    window.addEventListener('mousedown', this.mouseDown);
    window.addEventListener('mousemove', this.mouseMove);
    window.addEventListener('mouseup', this.mouseUp);
    window.addEventListener('resize', this.resize);

    // auto render unless otherwise specified
    if (noRender !== 'NO_RENDER') {
      this.render();
    }
  }

  _bind(...methods) {
    methods.forEach((method) => this[method] = this[method].bind(this));
  }

  mouseDown(e) {
    this.mousedown = true;
    this.uniforms.iMouse.value[2] = e.clientX;
    this.uniforms.iMouse.value[3] = e.clientY;
  }

  mouseMove(e) {
    if (this.mousedown) {
      this.uniforms.iMouse.value[0] = e.clientX;
      this.uniforms.iMouse.value[1] = e.clientY;
    }
  }

  mouseUp(e) {
    this.mousedown = false;
    this.uniforms.iMouse.value[2] = 0;
    this.uniforms.iMouse.value[3] = 0;
  }

  render(timestamp) {
    const gl = this.gl;

    let delta = this.lastTime ? ((timestamp - this.lastTime) / 1000) : 0;
    this.lastTime = timestamp;

    this.uniforms.iTime.value += delta;
    this.uniforms.iTimeDelta.value = delta;
    this.uniforms.iFrame.value++;

    gl.clear(gl.COLOR_BUFFER_BIT);

    Object.keys(this.uniforms).forEach((key) => {
      const t = this.uniforms[key].type;
      const method = t.match(/vec/) ? `${t[t.length - 1]}fv` : `1${t[0]}`;
      gl[`uniform${method}`](this.uniforms[key].location, this.uniforms[key].value);
    });

    gl.drawArrays(gl.TRIANGLES, 0, this.vertices.length / 2);

    requestAnimationFrame(this.render);
  }

  reportErrors() {
    const gl = this.gl;

    if (!gl.getShaderParameter(this.vertexShader, gl.COMPILE_STATUS)) {
      console.log(gl.getShaderInfoLog(this.vertexShader));
    }

    if (!gl.getShaderParameter(this.fragmentShader, gl.COMPILE_STATUS)) {
      console.log(gl.getShaderInfoLog(this.fragmentShader));
    }

    if (!gl.getProgramParameter(this.program, gl.LINK_STATUS)) {
      console.log(gl.getProgramInfoLog(this.program));
    }
  }

  resize() {
    this.canvas.width = this.uniforms.iResolution.value[0] = window.innerWidth;
    this.canvas.height = this.uniforms.iResolution.value[1] = window.innerHeight;

    this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
  }
}


new ShaderPen(`
 // Copyright Inigo Quilez, 2016 - https://iquilezles.org/
// I am the sole copyright owner of this Work.
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.

// based on https://www.shadertoy.com/view/XdXGDS

#define AA 2

// Other "Iterations" shaders:
//
// "trigonometric"   : https://www.shadertoy.com/view/Mdl3RH
// "trigonometric 2" : https://www.shadertoy.com/view/Wss3zB
// "circles"         : https://www.shadertoy.com/view/MdVGWR
// "coral"           : https://www.shadertoy.com/view/4sXGDN
// "guts"            : https://www.shadertoy.com/view/MssGW4
// "inversion"       : https://www.shadertoy.com/view/XdXGDS
// "inversion 2"     : https://www.shadertoy.com/view/4t3SzN
// "shiny"           : https://www.shadertoy.com/view/MslXz8
// "worms"           : https://www.shadertoy.com/view/ldl3W4
// "stripes"         : https://www.shadertoy.com/view/wlsfRn


vec3 shape( in vec2 uv )
{
	float time = iTime*0.05  + 47.0;
    
	vec2 z = -1.0 + 2.0*uv;
	z *= 1.5;
    
    vec3 col = vec3(1.0);
	for( int j=0; j<48; j++ )
	{
        float s = float(j)/16.0;
        float f = 0.2*(0.5 + 1.0*fract(sin(s*20.0)));

		vec2 c = 0.5*vec2( cos(f*time+17.0*s),sin(f*time+19.0*s) );
		z -= c;
		float zr = length( z );
	    float ar = atan( z.y, z.x ) + zr*0.6;
	    z  = vec2( cos(ar), sin(ar) )/zr;
		z += c;

        // color		
        col -= 0.5*exp( -10.0*dot(z,z) )* (0.25+0.4*sin( 5.5 + 1.5*s + vec3(1.6,0.8,0.5) ));
	}
        
    return col;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    float e = 1.0/iResolution.x;

    vec3 tot = vec3(0.0);
    for( int m=0; m<AA; m++ )
    for( int n=0; n<AA; n++ )
    {        
        vec2 uv = (fragCoord+vec2(m,n)/float(AA))/iResolution.xy;
	    vec3 col = shape( uv );
        float f = dot(col,vec3(0.333));
        vec3 nor = normalize( vec3( dot(shape(uv+vec2(e,0.0)),vec3(0.333))-f, 
                                    dot(shape(uv+vec2(0.0,e)),vec3(0.333))-f, 
                                    e ) );
        col += 0.2*vec3(1.0,0.9,0.5)*dot(nor,vec3(0.8,0.4,0.2));;
	    col += 0.3*nor.z;
        tot += col;
    }
    tot /= float(AA*AA);

    tot = pow( clamp(tot,0.0,1.0), vec3(0.8,1.1,1.3) );
	
    vec2 uv = fragCoord/iResolution.xy;
    tot *= 0.4 + 0.6*pow( 16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y), 0.1 );

    fragColor = vec4( tot, 1.0 );
}
`);
<body></body>
html,body{border:none;padding:0;margin:0;}
#container {position:absolute;width:100%;height:100%;}