Shader Template

In this example below you will see how to do a Shader Template with some HTML / CSS and Javascript

A template for playing with shaders using twgl.js. Includes stats.js for FPS, and CCapture for recording to webm (click to start, click again to stop and save).

Thumbnail
This awesome code was written by onion2k, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright onion2k ©
  • HTML
  • CSS
  • JavaScript
    <script id="fs" type="notjs">
  // Fragment shader

  #ifdef GL_ES
  precision mediump float;
  #endif

  uniform float u_time;
  uniform vec2 u_mouse;
  uniform vec2 u_resolution;
  uniform sampler2D u_texture;

  void main(void)
  {
      vec2 uv = gl_FragCoord.xy / u_resolution;
      vec4 texColor = texture2D(u_texture, uv);
      gl_FragColor = texColor;
  }

</script>



<!-- Probably ignore everything from here. -->

<script id="vs" type="notjs">
  // Vertex shader
  attribute vec4 position;
  void main() {
    gl_Position = position;
  }
</script>

<canvas id="c"></canvas>


/*Downloaded from https://www.codeseek.co/onion2k/shader-template-gzdGXe */
    body {
  display: grid;
  height: 100vh;
  align-items: center;
  justify-items: center;
  margin: 0;
  background-color: #000;
}
canvas {
  width: 800px;
  height: calc( 9 / 16 * 800px);
  border: 1px solid #fff;
}


/*Downloaded from https://www.codeseek.co/onion2k/shader-template-gzdGXe */
    "use strict";

var mX=1, mY=1;
var canvas = document.getElementById("c");
var rect = canvas.getBoundingClientRect();

var capturer = new CCapture( { format: 'webm' } );
var save = false;
var recording = false;

var gl = twgl.getWebGLContext(canvas);
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);

let imgTex = twgl.createTexture(gl, {
  src: 'https://source.unsplash.com/512x512/?code',
  crossOrigin: "",
  mag: gl.NEAREST,
  wrap: gl.REPEAT,
  flipY: true
});

var arrays = {
  position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0],
};

var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);

function render(time) {

  stats.begin();

  twgl.resizeCanvasToDisplaySize(gl.canvas);

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

  var uniforms = {
    u_time: time * 0.001,
    u_mouse: [mX,mY],
    u_resolution: [gl.canvas.width, gl.canvas.height],
    u_texture: imgTex
  };

  gl.useProgram(programInfo.program);

  twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
  twgl.setUniforms(programInfo, uniforms);
  twgl.drawBufferInfo(gl, bufferInfo);

	stats.end();

  requestAnimationFrame(render);

  if (save && recording) {
    save = false;
    recording = false;
    capturer.stop();
    capturer.save();
  }

  if (recording) {
    capturer.capture( gl.canvas );
  }

}

window.addEventListener('mousemove', (e) => {
  mX = (e.clientX - rect.left) / rect.width;
  mY = 1 - ((e.clientY - rect.top) / rect.height);
});

var stats = new Stats();
stats.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
document.body.appendChild( stats.dom );

document.addEventListener('DOMContentLoaded', (e)=>{
  let recBtn = document.createElement('button');
  recBtn.appendChild(document.createTextNode('• Rec'));
  document.body.appendChild(recBtn);
  recBtn.style.position = 'absolute';
  recBtn.style.bottom = '20px';
  recBtn.style.right = '20px';
  recBtn.style['z-index'] = '2';
  recBtn.addEventListener('click', (e)=>{
    if (recording) {
      save = true;
      recBtn.style.color = '#000';
    } else {
      capturer.start();
      save = false;
      recording = true;
      recBtn.style.color = '#f00';
    }    
  })
});

//Get this party started
requestAnimationFrame(render);


Comments